nntrivi2001 f887c16309 feat: model lists and prices that follow each AI tool, a Settings tab per tool, live lane status (#40)
Pricing: the LiteLLM sync now adds every current Claude / GPT (>= 5) /
Gemini (>= 3) chat model before it is used and keeps its own rows
(model_pricing.source = 'sync', the Auto badge) at the published rate. A
user's row (any PUT) and a deleted pattern (model_pricing_dismissed) are
never touched; a deleted built-in row is not re-seeded at the next start; a
reset re-applies the list at once; retired Claude models are priced only
once used.

Models: GET /api/ai-tools/:id/models reads each tool's own list (Codex's
models_cache.json, Claude's aliases named after the newest version plus
priced versions, a catalog tool's vendor rows plus the models its sessions
used). A catalog `model: {flag, vendor?}` field passes `<flag> <id>`
(validated: never a flag or shell text); a per-tool default model starts
each run, and a resume keeps the session's own model.

Settings: every installed, enabled catalog tool without its own tab gets
one (AiToolConfig.tsx): path, homepage, Update, sessions/cost/lanes,
default model, vendor pricing, and the config files its release catalog
lists, edited over the opened sha, syntax-checked, backed up, written
atomically; credential-looking names refused. Antigravity keeps its hooks
card there.

Lanes: a just-started run no longer reads "dead" (age counts the run's
start while the old session is still bound); a second dashboard on the
same database re-broadcasts the lanes the other changed (PRAGMA
data_version, every 2 s); a lane start with a bad model answers 400.

DB: every migration runs under a cross-process lock (<db>-migrate.lock), so
two dashboards started at once on a fresh database both come up.
2026-10-01 13:39:17 +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, one working directory each; 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. Once you install a pipeline template (none ships), a lane moves through its stages and the dashboard shows where it is.
  • Stage detection. With a template installed, 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.
  • Git, from the dashboard. Each lane card shows its branch, ↑ahead ↓behind and its uncommitted files, with buttons for the ordinary moves: fetch, pull (always --ff-only), push, commit-all, and switching branch on a clean tree. Beside the lane sits a collapsible Changes panel — an overview of the changed files, a full review of every diff, or one file at a time, comparing either uncommitted work or the whole branch against its base. There is no merge/rebase/reset button by design: recovery from those needs a terminal.
  • Per-lane app stacks. A repo that declares .agenthub/profile/ gets its own slot, ports and services per lane (agenthub lanes up|down|logs).

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).
  • Appearance. Settings → Appearance picks Dark / Light / System (follows the OS live) and a theme per mode — dark: Default, Darcula, Apple Dark; light: Default, Apple Light, IntelliJ Light, Canvas. Each mode remembers its own theme, so the sidebar's quick toggle swaps between the two. Per-browser only.
  • 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
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
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.

macOS (code-audited, untested on a Mac): brew install node git tmux (Node

= 22.5 for the plugin), add ~/.local/bin to PATH in ~/.zshrc. There is no systemd, so the dashboard runs until logout/reboot and comes back at the next Claude Code session, or by hand with agenthub start. Details and a checklist to verify it: INSTALL.md § macOS.

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.

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. agenthub service install sets up a systemd --user service (Linux) or a LaunchAgent (macOS) 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       # Linux: ~/.config/systemd/user/agenthub.service
                               # macOS: ~/Library/LaunchAgents/io.smartgift.agenthub.plist
agenthub service status        # systemctl --user status / launchctl print
agenthub service uninstall     # disable and remove it

On Linux, 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)
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 may reset that worktree, behind a three-check destroy guard and a counted preflight the caller has to echo back. Removing a lane — either kind — deletes only the dashboard's record of it: the working tree, its branch and its database stay, for you to delete yourself.
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 sessions and token usage are read from Codex's own rollout journals: every Codex session (a lane's or not) appears in Sessions with a Codex badge and is priced like any other, with OpenAI rates filled in automatically (Settings → Codex → Overview). For a live feed, install Codex hooks from the same tab: the next time Codex starts it asks you to trust them (Trust all and continue), and from then on each tool call lands in the session's timeline, a codex lane turns running/idle as each turn starts and ends, and "Codex needs your permission" shows on the lane card and as a notification while Codex waits for an approval. A Codex lane also carries no pipeline — no stage, no pipeline map, nothing inferred or advanced; without hooks the dashboard mirrors its running/idle status from the rollout journals on disk ($CODEX_HOME/sessions/**/rollout-*.jsonl, polled every DASHBOARD_CODEX_POLL_MS ms, default 15000).

An Antigravity lane runs Antigravity's agy CLI. Its sessions and token usage are read from agy's own conversation files (~/.gemini/antigravity-cli/conversations/<id>.db, every DASHBOARD_ANTIGRAVITY_POLL_MS ms, default 15000): every agy CLI session appears in Sessions with an Antigravity badge, priced with Gemini rates that are filled in automatically (Settings → Antigravity). Antigravity hooks, in the same tab, add a live feed: each tool call in the session's timeline and a lane that turns running/idle as a run starts and ends. agy asks for no trust, and it has no hook for a permission prompt, so an Antigravity lane never shows "needs your permission". agy fires no hook when it exits, nor when a run ends on an API error or a permission refused in headless mode, so a session gone quiet is marked completed and its lane set idle — after ten minutes of quiet for a session the hooks report on (a long tool call writes nothing, and after a Stop agy may still be waiting for you), after two minutes for one without hooks. Antigravity lanes carry no pipeline either.

Pipelines are dormant. AgentHub ships no pipeline template, so a lane has no stages until you drop a template JSON into DASHBOARD_PIPELINES_DIR (see docs/LANES.md); until then agenthub stage answers ENOPIPELINE and the Workspace hides the pipeline map. Further development is planned.

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, the git surface (GET /api/lanes/:id/git, /git/changes, /git/log, /git/file, /git/ls, /git/tree, POST /:id/git/:action), 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%