[2026-05-29] hermes kraken+eagle+deployment patterns, htpc magic4pc+steam emulators, tv luna-send

This commit is contained in:
Alexey Martemyanov
2026-05-29 03:03:06 +06:00
parent 67fee70ba3
commit cea0db4168
10 changed files with 563 additions and 9 deletions
@@ -0,0 +1,107 @@
---
date: 2026-05-29
status: complete
---
# Wiki Curation — 2026-05-29
## Done
- **Conflict scan:** No git conflict markers in ~/obsidian/ ✅
- **Previous run (2026-05-28):** status=complete, no Unfinished ✅
- **Orientation:** SCHEMA.md, index.md (50 pages), log.md (last 30 lines)
- **Sessions:** No sessions for 2026-05-29 (cron run itself — not crystallizable)
- **Vault changes since 2026-05-28 02:00:**
- `family/how-to/magic4pc-webos.md` — detailed WebOS TV app: build
(--openssl-legacy-provider pitfall), deploy.sh flow, auto-launch
logic (boot/wake run-state files), Back+keyboard WebOS quirk
- `family/how-to/tv-luna-send.md` + `htpc-webos-luna.md` — luna-send
SSH workaround (`script(1)` PTY trick), wrapper script location and
usage, subscribe-mode limitation
- `family/how-to/htpc-migration-plan.md` — EmuDeck Flatpak save paths
table (8 emulators), ROM symlink structure from Data partition,
non-Steam Windows games library paths
- `family/projects/aide-kraken-backend.md` — Hermes Kraken as
OpenAI-compatible API backend for Android Aide app via Cloudflare
Tunnel (created 2026-05-13, newly surfaced)
- `family/schedule/vacation-july-august-2026.md` — personal schedule,
skipped (out of scope)
- **Inbox:** ~/obsidian/wiki/raw/inbox/ empty (processed/ has 1 old file) ✅
### Crystallization — new pages
**tech/tv-luna-send.md** (new) — WebOS TV luna-send via SSH
- Sources: `family/how-to/tv-luna-send.md` + `family/how-to/htpc-webos-luna.md`
- `script(1)` PTY workaround, `tv-luna-send.sh` wrapper usage, common
Luna URIs, subscribe-mode limitation
**tech/hermes-kraken-api.md** (new) — Hermes Kraken OpenAI API server
- Source: `family/projects/aide-kraken-backend.md`
- Architecture diagram (Aide → CF Tunnel → hermes-kraken:8642), config,
container restart command, Aide Android setup, Cloudflare tunnel
reconfiguration
### Crystallization — updated pages
**tech/htpc-magic4pc.md** (updated) — WebOS TV app side added
- WebOS build section (webpack Node 25 pitfall)
- deploy.sh flow + IPK packaging pitfalls
- Auto-launch logic (boot/wake run-state files, init.d script)
- Back key + system keyboard quirk (`_kbWasOpen` fix)
- Added `[[tech/tv-luna-send]]` cross-link
**tech/htpc-steam-emulators.md** (updated) — EmuDeck paths added
- Full EmuDeck Flatpak save paths table (8 emulators)
- ROM symlink commands from Data partition to ~/Emulation/roms/
- Non-Steam Windows games library paths
### Synthesis (MANDATORY)
**concepts/hermes-deployment-patterns.md** (new)
- Co-occurrence: `hermes-eagle-mac` + `hermes-docker-kraken` + new
`hermes-kraken-api` = 3 Hermes deployment pages, no synthesis existed
- Three models compared: Eagle native (claude-proxy, launchd, Zulip
transport), Kraken Docker (docker run, no compose), Kraken API server
(OpenAI-compat endpoint, Cloudflare Tunnel, mobile clients)
- Added backlinks from hermes-docker-kraken + hermes-eagle-mac
### Navigation updated
- `index.md`: 3 entries added (tv-luna-send, hermes-kraken-api,
hermes-deployment-patterns); count 50→53; date bumped to 2026-05-29
- `log.md`: entry appended
## Validation fixes
All 5 new/modified wiki pages passed pre-commit validation checks:
- NO_FRONTMATTER: ✅
- BARE_MULTI_LINK in related: ✅ (all YAML lists, no inline multi-links)
- WIKILINK_IN_FIELD: ✅
- VARIATION_SELECTOR: ✅
- TITLE_LOOKS_LIKE_SLUG: ✅ (all titles human-readable)
- ALIASES_MISSING_BILINGUAL: ✅ (no aliases fields on new pages)
No fixes needed post-validation.
Also updated hermes-docker-kraken.md and hermes-eagle-mac.md for
cross-links — both passed frontmatter validation.
## Unresolved conflicts
(none)
## Unfinished
(none)
## Stats
- Conflicts resolved: 0
- Inbox processed: 0 (empty)
- Sessions crystallized: 0 / 0 checked (no sessions today)
- Pages created: 3 (tv-luna-send, hermes-kraken-api,
hermes-deployment-patterns)
- Pages updated: 4 (htpc-magic4pc, htpc-steam-emulators,
hermes-docker-kraken, hermes-eagle-mac)
- Synthesis pages created: 1 (hermes-deployment-patterns)
- Lint issues: 0
- Validation issues fixed: 0
@@ -0,0 +1,82 @@
---
title: Hermes Deployment Patterns
created: '2026-05-29'
updated: '2026-05-29'
type: concept
namespace: personal
tags: [hermes, architecture, agent, eagle, kraken, infra]
sources: []
confidence: medium
related:
- "[[tech/hermes-eagle-mac]]"
- "[[tech/hermes-docker-kraken]]"
- "[[tech/hermes-kraken-api]]"
- "[[personal-os-architecture]]"
---
# Hermes Deployment Patterns
Three distinct ways Hermes runs in the Personal OS ecosystem. Each serves
a different access model and client type.
## Pattern 1: Eagle Native (Mac M4)
**Where:** Eagle Mac M4 Max, native process (not Docker)
**Transport:** Zulip (Docker)
**Model backend:** `openclaw-claude-proxy` on port 3456 — wraps
`claude --print` as an OpenAI-compatible endpoint, preserving tool_use.
**Autostart:** launchd (`ai.claude-proxy.plist`)
**Why native:** Mac file system access, MCP tools (obsidian-mcp), and the
cron wiki-curation job all need full host access. Docker would require
volume mounts for every integration.
**Key pitfall:** `claude-proxy` wrapper script must `source ~/.hermes/.env`
explicitly — launchd does not inherit login session env. See
[[tech/hermes-eagle-mac]].
## Pattern 2: Kraken Docker (RPi5)
**Where:** Kraken RPi5, `docker run` (not compose)
**Transport:** Zulip (same instance or separate)
**Model backend:** Gemini or OpenRouter via Hermes gateway
**Autostart:** `--restart unless-stopped` on the container
**Why docker run, not compose:** explicit restart behavior; avoids accidental
`docker compose down` wipes. Config volume: `~/.hermes` on Kraken host.
See [[tech/hermes-docker-kraken]].
## Pattern 3: Kraken API Server (OpenAI-compat)
**Where:** Kraken RPi5, same hermes-kraken container
**Transport:** HTTPS via Cloudflare Tunnel (`kraken.qentra.top`)
**Model backend:** Gemini / OpenRouter (same gateway)
**Clients:** Android Aide app (BYOK → Custom Endpoint), any OpenAI SDK
**Why Cloudflare Tunnel:** no port-forwarding on home router required.
The tunnel terminates at cloudflared running with `network_mode: host`,
hitting `localhost:8642` directly.
See [[tech/hermes-kraken-api]].
## Comparison
| Dimension | Eagle Native | Kraken Docker | Kraken API |
|-----------|-------------|---------------|-----------|
| Model | claude-sonnet via proxy | Gemini/ORouter | Gemini/ORouter |
| Transport | Zulip | Zulip | HTTPS REST |
| Clients | Cron, MCP tools | Zulip bot clients | Mobile / OpenAI SDK |
| External access | No | No | Yes (CF Tunnel) |
| MCP/tools | Full (host access) | Docker volumes | Not applicable |
| Rate limits | Claude OAuth (proxy workaround) | API keys | API keys |
## Design Principle
Hermes deployments follow the client's access model:
- **Interactive/tool-heavy** → Eagle native (full host, MCP)
- **Always-on background** → Kraken Docker (low-power, 24/7)
- **Mobile / external** → Kraken API server (HTTPS, standard protocol)
This avoids running a single large instance with conflicting requirements.
See [[personal-os-architecture]] for the full system overview.
+4 -1
View File
@@ -7,7 +7,7 @@ updated: '2026-05-25'
> Content catalog. Every wiki page listed with a one-line summary.
> Read this first to find relevant pages for any query.
> Last updated: 2026-05-28 | Total pages: 50
> Last updated: 2026-05-29 | Total pages: 53
## Personal OS — Core
@@ -51,7 +51,9 @@ updated: '2026-05-25'
- [[tech/reflect-skip-fuse]] — New SwiftUI View requires manual Kotlin stub in 2 places
- [[tech/arr-stack-taiga]] — Taiga arr stack (2026-05-20), config, router.py location
- [[tech/hermes-eagle-mac]] — Hermes on Eagle Mac M4; claude-proxy, Zulip setup, known pitfalls
- [[tech/hermes-kraken-api]] — Hermes Kraken OpenAI-compat API server; Cloudflare Tunnel, Aide Android client
- [[tech/jellyfin-transcode-rpi5]] — Jellyfin RPi5 transcoding pitfalls; PGS/subtitle handling
- [[tech/tv-luna-send]] — WebOS TV luna-send via SSH; script(1) PTY workaround, wrapper, common URIs
- [[tech/vault-git-sync]] — Vault git sync via Taiga bare repo; setup, pull hooks, pitfalls
- [[tech/vps-qentra]] — VPS qentra.top: IP, nginx+Cloudflare stack, subdomain setup
- [[tech/xgimi-play6-setup]] — XGIMI Play 6 (GMUI 6): ADB-over-network setup, launcher, keyboard
@@ -73,6 +75,7 @@ updated: '2026-05-25'
- [[concepts/executor-security-incident]] — Post-mortem: autonomous Asana boundary crossing (May 2026); root causes
- [[concepts/agent-memory-architecture]] — LLM agent memory taxonomy (arXiv 2603.07670) applied to personal-os
- [[concepts/knowledge-lifecycle]] — How knowledge flows from session to permanent wiki memory
- [[concepts/hermes-deployment-patterns]] — Three Hermes deployment models: Eagle native, Kraken Docker, Kraken API server
- [[concepts/multi-agent-design-patterns]] — Five reusable patterns: orchestrator/worker, scope tables, memory layers, role specialization
## Concepts — Vault & Wiki
+30
View File
@@ -76,6 +76,36 @@ type: meta
- Lint: watchlist-automation.md has tags [watchlist, automation, synthesis] not in SCHEMA taxonomy (pre-existing); torrents tag on media-pipeline-pitfalls.md also pre-existing; no broken wikilinks in new/modified pages
- Validation: all 4 modified/created pages passed pre-commit checks ✅
## [2026-05-29] update | Crystallization + synthesis (Hermes deployment patterns)
- Conflicts: 0 found (scan: all ~/obsidian/**/*.md)
- Previous run (2026-05-28): status=complete, no Unfinished ✅
- Inbox: empty
- Sessions: none for 2026-05-29 (no sessions found)
- Vault changes since 2026-05-28 02:00:
- `family/how-to/magic4pc-webos.md` — detailed WebOS TV app: build, deploy,
auto-launch, Back+keyboard quirk
- `family/how-to/tv-luna-send.md` + `htpc-webos-luna.md` — luna-send SSH
workaround and wrapper script
- `family/how-to/htpc-migration-plan.md` — EmuDeck Flatpak save paths table,
ROM symlinks from Data partition
- `family/projects/aide-kraken-backend.md` — Hermes Kraken as OpenAI-compat
API backend for Android Aide app via Cloudflare Tunnel
- `family/schedule/vacation-july-august-2026.md` — personal schedule, skip
- Created: tech/tv-luna-send.md (from tv-luna-send.md + htpc-webos-luna.md)
- Created: tech/hermes-kraken-api.md (from aide-kraken-backend.md)
- Updated: tech/htpc-magic4pc.md — WebOS build/deploy/auto-launch/Back+keyboard
- Updated: tech/htpc-steam-emulators.md — EmuDeck save paths + ROM symlinks
- Synthesis: concepts/hermes-deployment-patterns.md — 3 deployment models:
Eagle native, Kraken Docker, Kraken API server (cross-refs hermes-eagle-mac +
hermes-docker-kraken + hermes-kraken-api)
- Updated: tech/hermes-docker-kraken.md — added related links to new pages
- Updated: tech/hermes-eagle-mac.md — added deployment-patterns cross-link
- Updated: index.md — 3 pages added; count 50→53; date 2026-05-29
- Lint: all new pages have ≥1 inbound content link; 0 broken wikilinks in
new/modified pages; tags all from SCHEMA taxonomy ✅
- Validation: all 5 new/modified wiki pages passed pre-commit checks ✅
## [2026-05-28] update | Crystallization + synthesis + lint fixes
- Conflicts: 0 found (scan: all ~/obsidian/**/*.md)
- Inbox: empty
+3 -1
View File
@@ -1,12 +1,14 @@
---
title: Hermes Docker on Kraken
created: '2026-05-23'
updated: '2026-05-23'
updated: '2026-05-29'
type: tech
namespace: personal
tags: [hermes, docker, kraken, infra, how-to]
related:
- "[[tech/kraken-network]]"
- "[[concepts/hermes-deployment-patterns]]"
- "[[tech/hermes-kraken-api]]"
---
# Hermes Docker on Kraken
+1
View File
@@ -226,3 +226,4 @@ Claude падает с "Failed to spawn process". Проверить логи:
- [[tech/hermes-docker-kraken]] — Hermes на Кракене (Docker)
- [[tech/kraken-network]] — сетевая топология
- [[concepts/hermes-deployment-patterns]] — сравнение трёх моделей деплоя Hermes
+93
View File
@@ -0,0 +1,93 @@
---
title: Hermes Kraken — OpenAI-Compatible API Server
created: '2026-05-29'
updated: '2026-05-29'
type: tech
namespace: personal
tags: [hermes, kraken, infra, agent, how-to]
sources:
- family/projects/aide-kraken-backend.md
confidence: medium
related:
- "[[tech/hermes-docker-kraken]]"
- "[[tech/vps-qentra]]"
---
# Hermes Kraken — OpenAI-Compatible API Server
Hermes on Kraken exposes an OpenAI-compatible `/v1/chat/completions`
endpoint (`gateway/platforms/api_server.py`). Exposed externally via
Cloudflare Tunnel → used by the Android **Aide** app as a Hermes-backed
assistant.
## Architecture
```
Android (Aide)
└── HTTPS → hermes.kraken.qentra.top/v1/chat/completions
↓ Cloudflare Tunnel
cloudflared (Kraken, host network)
↓ localhost:8642
hermes-kraken (docker run, network_mode: host)
Hermes gateway → Gemini / OpenRouter / ...
```
`network_mode: host` means port 8642 is directly on the Kraken host —
no port mapping needed.
## Config (Kraken /opt/data/config.yaml)
```yaml
api_server:
enabled: true
port: 8642
host: "0.0.0.0"
key: "<secret>" # openssl rand -hex 32
```
Restart container via Portainer or:
```bash
BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=3
CID=$(curl -s -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/json" \
| jq -r '.[] | select(.Names[] | contains("hermes-kraken")) | .Id')
curl -s -X POST -H "X-API-Key: $KEY" \
"$BASE/api/endpoints/$EP/docker/containers/$CID/restart"
```
Health check: `curl -s http://localhost:8642/health`
## Cloudflare Tunnel Setup
Tunnel name: `kraken`. Public hostname (CF Zero Trust dashboard):
- **Hostname:** `kraken.qentra.top`
- **Type:** HTTP (not SSH)
- **URL:** `localhost:8642`
SSH to Kraken still works via VPS reverse tunnel (port 2223) — the CF
hostname change does not affect SSH access.
## Aide Android Client Config
Provider: Custom Endpoint
| Field | Value |
|-------|-------|
| Base URL | `https://kraken.qentra.top/v1` |
| API Key | secret from config.yaml |
| Model | `hermes-agent` (maps to Hermes internally) |
## What Was Not Changed
- cloudflared container — already running
- VPS reverse SSH tunnel — unaffected
- `network_mode: host` on hermes-kraken — already set
## See Also
- [[tech/hermes-docker-kraken]] — how Hermes runs on Kraken (docker run
pattern, no compose)
- [[tech/vps-qentra]] — VPS qentra.top: Cloudflare + nginx stack
+95 -2
View File
@@ -1,15 +1,18 @@
---
title: HTPC — magic4pc (LG Magic Remote)
created: '2026-05-28'
updated: '2026-05-28'
updated: '2026-05-29'
type: tech
namespace: family
tags: [htpc, how-to, pitfalls]
sources: [family/how-to/htpc-magic4pc.md]
sources:
- family/how-to/htpc-magic4pc.md
- family/how-to/magic4pc-webos.md
confidence: medium
related:
- "[[htpc-bazzite-proton]]"
- "[[tech/htpc-steam-emulators]]"
- "[[tech/tv-luna-send]]"
---
# HTPC — magic4pc (LG Magic Remote)
@@ -96,7 +99,97 @@ Sudoers rule (no-password systemctl):
bazzite ALL=(ALL) NOPASSWD: /usr/bin/systemctl
```
## WebOS TV App — Build & Deploy
The TV-side is a React/Enact WebOS app + Node.js service bundled into
an IPK. Sources: `~/Developer/magic4pc/webos/`.
### Build
```bash
cd ~/Developer/magic4pc/webos
NODE_OPTIONS=--openssl-legacy-provider npm run build
```
**Pitfall:** `--openssl-legacy-provider` is required — the old webpack
is incompatible with Node.js 25+.
### Package IPK
```bash
/Users/admin/webOS_TV_SDK/CLI/bin/ares-package dist/ service/ --outdir .
```
**Pitfall:** both `dist/` and `service/` arguments are required —
omitting `service/` excludes the Node.js service from the IPK.
**Pitfall:** `npm run package` = `ares-package -n` (unsigned) — TV
rejects unsigned packages. Use the SDK command directly.
### Deploy (deploy.sh)
```bash
cd ~/Developer/magic4pc/webos && ./deploy.sh
```
Script flow: build → package → scp → close → remove → install → launch.
Uses [[tech/tv-luna-send]] wrapper for close/remove/launch.
For install (subscribe mode) — direct `ssh+script` with polling on
`"state":"installed"`.
**Pitfall:** `ares-install` / `ares-launch` are unreliable — they don't
wait for completion. Use `luna-send dev/install` via `script` wrapper.
### Version in UI
Displayed as `1.1.0 (YYYY-MM-DD HH:MM)` — injected by webpack at
build time via `process.env.BUILD_DATE`.
## Auto-launch on Boot/Wake
Magic4pc launches a configured app when the TV boots or wakes.
| File | Location | Purpose |
|------|----------|---------|
| `magic4pc-settings` | PERSISTENT_DIR | Selected app ID |
| `magic4pc-last-app` | PERSISTENT_DIR | Last foreground app |
| `magic4pc-run-state` | `/tmp/` | `running` after first launch |
`PERSISTENT_DIR = /media/developer/apps/usr/palm/services/me.wouterdek.magic4pc.service`
Logic:
- **Boot/wake:** `/tmp` is cleared → no `run-state``freshStart=true`
→ launches configured app
- **Manual launch:** `run-state=running` already present → skips auto-launch
The `init.d` script on TV (`/var/lib/webosbrew/init.d/magic4pc`) removes
`run-state` on suspend so wake triggers fresh launch. Always edit in
repo (`tv-scripts/init.d-magic4pc.sh`), never directly on TV.
## WebOS Back Key + System Keyboard
When the system keyboard is open, **Back #1** is consumed by the OS
(closes keyboard) — the `keydown` DOM event and `onButtonDown` are
**not** fired. **Back #2** arrives normally.
Fix used in `MainPanel.js` (`_kbWasOpen` flag):
```js
// Input.onActivate:
this._kbWasOpen = true;
// onButtonDown on Back:
if (this.state.wolMacActive || this._kbWasOpen) {
this._kbWasOpen = false;
return; // suppress panel close
}
```
Approaches that don't work: `Popup.noAutoDismiss`, timeout heuristic,
polling `document.activeElement` (keyboard is a system overlay, focus
never moves to INPUT).
## See Also
- [[htpc-bazzite-proton]] — Proton game compatibility on this HTPC
- [[tech/htpc-steam-emulators]] — Steam, emulators, gamepad config
- [[tech/tv-luna-send]] — luna-send SSH wrapper for WebOS TV commands
+45 -5
View File
@@ -1,13 +1,16 @@
---
title: HTPC Steam & Emulators
created: '2026-05-23'
updated: '2026-05-28'
updated: '2026-05-29'
type: tech
namespace: family
tags: [htpc, steam, emulators, gamepad, how-to, pitfalls]
sources:
- family/how-to/htpc-migration-plan.md
related:
- "[[htpc-kodi-layout]]"
- "[[htpc-bazzite-proton]]"
- "[[tech/htpc-magic4pc]]"
---
# HTPC Steam & Emulators
@@ -43,9 +46,46 @@ only one `/dev/input/js`; Steam sees one controller.
`~/controller-profiles/`
- Steam shortcuts for non-Steam Windows games: use Proton Experimental
## Save Locations (approximate)
## EmuDeck Save Paths (Flatpak)
| System | Path |
|--------|------|
| Steam | `~/.steam/steam/userdata/` |
| Emulator | Save path |
|----------|-----------|
| RetroArch | `~/.var/app/org.libretro.RetroArch/config/retroarch/saves/` |
| Dolphin (GC/Wii) | `~/.var/app/org.DolphinEmu.dolphin-emu/data/dolphin-emu/` |
| Citra / Lime3DS | `~/.var/app/org.citra_emu.citra/` |
| PCSX2 (PS2) | `~/.var/app/net.pcsx2.PCSX2/config/PCSX2/memcards/` |
| RPCS3 (PS3) | `~/.var/app/net.rpcs3.RPCS3/config/rpcs3/dev_hdd0/` |
| PPSSPP (PSP) | `~/.var/app/org.ppsspp.PPSSPP/config/ppsspp/PSP/SAVEDATA/` |
| melonDS (NDS) | `~/.var/app/net.kuribo64.melonDS/` |
| Ryujinx (Switch) | `~/.var/app/org.ryujinx.Ryujinx/config/Ryujinx/bis/user/save/` |
| Steam | `~/.steam/steam/userdata/` |
## ROM Symlinks (Data partition → EmuDeck)
Emulators expect ROMs at `~/Emulation/roms/<system>/`. Symlinks from
the Data partition (`/run/media/bazzite/Data/`):
```bash
ln -s "/run/media/bazzite/Data/n64 roms" ~/Emulation/roms/n64
ln -s "/run/media/bazzite/Data/snes roms" ~/Emulation/roms/snes
ln -s "/run/media/bazzite/Data/gba roms" ~/Emulation/roms/gba
ln -s "/run/media/bazzite/Data/3ds roms" ~/Emulation/roms/3ds
ln -s "/run/media/bazzite/Data/ps2 roms" ~/Emulation/roms/ps2
ln -s "/run/media/bazzite/Data/dolphin roms" ~/Emulation/roms/wii
ln -s "/run/media/bazzite/Data/cemu roms" ~/Emulation/roms/wiiu
ln -s "/run/media/bazzite/Data/mame roms" ~/Emulation/roms/mame
ln -s "/run/media/bazzite/Data/sega roms" ~/Emulation/roms/genesis
ln -s "/run/media/bazzite/Data/nes" ~/Emulation/roms/nes
```
After symlinking, run **Steam ROM Manager** (EmuDeck) from Desktop Mode
to import ROMs into Steam with cover art.
## Non-Steam Windows Games
`/run/media/bazzite/Data/games/` — 38 pre-installed games (Bayonetta,
Cuphead, GTA V, Witcher 3, etc.). Add as Non-Steam games with
Proton Experimental.
`/run/media/bazzite/Data/steam/steamapps/common/` — already-Steam games
(Gang Beasts, Shovel Knight, etc.). Add as a second Steam library path.
+103
View File
@@ -0,0 +1,103 @@
---
title: WebOS TV — luna-send via SSH
created: '2026-05-29'
updated: '2026-05-29'
type: tech
namespace: family
tags: [htpc, how-to, pitfalls]
sources:
- family/how-to/tv-luna-send.md
- family/how-to/htpc-webos-luna.md
confidence: medium
related:
- "[[tech/htpc-magic4pc]]"
- "[[tech/htpc-kodi-layout]]"
---
# WebOS TV — luna-send via SSH
`luna-send` on WebOS writes output to the TTY, not stdout. SSH without a
PTY produces no output. The `script(1)` workaround captures output via a
pseudo-TTY.
TV IP: `192.168.1.75` (aliases: `root@LGwebOSTV`, `root@tv`).
## The Problem
```bash
ssh root@192.168.1.75 "luna-send -n 1 -f luna://..." # → silent
ssh -t root@192.168.1.75 "luna-send -n 1 -f luna://..." # → still silent
```
Root cause: `luna-send` detects whether its stdout is a TTY and refuses to
write to a pipe.
## The Fix: script(1)
```bash
ssh root@192.168.1.75 \
"script -q -c \"luna-send -n 1 -f luna://com.webos.applicationManager/running '{}'\" \
/tmp/o.txt; cat /tmp/o.txt"
```
`script(1)` allocates a pseudo-TTY and records output to `/tmp/o.txt`.
The wrapper then reads the file, filters the Script header/footer lines,
and removes the temp file.
## Wrapper: tv-luna-send.sh
Location: `~/Automation/tv-luna-send.sh` on Eagle.
```bash
# Usage (same flags as luna-send)
~/Automation/tv-luna-send.sh [luna-send flags] luna://service/method 'json'
# List running apps
~/Automation/tv-luna-send.sh \
-n 1 -f luna://com.webos.service.applicationmanager/running '{}'
# Close an app
~/Automation/tv-luna-send.sh \
-n 1 -f luna://com.webos.service.applicationmanager/closeByAppId \
'{"id":"me.wouterdek.magic4pc"}'
# Launch an app
~/Automation/tv-luna-send.sh \
-n 1 -f luna://com.webos.applicationManager/launch \
'{"id":"me.wouterdek.magic4pc"}'
# Query magic4pc service status
~/Automation/tv-luna-send.sh \
-n 1 -f luna://me.wouterdek.magic4pc.service/query '{}'
```
Set `TV_HOST` env to override the default target (`root@LGwebOSTV`).
DNS resolves via home router at `192.168.1.1`.
## Common Luna URIs
| URI | Purpose |
|-----|---------|
| `.../applicationmanager/running` | List running apps |
| `.../applicationmanager/closeByAppId` | Close app by ID |
| `.../appInstallService/dev/install` | Install IPK (subscribe) |
| `.../appInstallService/dev/remove` | Remove app |
| `.../applicationManager/launch` | Launch app |
| `.../applicationManager/getForegroundAppInfo` | Get active app |
| `...magic4pc.service/query` | Magic4pc service status |
Full service prefix: `com.webos.service.applicationmanager`,
`com.webos.appInstallService`, `com.webos.applicationManager`.
## Limitation: Subscribe Mode (-i)
`luna-send -i` (infinite subscribe, used for `dev/install`) does **not**
work through the wrapper — it never terminates normally. The
`magic4pc/webos/deploy.sh` handles install directly via `ssh+script` with
inline polling for `"state":"installed"`.
## Where Used
`magic4pc/webos/deploy.sh` — close, remove, and launch steps in the deploy
pipeline. See [[tech/htpc-magic4pc]] for the full magic4pc build and deploy
workflow.