nntrivi2001 5ba9e07d78 feat(cc-config,lanes): per-profile quota, and three fixes that made a write look lost
Closes #19, #20, #21, #27.

#19 — a saved auth profile now reports how much of its account's quota is
already spent, which is the only number that decides which one is worth
switching to. Nothing under CLAUDE_HOME records it, so it comes from the same
endpoint the CLI's own /usage reads, answered for whichever account's OAuth
token is presented. It is a POST and a button, never a poll: every profile that
is not the active one is normally expired, so answering means refreshing it
first, and a refresh ROTATES the stored refresh token. The rotated pair is
written straight back — dropping it would leave the profile holding a
credential Anthropic has already retired, i.e. an account needing a fresh
login. The token is read, put in an Authorization header, and never returned,
logged or echoed; what leaves the server is two percentages and two reset
times.

#20 — a settings patch that changes nothing wrote nothing but still took a
timestamped backup, so opening the config panel quietly grew a backup
directory inside every lane. patchSettings now compares the rendered output
with what is already on disk and returns early, fixed once where all callers
route through. A lane's git exclude also picks up .claude/.cc-config-backups/
beside settings.local.json.

#21 — the router apply route was the only mutating lane route that never
broadcast its lane. The write reached disk and the column, but the client's
cached row kept the old router_profile forever: the picker looked right until
the user switched lanes and back, at which point the effect re-read the stale
row and flipped the selection to the previous profile. One broadcastLane, plus
a lane-switch guard so an apply that resolves after the user has moved on no
longer paints its result onto whichever lane is now on screen.

#27 — Add-lane in worktree mode left the dialog up after a clean setup with a
dead confirm button and no obvious way out. It closes itself when nothing
failed, and when something did, the summary stays and the confirm becomes a
real Close.
2026-09-17 22:20:32 +07:00

AgentHub

Internal SmartGift build. Local-first control surface for Claude Code agents — monitoring is one part of it, not the whole. Hooks POST every tool call to an Express + SQLite server and a React UI updates over WebSocket; lanes track parallel agent work through a pipeline; and the agenthub CLI drives real terminal sessions, lane runtimes, and Claude Code's own configuration.

AgentHub records and shows — it does not orchestrate. The session in control makes every decision.

Internal build — all rights reserved.

(Tiếng Việt: README.vi.md)

Main features

Observe

  • Sessions, agents, events. Everything Claude Code emits, recorded and searchable: tool calls, token usage, cost, subagent trees, transcripts.
  • Analytics and cost. Per-model token totals and estimated cost, with editable pricing rules; top tools, agent types, and workflow patterns.
  • Activity feed and alerts. A live event stream, alert rules, and webhook targets that fire on them.
  • History import. Every session under ~/.claude/projects/ is imported on startup; archives from another machine come in through Settings → Import History (idempotent, never double-counts tokens).
  • Remote sources. Pull session history from other machines over SSH (agenthub remote-sources).

Drive

  • Lanes. One lane per working directory, surviving session restarts. A lane moves through pipeline stages and the dashboard shows where it is.
  • Stage detection. The stage is inferred from the tool stream, so a session that never calls agenthub stage still shows progress — rendered dashed amber and never as done, because an inference is not evidence.
  • Run Claude Code or Codex from the browser. A real terminal (tmux + a real PTY, rendered with xterm.js) attached to a lane's directory — the exact TUI you'd see locally, fully interactive, resumable, and attachable from a real terminal too via agenthub lanes shell. Which CLI it starts is the lane's own setting. This is the part that needs tmux installed — see Prerequisites.
  • Per-lane app stacks. A repo that declares .agenthub/profile/ gets its own slot, ports and services per lane (agenthub lanes up|down|logs).
  • Ship pipelines. /agenthub:ship-full and /agenthub:ship-quick drive a feature from intake to PR, declaring every stage to the dashboard as it goes.

Configure

  • Claude Code + Codex configuration explorer. Settings hosts one panel per tool: every plugin, skill, subagent, slash command, MCP server, hook, settings file, memory file, marketplace, keybinding and statusline Claude Code knows about — read for all of them, edit/create/delete for the text-file surfaces (skills, agents, commands, output styles, CLAUDE.md). Plugins, MCP, hooks and settings.json stay read-only: they race with the live CLI.
  • Updates. Release-based update detection with an in-UI Update all (marketplaces → every plugin → AgentHub last → one session reload).
  • A CLI for all of it (agenthub, plus agenthub repl), a PWA install, and a UI in English, Vietnamese, Chinese and Korean.

Prerequisites

Need Version Required for
Node.js >= 20 (>= 22.5 for a plugin install) Everything. Both suites are verified green on 24 and 26
npm 9+ Ships with Node
git any Cloning, and every lane operation (worktrees, branch/status reads)
tmux 3.x The browser run console, agenthub lanes shell, typing /reload-plugins into a live pane, the Codex nudge
Claude Code 2.x Hook ingestion — the whole monitoring side
Codex CLI any Optional — only for codex lanes
GitHub CLI (gh) any Optional — only for agenthub lanes ci status and the PR stages of the ship pipelines
systemd (user) — Optional — only for agenthub service install (Linux auto-start on boot)

Node 25 is the one version to avoid: it breaks 6 server tests through a better-sqlite3 ABI mismatch and 20 client tests through a global localStorage change. Both were gone again by 26 (1712 server + 488 client tests green on v26.8.1).

Installing tmux

The dashboard shells out to the tmux binary; there is no bundled fallback, so Start Run and agenthub lanes shell fail without it. Everything else (sessions, analytics, lanes, stage detection, the CLI) works fine.

sudo apt install tmux        # Debian / Ubuntu
sudo dnf install tmux        # Fedora / RHEL
brew install tmux            # macOS
sudo pacman -S tmux          # Arch

Windows has no native tmux — run AgentHub under WSL2 and install it there.

Verify, both from your shell and from the server's point of view:

tmux -V                                      # e.g. tmux 3.4
curl -s localhost:4820/api/run/tmux          # {"available":true}

A lane's run lives in a tmux session named agenthub-lane-<id>, so the browser terminal and a local tmux attach -t agenthub-lane-<id> (or agenthub lanes shell) are two clients on the same pane — they stay in sync, and killing the dashboard never kills the run.

The superpowers plugin

The superpowers plugin is required by the ship-feature pipelines only, not by the dashboard. /agenthub:ship-feature and /agenthub:ship-feature-lane drive superpowers:brainstorming, writing-plans, test-driven-development, requesting-code-review and verification-before-completion phase by phase, and both built-in pipeline templates name those same slash commands as their per-node drivers. Without it the dashboard, hooks and CLI all work normally — the two pipeline skills are what stop partway. /agenthub-doctor reports it as a WARN row.

You do not normally have to install it. The plugin's SessionStart bootstrap installs it for you, once, in its detached worker — so a session never waits on the clone, and the current session needs /reload-plugins before the skills resolve (any later session picks them up on its own). The outcome is logged to ~/.claude/agenthub/runtime/bootstrap.log, and /agenthub-update retries a failed one. To install it by hand instead, or after opting out:

claude plugin install superpowers@claude-plugins-official

Set AGENTHUB_AUTO_INSTALL_PLUGINS=0 to opt out of the automatic install. Only the plugins on a fixed allowlist in server/lib/skill-plugins.js are ever installed this way — superpowers today. A custom pipeline template naming some other plugin's command is reported by /agenthub-doctor and never installed, because a template is a file anyone can drop into DASHBOARD_PIPELINES_DIR.

Install as a Claude Code plugin

Two commands on a machine that has nothing but Claude Code, no clone and no npm run setup:

/plugin marketplace add https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git
/plugin install agenthub@agenthub

The first session start installs the hooks, boots the server, puts agenthub on PATH; it runs detached, so the session never waits on it. /agenthub-doctor reports the state, /agenthub-open builds the UI and prints the URL, /agenthub-update refreshes after a plugin update. This path needs Node >= 22.5 (no native better-sqlite3, so the server uses node:sqlite). Details, including what to delete on uninstall: docs/PLUGINS.md.

Install from a checkout

npm run setup          # root and client dependencies
npm run build          # builds the client into client/dist
npm start              # serves the built client and the API on :4820

Open http://localhost:4820.

Development, with hot reload:

npm run dev            # server on :4820, Vite client on :5173

DASHBOARD_PORT overrides the port, DASHBOARD_CLIENT_DIST overrides where the built UI is served from (defaults to client/dist; the plugin install points it at its own runtime directory). postinstall writes the Claude Code hook entries that feed the dashboard — do not run it when the agenthub plugin is installed, or every event is counted twice.

Run as a service (auto-start on boot)

npm start only runs while that terminal (or agenthub start's background process) is alive — a reboot loses it. On Linux, agenthub service install sets up a systemd --user service instead, so :4820 is up again on its own after every reboot, with no manual step and no Claude Code (or any AI tool) needed to trigger it:

npm run build              # the service serves the built client, same as npm start
agenthub service install       # writes + enables ~/.config/systemd/user/agenthub.service
agenthub service status        # systemctl --user status agenthub
agenthub service uninstall     # disable and remove it

agenthub service install also tries loginctl enable-linger so the service starts on a cold boot, before anyone logs in; if that needs elevated rights on your machine it prints the sudo loginctl enable-linger <user> command to run once yourself. Plugin installs get the same persistence automatically — see Auto-start on boot in docs/PLUGINS.md.

The CLI

agenthub is linked by npm run setup; otherwise call node bin/agenthub.js.

agenthub status            # is the dashboard up
agenthub start             # start it in the background and wait for healthy
agenthub service install   # auto-start on boot via systemd --user (Linux)
agenthub sessions          # recent sessions
agenthub lanes             # lanes with stage and progress
agenthub lanes pipeline    # this lane's pipeline template, or switch it
agenthub lanes node <id>   # run ONE pipeline node's own command (no id: list them)
#                        (in a session: /intake, /qc, /ship-full, /ship-quick …)
agenthub stage <name>      # declare the current lane's stage
agenthub tail              # live event feed

agenthub --help lists the rest.

Lanes

A lane is a working directory the dashboard watches. Two kinds:

  • adopted — a directory you already had. The dashboard only reads it; it is never reset or deleted.
  • managed — a git worktree the dashboard created under LANES_ROOT. It owns the full lifecycle and may reset or remove it, behind a three-check destroy guard and a counted preflight the caller has to echo back.
agenthub lanes add --cwd /path/to/repo --title "My feature"    # adopt
agenthub lanes add --repo /path/to/repo --slug my-feature      # managed worktree

Every lane also carries the CLI that drives it — claude (the default) or codex — picked in the Add-lane modal and fixed for the life of the lane. A Codex lane's run panel offers Codex's own sandbox, approval and reasoning-effort choices, and resumes with codex resume --last. Codex emits none of this dashboard's hooks, so a Codex lane records its runs but stays absent from Sessions and Analytics. Its stage detection works anyway, from Codex's own rollout journals on disk ($CODEX_HOME/sessions/**/rollout-*.jsonl, polled every DASHBOARD_CODEX_POLL_MS ms, default 15000), and on a Codex lane a detection also advances the declared stage — the one place an inference moves the blue current ring, because a Codex session has no hook and nothing else would ever move it. What a Codex lane cannot get for free is evidence: an auto-advanced node stays amber (passed-no-evidence), never green, since only the session itself can say what it finished. Three things help it get there: the run console pre-fills a codex pane's opening prompt with a stage-declaration checklist built from its own pipeline nodes, agenthub lanes agents install writes the same instructions as a marker-delimited block in the lane's AGENTS.md, and a 60s sweep (DASHBOARD_CODEX_NUDGE_MS, 0 disables) types a one-line reminder into a lane's pane if its current stage sits without evidence for more than two minutes.

The declared stage comes from agenthub stage. The inferred stage comes from tool events and expires after DETECTION_TTL_MS (default 5 minutes), so a lane can move backwards between work sessions. Detection never writes the declared stage, and an inferred node never renders as done.

A lane's pipeline template can be switched after creation — agenthub lanes pipeline <template> from the terminal, or the pipeline-template picker next to the lane's title in the Workspace detail panel. Both re-resolve the lane's current declared stage against the new template's nodes and warn if it no longer matches one.

A lane can also run its own application stack, isolated per lane, when its repository declares a profile at <repo>/.agenthub/profile/ — a profile.env of declarations plus shell hooks the dashboard calls. Each lane gets a slot, and its ports and per-lane directories derive from it:

agenthub lanes up          # boot the stack of the lane owning this directory
agenthub lanes runtime     # slot, ports, service health
agenthub lanes logs api    # tail a service log
agenthub lanes down

Services are fully detached, so restarting the dashboard never stops a running lane. This is resource namespacing on the host, not a container: lanes run as the same user and share the network.

docs/LANES.md has the pipeline model, the destroy guard, the preflight contract, the Workspace page, GET /api/lanes/:id/git, and the full runtime/profile contract.

Tests

npm run test:server    # node:test
npm run test:client    # Vitest

Both must be green before a commit; the pre-commit hook runs them plus Prettier.

Layout

Path What
server/ Express API, SQLite schema, hook ingest, lane and worktree libraries
client/ React 18 + Vite + Tailwind dashboard
bin/agenthub.js CLI
docs/ Architecture, API, lanes, database
plugins/ Claude Code plugins shipped with the dashboard

Docs

S
Description
AgentHub (phase 1): self-hosted with Claude plugin
http://localhost:4820
Readme 151 MiB
v2.8.10 Latest
2026-10-16 07:54:43 +00:00
Languages
JavaScript 53.9%
TypeScript 44.9%
Shell 0.6%
CSS 0.4%