-
v1.5.4 Stable
released this
2026-09-10 16:23:57 +00:00 | 235 commits to main since this releaseFixed
A self-update left the dashboard serving the previous version's UI.
After 1.5.2 → 1.5.3 applied itself, the server ran 1.5.3 while the browser still showed 1.5.2. The client build had failed and
runtime/client-diststill held the old bundle, so nothing looked broken — the only signal anywhere was the Settings page'sUI build v1.5.2 (rebuild client to match)line.Cause: the entire client build toolchain (
vite,typescript,@vitejs/plugin-react,tailwindcss,@types/*) is a devDependency, and npm readsNODE_ENV=productionas--omit=dev:$ NODE_ENV=production npm config get omit devThe dashboard server runs with
NODE_ENV=production, and every bootstrap descended from it inherits that — the plugin-update chain, and anySessionStartfired by aclauderunning inside a tmux pane the server started. Sonpm ciinstalled 58 packages instead of ~330,vitewas never there,tsc -bdied on missing type declarations, andbuildClientreturnedfailedwith the stale bundle left in place. Every build before this succeeded only because it ran from a hookclaudeinvoked directly, with noNODE_ENV— the first real self-update was the first time the condition occurred.--include=devis now passed on both install paths; a CLI flag outranks the env, which is the point. Verified by runningbuildClientwithNODE_ENV=productionagainst the installed plugin root: previouslyfailed, nowbuilt, and the served bundle carries the new version.A successful update chain no longer reports nothing.
plugin-update-helperwrites its verdict before the bootstrap handover as well as after: that step retires the process tree the helper hangs off, and the observed run reached the new server with no verdict file at all, so the dashboard showedlast_plugin_update: nullfor an update that had in fact succeeded.Verification
server/__tests__/plugin-bootstrap.test.js+1 test pinning--include=devon every dependency-install path.npm run test:server1708 passing.- Live: the update chain ran end-to-end for real (
plugin-update.log: marketplace update →agenthubupdatedb868a2fa8566→67c948bbe2f8→plugin-bootstrap --force), which is how this was found.
Downloads
-
v1.5.3 Stable
released this
2026-09-10 10:10:52 +00:00 | 237 commits to main since this releaseFixed
Every tmux-backed run was silently unpersisted, so a resumed session showed nothing.
dashboard_runs.modeisNOT NULL,recordRunswallows insert errors by design, andpty-run.jspassedmode: null— so the insert threw on every single run and nothing was recorded. In a live database the newest run row predatedpty-run.jsreplacingrun-spawner.js.publicRunreadscwd,model,prompt_preview,started_atandsession_idoff that row (the handle itself is recomputed from tmux on every read), which produced the two visible symptoms:- the runs modal showed a live row with no cwd, no model, no prompt and a start date of Jan 1 1970;
- a resumed session kept its separate
externalbadge, because the client dedupes an external session against the session ids carried by run rows and no run row ever carried one.
Changes:
pty-run.jsrecordsmode: "interactive"— every run here is one interactive pane.dashboard-runs.jsstill never fails a live run on a db error, but now warns instead of swallowing silently. That silence is what hid this for six weeks.RunHistoryrenders a missing start time as-instead of dating the row to the epoch.
Adopting a busy pane no longer reports work it did not do. A
start/resume against a lane whose pane is already running an agent now returns409 ERUNLIVE(from the lane start action andPOST /api/run) when the request carried apromptor aresumeSessionId— that argv cannot be typed over a live agent, so answering200claimed a resume that never spawned. A start that asks for nothing but a pane still adopts it silently.Verification
server/__tests__/pty-run.test.js+4 tests (row lands with cwd/model/prompt/lane/started_at and a non-nullmode; a resumed run carries the session id; the two ERUNLIVE refusals; a bare start still adopts). Regression proven by flippingmodeback to null — the suite fails.npm run test:server1707 passing ·npm run test:client488 passing.
Downloads
-
v1.5.2 Stable
released this
2026-09-10 09:48:25 +00:00 | 239 commits to main since this releaseFixed
Update detection was blind on a plugin-cache install that isn't a git clone.
A marketplace entry with
"source": "url"— this project's own — makes Claude Code unpack an archive instead of cloning, so~/.claude/plugins/cache/sg/agenthub/<sha>has no.git.getUpdatesStatusprobed for.gitfirst and returned "Install directory is not a git clone; check for updates manually", skipping the whole release layer added in 1.5.0:update_availablestayedfalsehowever many releases were published,plugin_marketplace/plugin_namewere never set, soPOST /api/updates/apply's plugin branch could never fire — it answered 409, wrongly claiming nothing newer was published.
Because the symptom reads as "up to date", the bug was invisible for as long as the install happened to be current.
The fix: the plugin branch now runs before the
.gitprobe and answers without git at all. The repository URL comes from the marketplace manifest on disk (known_marketplaces.json→.claude-plugin/marketplace.json→source.url; agithubowner/reposhorthand yieldsnullrather than a guessed host), andpackage.jsonis the only local comparison signal. A failed release lookup is reported asrelease_checkand never as "nothing newer".UI/CLI: the "not a git clone" note is gated on
install_kind !== "plugin", so Update now is offered wherever the dashboard can actually check and apply.An already-open Claude Code session still needs
/reload-pluginsfor new skills/commands — that is REPL-scoped and no server can trigger it.Verification
- New regression suite
server/__tests__/update-check-plugin-nogit.test.js(20 tests) pins the git-free path. npm run test:server1703 passing ·npm run test:client487 passing ·npm run buildclean.
Downloads
-
1.5.1 Stable
released this
2026-09-10 09:18:48 +00:00 | 241 commits to main since this releaseAgentHub 1.5.1
Release-based update detection, and a button that works
- Update detection now reads the forge's releases API and compares the published tag to this install's
package.jsonversion, instead of counting commits against the default branch — a commit count says nothing about whether a version shipped, and on the plugin cache (a depth-1 clone) every distance is a graft artefact. - When no release can be read, detection falls back to the commit count and puts the reason in
release_check, so "up to date" never silently means "we couldn't look". - New
dev_buildstate: a checkout ahead of the newest release readsDev build · N aheadinstead of a false "Up to date". - On a shallow clone every
commits_*_releasefield isnullanddev_buildis never asserted; the version string is the only signal used.
One-click self-apply, for both install kinds
POST /api/updates/applypicks its mode from how the copy was installed, never from the request body:- checkout — fast-forward onto the release tag, rebuild, self-restart.
- plugin cache — handed to a detached chain:
claude plugin marketplace update→claude plugin update -y→plugin-bootstrap.js --forcefrom the new cache directory, which retires the old server and starts its replacement.
Every chain outcome is recorded to
plugin-update.jsonin the runtime dir — outside the cache the update replaces — so the next server reports it aslast_plugin_update. A failed chain is otherwise indistinguishable from a slow one.Update all, and reloading open sessions
In
/settings?tool=claude-code→ Plugins:- Update all — every marketplace, then every installed plugin, then one reload. AgentHub itself goes last, because its bootstrap restarts the dashboard; progress is journalled to disk and survives that restart. A batch left
runningfor over an hour is reported asabandonedso the button can't wedge. - Reload sessions — types
/reload-pluginsand/reload-skillsinto the dashboard's live lane panes over tmux. Both commands are scoped by Claude Code to the session that runs them, so this reuses running sessions and spawns noclaudeprocess — a one-shot headless run would reload only itself and leave a junk session behind. - Updating a single plugin reloads immediately; the batch reloads once at the end.
Fixes
claude plugin updatewas invoked without-ywhile stdin is closed, which the CLI refuses whenever stdin is not a TTY — the per-plugin Update button failed for any plugin whose marketplace declares an install command.CcConfigChangedPayload.actionclaimedwrite | deletewhile nine other values were already being emitted.- Corrected three
ARCHITECTURE.mdstatements that claimedPOST /api/updates/applydid not exist.
Other
- Sidebar subtitle, splash screen and page title now read SmartGift Solution.
Upgrading: a plugin-cache install can use the in-app Update now button from the next release onward. To get onto this one, run
claude plugin update agenthub@sg -y(or/agenthub-update); an already-open Claude Code session still needs/reload-pluginsfor new skills and commands.Downloads
- Update detection now reads the forge's releases API and compares the published tag to this install's
-
1.5.0 Stable
released this
2026-09-09 09:17:27 +00:00 | 248 commits to main since this releaseAgentHub 1.5.0
Codex config panel
- Read, create and customize Codex config surfaces from
/settings(ownCODEX_HOMElookup, commented TOML fields preserved, symlinked surfaces followed). - Codex config API namespace +
codex mcp/pluginCLI wrapped in argv-safe calls; artifacts written with backup + atomic rename. - Codex gets the same tab bar as Claude Code; the Cursor tab is gone.
Claude Code settings
- Switch between Claude Code accounts while keeping the workspace; one account is one profile, renamed in place.
- Add and remove MCP servers through the
claudeCLI (mcp add --urlform supported,--envcovered). - Create a new project's memory file from Settings.
Fixes
- Config path containment: closed symlink write escapes (
GET /file, project writes, parent-dir checks,listBackupsscope) and the caller-chosen write target. CLAUDE_CONFIG_DIRis no longer pinned whenCLAUDE_HOMEis unset;.claude.jsonis read from the root the CLI actually writes it to (beside~/.claude, not inside).- MCP scope was inverted — user/local are exposed, not user/project.
- Lanes: every pipeline run is counted, not one per lane.
- Doctor catches half-written plugin installs, not just absent ones.
- Client build installs its deps with
npm ci.
Full changelog:
v1.4.6...v1.5.0(50 commits).Downloads
- Read, create and customize Codex config surfaces from
-
1.4.6 Stable
released this
2026-09-08 07:03:18 +00:00 | 294 commits to main since this releaseDownloads