refactor!: rebrand CCAM to AgentHub

Clean break, no compatibility alias. Renames the product name, the CLI
binary (`ccam` -> `agenthub`), the env var prefix (`CCAM_` ->
`AGENTHUB_`), the Prometheus metric namespace (`ccam_*` ->
`agenthub_*`), the tmux session prefix (`ccam-lane-<id>` ->
`agenthub-lane-<id>`), the per-repo runtime profile directory
(`.ccam/profile` -> `.agenthub/profile`), the lanes state root
(`~/.claude/ccam-lanes` -> `~/.claude/agenthub-lanes`), the bundled
plugins (`plugins/ccam*` -> `plugins/agenthub*`) and their slash
commands (`/ccam-doctor` -> `/agenthub-doctor`, `/ccam:*` ->
`/agenthub:*`).

Because there is no alias, an existing install has to be updated by
hand: rename its `.ccam/profile` directory and any `CCAM_*` variables,
and reinstall the plugin under its new name.

Two other name families are deliberately left alone here, since they are
not just strings: the `Claude-Code-Monitor` repository/marketplace name,
and the `agent-dashboard` npm package plus its `~/.claude/agent-dashboard`
runtime directory, which holds the live database and needs a migration
rather than a rename.

Verified: server 1406/1406, client 459/459, `grep -i ccam` clean across
tracked files, `openapi.yaml` regenerated (95 paths, unchanged count).
This commit is contained in:
2026-09-07 12:09:15 +07:00
parent ae9b3dbcd5
commit 17d56d0e01
345 changed files with 2705 additions and 2727 deletions
@@ -1,4 +1,4 @@
# Plugin-first install — CCAM usable straight from a Claude Code plugin install
# Plugin-first install — AgentHub usable straight from a Claude Code plugin install
Date: 2026-08-10
Status: approved (design)
@@ -6,12 +6,12 @@ Status: approved (design)
## Goal
On a machine with nothing but Claude Code installed, these two commands must
leave the user with a working CCAM — hooks flowing, server up, dashboard
reachable, `ccam` CLI on PATH, MCP tools connected:
leave the user with a working AgentHub — hooks flowing, server up, dashboard
reachable, `agenthub` CLI on PATH, MCP tools connected:
```
/plugin marketplace add <ccam repo>
/plugin install ccam@claude-code-agent-monitor-plugins
/plugin marketplace add <agenthub repo>
/plugin install agenthub@claude-code-agent-monitor-plugins
```
No repo clone, no `npm run setup`, no `npm run install-hooks`, no manual
@@ -19,8 +19,8 @@ No repo clone, no `npm run setup`, no `npm run install-hooks`, no manual
## Why the current state does not do this
- The only plugin with a server connection, `ccam-dashboard`, declares its MCP
server as `../../mcp/build/index.js` (`plugins/ccam-dashboard/.mcp.json`).
- The only plugin with a server connection, `agenthub-dashboard`, declares its MCP
server as `../../mcp/build/index.js` (`plugins/agenthub-dashboard/.mcp.json`).
Plugins installed from a marketplace subdir are cached as **that subdir
only** — verified against `~/.claude/plugins/cache/claude-plugins-official/superpowers/6.2.0/`,
which contains the plugin directory's contents and nothing above it. The
@@ -32,14 +32,14 @@ No repo clone, no `npm run setup`, no `npm run install-hooks`, no manual
## Approach: declare the whole repo as one plugin
Add a **root-level** plugin named `ccam` with `"source": "."` in
Add a **root-level** plugin named `agenthub` with `"source": "."` in
`.claude-plugin/marketplace.json`. Claude Code then caches the *entire repo*
into `~/.claude/plugins/cache/<marketplace>/ccam/<version>/` — verified against
into `~/.claude/plugins/cache/<marketplace>/agenthub/<version>/` — verified against
`~/.claude/plugins/cache/caveman/`, whose cached tree contains the full source
repo (`src/`, `tests/`, `benchmarks/`), because that marketplace declares its
plugin with `"source": "./"`.
So `server/`, `client/`, `mcp/`, `scripts/` and `bin/ccam.js` are all present
So `server/`, `client/`, `mcp/`, `scripts/` and `bin/agenthub.js` are all present
under `${CLAUDE_PLUGIN_ROOT}` the moment the plugin is installed. No second
clone, no credentials beyond the marketplace add itself, no committed copy of
the server, no dependency on undocumented cache internals beyond the documented
@@ -61,7 +61,7 @@ gains no new top-level directories.
`.claude-plugin/marketplace.json` gains one entry:
```json
{ "name": "ccam", "source": ".", "description": "...", "tags": [...] }
{ "name": "agenthub", "source": ".", "description": "...", "tags": [...] }
```
### 2. Hooks — inline in `plugin.json`
@@ -95,7 +95,7 @@ Runs from the `SessionStart` hook. Never blocks a session.
Runtime state lives under `~/.claude/agent-dashboard/runtime/`, reusing the
existing data-dir convention (`server/lib/claude-home.js:37`, where the SQLite
DB already lives) rather than inventing a new directory. `/.ccam/` at the repo
DB already lives) rather than inventing a new directory. `/.agenthub/` at the repo
root is an unrelated lane profile and must not be confused with it.
Sequence:
@@ -118,13 +118,13 @@ Sequence:
fresh version directory, discarding anything installed into the old one.
`--ignore-scripts` is required because `scripts/postinstall.js` otherwise
runs a full `client/` install, pulling the whole Vite dev toolchain.
5. **Legacy hook cleanup.** If `~/.claude/settings.json` still carries CCAM hook
5. **Legacy hook cleanup.** If `~/.claude/settings.json` still carries AgentHub hook
entries from a previous `npm run install-hooks`, remove them and print one
line. Without this, every event is POSTed twice and token/cost figures
double. Detection reuses `isOurEntry()` from `scripts/install-hooks.js`.
6. **CLI on PATH.** Symlink `bin/ccam.js` to `~/.local/bin/ccam`. Skills and
commands throughout the repo (`ccam stage`, `ship-feature-lane`) shell out
to `ccam` and fail without it.
6. **CLI on PATH.** Symlink `bin/agenthub.js` to `~/.local/bin/agenthub`. Skills and
commands throughout the repo (`agenthub stage`, `ship-feature-lane`) shell out
to `agenthub` and fail without it.
7. **Start server.** Spawn `server/index.js` detached, `stdio: "ignore"`,
`unref()`, with `NODE_PATH` pointed at `runtime/node_modules`. The hook
returns immediately; the first install (1–3 minutes) proceeds in the
@@ -132,7 +132,7 @@ Sequence:
8. **Record state.** Write `runtime/state.json`.
The client UI bundle is *not* built here. Hooks, the API and MCP do not need
it; it is built lazily by `/ccam-open`.
it; it is built lazily by `/agenthub-open`.
### 4. Client dist relocation — `server/index.js`
@@ -143,7 +143,7 @@ checkout behavior is unchanged.
The bootstrap always starts the server with `DASHBOARD_CLIENT_DIST` set to
`runtime/client-dist/`, whether or not a bundle is there yet — a missing
directory serves the API fine and only the UI route 404s. `/ccam-open` builds
directory serves the API fine and only the UI route 404s. `/agenthub-open` builds
into that same directory, so no server restart is needed to pick the bundle up.
### 5. MCP — commit `mcp/build/`
@@ -152,27 +152,27 @@ Claude Code starts a plugin's MCP servers as the session opens and offers no
"not ready yet, retry" state, so an async bootstrap cannot win that race.
`mcp/build/` is therefore committed (removed from `.gitignore` and `mcp/.gitignore`)
and the root `.mcp.json` points at `${CLAUDE_PLUGIN_ROOT}/mcp/build/index.js`
with `CCAM_DASHBOARD_URL` defaulted to `http://localhost:4820`.
with `AGENTHUB_DASHBOARD_URL` defaulted to `http://localhost:4820`.
Cost: the build artifact must stay in sync with `mcp/src`. A pre-commit check
fails when `mcp/src` is newer than `mcp/build`.
The existing `plugins/ccam-dashboard/.mcp.json` keeps its broken relative path
The existing `plugins/agenthub-dashboard/.mcp.json` keeps its broken relative path
fixed to `${CLAUDE_PLUGIN_ROOT}` form as part of this work, so the subdir plugin
is not left in a knowingly broken state.
### 6. Commands — `plugins/ccam/commands/`
### 6. Commands — `plugins/agenthub/commands/`
The plugin root is the repo root, so `plugin.json` declares an explicit
`"commands": "./plugins/ccam/commands"` path. This keeps the new command files
`"commands": "./plugins/agenthub/commands"` path. This keeps the new command files
inside `plugins/`, next to the ten existing plugins, instead of adding a
top-level `commands/` directory to the repo root.
- `/ccam-doctor` — bootstrap state, Node version, server liveness, DB path,
- `/agenthub-doctor` — bootstrap state, Node version, server liveness, DB path,
duplicate-hook detection, CLI symlink, MCP build freshness.
- `/ccam-update` — refresh dependencies and restart the server after a plugin
- `/agenthub-update` — refresh dependencies and restart the server after a plugin
update.
- `/ccam-open` — lazily build the client bundle if missing, then open the
- `/agenthub-open` — lazily build the client bundle if missing, then open the
dashboard.
## Data and lifecycle
@@ -196,7 +196,7 @@ deduplicates hook ingest to a single port.
by full detachment (`detached`, `stdio: "ignore"`, `unref()`) and an
immediate hook return. Verified by timing the hook on a cold `HOME`.
- *Duplicate hooks double-count cost.* Events carry no id, so ingest cannot
deduplicate. Mitigated by step 5 of the bootstrap plus a `/ccam-doctor` check.
deduplicate. Mitigated by step 5 of the bootstrap plus a `/agenthub-doctor` check.
- *MCP unavailable at session start.* Resolved by committing `mcp/build/`.
**Medium severity**
@@ -204,8 +204,8 @@ deduplicates hook ingest to a single port.
- *Two sessions spawn two servers* → `EADDRINUSE`. Mitigated by the lock, with
a stale-lock timeout so a crashed bootstrap does not wedge every later
session.
- *`ccam` not on PATH* when `~/.local/bin` is absent from the user's PATH.
`/ccam-doctor` reports it and prints the line to add.
- *`agenthub` not on PATH* when `~/.local/bin` is absent from the user's PATH.
`/agenthub-doctor` reports it and prints the line to add.
- *Windows.* `npm.cmd` resolution (already handled in `scripts/postinstall.js`
via `shell: true`), detached spawn semantics, and `mkdir` locking are the
least-tested paths.
@@ -222,7 +222,7 @@ deduplicates hook ingest to a single port.
## Verification
1. Install the local marketplace and confirm
`~/.claude/plugins/cache/<mp>/ccam/*/server/` exists — this gates everything
`~/.claude/plugins/cache/<mp>/agenthub/*/server/` exists — this gates everything
else.
2. `npm run test:server` for the `DASHBOARD_CLIENT_DIST` override.
3. Unit tests for bootstrap: fast path, stale-lock reclaim, Node version gate,