• v1.6.3 fb3796f064

    nntrivi2001 released this 2026-09-15 07:56:38 +00:00 | 210 commits to main since this release

    Add-lane modal card toggles

    The "create a README" checkbox and the AI Router radio group in the Add-lane modal already render as cards that light up when selected — so the tick box and the radio dots were drawing a state the card itself was showing. Both are gone from the visuals.

    • The inputs are hidden (sr-only), not removed — keyboard navigation and screen readers work exactly as before, and the cards now take a focus-within ring so the focused control is still visible.
    • The "AI Router" radio's disabled state needed its own visual branch: the greyed-out dot had been carrying that signal, so the card now expresses it directly.

    Visual only — no behaviour, API, or schema change.

    Downloads
  • v1.6.2 6e685ce1c3

    nntrivi2001 released this 2026-09-15 04:02:49 +00:00 | 212 commits to main since this release

    A retired plugin build no longer downgrades the dashboard

    claude plugin update unpacks the new version into a new cache directory and prints "Restart to apply changes". A Claude Code process that was already running does not: it keeps loading the OLD directory, hooks and all.

    Every session such a process opened then ran the OLD bootstrap, which saw a state.json naming a different root, concluded the server had to be replaced, repointed agenthub.service at itself, and restarted the dashboard onto the version you had just upgraded away from. The dashboard reported the old version and offered the update again — once per session, forever, while installed_plugins.json and the cache both said the new version was installed. An "Update now" from that session succeeded and changed nothing.

    • supersededBy() reads Claude Code's installed_plugins.json. When a sibling cache directory is the recorded install, the bootstrap logs one line and does nothing else — no dependencies, no unit, no server. --force does not override it: the self-update chain forces from the new directory, which is never superseded, so the only --force refused is a deliberate downgrade. It cannot hand over to the new build either (the process it would replace is the one loading it), so the log line says to restart Claude Code.
    • Matched by sibling directory rather than by the <plugin>@<marketplace> key — correct without parsing a cache path or trusting a name. An entry pointing at a directory that no longer exists is ignored rather than wedging the bootstrap shut.

    The plugin cache now prunes itself

    The same updates leave a full copy of the repo — node_modules and all — per release. Twelve of them measured 1.7 GB on one machine.

    pruneRetiredPluginRoots() runs after the bootstrap's state is durable, so a bad prune cannot cost the record of a good bootstrap. Four independent readings of "still in use" are protected, and nothing matching any of them is ever deleted:

    Protected Why
    This build It is running.
    Every installPath in installed_plugins.json Claude Code says it is installed.
    The directory agenthub.service names (foreign unit included) A service is executing from it.
    Any directory named in settings.json hooks A Claude Code process that has not been restarted is still executing from there.

    Plus the two newest survivors as a rollback cushion, and nothing at all outside ~/.claude/plugins/cache/. Steady state is roughly four directories instead of twelve. Best effort throughout: a directory that will not delete is left alone, never an error.

    Upgrading

    If your dashboard has been reporting an old version and offering the same update repeatedly, quit Claude Code and reopen it once after updating. That is the state this release fixes, and the fix ships in the new build — the stuck old build does not have it. From then on it cannot recur.

    No API, schema, or behaviour change to the dashboard itself.

    Downloads
  • v1.6.1 713e9fe58b

    nntrivi2001 released this 2026-09-14 09:35:16 +00:00 | 214 commits to main since this release

    Update modal — footer buttons fit on one line

    The update dialog wrapped every footer label mid-word ("Check / now", "Copy / command") and looked broken.

    • whitespace-nowrap on the footer container — white-space inherits, so one class covers all four buttons.
    • flex-wrap beside it, so a long translation breaks the row rather than the words.
    • Dialog widened from max-w-lg to max-w-2xl.
    • The restarting button no longer carries a full sentence. In Vietnamese it was 52 characters long and overflowed the row on its own — and that same sentence is already shown in the status banner directly above the footer. The button uses a new short label; the banner is unchanged.

    UI only. No API, schema or behaviour change.

    Downloads
  • v1.6.0 e895c0e8eb

    nntrivi2001 released this 2026-09-14 09:08:31 +00:00 | 216 commits to main since this release

    AI Router profiles

    A new AI Router tab in Settings, next to Codex, stores named router endpoints (9Router, OpenRouter, a self-hosted gateway) as profiles: base URL, API key, a default model and optional per-tier overrides. A lane picks one when it is created, via a Native / AI Router radio, and the choice is written into that lane's own config.

    • Claude lane — eight env keys merged into its own .claude/settings.local.json.
    • Codex lane — $CODEX_HOME/<name>.config.toml, the layer codex -p <name> loads. The base config.toml is never touched.

    Native is a built-in profile, not a branch: it blanks the two connection variables (an absent key at project scope would let a user-level router apply) and removes the model names (writing them would override your own global model choice).

    Key material never leaves the server. Profiles live one file each under <CLAUDE_HOME>/agenthub-routers/ (0700/0600), GET /api/ai-routers reports only hasKey, and no route returns a profile in full.

    Three fixes this release depends on

    • wire_api = "chat" is rejected outright by codex-cli 0.149, so every Codex lane on a router would have failed to start. The layer now writes responses, and writes env_key only when the profile actually has a key.
    • The API key is no longer typed into a pane. tmux.sendCommand used send-keys with a KEY=... cmd prefix — visible in the pane the dashboard streams to the browser, in the tmux scrollback, and in ~/.bash_history. It now takes over the idle pane with respawn-pane -k -e, passing env through argv.
    • Editing or deleting a profile reaches the lanes using it. Attaching copies a profile, so a rotated key would otherwise never reach the lane still holding the revoked one. An edit re-applies; a delete resets those lanes to native and removes the Codex layer file. Per-lane failures are reported in the tab.

    .claude/settings.local.json is also added to each lane's git exclude — agenthub lanes reset runs git clean -fd without -x, which would delete it, and untracked meant the key was committable.

    DB: lanes.router_profile, nullable and additive.

    Server 1783/1783, client 503/503.

    Downloads
  • v1.5.10 Stable

    nntrivi2001 released this 2026-09-14 06:10:21 +00:00 | 218 commits to main since this release

    A plugin-install bug fix that was invisible in the worst way: the dashboard's update check could never see a release, and reported it as nothing at all.

    Fixed

    Every plugin-cache install can now detect a release.

    Check for updates on a plugin install answered release_check: "no_remote" and showed no version — on every machine, for every release ever published.

    The cause: this project's marketplace entry is "source": "./" — the plugin is the marketplace repository — but the resolver only accepted a source that was an explicit URL string or a { url } object. A relative source yielded null, so no releases API URL was ever built and no HTTP request was ever made. Nothing was unreachable; the dashboard simply never asked.

    A relative source ("./", "./plugins/x") now falls back to the manifest's own top-level repository. A owner/repo shorthand still resolves to null — that names a different repository, so borrowing the marketplace's URL would be a confidently wrong answer rather than an honest "cannot tell".

    Note for existing installs: an install running 1.5.9 or earlier carries the broken check and cannot detect this release by itself. Update it once by hand:

    claude plugin marketplace update claude-code-agent-monitor-plugins && claude plugin update agenthub@claude-code-agent-monitor-plugins -y
    

    From this version on, the button works on its own.

    Changed

    The Add-lane modal's Create/update readme file option is now a selectable card, matching the lane strip's selected/unselected treatment, with its hint inside the card. The "codex has no slash commands" clause is gone from the hint — the option is already hidden for a Codex lane, so the sentence only ever explained an absence you could not see.

    Downloads
  • v1.5.9 91af3dca86

    v1.5.9 Stable

    nntrivi2001 released this 2026-09-14 04:22:11 +00:00 | 221 commits to main since this release

    One new convenience in the Add-lane modal.

    Added

    A lane can open already writing its own docs.

    Under the Pipeline template select, the Add-lane modal now offers a Create/update readme file checkbox. Tick it and the new lane's terminal run starts right after creation with /sg-all:sg-md-writing as its first message — the lane opens with the docs skill already working on its CLAUDE.md/AGENTS.md set instead of waiting for you to type the command yourself.

    A skill only exists inside a CLI session, so there is nothing server-side to call instead: the checkbox opens the lane's own run, exactly as if you had typed the slash command into the pane. It requires the sg-all plugin to be installed in Claude Code; without it the session simply reports an unknown command.

    The checkbox is shown for Claude lanes only — Codex has no slash commands, the same reason the console prefills prose rather than a command for a codex lane. Leave it unticked and lane creation behaves exactly as before: no run is started.

    Docs: docs/LANES.md § Adding a lane.

    Downloads
  • v1.5.8 b7e81af0b6

    v1.5.8 Stable

    nntrivi2001 released this 2026-09-11 09:49:21 +00:00 | 223 commits to main since this release

    Follow-up to v1.5.7, which stopped the self-update from killing a systemd-managed dashboard. This release cleans up the residue an already-interrupted update left behind, and makes it visible.

    Fixed

    A systemd unit left pointing at a retired plugin version now repairs itself.

    This is the quietest failure in the whole chain: the server is running, /agenthub-doctor reads OK on every row, and the unit still names a plugin 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.

    The bootstrap's fast path now rejects that state, so the next Claude Code session repairs the unit instead of short-circuiting past it. unitIsStale is deliberately pure filesystem work: the fast path runs on every single SessionStart and may not spawn a process.

    Two things it carefully does not do:

    • Repairing the unit is not restarting the server. When the running server is current and healthy, the corrected unit is left to take effect at the next start. Restarting a working dashboard to fix a file that only matters at boot is churn the user feels for nothing.
    • A stale unit alone never starts a second server. The detached-spawn fallback is now guarded, so it cannot spawn onto a port the live server already holds.

    An installed-but-stopped unit no longer counts as owning the server. Ownership now requires the unit to be active. Treating a stopped unit as the owner skipped the stop and then asked systemd to start a server onto an occupied port — a crash loop, courtesy of the Restart=always added in 1.5.7.

    Added

    /agenthub-doctor reports systemd. A new row, WARN and never FAIL:

    • the unit names a previous plugin version — says plainly that the dashboard will not come back after a reboot, and gives the fix;
    • the unit is installed but not running;
    • a unit that AgentHub did not write is reported and left untouched;
    • no unit at all is reported as fine — a plugin install without agenthub service install is a normal setup where the server starts per session.

    Notes

    Machines already stuck from before 1.5.7 still need one manual bootstrap run — the stuck install is the thing that would otherwise apply the fix. See the v1.5.7 notes. After that, both the update path and the stale-unit path are self-healing.

    Downloads
  • v1.5.7 49a041b1dc

    v1.5.7 Stable

    nntrivi2001 released this 2026-09-11 09:34:14 +00:00 | 225 commits to main since this release

    Fixed

    A plugin self-update took the dashboard down and left it down.

    If you run the dashboard as a systemd --user service (agenthub service install, or any plugin bootstrap on Linux), pressing Update now killed it. The update chain itself ran fine — marketplace update, plugin update, new cache directory, deps, UI build — and then the bootstrap reached the step where it stops the server it is replacing. That server was systemd-managed, and the bootstrap is a descendant of it, so it runs inside the unit's cgroup. Two failures fired at the same instant:

    • the server exits 0, and the unit's Restart=on-failure reads a clean exit as "meant to stop" — systemd did not bring it back;
    • KillMode=control-group (systemd's default) reaped the bootstrap itself, mid-run, before it could repoint the unit at the new plugin root or write runtime/state.json.

    What that looked like on disk: bootstrap.log ending at stopped the server started from the previous plugin version with no line after it, a surviving .bootstrap.lock holding a dead pid, a state.json still naming the previous version, and a unit whose ExecStart still pointed at the old cache directory. The dashboard then stayed down until some later Claude Code session happened to run the bootstrap again — which is why this could go unnoticed for a while: a session started soon enough usually repaired it.

    The fix

    scripts/systemd-service.js splits installation in two:

    • writeUserService repoints the unit at the new plugin root and starts nothing — so the unit can be corrected while the old server is still serving requests;
    • restartUserService restarts with --no-block, because the caller is inside the cgroup being restarted and must not wait to be killed.

    plugin-bootstrap.js now checks whether a unit of ours owns the server. If it does, it never stops it by hand, and defers the restart until after writeState and releaseLock — by then there is nothing left to lose. If there is no unit (or a foreign one), the old stop-then-start path is unchanged: nothing there is inside a cgroup.

    The unit is also written with Restart=always instead of on-failure, so a graceful SIGTERM from anything at all no longer leaves the dashboard down for good. An explicit systemctl stop — what agenthub service uninstall does — still stops it.

    agenthub service install keeps the old one-step behaviour: it runs from your own shell, outside the unit's cgroup.

    If your dashboard is down right now

    This release cannot repair an install that is already stuck, because the stuck install is the thing that would apply it. Run the bootstrap by hand once (it reclaims the stale lock on its own):

    node ~/.claude/plugins/cache/<marketplace>/agenthub/<newest-dir>/scripts/plugin-bootstrap.js --force
    

    Then check with /agenthub-doctor. Updates after that one are self-healing.

    Documentation

    docs/PLUGINS.md gains a Who may stop the server section with the cgroup rule and the two-path table; the rule is also recorded in CLAUDE.md's non-negotiables so it is not undone later. The uninstall snippet said a bare kill is undone by Restart=on-failure — it is now Restart=always, and the systemd unit must be disabled first.

    Downloads
  • v1.5.6 0335e0e6bc

    v1.5.6 Stable

    nntrivi2001 released this 2026-09-11 09:01:33 +00:00 | 227 commits to main since this release

    Fixed

    agenthub update-check printed the literal null on every plugin-cache install.

    The CLI prints the status payload's message as its headline, and the plugin branch of getUpdatesStatus hardcoded it to null — on the one install kind that has no commit count to fall back on, so the verdict line carried nothing at all:

    ⬆  null
    

    That branch compares versions exactly like the checkout branch does, so it now builds the same sentence from what it had already computed:

    ⬆  Release v1.5.5 is available (this install reports 1.5.4).
    

    Four outcomes are covered: a newer release, already on the newest, no local version to compare against, and a failed release lookup. The dashboard UI builds its own text and never read message, so nothing there changes.

    The git-free regression test asserted message === null as a proxy for "did not fall through to the not-a-git-clone payload"; it now asserts that on the message's content, which is what it always meant.

    Documentation

    • docs/PLUGINS.md still promised MCP tools. c7dbaf2 dropped the MCP server; the doctor row list also claimed an "MCP build freshness" check that plugin-doctor.js does not emit. Both corrected — the dashboard still reads Claude Code's MCP configuration in the config explorer, it just no longer serves one.
    Downloads
  • v1.5.5 3ed88062d6

    v1.5.5 Stable

    nntrivi2001 released this 2026-09-11 08:36:46 +00:00 | 230 commits to main since this release

    Fixed

    Starting a run on a host without tmux blamed the request.

    Every run the dashboard starts is a tmux session. On a machine with no tmux binary, POST /api/run (and the lane start action) let spawnSync tmux ENOENT escape from three calls down, and the route mapped it to 400 — telling the user their request was malformed, naming no fix, and reaching the console pane as a raw errno.

    The precondition is now checked in spawnRun, which both spawn paths already route through, so one guard covers them. It throws ETMUXMISSING with the install command in the message, and both routes answer 503: the request was fine, the dependency is not installed. The client already renders error.message from the body verbatim, so the fix needed no UI change.

    Added

    Both doctors now report tmux.

    • /agenthub-doctor gained a tmux row — WARN, never FAIL: without the binary the run console, agenthub lanes shell and the session-reload keystrokes stop working, while sessions, analytics, lanes and the CLI are unaffected. Failing a doctor run over a partial feature loss would cry wolf.
    • agenthub doctor asks the server instead (GET /api/run/tmux), because the PATH that decides whether a run starts is the server's, not the caller's shell's — a systemd --user service never reads your shell profile.

    Documentation

    • README / README.vi gained a prerequisites table (node, npm, git, tmux, Claude Code, Codex, gh, systemd) and per-OS tmux install + verify steps; the feature list is regrouped into observe / drive / configure and now covers analytics, alerts, history import, remote sources, the Claude Code + Codex configuration explorer and Update all.
    • INSTALL.md gained Step 0 — System packages, plus a troubleshooting entry that separates "tmux is missing" from "the server has a different PATH". The same entry is in SETUP.md; docs/DEPLOYMENT.md's prerequisites list was the last one still saying node + npm alone.
    • The node advice said "stay on 20/22/24". Only 25 is actually bad (better-sqlite3 ABI + a global localStorage change); 1712 server and 488 client tests are green on v26.8.1.
    Downloads