Engineering

Claude Code Integration#

Co-Vibe supports Claude Code in two ways:

  1. Claude Code can call Co-Vibe MCP tools through the project .mcp.json.
  2. Claude Code hooks submit verified model and token usage through covibe_ingest_agent_telemetry.

Setup#

Start Co-Vibe:

bash
npm run dev

Create an MCP token in the UI, install the companion with the command shown in Agent Setup, then export the token before opening Claude Code. Hosted builds serve the companion package from /downloads/co-vibe.tgz, so the default command looks like:

bash
npm install --save-dev http://localhost:3000/downloads/co-vibe.tgz \
  && printf "Co-Vibe MCP token: " \
  && read -rs COVIBE_MCP_TOKEN \
  && printf "\n" \
  && export COVIBE_MCP_TOKEN \
  && npm exec -- covibe-local setup --base-url http://localhost:3000 \
  && npm exec -- covibe-local doctor --base-url http://localhost:3000 \
  && claude

For hosted Co-Vibe, keep the same local commands but use the hosted tenant URL in the install command, setup base URL, and doctor base URL. Developers do not need to run the cloud app locally, but they still need the installed companion package in each tracked repo for hooks, transcript usage, git-aware snapshots, and .covibe/telemetry inbox flushes for Codex/Cursor wrapper exports. Use only the Co-Vibe origin for --base-url, not credentials, /callback, query strings, hashes, or another path. Setup reads COVIBE_MCP_TOKEN for readiness checks and the first snapshot; the token is not written to repo config. The copied block is an && chain so doctor and Claude do not open when install or setup fails.

The token prompt is optional: when no --token, COVIBE_MCP_TOKEN, or stored credentials exist, covibe-local setup runs a browser device flow, the developer approves the request once in the console, and per-agent typed tokens land in ~/.covibe/credentials.json (mode 0600). The written .mcp.json carries a non-secret COVIBE_AGENT=claude-code marker so the stdio bridge can look up the right token; COVIBE_MCP_TOKEN keeps precedence for existing setups. See device-setup.md for the full flow.

One setup run integrates every supported agent: it writes the Claude Code files below, a Codex ~/.codex/config.toml MCP entry when Codex is installed (see codex-integration.md), Cursor .cursor/mcp.json plus .cursor/hooks.json files when Cursor is installed (see cursor-integration.md), and a marker-delimited overlap-protocol snippet in the repo's AGENTS.md, in CLAUDE.md (created if missing when claude-code is configured), and in .cursor/rules/covibe.mdc when cursor is configured (skip with --no-agent-rules, reapply with covibe-local agent-rules [--agents ...]). Setup prints one INFO line per file it writes, reports already up-to-date files, and supports --dry-run to print the planned writes without touching anything (a token is not required for a dry run).

Claude Code reads .mcp.json and exposes the Co-Vibe tools from the covibe server. If Claude asks whether to trust the project MCP server, approve it for this repository.

Automatic Usage Capture#

The project .claude/settings.json registers scripts/claude-code-covibe-hook.ts for SessionStart, Stop, and SessionEnd.

The hook:

  • starts a Co-Vibe claude-code session when Claude Code starts
  • submits bounded git/repo snapshots without file contents
  • includes dirty files, unpushed commit files, and deterministic diff hashes
  • receives warning responses when another session has overlapping dirty or unpushed files, and surfaces them to the agent: on SessionStart and Stop the hook emits the conflict (owner, branch, files, what to do) as hookSpecificOutput.additionalContext — covering both a teammate's session and the same developer's other agent session
  • warns mid-session: a PostToolUse hook (matcher Edit|Write|MultiEdit|NotebookEdit) checks each edited file against the conflict map cached from the latest snapshot warning and injects a one-time per-file warning as additionalContext — no server roundtrip per edit
  • reads only new usage-bearing records from Claude's transcript JSONL
  • sends model, token, cache, and cost counters to covibe_ingest_agent_telemetry
  • ends the Co-Vibe session when Claude Code exits

The hook does not submit prompt text, model responses, code snippets, or full transcript records. It builds a compact claude_sdk_result payload with usage counters only. Co-Vibe still parses and prices the payload server-side. Repos excluded with covibe-local exclude are never logged: the hook exits before any tool call or state write (see device-setup.md). For other repos, hook activity registers the repo in ~/.covibe/repos.json so the machine-level watch service picks it up automatically — no per-repo registration command.

Environment#

Required (one of):

  • COVIBE_MCP_TOKEN (legacy shared token; takes precedence when set)
  • a claude-code token in ~/.covibe/credentials.json written by the device-flow setup (see device-setup.md)

Optional:

  • COVIBE_BASE_URL, default http://localhost:3000
  • COVIBE_AGENT, the credentials-file lookup key written into .mcp.json
  • COVIBE_CREDENTIALS_PATH, default ~/.covibe/credentials.json
  • COVIBE_CLAUDE_AGENT_NAME, default Claude Code
  • COVIBE_BRANCH, when a wrapper wants to pin the branch label
  • COVIBE_CLAUDE_HOOK_STATE, default data/claude-code-hook-state.json

If no token can be resolved, the hook exits successfully without logging so Claude Code is never blocked by Co-Vibe setup.

Verification#

Run:

bash
npm run claude:hook < sample-hook-input.json
npx vitest run tests/unit/claude-code-hook.test.ts tests/unit/verified-telemetry.test.ts
View as .md