ccc

Code Change Capture Visualiser Example

Developers And Agents

Ways to see and review what changed, beyond the command line:


Visualisation

ccc run --vis serves a 2D map of the project at http://127.0.0.1:6767/vis and opens it in your browser. The VS Code extension shows the same page in its panel. It follows the C4 model from the whole system down to the code, then goes one level further: the logic of a single function, drawn as a node graph.

ccc run --vis

Levels

Level Boxes Arrows
Context the system; peer repositories from externals in .ccc/map.json; endpoints nothing in the map answers cross-calls, by transport
Containers services from .ccc/map.json, or top-level directories without one resolved and declared calls between services
Components the files in one container; other containers it touches sit outside the boundary file-to-file calls
Code the functions in one file, each with an input pin and one output pin per function it calls resolved calls; functions in other files as stand-ins
Logic one function: entry, calls, branches, switch/match/try arms, loops, closures, returns and throws execution order

Every level is built from the same map the MCP tools read, so every supported language is drawn the same way. Like the rest of ccc, it reads syntax, not behaviour. An arrow is a call the resolver found evidence for, and a branch is a node in the syntax tree, not a path anything was seen to take. Calls that reach nothing in the project (the standard library, a dependency) are folded into grey pills; the toolbar shows them in full or hides them.

Getting around

Key or action What it does
Double-click or Enter Drill down a level.
Escape Go back up a level.
Breadcrumb Jump to any level.
/ Search for functions and files, and open them directly.
Drag Rearrange boxes. Positions are remembered per view.

Every view has its own URL, so the browser’s back button works and views can be bookmarked. The page reloads by itself when the map changes. A view of 50 or more components or functions is laid out a group at a time.

The player

A player along the foot of the page replays what agents did through ccc. Each ask plays as a story: the agent’s plan, every step it took and how it ended. The story is told in subtitles and read aloud, and the bar is cut into chapters, listed in a rail beside the canvas.

Key What it does
Space Play or pause.
← / → Step back or forward.
L Turn Live on or off.
c Turn subtitles off or on.
m Turn the voice off or on.

The voice is a local model, downloaded once per machine (see ccc voice). Every ccc server on a project shares its steps through .ccc/timeline.jsonl, which is kept out of git. So the visualiser shows an agent’s work whichever server the agent talks to.

The data behind it

The page is built from plain JSON, which is served with or without --vis:

curl -s localhost:6767/vis.json                              # context, containers, components
curl -s 'localhost:6767/vis/code?file=src/scan.rs'           # one file's functions and calls
curl -s 'localhost:6767/vis/flow?file=src/scan.rs&line=76'   # one function's logic

IDEs

VS Code

extensions/vscode puts ccc’s analysis on the code it applies to. It runs its own ccc analyser in the background for each workspace folder and reads it over loopback HTTP, so nothing leaves your machine and nothing needs configuring to start. When no ccc binary is found, it downloads the release for your platform.

Install. cargo build --release packages the extension next to the binary:

cargo build --release                             # -> dist/ccc-codecache.vsix
code --install-extension dist/ccc-codecache.vsix

To build only the extension: cd extensions/vscode && npm install && npm run package. It isn’t published to the Marketplace.

Hints. Each changed function carries a clickable CodeLens:

Hint What it means
✓ 3 tests The function changed and tests cover it. Opens them, nearest call hop first.
✗ no smoke test Nothing covers the change. The kind of test worth writing is named: smoke, integration, contract, perf or load.
→ billing This line calls into another service. Opens the callee.
← gateway Another service calls this function. Opens the callers.
▲ 37 callers A hot path: among the most called, most complex or widest fan-out.
↻ cycle of 3 The function is in a call cycle.
↑ calls billing in acme/billing The call leaves the repository. Opens the handler when that peer is checked out locally.

Test, coverage and service-boundary hints are based on the diff. A file identical to the base ref has none, by design. Hot paths and cycles come from the call graph alone, so they show on any file. Every function also shows its complexity as a circled number from 1 to 10 between its name and signature, coloured from grey to red as it climbs.

The panel. Click the Code Change Capture mark in the activity bar. It has three views:

Everything runs against the working tree, so uncommitted and untracked files count. Hints reflect the last saved state; they fade while a file has unsaved edits and refresh on save.

The extension’s own page, extensions/vscode/README.md, lists its commands.

Settings:

Group Settings
Analyser ccc.binaryPath (your own ccc), ccc.autoInstall (false stops the download), ccc.server.autoStart, ccc.server.address, ccc.server.port (0 picks a free port; a fixed one collides across windows), ccc.server.watchIntervalSec (0 lets the extension drive rescans), ccc.server.startupTimeoutMs, ccc.server.extraArgs (extra ccc run options, for example --auto), ccc.server.ignoreSkip (the same as --ignore-skip)
Hints ccc.enable, ccc.baseRef, ccc.hints.codeLens, a toggle per kind (ccc.hints.testTriggers, untested, outbound, inbound, hotPaths), ccc.hints.includeTestFiles, ccc.hints.crossServiceMode (auto, always, off), ccc.hints.minEvidence (evidence, any), ccc.untested.showUncoveredTargets, ccc.untested.minPriority
Complexity ccc.complexity.enabled, ccc.complexity.minScore
Decorations ccc.decorations.style (badge+gutter, badge, gutter), badgeMaxLength, dimWhenDirty, overviewRuler
Refresh ccc.refresh.onSave, onWindowFocus, intervalSec (off by default), debounceMs
Search ccc.search.mode (none, allow, block), ccc.search.urls and ccc.search.endpoints: what the search tool may reach, for example only your company’s docs and portals
Logging ccc.trace (off, messages, verbose)

ccc.hints.codeLens: false with ccc.decorations.style: badge+gutter shows end-of-line badges instead of lenses.

How the hints are worked out. The analysis is static. Knowing what it did and didn’t establish is the difference between a useful hint and a misleading one.

Troubleshooting. The status bar entry says what’s wrong:

Working on the extension:

cd extensions/vscode
npm install
npm run watch     # esbuild in watch mode, then F5 for an Extension Development Host
npm run check     # type-check
npm run package   # -> ../../dist/ccc-codecache.vsix

src/model.ts turns an /insights.json payload into hints without importing vscode, so it can be tested against a saved payload without an extension host.

Agents

The extension’s analyser runs on a free port so windows never clash. Each time it starts, it writes that port to .mcp.json (Claude Code) and .vscode/mcp.json (Copilot), so both find the server without being told. Both files are generated; keep them out of git. An agent session that was open when the analyser restarted still has the old port, so reload it.

Without the extension, register a ccc run yourself:

claude mcp add --transport http ccc http://127.0.0.1:6767/mcp
copilot mcp add --transport http ccc http://127.0.0.1:6767/mcp

Then add this block to an AGENTS.md at the repository root. Claude Code, Copilot, Cursor and other agents that read AGENTS.md pick it up at the start of every session:

# AGENTS.md

This repo has a Code Change Capture (ccc) map, served over MCP. Use it as the entry point for everything you do here.

- no bash, grep or sed usage for exploring the project
- Every interaction: use `ccc` tool calls to gather information about the source of this project.
- All thinking, navigation, and questions about the codebase go through the MCP server tools: (index, find, references, dependencies, vulnerabilities, deps, security, file, notes, changes, prompts, pr_summary, test_triggers, test_targets, lints, hot, services, search, violations, refresh)
- The web, internal docs and portals included, goes through `search`: `query` to search the configured endpoints, `url` to fetch one https page. Never WebFetch, WebSearch, another MCP server's fetch or browser tool, or `curl`/`wget` - ccc can't track those, and `violations` reports each one. If `search` refuses a URL, leave it unreached.
- ccc is the only writer: make every change through its edit tools - `edit_rename`, `edit_replace`, `edit_delete`, `edit_insert`, `edit_text` or `edit_move`, then `edit_apply` - never your own Edit/Write tools, `sed -i`, `mv` or shell redirection. `edit_discard` drops a staged changeset and `edit_revert` undoes an applied one.
- `edit_apply` rescans the map before it answers; call `refresh` only after a change made outside ccc.

With that in place, the agent’s answers come from ccc’s map, and every change goes back through ccc. That keeps each change inside the project, previewed before it is written, and revertible.


Replays

ccc can keep the story of a branch as a replay beside it, under refs/ccc/replay/<branch>: each ask, what the agent read and changed, and its narration. A reviewer can then play back how a change was made in the visualiser. A replay never lives in a branch’s files, so a merge can’t carry one into the default branch.

Turning recording on

Recording is opt-in, per repository: nothing is recorded or pushed until someone turns it on. Neither ccc run nor the VS Code extension asks, records or pushes anything by itself. Turn it on with ccc replay enable, or ccc: Session Recording… in VS Code. The answer is kept in git config ccc.replay, so both agree.

ccc replay enable     # record this repository's agent sessions
ccc replay disable    # stop; replays already saved stay where they are
ccc replay status     # whether recording is on, and who can read the remote

Once recording is on, the pre-push hook saves each branch’s replay as you push it. CLI.md has every replay command and option.

Keeping them private

A replay carries your prompts and the code each step touched. On a private repository, that’s ideal: everyone who can read the code can replay how it was written. On a public one, it’s a leak. So:

Team-encrypted replays

A team on runccc can encrypt every replay to its project’s key, so only the team can open one, wherever the repository lives, public remotes included. The project page gives the snippet for .ccc/map.json:

{ "replays": { "encrypt": { "project": "prj_some_random_key" } } }
ccc login     # sign in: approve the code in your browser
ccc whoami    # who you are, your teams, and the project this repository encrypts to
ccc logout    # revoke the token and forget it here

In VS Code there’s nothing to run. Turning recording on in a repository that encrypts its replays signs you in, opening the approval page in your browser. Team members must be in the same runccc team to view each other’s replays.

Each save fetches the project’s public key and encrypts every replay, so nothing in refs/ccc/ is readable in the clear. Where encrypt is set, a replay that can’t be encrypted isn’t saved. That happens when you’re not signed in, not on the team, or not on a paid plan, or when runccc is out of reach and no key was fetched in the last day. The push itself goes ahead, with a note explaining why the replay wasn’t saved.

A replay a teammate’s older ccc pushed in the clear is flagged by ccc replay status and the visualiser. It is encrypted, with its history started over, the next time its branch is pushed. Set service next to project, or RUNCCC_URL, to point ccc at another key service. The token and cached keys live in ~/.config/ccc/runccc/, readable only by you.

Secret warnings

The same scanner warns before a secret is committed or pushed, whether or not you record replays. It knows:

It checks every file, including .env, YAML and JSON as well as code. You’ll see the warning in several places:

A line meant to carry one, such as a test fixture, can say so with ccc:allow-secret. pragma: allowlist secret and gitleaks:allow are recognised too.

PROCEED WITH CAUTION - this will publish your agent conversations and/or transcriptions

DO NOT DO THIS: This makes your replays and transcriptions/conversations with the agent public. This causes an override of the default ccc behaviour (default behaviour prevents replays being pushed to public remotes). Adding the below snippet to .ccc/map.json will push replays and their transcriptions (including potentially sensitive content) to the public repo:

  // DO NOT DO THIS ON PUBLIC FACING REPOSITORIES
  { "replays": { "allow_public_remote": true } }