CCC

June 27, 2026 Β· View on GitHub

Start the next while Claude builds the first.

One local dashboard for every Claude Code, Codex, Cursor, Antigravity, and Kilo Code session on your machine. Spawn in parallel, ship in parallel.

πŸ“’ Shipping fast. Watch β†’ Releases (top-right) to get pinged on new versions without the noise.

Claude Command Center demo

Install with curl:

curl -fsSL https://raw.githubusercontent.com/amirfish1/claude-command-center/main/scripts/install.sh | CCC_FROM=readme bash

With Homebrew:

brew tap amirfish1/ccc
brew install ccc
ccc

Or download the macOS DMG and drag CCC.app to Applications: github.com/amirfish1/claude-command-center/releases/latest

Try the read-only demo first: ccc.amirfish.ai/demo (or amirfish1.github.io/claude-command-center/demo) - full kanban with seeded fake data, no install required.

CCC latches onto every Claude Code, Codex, Cursor, Antigravity, and Kilo Code session on your machine β€” terminal sessions, headless processes, and sessions you spawned from the dashboard. It treats each agent's on-disk state as the source of truth, so nothing slips through. Spawn the next task while the first is still building. Switch between projects without losing context. Ship multiple things at once.

See the engine support matrix below for what's first-class vs. partial per engine β€” spawn works across all supported engines, transcript ingestion and UX parity vary.

Recent

  • 2026-06-25 β€” v5.4.0 β€” Project tree: the "By objects" sidebar now splits a live "Current sessions" triage band over a hierarchical map of your day β€” sessions grouped under nestable, draggable Flow objects. Plus a new /api/sessions/events SSE stream (subscribe to session-state changes instead of polling) and a broad Codex, sidebar, and Total Recall search polish wave.
  • 2026-06-03 β€” v4.6.0 β€” Major performance pass: the dashboard idles instead of pinning a CPU core, group-chat opens ~40Γ— faster, long conversations open near-instantly (windowed load + scroll-up to load earlier), and Codex sessions with screenshots no longer stall on multi-MB images. New CCC self-health readout in the footer.
  • 2026-05-21 β€” v4.0.0 β€” Antigravity (Google DeepMind) joins the dashboard as a first-class engine alongside Claude Code and Codex.
  • 2026-05-21 β€” Drag any conversation row outside the window to pop it into a focused side pane, with 24 per-conversation accent colors.
  • 2026-05-19 β€” Template gallery mechanism for reusable new-session prompts, driven by static/templates.json. (#46)
  • 2026-05-19 β€” VS Code extension v0.1.0 published β€” spawn a session from the active workspace folder. (#52)
  • 2026-05-19 β€” One-command curl | bash installer; git clone demoted to a "From source" section. (#58)
  • 2026-05-19 β€” Static GitHub Pages demo with seeded mock data (no install required). (#49)
  • 2026-05-18 β€” Local macOS say text-to-speech button on conversations.

Star History Chart

If you install it, I'd love to hear how. Drop a ⭐, open an issue with what worked or what broke, or just say hi. This is a one-person project built around a specific workflow. Outside feedback is the only way I know how widely it lands. @amirfish1

Why this exists

Most Claude Code orchestration tools are opinionated wrappers. They want to own execution. You launch agents through them, and in return you get a dashboard. That's fine until it isn't. The moment you open a terminal, claude --resume something, and iterate on it by hand, you're outside the tool's universe. The dashboard can't see it. The work you just did doesn't show up on the kanban, against the issue, in the review queue.

This goes the other way. It treats Claude Code's on-disk state as the source of truth: ~/.claude/projects/*.jsonl transcripts, the ~/.claude/sessions/<pid>.json live registry, and per-tool-call sidecar files written by two hooks we install into ~/.claude/settings.json. If Claude Code is running anywhere on your machine, it shows up here. If you close the dashboard, your sessions keep running. If you open a terminal and iterate by hand, the card updates.

The dashboard also knows how to spawn headless sessions (via claude -p --input-format stream-json) and resume dormant ones on demand, but those are additive. The thing it's built around is attaching to work that already exists.

Quickstart

Try the demo: ccc.amirfish.ai/demo β€” read-only kanban with seeded fake data, no install required.

Requirements: macOS or Linux, Python 3, and Claude Code installed. Optional: gh for GitHub integration, vercel for deploy status. Linux is supported for headless / remote-box use (see Running on Linux); the macOS-only desktop conveniences degrade cleanly there. On Windows, run CCC inside WSL2 (Ubuntu or another Linux distro). Native Windows shells are not supported.

curl β€” clones into ~/.ccc/claude-command-center and runs in foreground. Re-running does a git pull.

curl -fsSL https://raw.githubusercontent.com/amirfish1/claude-command-center/main/scripts/install.sh | CCC_FROM=readme bash

Homebrew β€” installs into the Cellar, puts ccc on PATH, pins a brew-managed Python. Upgrade via brew upgrade ccc.

brew tap amirfish1/ccc
brew install ccc
ccc                              # foreground
brew services start ccc          # or run as a brew-managed background service

DMG β€” drag CCC.app to Applications, double-click to launch. Under the hood this runs the same install.sh (clones into ~/.ccc/claude-command-center and asks whether to install the launchd service). First launch shows the macOS "unidentified developer" prompt β€” right-click CCC.app β†’ Open β†’ Open. Only required once. Download from the latest release.

If you'd rather clone first and run the script directly, pass the channel as a flag instead: ./scripts/install.sh --from=readme.

From source

git clone https://github.com/amirfish1/claude-command-center
cd claude-command-center

# Try it. Runs in the foreground until Ctrl-C / terminal close
./run.sh

# Keep it. Install as a per-user launchd agent that starts now and at login
./run.sh --install-service

Open http://localhost:8090, then pick a repo from the repo dropdown before starting repo-scoped actions.

--install-service writes ~/Library/LaunchAgents/com.github.claude-command-center.plist and registers it in your per-user launchd domain so CCC starts immediately, restarts if it exits, and starts again at macOS login. It bakes in whatever PORT / CCC_* env vars were set when you ran it. Re-run it to update config; check with ./run.sh --service-status; remove with ./run.sh --uninstall-service. Service logs go to ~/.claude/command-center/logs/service.{out,err}.log. Normal CCC app updates keep using the same checkout path; re-run ./run.sh --install-service only when you want to change baked-in env vars or pick up a release that changes the launchd plist itself.

Running on Linux

CCC runs on Linux as a headless service you reach from the browser on another machine. The core (kanban, ~/.claude transcript ingestion, session spawn and drive) works the same as on macOS. The macOS-only desktop conveniences (screenshots, jump-to-terminal, open-in-desktop, native folder picker) are not available on Linux yet; the UI hides those controls automatically, so you never see a button that does nothing.

Windows users should use this Linux path under WSL2. Install Python 3, git, and your agent CLIs inside the WSL distro, then open http://localhost:8090 from the Windows browser after ./run.sh starts.

git clone https://github.com/amirfish1/claude-command-center
cd claude-command-center

# Try it in the foreground
./run.sh

# Keep it. Installs a systemd user service that starts now and at login
./run.sh --install-service

--install-service writes a systemd user unit to ~/.config/systemd/user/ccc.service and runs systemctl --user enable --now. Check it with ./run.sh --service-status (or systemctl --user status ccc), follow logs with journalctl --user -u ccc -f, and remove it with ./run.sh --uninstall-service. On a headless box with no active login session, run sudo loginctl enable-linger $USER once so the service survives logout and starts at boot. If systemctl is not available, run CCC in the foreground or under your own process manager instead.

In WSL2, ./run.sh --install-service requires a distro with systemd enabled. If your WSL distro does not expose systemctl --user, keep CCC in the foreground with ./run.sh or run it under your own process manager.

To reach the dashboard from another machine, see SECURITY.md for the CCC_BIND_HOST and same-origin options before exposing the port.

First launch (foreground or service) copies two hook scripts into ~/.claude/command-center/hooks/ and registers them in ~/.claude/settings.json. After that, every Claude Code session on your machine (terminal, headless, or dashboard-spawned) writes sidecar state the UI uses for the kanban.

Core concepts

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   writes   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ any claude  β”‚ ─────────> β”‚ ~/.claude/projects/*.jsonl     β”‚
β”‚ process     β”‚            β”‚ ~/.claude/sessions/<pid>.json  β”‚
β”‚ anywhere on β”‚            β”‚ ~/.claude/command-center/          β”‚
β”‚ your machineβ”‚            β”‚   live-state/<sid>.json        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                          β”‚  reads
                                          v
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚ server.py (stdlib)    β”‚
                              β”‚ :8090                 β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                          β”‚
                                          v
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚ static/index.html     β”‚
                              β”‚ kanban + detail pane  β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • Session: any Claude Code transcript on disk, alive or dormant.
  • Attach: the server reads Claude's own files + sidecar state the installed hooks write after every tool call. Nothing to configure per-session.
  • Columns: Backlog β†’ Planning β†’ Working β†’ Review β†’ In Testing β†’ Verified / Inactive / Archived. Columns are derived from session state (live? commits? pushed? sidecar activity?), overridable by drag.
  • Backlog: open GitHub issues + TODO.md entries, surfaced as cards next to your active sessions so everything lives on one board.
  • Objects & the Project tree: group sessions under named, nestable Flow objects to build a hierarchical map of the day's work. The sidebar's "By objects" view splits this tree from a live "Current sessions" triage band (last 5h), so structure and live activity stay side by side.

Engine support

CCC was built around Claude Code first; Codex, Cursor, Antigravity, and Kilo Code support followed. Spawn-from-dashboard works for all five. The rest varies:

EngineSpawn (headless from UI)Resume (terminal inject / headless resume)Transcript ingestionPer-session model picker
Claude Codeyesyes (both)yes β€” first-class JSONL (~/.claude/projects/*.jsonl)yes β€” UI picker, incl. 1M-context toggle
Codexyesyes (both)partial β€” Codex JSONL parsed, broader parity tracked in #57yes β€” UI picker via per-session override; default from CCC_CODEX_MODEL
Cursoryes β€” headless via cursor-agentyes β€” follow-ups route through cursor-agent --resumepartial β€” Cursor agent transcripts parsed from ~/.cursor/projects/yes β€” UI/default model picker; default from CCC_CURSOR_MODEL
Antigravityyes β€” headless via agy print modeyes β€” follow-ups route through AGY CLI or the running app's language-server RPCyes β€” JSONL transcripts from ~/.gemini/antigravity/brain/auto-detected from transcript metadata
Kilo Codeyes β€” headless via kilo run --autono β€” fire-and-forget headless run, no resume wiring yetyes β€” reads Kilo's SQLite store (~/.local/share/kilo/kilo.db); externally-launched sessions appear on the boardyes β€” UI/default model picker; default from CCC_KILO_MODEL

Note on Cursor IDE integration: While CCC spawns Cursor agents headlessly via the CLI, the Desktop IDE manages UI state internally using a highly-nested, proprietary Protobuf Merkle tree in store.db. Full "two-way chat sync" into the IDE is unsupported due to the extreme risk of workspace corruption. Instead, CCC performs a metadata integration: CLI sessions are injected into the IDE sidebar as bookmarks (with correct titles and timestamps) so you don't lose track of them, but they cannot be interacted with natively inside the IDE window. Use the CCC dashboard for full history.

If you'd like to see an engine bumped from "partial" to first-class, open an issue β€” it's mostly adapter work, the ingestion layer is engine-agnostic.

Features

  • Multi-engine orchestration: spawn, resume, and review Claude Code, Codex, Cursor, Antigravity, and Kilo Code sessions from one dashboard. See the engine support matrix for per-engine parity.
  • ACP adapter (optional): expose CCC over the Agent Client Protocol so editors and ACP clients (VS Code, JetBrains, Zed, and agents like Hermes) can drive Claude Code sessions over JSON-RPC stdio. Runs as a separate process (python3 ccc_acp.py); install with the acp extra. The core server stays stdlib-only.
  • Kanban across every session, with drag-drop between columns, rubber-band multi-select, and per-column tinting.
  • Project tree: the sidebar's By objects view stacks a live Current sessions band (everything active in the last 5h) over a Project tree β€” your day's work as a hierarchy, with sessions grouped under nestable Flow objects you name, drag, and reparent. Drag the divider to resize the two bands; collapse branches you're not using. The structured map sits beside the live triage list, so "what's running now" and "how it all fits" share one pane instead of one scrolling list.
  • Split conversations: drag any sidebar session onto the right or bottom edge of the open conversation to view two transcripts side-by-side, each with its own input bar. Closes back to single-pane with a click; collapses automatically below 900px.
  • GitHub integration: start a session from an issue with one click (auto-adds claude-in-progress label + self-assigns). Verify closes the issue with a commit-SHA comment. Drag to Archived closes as "not planned". Issue body + comments render inside the dashboard (no iframe; GitHub blocks that).
  • Attach to existing sessions: terminal claude processes show up automatically. Jump-to-terminal focuses them by TTY; rename/color the tab via Claude's own slash commands.
  • Open in Claude Desktop (macOS): third destination button beside Jump/Launch in the conversation toolbar; resumes the current CLI session inside the Claude Desktop app via the claude://resume deep link.
  • Fresh worktree spawns: toggle worktree mode to launch a session in <repo>-wt/<slug>/ on feat/<slug>. Optional .ccc/worktree-init scripts can copy local env files or install dependencies before the agent starts.
  • Headless spawn with follow-up: launch claude -p sessions from the dashboard and keep talking to them via an in-browser input bar (no terminal needed, stdin pipe stays open).
  • Resume-on-demand: injecting into a dormant session auto-spawns a headless claude --resume to deliver the message.
  • Auto-fix deploys: optionally polls Vercel, spawns a /fix-deploy session on new production ERRORs (deduped by commit SHA).
  • AI-assisted titles: click ✨ on any card to regenerate its title via claude -p (Haiku by default). Used for cleaning up auto-generated session slugs.

Orchestration skill

CCC ships a Claude Code skill (ccc-orchestration) that lets one Claude session spawn, inject into, and synchronously ask sibling sessions over plain HTTP. On startup the server copies the skill to ~/.claude/skills/ccc-orchestration/SKILL.md (set CCC_SKIP_SKILL_INSTALL=1 to opt out) and writes its base URL to ~/.claude/command-center/port.txt so the skill can discover the running instance without hardcoding a port.

Spawn calls pass repo_path (or cwd) plus optional engine: "claude" | "codex" | "cursor" | "antigravity" | "kilo" to /api/sessions/spawn; omitted engine/model values use the server-side defaults from the dashboard. Legacy engine: "gemini" maps to Antigravity. Successful spawns return spawn_id, engine, repo_path, cwd, optional parent_session_id, and session_id when the native engine has emitted one; callers can poll /api/sessions/spawned if session_id_pending is true. Passing report_to (or explicit parent_session_id) links spawned sibling sessions under the dispatcher in Current Sessions.

Once installed, a Claude session can run e.g.:

CCC_URL="$(cat ~/.claude/command-center/port.txt)"
REPO_PATH="$(pwd -P)"
curl -s "$CCC_URL/api/sessions?repo_path=$(python3 -c 'import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))' "$REPO_PATH")"

curl -s -X POST "$CCC_URL/api/ask" \
  -H "Content-Type: application/json" \
  -d '{"session_id": "<uuid>", "text": "What is 2+2?", "timeout_ms": 30000}'
# -> {"ok": true, "text": "4", "cost_usd": ..., "duration_ms": ..., "num_turns": 1}

Use this for persistent peer sessions (a marketing assistant, a deploy babysitter) that should survive past the current turn and show up on the kanban, not for one-shot internal subtasks (the built-in Task tool is better for those).

Cookbook

Recipes for wiring your own app into CCC β€” each with a copy-paste prompt you can hand to Claude Code so it implements the integration for you:

  • Annotate β†’ UX-fixes queue β€” click an element in your running app, type a note, and it becomes a numbered work item a Claude session claims and fixes.
  • In-app bug report widget β†’ GitHub issue β€” a floating "Report an issue" button that screenshots the page and opens a fully-contextualized GitHub issue, plus a customer-facing status view derived live from GitHub labels.

Architecture

Two files: a single Python file (stdlib-only HTTP server) and a single HTML file (vanilla JS, no framework, no build). State lives in JSON sidecar files under ~/.claude/command-center/, all human-readable, all rewriteable by hand.

The server has no background workers. Every API request scans Claude's session directories, merges in sidecar state, enriches with cached GitHub issue data, and returns a flat list. The client classifies into columns using rules like "has_push β†’ Review", "live + sidecar_has_writes β†’ Working".

Hooks are the only invasive thing. On first run the server copies hooks/post-tool-use.py and hooks/stop.py to ~/.claude/command-center/hooks/ and merges entries into ~/.claude/settings.json. After that, Claude Code fires them after every tool invocation, each hook writes a tiny JSON file under live-state/, and the server reads those to answer "is this session actually doing something right now or is it idle waiting for input?".

For more depth: docs/architecture.md, docs/session-attach.md.

Configuration

Env varDefaultPurpose
PORT8090HTTP port
CCC_CLAUDE_BIN(auto)Absolute path to the Claude Code CLI when a launchd service cannot see your shell PATH. Set it before ./run.sh --install-service to bake it into the agent.
CCC_CURSOR_BIN(auto)Absolute path to cursor-agent if it is not on the service PATH.
CCC_CURSOR_MODELautoDefault model for Cursor spawns/resumes when no dashboard or API model override is set.
CCC_KILO_BIN(auto)Absolute path to the Kilo Code CLI (kilo) if it is not on the service PATH.
CCC_KILO_MODELkilo/stepfun/step-3.7-flash:freeDefault model for Kilo spawns when no dashboard or API model override is set.
CCC_BIND_HOST127.0.0.1Interface to bind. Set to 0.0.0.0 to expose on the LAN. No auth, see SECURITY.md
CCC_ALLOWED_ORIGIN(empty)Comma-separated origins (e.g. http://my-mac.tailnet.ts.net:8090) added to the same-origin POST allowlist. Use with CCC_BIND_HOST=0.0.0.0 to reach the UI from another device on a trusted network (Tailscale / VPN). No auth, see SECURITY.md
CCC_TRUST_TAILNET(off)When set (1/true/yes/on), CCC shells out to tailscale status --json at startup and adds the local node's MagicDNS hostname + Tailscale IPs to the allowlist automatically. Same trust caveat as CCC_ALLOWED_ORIGIN.
CCC_TITLE_STRIP(empty)Comma-separated prefixes to strip from GitHub issue titles (e.g. ACME,FOO strips [ACME ...] and [FOO ...])
CCC_ORG_PATTERNS(empty)Multi-tenant org-tagger. Format: Label1:pat1a|pat1b;Label2:pat2. Each issue body is scanned and tagged with the first matching label so the UI can group backlog by org.
VERCEL_PROJECT(unset)Vercel project name. Leave empty to disable deploy polling.
CCC_TELEMETRY_DISABLED(unset)Set to 1 to hard-disable the anonymous opt-in daily ping at the process level. Telemetry is off by default β€” the env var is the corporate / CI kill switch that also hides the consent banner. Full contract: docs/telemetry.md.

The CCC_BIND_HOST, CCC_ALLOWED_ORIGIN, and CCC_TRUST_TAILNET knobs can also be set in ~/.claude/command-center/network.json so they survive shell restarts, or flipped from the Network access… entry in the sidebar settings popover. Env vars always win, useful for CI / one-shot overrides. The same security caveats apply: every trusted origin can run commands as you.

Roadmap

Shipped

  • Kanban over all live + dormant Claude Code, Codex, Cursor, Antigravity, and Kilo Code sessions
  • GitHub issue β†’ session β†’ verify β†’ close pipeline
  • Headless spawn with stdin-pipe follow-up
  • Resume-on-demand
  • Auto-fix-deploy (Vercel)
  • AI title regeneration
  • Cursor β€” session cards, transcript ingestion, headless spawn/resume via cursor-agent
  • Antigravity (Google DeepMind) β€” full session view, transcript ingestion, headless resume via AGY CLI or app RPC
  • Kilo Code β€” headless spawn via kilo run --auto, engine selector + model picker, and read-only ingestion of externally-launched sessions from Kilo's SQLite store
  • ACP adapter β€” drive Claude Code sessions over the Agent Client Protocol (ccc_acp.py, optional)

Not yet

  • First-class parity for Codex. Spawn, resume, and JSONL transcript parsing work, but broader UX polish still lags behind Claude Code β€” see the engine support matrix and #57.
  • Kilo Code resume / follow-up. Spawn and read-only ingestion both work (externally-launched sessions appear on the board and open with full transcripts); injecting follow-up turns into a Kilo session is not wired yet.
  • More agent runtimes (Aider, OpenCode, etc.). The ingestion layer is engine-agnostic; adapters just don't exist yet.
  • Code split. server.py and index.html are each one huge file on purpose, so you can read the whole product in an afternoon. That tradeoff bends eventually; it hasn't yet.

Out of scope

  • Desktop-Linux parity. Linux is supported headless (see Running on Linux) with a systemd service and clean degradation of the macOS-only desktop glue. Native Linux equivalents for screenshots, jump-to-terminal, and deep links (X11/Wayland, wmctrl/tmux) are a possible follow-on, not a current goal. Native Windows is unsupported; use WSL2 for the supported Windows route.
  • Multi-user / network-exposed mode. This is a local dev tool. If you're looking at it on a remote host, something has gone wrong.
  • Electron / native wrap. Browser is the UI on purpose.

Contributing

See CONTRIBUTING.md.

License

MIT Β© 2026 Amir Fish

Acknowledgments

Built on top of Claude Code. The gh CLI and Vercel CLI are optional integrations but do most of the heavy lifting where they're used.