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:
@@ -31,12 +31,12 @@ vi.mock("../../lib/api", async (importOriginal) => {
|
||||
// One installed plugin that actually contributes something, so the Claude Code
|
||||
// tab renders PluginCard's contribution chips instead of an empty list.
|
||||
const demoPlugin = {
|
||||
key: "ccam@sg",
|
||||
name: "ccam",
|
||||
key: "agenthub@sg",
|
||||
name: "agenthub",
|
||||
marketplace: "sg",
|
||||
scope: "user",
|
||||
version: "1.4.6",
|
||||
installPath: "/home/test/.claude/plugins/ccam",
|
||||
installPath: "/home/test/.claude/plugins/agenthub",
|
||||
installedAt: "2026-05-01T12:00:00.000Z",
|
||||
lastUpdated: "2026-06-01T09:30:00.000Z",
|
||||
gitCommitSha: "a1b2c3d",
|
||||
@@ -53,31 +53,31 @@ vi.mock("../../lib/api", async (importOriginal) => {
|
||||
{
|
||||
name: "ship-feature",
|
||||
description: "Implement a feature safely end-to-end.",
|
||||
file: "/home/test/.claude/plugins/ccam/skills/ship-feature/SKILL.md",
|
||||
file: "/home/test/.claude/plugins/agenthub/skills/ship-feature/SKILL.md",
|
||||
},
|
||||
{
|
||||
name: "file-headers",
|
||||
description: "Authorship header policy.",
|
||||
file: "/home/test/.claude/plugins/ccam/skills/file-headers/SKILL.md",
|
||||
file: "/home/test/.claude/plugins/agenthub/skills/file-headers/SKILL.md",
|
||||
},
|
||||
],
|
||||
agents: [
|
||||
{
|
||||
name: "qc-local",
|
||||
description: "Local browser QC.",
|
||||
file: "/home/test/.claude/plugins/ccam/agents/qc-local.md",
|
||||
file: "/home/test/.claude/plugins/agenthub/agents/qc-local.md",
|
||||
},
|
||||
],
|
||||
commands: [
|
||||
{
|
||||
name: "ccam-doctor",
|
||||
name: "agenthub-doctor",
|
||||
description: null,
|
||||
file: "/home/test/.claude/plugins/ccam/plugins/ccam/commands/ccam-doctor.md",
|
||||
file: "/home/test/.claude/plugins/agenthub/plugins/agenthub/commands/agenthub-doctor.md",
|
||||
},
|
||||
],
|
||||
outputStyles: [],
|
||||
},
|
||||
pluginJson: { name: "ccam", description: "The dashboard as a plugin.", version: "1.4.6" },
|
||||
pluginJson: { name: "agenthub", description: "The dashboard as a plugin.", version: "1.4.6" },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -614,7 +614,7 @@ describe("plugin contribution chips", () => {
|
||||
it("expands a plugin's skills by name on click, and collapses again", async () => {
|
||||
await openPluginsTab();
|
||||
|
||||
const chip = screen.getByTestId("plugin-contrib-ccam@sg-skills");
|
||||
const chip = screen.getByTestId("plugin-contrib-agenthub@sg-skills");
|
||||
expect(chip).toHaveAttribute("aria-expanded", "false");
|
||||
expect(screen.queryByText("ship-feature")).toBeNull();
|
||||
|
||||
@@ -631,16 +631,16 @@ describe("plugin contribution chips", () => {
|
||||
it("shows only one surface at a time, and prefixes a command with its slash", async () => {
|
||||
await openPluginsTab();
|
||||
|
||||
fireEvent.click(screen.getByTestId("plugin-contrib-ccam@sg-skills"));
|
||||
fireEvent.click(screen.getByTestId("plugin-contrib-ccam@sg-commands"));
|
||||
fireEvent.click(screen.getByTestId("plugin-contrib-agenthub@sg-skills"));
|
||||
fireEvent.click(screen.getByTestId("plugin-contrib-agenthub@sg-commands"));
|
||||
|
||||
expect(screen.queryByText("ship-feature")).toBeNull();
|
||||
expect(screen.getByText("/ccam-doctor")).toBeInTheDocument();
|
||||
expect(screen.getByText("/agenthub-doctor")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("leaves hooks as a plain chip - they have no per-item list to open", async () => {
|
||||
await openPluginsTab();
|
||||
|
||||
expect(screen.queryByTestId("plugin-contrib-ccam@sg-hooks")).toBeNull();
|
||||
expect(screen.queryByTestId("plugin-contrib-agenthub@sg-hooks")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user