Files
AgentHub/README.md
T
nntrivi2001 27313d4413 fix(run): refuse a run with ETMUXMISSING when the host has no tmux
Starting a run on a machine without tmux surfaced `spawnSync tmux ENOENT`
as a 400 — blaming the request for a missing host package, naming no fix,
and reaching the user as a raw errno in the console pane.

The guard goes in spawnRun, which both spawn paths (POST /api/run and
POST /api/lanes/:id/start) already route through, so one check covers
them; the message carries the install command. Both routes map the code to
503: the request was fine, the dependency is not installed. The client
already renders `error.message` from the body verbatim, so no UI change.

Also: README's node advice said "stay on 20/22/24"; 1712 server + 488
client tests are green on v26.8.1, so only 25 is actually the bad one.
2026-09-11 15:32:24 +07:00

309 lines
14 KiB
Markdown

# 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](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](#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.
```bash
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:
```bash
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:
```bash
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`](docs/PLUGINS.md).
## Install from a checkout
```bash
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:
```bash
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:
```bash
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](docs/PLUGINS.md#auto-start-on-boot) in `docs/PLUGINS.md`.
## The CLI
`agenthub` is linked by `npm run setup`; otherwise call `node bin/agenthub.js`.
```bash
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.
```bash
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:
```bash
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`](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
```bash
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
- [`ARCHITECTURE.md`](ARCHITECTURE.md) — request flow, schema, WebSocket surface
- [`docs/LANES.md`](docs/LANES.md) — lanes, pipelines, stage detection
- [`docs/API.md`](docs/API.md) — REST endpoints (`openapi.yaml` is generated)
- [`docs/DATABASE.md`](docs/DATABASE.md) — tables and migrations
- [`INSTALL.md`](INSTALL.md)
- [`CLAUDE.md`](CLAUDE.md) — the rules an agent working in this repo must follow