cctop
An htop-like monitor for AI coding agent sessions. Tracks Claude Code, Codex, OpenCode, and Pi sessions on your machine: cost estimation, token usage, tool invocations, subagents, and OS-level process metrics — refreshed live.
A Rust rewrite of an earlier Node implementation.
Install
Download a binary
Grab the archive for your platform from the
latest release and put
cctop somewhere on your PATH:
# Linux x86_64 (static — works on any distro)
|
# macOS (Apple silicon; use x86_64-apple-darwin on Intel)
|
On Windows, download cctop-x86_64-pc-windows-msvc.zip and extract cctop.exe.
Every archive ships with a .sha256 file next to it:
macOS will quarantine an unsigned download. If Gatekeeper blocks it:
With cargo
Or straight from the repository, without waiting for a release:
From source
The binary lands at target/release/cctop. It links no system libraries and
needs no runtime — a single file you can copy anywhere.
Building requires Rust 1.88 or newer (the code uses let-chains).
Usage
Keys
| Key | Action |
|---|---|
↑/k, ↓/j |
Move between sessions |
←, → |
Move between bottom panels |
1–7 |
Jump to a panel directly |
Shift+↑/↓ |
Scroll inside the active panel |
/ or F3 |
Filter sessions by text |
F6, >, < |
Sort-by panel |
F7 |
Filter by age (1d / 1w / 1mo) |
` |
Show only running sessions |
[, ] |
Move through the Tool Activity tool filter |
v |
Toggle inline diffs for edits |
L |
Toggle the Tool Activity live filter |
P / M / T |
Sort by status / memory / cost |
y |
Copy resume command or transcript path |
d |
Delete the selected session (not running) |
Esc |
Clear the active filter |
q or F10 |
Quit |
Mouse works too: click session rows, column headers, and panel tabs; scroll anywhere. In Tool Activity, click any row to expand the full untruncated argument, and click the sidebar to filter by tool.
Where data comes from
| Source | Path |
|---|---|
| Claude Code (CLI) | ~/.claude/projects/<slug>/<uuid>.jsonl |
| Claude for Mac | ~/Library/Application Support/Claude/{claude-code,local-agent-mode}-sessions/ |
| Codex | ~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl |
| OpenCode | ~/.local/share/opencode/opencode*.db (platform data directory) |
| Pi | ~/.pi/agent/sessions/**/*.jsonl |
CLAUDE_CONFIG_DIR, CODEX_HOME, OPENCODE_DATA_DIR,
PI_CODING_AGENT_DIR, and PI_CODING_AGENT_SESSION_DIR are honoured. Caches
live in ~/.cache/cctop/.
A note on cost figures
Claude and Codex costs are estimates: tokens multiplied by published per-token rates, taken from built-in tables and falling back to the LiteLLM database (cached for 24 hours). OpenCode and Pi already persist provider-calculated costs, which cctop reads directly.
Subscription plans — Claude Max, Pro, Team — are flat-rate or bundle tokens
differently, so these numbers will not match your invoice. Treat the $ column
as a measure of resource consumption, not as billing. Use --plan max or
--plan included to display bundled usage as incl instead.
Tool Activity columns
Each invocation shows the time, its arguments, and — where the transcript supports it — what it did:
19:16 main ~/cctop/src/ui/render.rs +43 -24 122ms ↓498.5K ↑ 1.2K
19:34 ↳aa1b82 ~/cctop/src/quota.rs +2 -0 88ms ↓ 41.2K ↑ 310
- origin —
mainfor the session itself, or↳<agent-id>for a subagent. Subagent activity is interleaved into the same log, so without this there's no way to tell an agent's edits from the parent's. +N -M— lines added and removed, from the edit result's patch. Pressvto expand the diff inline beneath the row.- duration — wall time from the call being issued to its result arriving.
↓/↑— tokens in and out for the assistant turn that issued the call. Claude only; Codex transcripts don't tie token counts to individual calls.
That last one deserves a caveat: billing is per API request, not per tool
call. When one turn issues several calls they all show that turn's figures,
marked with a leading *. Dividing the total between them would invent
precision the transcript doesn't contain. ↓ includes cache reads, which is why
it tracks total context size rather than the size of any one call.
Codex tools are decoded too: apply_patch shows the files it touched and its
line counts, update_plan shows progress and the step in flight, and
write_stdin distinguishes a real write from a poll for more output.
Design notes
A few things that are less obvious from the code:
- Token dedup. Streaming writes the same
requestIdrepeatedly with growing counts. Only the last entry per request is counted; summing them all inflates totals several-fold. - Cache keys carry a pricing generation. Cached entries hold computed
costs, so a refreshed rate table must invalidate them just as an appended
transcript does. Without this, sessions priced before the table loaded report
$0.00forever — their transcripts never change again. - Threads are excluded from process matching. Threads share their process's command line, so every one of them matches the same session and competes to be picked as the root — nondeterministically. The winner reports its own CPU and no children.
- Tail reads. Context usage and last-tool come from seeking backwards from EOF, so a live 50 MB transcript costs one 64 KB read per refresh, not a reparse.
- Ghost subagents. Claude Code purges old subagent transcripts but keeps the
tool_use/tool_resultpair in the parent. Those rows are reconstructed and marked◌, with—rather than0for figures that can no longer be measured.
Development