feat(install): auto-start the dashboard on boot via systemd, no Claude Code needed
Adds ccam service install/uninstall/status for checkout installs and wires the same systemd --user unit into plugin-bootstrap.js, so plugin-installed colleagues get boot persistence too instead of needing a Claude Code session to (re)start the server after every reboot.
This commit is contained in:
@@ -8,7 +8,10 @@
|
||||
*
|
||||
* The worker installs runtime dependencies, removes hook entries left behind by
|
||||
* an older `npm run install-hooks` (they would double-count every event), puts
|
||||
* the `ccam` CLI on PATH, and starts the dashboard server detached.
|
||||
* the `ccam` CLI on PATH, and starts the dashboard server — as a systemd
|
||||
* `--user` service when available (see `systemd-service.js`), so it survives
|
||||
* reboots without Claude Code being opened first; otherwise a detached spawn
|
||||
* scoped to this session, same as before.
|
||||
*
|
||||
* Everything writable lives under `~/.claude/agent-dashboard/runtime/` — NOT in
|
||||
* the plugin cache, which Claude Code garbage-collects and replaces wholesale
|
||||
@@ -466,8 +469,38 @@ function bootstrap(rt = runtimeDir(), { force = false } = {}) {
|
||||
}
|
||||
|
||||
if (movedRoot || !serverIsLive()) {
|
||||
const pid = startDashboard(rt);
|
||||
log(rt, `started the dashboard server (pid ${pid})`);
|
||||
const svc = require("./systemd-service");
|
||||
const result = svc.systemctlAvailable()
|
||||
? svc.installUserService({
|
||||
name: "ccam",
|
||||
description: "CCAM dashboard server (Claude Code plugin)",
|
||||
workingDir: PLUGIN_ROOT,
|
||||
execStart: `${process.execPath} ${path.join(PLUGIN_ROOT, "server", "index.js")}`,
|
||||
env: {
|
||||
NODE_ENV: "production",
|
||||
NODE_PATH: path.join(rt, "node_modules"),
|
||||
DASHBOARD_CLIENT_DIST: path.join(rt, "client-dist"),
|
||||
},
|
||||
})
|
||||
: "unavailable";
|
||||
if (result === "written" || result === "unchanged") {
|
||||
if (result === "written") svc.enableLinger();
|
||||
log(
|
||||
rt,
|
||||
result === "written"
|
||||
? "installed a systemd --user service — the dashboard now survives reboots without Claude Code"
|
||||
: "systemd --user service already up to date"
|
||||
);
|
||||
} else {
|
||||
// No systemd (macOS/Windows/WSL without it), or the unit exists but
|
||||
// wasn't ours to touch — same detached-spawn fallback as before,
|
||||
// scoped to this session only.
|
||||
const pid = startDashboard(rt);
|
||||
log(
|
||||
rt,
|
||||
`started the dashboard server (pid ${pid})${result === "foreign" ? " — a foreign systemd unit named 'ccam' already exists" : ""}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
writeState(
|
||||
|
||||
Reference in New Issue
Block a user