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
+7 -7
View File
@@ -78,7 +78,7 @@ describe("pipelines", () => {
});
it("keeps the evidence of a stage declared under an alias", () => {
// `lane.stages` is keyed by the raw declared string, so `ccam stage
// `lane.stages` is keyed by the raw declared string, so `agenthub stage
// planning --evidence x` files the record under "planning" while the node
// is "plan". Looking it up by node id alone loses the evidence and paints
// a `done` node amber — silently, and only for agents that use an alias.
@@ -151,12 +151,12 @@ describe("per-node driver command", () => {
assert.equal(byId.intake, "/superpowers:brainstorming");
assert.equal(byId.implementing, "/superpowers:test-driven-development");
assert.equal(byId.gates, "ccam lanes hook ci-gate");
assert.equal(byId.gates, "agenthub lanes hook ci-gate");
// A terminal or gate node has no work of its own to run: reaching it IS
// the declaration, so its command is the declaration - which keeps
// `ccam lanes node <id>` runnable for every node in the template.
assert.equal(byId.done, "ccam stage done");
assert.equal(byId["e2e-feature-passed"], "ccam stage e2e-feature-passed");
// `agenthub lanes node <id>` runnable for every node in the template.
assert.equal(byId.done, "agenthub stage done");
assert.equal(byId["e2e-feature-passed"], "agenthub stage e2e-feature-passed");
});
it("defaults a template node that declares no command to the empty string", () => {
@@ -334,7 +334,7 @@ describe("lanes lib", () => {
assert.equal(p.liveness, "idle");
// The template's driving slash command rides along so the run console can
// pre-fill its prompt with it.
assert.equal(p.pipeline_skill, "/ccam:ship-feature");
assert.equal(p.pipeline_skill, "/agenthub:ship-feature");
lanes.deleteLane(l.id);
});
@@ -1080,7 +1080,7 @@ describe("stage detection", () => {
db.prepare("UPDATE lanes SET detected_at = ? WHERE id = ?").run(oldTime, l.id);
// With nothing declared, the last detection IS the lane's last known
// progress — blanking it left every non-CCAM repo's card 100% pending
// progress — blanking it left every non-AgentHub repo's card 100% pending
// forever. Still amber (`detected`), still never `done`.
const payload = lanes.lanePayload(lanes.getLane(l.id));
const tests = payload.pipeline_nodes.find((n) => n.id === "tests");