Files
AgentHub/plugins/agenthub/commands/agenthub-doctor.md
T
nntrivi2001 c90dd7b147 fix(bootstrap): self-heal a systemd unit left on a retired plugin root
The residue an interrupted update leaves behind is invisible: the server
runs, every doctor row reads OK, and the unit quietly still names a cache
directory Claude Code deleted during the update. Nothing surfaces it until
a reboot, when the dashboard does not come back and nothing recorded why.

- fastPathOk now rejects a stale unit, so the next SessionStart repairs it
  instead of short-circuiting. `unitIsStale` is pure fs on purpose: that
  path runs on every session and may not spawn a process.
- Repairing the unit is not restarting the server. A current, healthy
  server keeps running and the corrected unit takes effect at the next
  start (`pendingSystemdRestart = systemdOwned && needsServer`), and the
  detached-spawn fallback is guarded by needsServer so a stale unit alone
  cannot start a second server onto a bound port.
- systemdOwned now also requires the unit to be ACTIVE. Installed-but-
  stopped owns nothing: skipping the stop there and asking systemd to start
  would bind an occupied port and crash-loop under Restart=always.
- /agenthub-doctor gains a systemd row naming the consequence ("will NOT
  come back after a reboot") and the fix. WARN, never FAIL — the dashboard
  in front of you works, and having no unit at all is a normal setup.

The fast-path test pins the regression against an otherwise fully healthy
install, live server included; without a live server it would have passed
against the unfixed code either way.
2026-09-11 16:45:47 +07:00

2.5 KiB

description
description
Diagnose a plugin-installed AgentHub — Node, npm, disk, bootstrap, server, hooks, CLI, systemd, tmux, UI build

Run the diagnostic and report what it found. Do not fix anything unless the user asks.

node "${CLAUDE_PLUGIN_ROOT}/scripts/plugin-doctor.js"

Print the output verbatim, then add at most three lines of guidance based on the FAIL and WARN rows:

  • FAIL Node → the installed Node is too old for node:sqlite; the server cannot start until Node is upgraded.
  • FAIL Hooks → duplicate hook entries double every token and cost figure. Starting a new Claude Code session removes them automatically (the bootstrap backs the file up as settings.json.agenthub-bak first).
  • FAIL Server → run /agenthub-update, then check ~/.claude/agenthub/runtime/bootstrap.log and server.log.
  • FAIL Runtime deps → the install is incomplete, not merely absent. Delete ~/.claude/agenthub/runtime/node_modules before running /agenthub-update; reinstalling over the broken tree is what let it survive.
  • FAIL npm or FAIL Disk → nothing else in the report can be trusted until these are fixed; both silently truncate installs.
  • WARN agenthub CLI → print the exact export PATH=... line from the output.
  • WARN Skill plugins → the pipelines name slash commands no installed plugin provides. The dashboard is unaffected; /agenthub:ship-feature(-lane) is what stops partway. The bootstrap normally installs these itself, so this row also means that attempt has not run or did not succeed — say /agenthub-update retries it, and print the claude plugin install … line from the output as the manual route.
  • WARN systemd → when it says the unit names a previous plugin version, the dashboard is running now but will NOT come back after a reboot. Starting a new Claude Code session repairs it; print the --force command from the output as the immediate fix. "installed but not running" just needs systemctl --user start agenthub.
  • WARN tmux → only the run console, agenthub lanes shell and the session-reload keystrokes are affected; monitoring, lanes and the CLI are not. Print the install command from the output. If the row says ok but Start Run still fails, the server has a different PATH than this check — ask it directly with curl -s localhost:4820/api/run/tmux.
  • WARN Dashboard UI → run /agenthub-open to build the bundle. When the row quotes a build error, report that error — it is the actual problem.

No preamble, no summary of things that passed.