feat(bridge): Linux port — systemd daemon autostart + POSIX fixes#54
feat(bridge): Linux port — systemd daemon autostart + POSIX fixes#54doug-w wants to merge 2 commits into
Conversation
Port the Node.js bridge to Linux. The daemon runtime, mDNS (pure-JS bonjour-service), Pixoo/ADB, and the PTY flow already worked; the gaps were autostart and a few macOS-flavored fallbacks. - linux-service.ts: systemd --user unit (agentdeck-daemon.service) mirroring windows-service.ts — buildUnitFile (Restart=on-failure ≈ LaunchAgent KeepAlive), hasSystemctl probe, install/start/stop/disable helpers over `systemctl --user`, XDG-aware unit path. Unit-tested (systemctl calls are integration-only). - cli.ts: `daemon install`/`uninstall` grow a Linux branch (was a hard exit on non-darwin) — install writes+enables+starts the unit and installs Codex/OpenCode hooks; degrades to a manual-start hint without systemd; uninstall gracefully /shutdowns then disables + removes the unit. - pty-manager.ts / check-deps.ts: shell fallback /bin/zsh → /bin/bash when $SHELL is unset (matters for the headless daemon unit). - setup.ts: Linux-aware — checks for a cc/make/python3 toolchain instead of Xcode CLT, skips the Stream Deck app/CLI steps (unavailable on Linux), and prints systemd autostart next-steps. - Docs: daemon.md Autostart, README "Linux (Bridge + Daemon)" section, and a CLAUDE.md "Linux dev setup" pointer. Verified on Debian 13 / Node 24: pnpm build clean, 1696 tests pass incl. the new linux-service suite, node-pty compiles natively, agentdeck CLI runs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
puritysb
left a comment
There was a problem hiding this comment.
The Linux port is well scoped, but the generated user unit hardcodes WorkingDirectory=~/.agentdeck. On a fresh install that directory may not exist, causing systemd to fail at the CHDIR step before Node starts. It also ignores the repository-supported AGENTDECK_DATA_DIR override. Please either create the selected data directory during install and use the same resolver as the daemon, or remove WorkingDirectory if it is not required. Add a unit test covering a fresh/overridden data directory. The current CI does not exercise the systemctl integration path, so this failure would otherwise only appear on a real new Linux install.
…ted on install Addresses PR puritysb#54 review: the generated user unit hardcoded WorkingDirectory=~/.agentdeck, which (1) ignored the AGENTDECK_DATA_DIR override the rest of the daemon respects, and (2) could fail systemd's CHDIR step before Node starts if the dir didn't exist on a fresh install. - New getDataDir() mirrors the daemon's inline resolver (AGENTDECK_DATA_DIR || ~/.agentdeck); buildUnitFile() uses it for WorkingDirectory (with an explicit workingDir opt override for testing). - installUnit() mkdir -p's the data dir before writing the unit, so CHDIR never fails on a fresh/overridden install. - Tests cover the default fallback, AGENTDECK_DATA_DIR override in WorkingDirectory, getDataDir resolution, and installUnit creating a not-yet-existing nested data dir. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012q6HRNJyVeMZiQcX4ZF7XF
|
Addressed in 2c0b9a9.
Full suite green (1180 bridge tests). |
puritysb
left a comment
There was a problem hiding this comment.
Thanks for fixing the fresh-directory CHDIR failure. The directory is now created before systemctl runs, and the focused tests/typecheck pass, but the AGENTDECK_DATA_DIR override still does not survive into the service process.
buildUnitFile() uses the install command's current environment to write WorkingDirectory=<override>, but the generated unit does not include an Environment=AGENTDECK_DATA_DIR=... directive (or an EnvironmentFile). A systemd user manager is not guaranteed to inherit the interactive shell environment used for agentdeck daemon install, and after login/boot it normally will not have this ad-hoc variable. The daemon then executes with no AGENTDECK_DATA_DIR, so session-registry.ts/APME/etc. fall back to ~/.agentdeck while systemd merely chdirs into the override directory. This breaks the claimed data-dir parity and can split daemon state across two locations.
Please persist the selected override into the unit with correct systemd escaping (only when explicitly set), or remove override support from this unit and avoid claiming it. Add a test that parses the generated unit and verifies the launched process receives the override, not only that WorkingDirectory and the directory exist. It would also be good to quote/escape all generated path values consistently while touching the unit builder.
Verification at 2c0b9a9: tsc --noEmit passed and linux-service.test.ts passed 12/12.
|
This remains the closest external PR to merge, so I am keeping it open. The remaining blocker is still the systemd process environment, not only its working directory: when Please add a unit-file test that verifies the launched process receives the override, rebase onto current master (the branch is now 133 commits behind), rerun the full CI matrix, and repeat the fresh Debian systemd user-service install test. Once those are green, this can return for final review. |
Ports the Node.js bridge to Linux. The daemon runtime, mDNS (pure-JS
bonjour-service), Pixoo/ADB, and the PTY flow already worked; the gaps were autostart and a few macOS-flavored fallbacks. Stream Deck's desktop app is unavailable on Linux, so plugin-host steps are intentionally out of scope.linux-service.ts: systemd--userunit (agentdeck-daemon.service) mirroringwindows-service.ts—buildUnitFile(Restart=on-failure≈ LaunchAgent KeepAlive),hasSystemctlprobe, install/start/stop/disable oversystemctl --user, XDG-aware path. Unit-tested (systemctl calls integration-only).cli.ts:daemon install/uninstallgain a Linux branch (was a hard exit on non-darwin); degrades to a manual-start hint without systemd; installs Codex/OpenCode hooks for parity.pty-manager.ts/check-deps.ts: shell fallback/bin/zsh→/bin/bashwhen$SHELLis unset (matters for the headless daemon unit).setup.ts: checks for acc/make/python3toolchain instead of Xcode CLT; skips Stream Deck app/CLI steps (unavailable on Linux).daemon.mdAutostart, README "Linux (Bridge + Daemon)", CLAUDE.md "Linux dev setup" pointer.Verified on Debian 13 / Node 24:
pnpm buildclean, 1696 tests pass incl. the newlinux-servicesuite,node-ptycompiles natively,agentdeckCLI runs.🤖 Generated with Claude Code