Files
AgentHub/docs/CLI.md
T
nntrivi2001 84e2a9f0ac feat(server-s3): one Linux user per account (S3) — experimental
Server mode can now run each account as its own Linux user (ah-<name>)
when `agenthub server install-system` has set S3 up. The dashboard
reaches a member only through sudo -u / write-as / pane-launch, reads a
member's files only through owner- and type-checked opens, and hooks
are authenticated by peer uid. Local mode and server mode without S3
are unchanged.

EXPERIMENTAL: tested with fake sudo and fake accounts only. It has not
yet been verified on a real install with real member accounts, sudo or
a real Codex login. Do not offer it to real users yet.

- S3 core: provisioning, per-member tmux servers, the proxy key
  gateway, shared tools in /opt, dropped capabilities for children
  (P0–P5)
- P4: plan and quota per member home
- P6: ~/.claude.json seed; opt-in plugin baseline installed as the
  member; managed-settings spike script (not run)
- P7: Codex account pool (`agenthub accounts add --tool codex`)
- Roles merged with main's admin / analyst / developer: analysts write
  only their own rows, under S3 as well
- Per-account prefs: one implementation (Chat UI + onboarding)
- Security reviews F1–F49 (five rounds), each fix with a regression
  test: symlink/TOCTOU-safe member reads, no host writes in a member
  home, credentials and the data dir never served, owner and folder
  account must agree, pane tokens bound to the pane's uid, bounded
  sudo/tmux/git calls and member reads (no hang or crash from a member),
  async route rejections answer 500 instead of exiting
- Docs: docs/SERVER-MODE.md (S3 model, accepted ceilings, operator
  runbook), docs/plans/server-mode/S3-PLAN.md, CLAUDE.md S3 rules

Tests: server 2838/2841 (3 need 127.0.0.1:3000, held on this box);
client 1162/1162; tsc clean; headers check passes.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-09 14:57:10 +07:00

339 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# `agenthub` CLI Reference
The complete guide to `agenthub`, the command-line interface to AgentHub — the local control surface for Claude Code agents. Monitoring, workspaces, terminal runs and Claude Code's own configuration, all from your terminal.
---
## Table of Contents
- [Overview](#overview)
- [Installation & Linking](#installation--linking)
- [Server Discovery](#server-discovery)
- [Commands](#commands)
- [Server Lifecycle](#server-lifecycle)
- [Interactive REPL](#interactive-repl)
- [Offline Mode](#offline-mode)
- [Monitoring](#monitoring)
- [Data Browsing](#data-browsing)
- [Insights](#insights)
- [Alerts & Webhooks](#alerts--webhooks)
- [Pricing](#pricing)
- [Import](#import)
- [Remote Sources](#remote-sources)
- [Workspaces](#workspaces)
- [Integrations](#integrations)
- [Administration](#administration)
- [Safety Model](#safety-model)
- [Output & Scripting](#output--scripting)
- [Troubleshooting](#troubleshooting)
---
## Overview
`agenthub` (`bin/agenthub.js`) is a **dependency-free** Node.js CLI over the local dashboard API. Everything the web app can do — monitoring, browsing, analytics, alerting, pricing, imports, administration — is available as a terminal command. It ships with the repository, requires no additional install step beyond the normal project setup, and talks only to your local dashboard server.
```
agenthub <command> [options]
```
```mermaid
flowchart LR
U["Terminal\nagenthub <command>"] --> CLI["bin/agenthub.js\n(zero dependencies)"]
CLI -->|"env override"| ENV["CLAUDE_DASHBOARD_PORT /\nDASHBOARD_PORT"]
CLI -->|"else discovery"| REG["~/.claude/.agenthub.json\n(PID-liveness-checked)"]
CLI -->|"else fallback"| DEF["http://127.0.0.1:4820"]
ENV --> API["Dashboard REST API"]
REG --> API
DEF --> API
API --> OUT["Box-drawn tables / status icons / bar charts /\nplain text when piped"]
```
## Installation & Linking
`npm run setup` ends with a fail-soft `npm link` (the `link-cli` script), so after a normal local setup `agenthub` is on your PATH from any directory:
```bash
git clone https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git
cd AgentHub
npm run setup # installs deps AND links agenthub globally
agenthub help
```
If linking needed elevated permissions in your environment, setup still succeeds and prints a hint — run `npm link` once from the repo root yourself, or invoke the CLI directly with `node bin/agenthub.js <command>`.
### With a plugin install (no checkout)
The `agenthub` plugin's bootstrap writes a launcher to `~/.local/bin/agenthub` on
session start — a small script rather than a symlink into the plugin cache,
which is replaced on every plugin update. It never overwrites a `agenthub` it did
not write, so a linked checkout keeps winning. If `~/.local/bin` is not on your
PATH, `/agenthub-doctor` says so and prints the exact `export PATH=...` line to add.
## Server Discovery
The CLI finds your running dashboard the same way the Claude Code hook handler does:
| Priority | Source | Notes |
| -------- | ------ | ----- |
| 1 | `CLAUDE_DASHBOARD_PORT` / `DASHBOARD_PORT` env vars | Explicit override wins |
| 2 | `~/.claude/.agenthub.json` | Written by every running dashboard (`{port, pid, startedAt}` entries); stale entries are skipped via a PID liveness check |
| 3 | `http://127.0.0.1:4820` | Default port fallback |
If no server answers, every API-backed command exits `1` with the `○ Dashboard server is NOT running` indicator and the ways to start one (see [Server Lifecycle](#server-lifecycle)).
## Commands
### Server Lifecycle
The CLI talks to the local dashboard server — **API-backed commands require it to be running**. When it isn't, every such command prints a consistent indicator and exits `1`:
```
○ Dashboard server is NOT running (tried http://127.0.0.1:4820)
This command needs the server. Start it with one of:
agenthub start # production server in the background
npm run dev # dev mode (hot reload), foreground
npm start # production mode, foreground
```
| Command | Description |
| ------- | ----------- |
| `agenthub status` | At-a-glance up/down indicator (`●` running / `○` not running); exits `1` when down |
| `agenthub start [--port N]` | Start the production server **in the background** (detached; survives closing the terminal), wait up to 30 s for `/api/health`, print the URL + PID and the `agenthub stop` hint. Logs append to `data/agenthub-server.log`. No-ops with a pointer when a server is already up. Requires a built client (`npm run build` once). Always ends a Quit (`agenthub stop`); in a plugin install it starts the server the way a session does — by running `scripts/plugin-bootstrap.js` |
| `agenthub stop` | **Quit AgentHub** (issue #65): closes every workspace terminal (`agenthub-lane-*` tmux sessions — running agents stop), stops the server — through `systemctl --user stop` / `launchctl bootout` when the autostart unit runs it — and keeps it stopped: Claude Code's `SessionStart` bootstrap starts no server while `<data dir>/runtime/stopped` exists. `agenthub start` (or any server starting, e.g. a boot/login with autostart on) clears it. With the server already down it only sets the flag |
| `agenthub uninstall [--yes]` | **Uninstall AgentHub** (`scripts/uninstall.js`; Settings → System has the same button). Without `--yes` it only lists what is there and exits 1. With it, in order: closes every workspace terminal, removes the systemd/launchd unit, stops every dashboard server, the status-area icon and workspace stacks, takes AgentHub's own entries out of `~/.claude/settings.json` (hooks, statusline; backup `settings.json.agenthub-uninstall.bak`), Codex `hooks.json` and Antigravity `hooks.json`, deletes the AI Proxy `$CODEX_HOME/<name>.config.toml` files, runs `claude plugin uninstall` for `agenthub@*` and every plugin of the `agenthub` marketplace and removes that marketplace (never a shared one), then deletes `~/.local/bin/agenthub`, `~/.config/agenthub/`, `~/.claude/.agenthub.json`, `~/.claude/agenthub-{proxies,routers,git-credentials,accounts,profiles}`, `agenthub-lanes/.state` and `.locks`, the plugin's cached copies and the data directory (database included). **Kept:** the AI tools' own conversations (`~/.claude/projects`, `~/.codex/sessions`, …), workspace worktrees and branches, anything in your repositories, config backups. A data directory that is the home, `CLAUDE_HOME`, a checkout or not recognisably AgentHub's is refused. A failing step is logged and the rest still run; log: `$TMPDIR/agenthub-uninstall-<uid>.log`. Needs no running server. Run inside a dashboard terminal, it closes that terminal last. |
| `agenthub tray` | Show AgentHub's **status-area icon** now, in the foreground (`scripts/tray.js`): Open AgentHub, Quit AgentHub (a submenu asks again, then runs `agenthub stop`), Start AgentHub after a quit (`agenthub start`), Hide this icon. A production server already keeps the icon up on its own unless Settings → System turned it off; this command does not change that setting. Exits at once when an icon is already running |
| `agenthub repl` (aliases `shell`, `i`) | Open the **interactive shell** — see [Interactive REPL](#interactive-repl) |
| `agenthub server setup [--hostname name] [--admin name]` | Turn **server mode** on (logins for a shared dashboard): writes `AGENTHUB_MODE=server` (and `DASHBOARD_ALLOWED_HOSTS`) to the settings file and creates the first admin, asking for its password. Works with the server down; restart it afterwards. See [SERVER-MODE.md](SERVER-MODE.md) |
| `agenthub server install-system [--dry-run\|--uninstall]` | **One Linux user per account** (S3). Run as the account that runs the dashboard, never as root: it runs `scripts/server/install-system.sh` through one `sudo`. That script creates the groups, `/srv/agenthub/users`, `/opt/agenthub`, the sudoers file, the member hooks and `hidepid`, and installs the system unit `agenthub.service`. The command then points the unit at this install, writes `AGENTHUB_USERS_ROOT`, and moves the dashboard from the `systemd --user` unit to the system one (panes stay). `--dry-run` prints the sudo command; `--uninstall` goes back to the user unit. See [SERVER-MODE.md](SERVER-MODE.md#one-linux-user-per-account) |
| `agenthub server tools` | One Linux user per account: publish this install's scripts and every installed AI tool under `/opt/agenthub` (`tools/bin/<command>`), where every account's pane runs them. The server also does this at start and after each install or update. Prints each tool's shared copy, or why it could not be shared |
| `agenthub server off` / `agenthub server status` | Back to local mode (accounts kept) / show the mode and account count |
| `agenthub accounts list\|add <name>\|remove <name>` | The **Claude account pool**: new Claude sessions spread over these accounts (each a `claude setup-token` token, typed hidden or read from stdin). `list` shows live panes, $ in the last 5 h / 7 d, and quota. With `--tool codex` the same for the **Codex account pool**: `add <name> --tool codex --api-key` (key typed hidden or on stdin) or `--from <dir>` (a `codex login` home or its `auth.json`). See [SERVER-MODE.md](SERVER-MODE.md#claude-account-pool) |
| `agenthub users list\|add <name> [--role admin\|analyst\|member]\|passwd <name>\|role <name> <role>\|disable <name>\|enable <name>\|provision <name>\|--all\|assign <workspace id> <name>\|audit [--limit N]` | Server mode's accounts, written straight to the database. Once `install-system` ran, `add` first creates the Linux user `ah-<name>`; a name must then be lower case: a letter, then up to 28 letters, digits, `_` or `-`. `disable`/`enable` lock or unlock that Linux user too, and `provision` gives users made earlier their Linux user (idempotent); `assign` gives a workspace made before server mode an owner; `audit` lists admin/analyst reads of members' sessions. Inside a dashboard pane in server mode, every command acts as the workspace's owner through the pane's `AGENTHUB_PANE_TOKEN`. A password is typed hidden twice, or read from the first line of stdin |
### Interactive REPL
`agenthub repl` (also `agenthub shell` / `agenthub i`) opens a persistent prompt where you type commands **without the `agenthub` prefix** — ideal for a monitoring session where you run `sessions`, drill into a `session <id>`, check `kanban`, then `cost`, without re-typing `agenthub` each time. On entry it prints a **AgentHub word-mark welcome banner** with the version and live server status.
```
_____ _____ _____ _____
/\ \ /\ \ /\ \ /\ \
/::\ \ /::\ \ /::\ \ /::\____\
… (AgentHub word-mark) …
AgentHub · interactive shell · v1.5.0 ● 127.0.0.1:4820
Type commands without the 'agenthub' prefix — e.g. sessions --limit 5
help all commands · help <cmd> details · Tab completes · ↑/↓ history · exit to quit
● agenthub 127.0.0.1:4820 › sessions --limit 3
… table …
○ agenthub offline › stats # prompt dot turns red when the server is down
```
- **Live status prompt** — a green `●` + resolved host when the server is up, a red `○` + `offline` when it isn't (probed with a short, cached health check).
- **Tab completion** for commands, subcommands (`alerts ack`, `pricing set`, …), and flags (`--limit`, `--status`, …).
- **Arrow-key history**, persisted across sessions to `data/.agenthub_repl_history`.
- **Full command surface** — every command in this reference works inside the shell exactly as on the one-shot CLI (they are dispatched as child `agenthub` processes).
- **Shell built-ins:**
| Built-in | Description |
| -------- | ----------- |
| `help` / `?` | Shell built-ins **plus the full grouped command catalog** |
| `help <command>` | Details (invocation + description) for one command |
| `commands` | Compact list of every command, grouped by category |
| `watch [seconds] <command …>` | Re-run a command on a timer (default 2 s), clearing the screen each tick, until `Ctrl+C` — a terminal live view (e.g. `watch 5 kanban`) |
| `history` | Recent command history |
| `banner` | Reprint the welcome banner |
| `clear` / `cls` | Clear the screen |
| `exit` / `quit` / `q` | Leave the shell (also `Ctrl+D`) |
- **Robust isolation** — each entered line runs as a short-lived child `agenthub` process, so a non-zero exit, an offline refusal, or a blocking `tail` / `watch` (both stop on `Ctrl+C`) can **never** take the shell down with it. Offline reads and server-only refusals behave exactly as they do on the one-shot CLI.
- Works with piped input too (`printf 'stats\nexit\n' | agenthub repl`) for scripting, running each line in order and exiting at EOF.
### Offline Mode
When the server is down, **read-only commands automatically fall back to reading `data/dashboard.db` directly** (SQLite; a safe second reader). Every offline run starts with a banner:
```
⚠ Offline mode — server not running; reading data/dashboard.db directly.
Data is as of the last capture — live capture and full features need the server: agenthub start
```
| Works offline | Server required (with the printed reason) |
| ------------- | ----------------------------------------- |
| `sessions`, `session <id>`*, `agents`, `events`, `kanban`, `stats`, `pricing` (list), `alerts` (list), `rules`, `export`, `doctor` | `tail` (live capture), `analytics` / `workflows` / `runs` / `cost` (server-side aggregation & pricing math), `alerts ack`, `webhooks` (all), `pricing set/delete/reset`, `import`, `remote-sources` (all — SSH pull needs the server), `cleanup`, `clear-data`, `reinstall-hooks`, `update-check` (server-side git fetch), `info`, `health` |
\* `session <id>` shows everything except the cost line, which requires the server's pricing engine. Offline export payloads carry `"exported_offline": true`. Offline data is as of the last capture — with no server running, no hooks are being ingested either.
**Status correctness offline:** while the server is down its dead-session liveness reap isn't running, so the DB can hold `active`/`waiting` rows for sessions that have since exited. Offline output therefore runs the **same process-liveness probe** the server's watchdog uses and corrects the *displayed* status of any active session whose cwd has no running `claude` process (footnote: `※ N session(s) displayed as completed by the process-liveness probe`) — the database itself is never modified. Where the probe can't answer (Windows, containers), a `※ Statuses are as stored…` caveat is printed instead whenever active rows are shown.
### Monitoring
| Command | Description |
| ------- | ----------- |
| `agenthub health` | One-line reachability check with the resolved URL and server timestamp |
| `agenthub stats` | Totals (sessions, agents, events), today's event count, WS connections, and the sessions-by-status distribution |
| `agenthub kanban` | The Kanban board as text: sessions grouped into Active / Waiting / Completed / Error / Abandoned and agents into Working / Waiting / Completed / Error, with current tools |
| `agenthub tail [--session <id>]` | Live event feed — polls `/api/events` every 2 s and prints only new rows (the Activity Feed without a WebSocket client). `Ctrl+C` stops |
### Data Browsing
| Command | Description |
| ------- | ----------- |
| `agenthub sessions [--status s] [--q text] [--limit n]` | Server-filtered session table: short ID, status, name, agent count, duration, model, relative last-update |
| `agenthub session <id>` | Deep dive: metadata card, per-session cost, a parent→child **agent tree** (`├─`/`└─`) with live tools, and the most recent events |
| `agenthub agents [--status s] [--session id] [--limit n]` | Agent table with type, current tool, and duration |
| `agenthub events [--session id] [--limit n]` | Newest-first event log with type, tool, and summary |
### Insights
| Command | Description |
| ------- | ----------- |
| `agenthub analytics` | Token totals (input / output / cache read / cache write), top tools by call count, agent-type distribution, average events per session |
| `agenthub workflows [--session id]` | Workflow-intelligence stats (sessions analyzed, subagents, success rate, depth, compactions) and the top detected patterns; `--session` drills into one session |
| `agenthub runs [--session id]` | Dynamic Workflow-tool runs: status, agent count, tokens, tool calls, duration |
| `agenthub cost [--session <id>]` | Total estimated cost with a per-model bar-chart breakdown; `--session` scopes it to one session (mirrors `/api/pricing/cost/:sessionId`). Any billed **server-tool surcharges** (web search $/1k, code-execution container-time) are shown on a surcharges line. Models with usage but **no matching pricing rule** (priced at $0 and excluded from the total) are listed in a warning with their token volume and the `agenthub pricing set` invocation that fixes it |
### Alerts & Webhooks
| Command | Description |
| ------- | ----------- |
| `agenthub alerts [--unacked] [--limit n]` | Fired-alert feed with state, trigger time, rule, and message |
| `agenthub alerts ack <id>` | Acknowledge one alert |
| `agenthub alerts ack-all` | Acknowledge every unacknowledged alert |
| `agenthub rules` | Alert rules with enabled state, type, and cooldown |
| `agenthub webhooks` | Webhook targets (URLs masked server-side, secrets never returned) |
| `agenthub webhooks test <id>` | Fire a synthetic test alert at a target and report the delivery result; exits non-zero on failure |
### Pricing
| Command | Description |
| ------- | ----------- |
| `agenthub pricing` | All model pricing rules with per-mtok rates, including **Fast In/Out** and **Intro In/Out** columns for fast-mode premiums and time-limited promo pricing |
| `agenthub pricing set <pattern> --input N --output N [--cache-read N] [--cache-write N] [--cache-write-1h N] [--name label]` | Create or update a rule (SQL `LIKE` pattern, e.g. `claude-opus-4-6%`) |
| `agenthub pricing set <pattern> … [--fast-input N] [--fast-output N]` | Also set **fast-mode** premium rates on the rule |
| `agenthub pricing set <pattern> … [--intro-input N] [--intro-output N] [--intro-cache-read N] [--intro-cache-write N] [--intro-cache-write-1h N] --intro-until YYYY-MM-DD` | Set a **time-limited introductory (promo) rate block**. The intro fields are only sent when an `--intro-*` flag is present, so a plain rate edit never clobbers an existing promo; a bare `--intro-until` (no date) clears it |
| `agenthub pricing delete <pattern>` | Delete a rule |
| `agenthub pricing reset` | Restore the default rate table |
### Import
| Command | Description |
| ------- | ----------- |
| `agenthub import rescan` | Re-scan the default `~/.claude/projects` tree (idempotent; prints imported / backfilled / skipped / errors) |
| `agenthub import path <dir>` | Recursively import every `.jsonl` under an absolute directory (`~` is expanded server-side) |
| `agenthub import-data <file.json>` | Restore a full dashboard export produced by `agenthub export` (or **Settings → Export data**). Idempotent and non-destructive — sessions already present are skipped whole, so it safely **consolidates several machines** into one dashboard. The file is uploaded to the server, like the dashboard's Restore button |
### Remote Sources
Manage the remote (SSH) machines this dashboard pulls Claude Code history from — the terminal equivalent of **Settings → Remote Data Sources**. Authentication defers entirely to your SSH stack (`~/.ssh/config`, ssh-agent, keys, known_hosts); **no secrets are passed or stored**. `remotes` is an alias for `remote-sources`.
| Command | Description |
| ------- | ----------- |
| `agenthub remote-sources` (alias `remotes`) | List configured sources with id, auto-sync on/off, status, label, host, **session count**, and last-sync time, followed by a totals line (sources / auto-syncing / sessions collected) |
| `agenthub remote-sources add --label <name> --host <user@host> [--port N] [--identity <path>] [--remote-home <path>] [--codex] [--codex-home <path>] [--disabled]` | Add a source. `--host` is an ssh destination (`user@host`) or a `~/.ssh/config` alias; `--codex` also pulls its Codex history (from `--codex-home`, default `~/.codex`); `--disabled` skips it in the background poller |
| `agenthub remote-sources test <id>` | Probe SSH connectivity and check the remote `~/.claude/projects` exists; exits non-zero on failure |
| `agenthub remote-sources sync [id]` | Pull history now — one source by id, or **all** sources when the id is omitted. Prints imported / tagged counts |
| `agenthub remote-sources rm <id> [--purge]` | Remove a source (its imported sessions are detached back to `local` by default; `--purge` also **deletes** them) |
### Workspaces
A workspace is a durable unit of parallel agent work — one working directory, many sessions over time. Full guide: [`docs/LANES.md`](LANES.md).
`agenthub workspace …` (or `agenthub workspaces` for the list) is the name to use. `agenthub lanes …` and `--lane <id>` are the old names and keep working — the same commands as `agenthub workspace …` and `--workspace <id>` — so scripts and skills written before the rename need no change.
| Command | Description |
| ------- | ----------- |
| `agenthub workspaces` | List workspaces with stage, status, liveness and progress |
| `agenthub workspace add --cwd <path> --title <text> [--tool <id>]` | Adopt an existing directory as a workspace; `--tool` is an AI Tools id (default `claude`) |
| `agenthub workspace add --repo <path> [--title <text>] [--base <branch>] [--slug <slug>] [--tool <id>]` | Provision a dashboard-managed git worktree as a new workspace |
| `agenthub workspace profile init <repo> [--force]` | Detect a Node.js project (single-service or backend+frontend monorepo) and scaffold `.agenthub/profile/`. Refuses to overwrite an existing one without `--force` |
| `agenthub workspace pipeline [<template-id>] [<id>]` | Show which pipeline template a workspace renders against, plus the available templates and their node counts (none until you install one in `DASHBOARD_PIPELINES_DIR`); pass a template id to switch. An unknown id is refused (`400 EBADPIPELINE`), and a switch that leaves the workspace's current stage unresolvable warns |
| `agenthub workspace profile check [<path>]` | Validate a profile — parses, every referenced hook exists and is executable, no leftover `TODO:`, declared ports free. `<path>` defaults to the current directory (not a workspace id) |
| `agenthub workspace reset\|remove\|purge <id> [--force] [--keep-db] --yes` | Show preflight facts, then perform a destructive action. Refuses without `--yes`; `--force` is required when commits are unpushed; `--keep-db` (`reset` only) skips dropping/recreating a data-isolated workspace's database |
| `agenthub stage <stage> [--tool claude\|codex] [--evidence <text>] [--note <text>] [--result pass\|fail]` | Declare the workspace's current pipeline stage. Called by a skill at each phase boundary. With no pipeline template installed (AgentHub ships none — see [Custom pipeline templates](LANES.md#custom-pipeline-templates)) it answers `400 ENOPIPELINE`. `<stage>` may be a node id or one of its template's aliases; a name matching neither is still recorded but warns on stderr (exit stays `0`) that the pipeline map won't show it. `--tool` picks between a `claude` and a `codex` workspace sharing one directory |
| `agenthub feature list [<id>]` | List every feature this workspace has activated, archived or live |
| `agenthub feature activate <slug> [--title text] [<id>]` | Switch to a feature by slug (echoes the canonicalized slug), archiving the current one first |
| `agenthub feature show <slug> [<id>]` | Show one feature's saved pipeline — works on an archived one too |
**Runtime** — the workspace's own application stack, as opposed to `start`/`stop`, which drive its Claude run. Two lifecycles, one workspace id. Each requires the repository to declare a profile at `<repo>/.agenthub/profile/` ([contract](LANES.md#workspace-runtime-running-a-workspaces-own-stack)); without one they report that nothing is configured rather than failing.
| Command | Description |
| ------- | ----------- |
| `agenthub workspace up [<id>] [--no-build]` | Boot the stack through the profile's `boot` + `health` hooks, then poll until it is healthy or the boot fails. `--no-build` reuses an existing build |
| `agenthub workspace down [<id>]` | Stop the stack. Idempotent, and a no-op for a workspace that was never up |
| `agenthub workspace runtime [<id>]` | Slot, ports (flagging any that stepped aside from its base), the workspace's database name and Redis index when its profile declares them (see [Data isolation](LANES.md#data-isolation-database-redis-and-env-a2)), per-service liveness, log paths, and the last boot error |
| `agenthub workspace logs [<id>] <service> [--tail N]` | Tail one service or hook log (`--tail` in bytes, default 64 KiB) |
| `agenthub workspace hook [<id>] <name> [args…]` | Run one of the profile's hooks: `bootstrap`, `boot`, `health`, `migrate`, `seed`, `ci-gate`, `e2e`, `regen`, `db-create`, `db-drop` |
| `agenthub workspace proof-link [<id>]` | Converge clone-root `proof/` onto `.playwright-mcp/proof` (idempotent, never run automatically) |
| `agenthub lock status [<name>]` | Show one lock's holder, or every currently-held lock |
| `agenthub lock acquire <name> [--holder X] [--timeout N]` | Acquire a cross-workspace named lock, polling until free (or `--timeout` seconds elapse). Holder defaults to the calling workspace (`lane<slot>`) |
| `agenthub lock release <name> [--holder X]` | Release a lock. Refused (409) when `--holder` doesn't match the current owner |
Omit `<id>` and the command addresses the workspace owning the current directory, so a session running inside a workspace never needs to know its own id. Only a leading all-digits argument is read as an id — `agenthub workspace logs web --tail 4096` addresses the workspace by directory, not workspace 4096.
Resolution order, shared by every cwd-resolving command: `--workspace` (old name `--lane`)/leading id → `AGENTHUB_LANE_ID` (exported into every tmux pane the dashboard starts) → `--tool <id>`, else the harness's marker (`CLAUDECODE` means claude; Codex has no equivalent marker, so a codex session outside a dashboard pane passes `--tool codex`) → the workspace owning the directory. One directory can back a `claude` workspace and a `codex` workspace at once, so when two candidates remain the command fails and names both instead of picking one — see [Which workspace a CLI command addresses](LANES.md#which-workspace-a-cli-command-addresses).
Because a workspace's services are fully detached, restarting the dashboard (or `agenthub update`) never stops a running stack.
### Integrations
| Command | Description |
| ------- | ----------- |
| `agenthub mcp` | Run the read-only MCP server on stdio (`mcp/server.js`). Register it with `claude mcp add agenthub -- agenthub mcp`; never registered automatically. `AGENTHUB_URL` overrides the dashboard it asks — see [MCP.md](MCP.md) |
| `agenthub statusline` | Render the Claude Code statusline from the statusline JSON on stdin (what a plugin install's `statusLine` runs) — see [STATUSLINE.md](STATUSLINE.md) |
| `agenthub statusline install [--force]` | Write AgentHub's `statusLine` into `$CLAUDE_HOME/settings.json` (default `~/.claude/settings.json`). Refuses (exit 1) when another `statusLine` is there unless `--force`; the old file is backed up beside itself as `settings.json.agenthub-backup-<timestamp>` |
| `agenthub statusline uninstall [--force]` | Remove AgentHub's `statusLine` (another one only with `--force`), with the same backup |
### Administration
| Command | Description |
| ------- | ----------- |
| `agenthub doctor` | Diagnosis: API reachability, hook installation status + path, database path/size/row counts, server uptime and Node version, WS connections, whether `tmux` is on **the server's** PATH (asked via `GET /api/run/tmux` — a systemd `--user` service does not read your shell profile), remote-source status |
| `agenthub info` | The raw `/api/settings/info` JSON (pipe it to `jq`) |
| `agenthub export [file.json]` | Full JSON data export (sessions, agents, events, tokens, workflows, dashboard runs, alert rules, pricing) — defaults to a dated filename. Re-importable via `agenthub import-data` |
| `agenthub cleanup --hours N --days M` | Abandon active sessions idle for `N` hours and/or purge completed sessions older than `M` days |
| `agenthub reinstall-hooks` | Rewrite the Claude Code hook entries in `~/.claude/settings.json` |
| `agenthub update-check` | Ask the server whether a newer **release** has been published, read from the forge's own releases API (a checkout derives the repo from its `origin` remote; a plugin-cache install, which has no clone and often no `.git` at all, derives it from the marketplace manifest on disk); falls back to a commit count against the canonical remote when no release can be read, with the reason in `release_check`. Prints the release tag against the running version, a situation note for fork/feature-branch checkouts, and the **copy-paste update command**. Reports `dev_build` when the install is ahead of the newest release, and `plugin_managed` for an install under `~/.claude/plugins/cache/`. The dashboard UI can self-apply either kind (`POST /api/updates/apply`): a fast-forwardable checkout is fast-forwarded onto the release tag, rebuilt and self-restarted; a plugin install is handed to a detached `claude plugin marketplace update` → `claude plugin update` → `plugin-bootstrap.js --force` chain instead. `/agenthub-update` remains the manual equivalent, and an already-open Claude Code session still needs `/reload-plugins` to pick up new skills and commands. Also refreshes the update banner in any open dashboard tab (same `update_status` broadcast) |
| `agenthub clear-data --yes` | Delete **all** data (schema preserved). Refuses to run without `--yes` |
| `agenthub open` | Open the dashboard in your default browser (`open` / `xdg-open` / `start`) |
| `agenthub version` | Print the agenthub version (also `--version` / `-v`) |
| `agenthub help` | Full command reference (also shown with no arguments) |
## Safety Model
- **Read commands are always safe** — they only issue `GET`s.
- **Mutating commands** (`alerts ack`, `pricing set/delete/reset`, `import`, `cleanup`, `reinstall-hooks`) map 1:1 to explicit dashboard actions and run immediately, exactly like clicking the equivalent button.
- **The one destructive command, `clear-data`, refuses to run without `--yes`** and prints exactly what it would delete. There is no bulk-destructive behavior anywhere else.
## Output & Scripting
The CLI renders a full terminal UI while staying 100% script-friendly:
- **Box-drawn tables** with bold headers, right-aligned numeric columns, and terminal-width fitting — over-wide columns are clipped with an ellipsis so the frame never wraps mid-row.
- **Status icons + colors** everywhere a status appears: `● active` (green), `◐ working` (green), `○ waiting` (yellow), `✔ completed` (dim), `✖ error` (red), `◦ abandoned` (dim).
- **Inline bar charts** for the sessions-by-status distribution (`stats`), top tools and agent types (`analytics`), and the per-model cost breakdown (`cost`).
- **Real tree rendering** (`├─`/`└─` with continuation rails) for the agent hierarchy in `session <id>`, and status lanes with branch rows in `kanban`.
- Session tables include a relative **Updated** column (`4m ago`) so freshness is visible at a glance; event types are color-coded consistently across `events`, `tail`, and `session <id>`.
- `agenthub start` animates a spinner on a TTY (dot-trail when piped).
Color rules (informal CLI conventions):
| Condition | Effect |
| --------- | ------ |
| stdout is a TTY | Colors **on** |
| Output piped / redirected | Colors **off** automatically — `agenthub sessions \| grep error` and `agenthub info \| jq .db.counts` see plain text |
| `NO_COLOR=1` env or `--no-color` anywhere on the command line | Colors **off** |
| `FORCE_COLOR=1` or `AGENTHUB_COLOR=1` | Colors **on** even when piped (useful under `watch`/CI) |
- `agenthub version` (also `--version` / `-v`) prints the package version.
- Exit codes: `0` success, `1` for unreachable server, API errors, usage errors, unknown commands, or a failed `webhooks test` — safe to use in scripts and CI.
## Troubleshooting
| Symptom | Fix |
| ------- | --- |
| `○ Dashboard server is NOT running` | Start it: `agenthub start` (background), `npm run dev`, or `npm start`. If it runs on a custom port, set `DASHBOARD_PORT` or rely on the discovery file |
| `agenthub: command not found` | Run `npm link` from the repo root (setup's fail-soft link may have skipped on permissions), or use `node bin/agenthub.js …` |
| Wrong server answers (multiple dashboards) | Set `CLAUDE_DASHBOARD_PORT` explicitly — env overrides always beat discovery |
| `tail` shows nothing | Events only flow while hooks are installed and a Claude Code session is active — check `agenthub doctor` |