nntrivi2001 4905d63b97 fix(lanes): clear stale detection on real stage transitions, exclude scratch dirs from implement detect
setStage() left detected_stage/signal/at untouched across a real transition,
so a prior task's leftover inference (e.g. `tests` from earlier work) both
misrepresented a fresh task's progress and — because recordDetection is
forward-only — silently rejected every real detection behind it until the
old one aged past DETECTION_TTL_MS. A real stage change now clears the
detection columns; a same-stage heartbeat leaves a live detection alone.

Also excludes `.superpowers/` from the `implement` node's Write detect rule
- brainstorm-companion scratch files were being counted as implementation
work.

fix(client): disable Node's default --experimental-webstorage in tests

Node 25 enables --experimental-webstorage by default, which defines a
broken global `localStorage` (no backing file configured) ahead of jsdom's
own full polyfill. Every test touching real localStorage failed with
"localStorage.clear/getItem is not a function" — not flaky, not test-specific,
just this one Node default. NODE_OPTIONS=--no-experimental-webstorage on the
test scripts lets jsdom's polyfill take over as before.
2026-07-31 10:53:07 +07:00

Claude Code Monitor

Internal SmartGift build. Local-first dashboard for Claude Code: hooks POST every tool call to an Express + SQLite server, a React UI updates over WebSocket, and lanes track parallel agent work through a pipeline.

Internal build — all rights reserved.

What it does

  • Sessions, agents, events. Everything Claude Code emits, recorded and searchable: tool calls, token usage, cost, subagent trees, transcripts.
  • Lanes. One lane per working directory, surviving session restarts. A lane moves through pipeline stages and the dashboard shows where it is.
  • Stage detection. The stage is inferred from the tool stream, so a session that never calls ccam stage still shows progress — rendered dashed amber and never as done, because an inference is not evidence.
  • Run Claude from the browser. Spawn a session in a lane's directory, stream its output, send follow-ups, resume any past session.
  • Analytics, alerts, Kanban and a workflow view, plus an MCP server and a CLI.

Requirements

Node >= 20 (engines in package.json). Node 24 is what the test suites are verified on — node 25 currently breaks 6 server tests through a better-sqlite3 ABI mismatch and 20 client tests through a global localStorage change.

Install and run

npm run setup          # root, client and vscode-extension dependencies
npm run build          # builds the client into client/dist
npm start              # serves the built client and the API on :4820

Open http://localhost:4820.

Development, with hot reload:

npm run dev            # server on :4820, Vite client on :5173

DASHBOARD_PORT overrides the port. postinstall writes the Claude Code hook entries that feed the dashboard.

The CLI

ccam is linked by npm run setup; otherwise call node bin/ccam.js.

ccam status            # is the dashboard up
ccam start             # start it in the background and wait for healthy
ccam sessions          # recent sessions
ccam lanes             # lanes with stage and progress
ccam stage <name>      # declare the current lane's stage
ccam tail              # live event feed

ccam --help lists the rest.

Lanes

A lane is a working directory the dashboard watches. Two kinds:

  • adopted — a directory you already had. The dashboard only reads it; it is never reset or deleted.
  • managed — a git worktree the dashboard created under LANES_ROOT. It owns the full lifecycle and may reset or remove it, behind a three-check destroy guard and a counted preflight the caller has to echo back.
ccam lanes add --cwd /path/to/repo --title "My feature"    # adopt
ccam lanes add --repo /path/to/repo --slug my-feature      # managed worktree

The declared stage comes from ccam stage. The inferred stage comes from tool events and expires after DETECTION_TTL_MS (default 5 minutes), so a lane can move backwards between work sessions. Detection never writes the declared stage, and an inferred node never renders as done.

docs/LANES.md has the pipeline model, the destroy guard, the preflight contract, the Workspace page, and GET /api/lanes/:id/git.

Tests

npm run test:server    # node:test
npm run test:client    # Vitest

Both must be green before a commit; the pre-commit hook runs them plus Prettier.

Layout

Path What
server/ Express API, SQLite schema, hook ingest, lane and worktree libraries
client/ React 18 + Vite + Tailwind dashboard
bin/ccam.js CLI
mcp/ MCP server exposing read-only dashboard tools
desktop/ Electron wrapper that embeds the server
docs/ Architecture, API, lanes, database, deployment
plugins/ Claude Code plugins shipped with the dashboard

Docs

S
Description
No description provided
Readme 72 MiB
Languages
JavaScript 52%
TypeScript 45.2%
HTML 1.3%
Shell 0.6%
CSS 0.4%
Other 0.4%