0004cf7036
A lane's `remove` tore down what the lane pointed at: `git worktree remove --force`, a branch delete, and a drop of the lane's own database. One mis-click on a dashboard row cost a whole branch's unpushed code — and the row is the only thing AgentHub actually owns. `remove` now stops the run and the stack, clears AgentHub's own runtime bookkeeping under `LANES_ROOT/.state/lane<slot>/`, and deletes the row. The working tree, its branch, git's worktree records and the database stay exactly where they are, for the user to delete by hand when they mean to. That also fixes #28. Removal used to route through `assertDestroyable`, whose third check demands the cwd appear in `git worktree list`; a managed lane whose directory git no longer listed answered `ENOTWORKTREE` ("lane is not listed as a worktree in …") and could never be dropped from the dashboard at all. Removal no longer asks git anything, so no preflight blocker stops it, and the unpushed-commits force-gate now applies to `reset` alone — nothing `remove` does can discard a commit. The UI follows: one label for both lane kinds ("Delete lane record"), copy that says what survives, and no Force checkbox on removal. `removeWorktree`/`removeLaneData` remain in place as guarded primitives; no route calls them any more.
311 lines
14 KiB
Markdown
311 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 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.
|
|
|
|
```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
|