Initial commit — Luma Home trampoline for webOS 5/6

Bind-mounts a transparent web page over LG Home that launches Luma
via WebOSServiceBridge, with a subscription-based background watcher
as fallback. Tested on LG 65NANO813PA, webOS 6.5.3.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Kaloyan DanchevandClaude Opus 4.6 committed 2026-10-23 19:01:45 +03:00
commit 332bbc8fe2
5 files changed
+177

No files matched your search

+79
View File
@@ -0,0 +1,79 @@
# luma-home
Replaces the LG webOS Home screen with [Luma](https://github.com/ecklf/lg-luma) on webOS 5/6 TVs rooted via [Homebrew Channel](https://github.com/nicko88/LG-Homebrew).
## How it works
LG Home (`com.webos.app.home`) is a native QML app. This project bind-mounts a transparent web page over its directory so SAM sees a web-type Home. The web page immediately calls `WebOSServiceBridge` to launch Luma. A background watcher provides a fallback redirect via `luna-send` subscription.
### Components
| File | On TV at | Purpose |
|------|----------|---------|
| `overlay/appinfo.json` | `/media/developer/luma-home/overlay/` | Home manifest — web type, transparent, no splash |
| `overlay/index.html` | same | Minimal page that launches Luma via WebOSServiceBridge |
| `boot-hook.sh` | `/media/developer/luma-home/` | Homebrew Channel boot hook — mounts overlay, restarts SAM, launches Luma |
| `watcher.sh` | same | Background watcher — subscribes to foreground events, redirects Home→Luma |
### Boot flow
1. Homebrew Channel runs `boot-hook.sh` at cold boot
2. Bind-mount replaces `/usr/palm/applications/com.webos.app.home` (RAM only — reboot without the hook restores stock)
3. SAM restarts and reads the web manifest
4. Luma launches as the initial app
5. Watcher starts in the background
### Home button flow
1. User presses Home → system opens `com.webos.app.home` (our transparent web page)
2. `index.html` JS fires `WebOSServiceBridge` → launches Luma
3. Watcher catches the foreground change as backup → also launches Luma
## Requirements
- LG webOS TV rooted with Homebrew Channel (tested on webOS 6.5.3)
- Luma v2.1.0+ installed as `com.ecklf.luma`
- Telnet or SSH access to the TV
## Install
```sh
# Copy files to TV
scp -r overlay/ boot-hook.sh watcher.sh root@<TV_IP>:/media/developer/luma-home/
# SSH into TV and install the boot hook
chmod +x /media/developer/luma-home/boot-hook.sh /media/developer/luma-home/watcher.sh
ln -sf /media/developer/luma-home/boot-hook.sh /var/lib/webosbrew/init.d/10-luma-home
# Run it now (or reboot)
sh /media/developer/luma-home/boot-hook.sh
```
## Uninstall
```sh
# Remove boot hook
rm /var/lib/webosbrew/init.d/10-luma-home
# Kill watcher
kill $(cat /tmp/luma-watcher.pid 2>/dev/null)
# Unmount overlay (or just reboot)
umount /usr/palm/applications/com.webos.app.home
```
## Known limitations
- Brief visual transition when pressing Home (web page loads before Luma appears)
- `blockSystemApp` API (used by Luma's built-in Home integration for webOS 25/26) does not exist on webOS 5/6, so we use `systemctl restart sam` instead
- Native Home replacement (Luma binary as Home directly) does not work on webOS 6 — SAM handles native system apps differently
## Future
Fork Luma and patch `home.cjs` to support webOS 5/6 natively — replace the version check and `blockSystemApp` calls with the `systemctl restart sam` approach proven here.
## Tested on
- LG 65NANO813PA, webOS 6.5.3-47 (kisscurl-koli)
- Luma v2.1.0
- Homebrew Channel v0.7.3
+31
View File
@@ -0,0 +1,31 @@
#!/bin/sh
# Luma Home trampoline — bind-mount a transparent web page over LG Home,
# then launch Luma on top. A subscription watcher re-launches Luma every
# time the Home button is pressed (backup for when WebOSServiceBridge in
# the web page does not fire).
#
# Install:
# ln -sf /media/developer/luma-home/boot-hook.sh /var/lib/webosbrew/init.d/10-luma-home
#
# Requires: Homebrew Channel, Luma (com.ecklf.luma) installed via IPK.
# Tested on: webOS 6.5.3-47 (LG 65NANO813PA)
export PATH=/usr/bin:/usr/sbin:/bin:/sbin:$PATH
L=/media/developer/luma-home
H=/usr/palm/applications/com.webos.app.home
kill $(cat /tmp/luma-watcher.pid 2>/dev/null) 2>/dev/null
if ! grep -q " $H " /proc/mounts; then
mount --bind $L/overlay $H
systemctl restart sam
i=0
while [ $i -lt 30 ]; do
systemctl is-active sam >/dev/null 2>&1 && break
sleep 2; i=$((i+1))
done
sleep 5
luna-send -n 1 -w 10000 -f luna://com.webos.applicationManager/launch '{ "id": "com.ecklf.luma" }' </dev/null >/dev/null 2>&1
fi
nohup $L/watcher.sh </dev/null >/dev/null 2>&1 &
+24
View File
@@ -0,0 +1,24 @@
{
"id": "com.webos.app.home",
"version": "1.0.0",
"vendor": "LG Electronics",
"type": "web",
"main": "index.html",
"title": "Home",
"transparent": true,
"noSplashOnLaunch": true,
"icon": "icon.png",
"mediumIcon": "icon.png",
"largeIcon": "icon.png",
"iconColor": "#1ec15f",
"visible": false,
"disableBackHistoryAPI": true,
"lockable": false,
"hasPromotion": false,
"accessibility": {
"supportsAudioGuidance": true
},
"defaultWindowType": "home",
"handleScreenRemoteKey": true,
"bgColor": "#000000"
}
+22
View File
@@ -0,0 +1,22 @@
<!doctype html>
<html><head><meta charset="utf-8"><title>Home</title>
<meta name="viewport" content="width=1920">
<style>html,body{margin:0;padding:0;width:1920px;height:1080px;background:transparent;overflow:hidden}</style>
<script>
(function(){
try {
var b = new WebOSServiceBridge();
b.onservicecallback = function(){};
b.call('luna://com.webos.applicationManager/launch', JSON.stringify({id:'com.ecklf.luma'}));
} catch(e) {
setTimeout(function(){
try {
var b2 = new WebOSServiceBridge();
b2.onservicecallback = function(){};
b2.call('luna://com.webos.applicationManager/launch', JSON.stringify({id:'com.ecklf.luma'}));
} catch(e2){}
}, 500);
}
})();
</script>
</head><body></body></html>
+21
View File
@@ -0,0 +1,21 @@
#!/bin/sh
# Foreground watcher — subscribes to app manager events and launches Luma
# whenever the web Home trampoline appears in the foreground. The outer
# loop restarts the subscription if it drops.
echo $$ > /tmp/luma-watcher.pid
while true; do
luna-send -i luna://com.webos.applicationManager/getForegroundAppInfo \
'{ "subscribe": true }' 2>/dev/null \
| while IFS= read -r line; do
case "$line" in
*com.webos.app.home*)
luna-send -n 1 -w 5000 -f \
luna://com.webos.applicationManager/launch \
'{ "id": "com.ecklf.luma" }' >/dev/null 2>&1
;;
esac
done
sleep 2
done