Per-project token, cost, and time analysis of Claude Code session logs. Zero dependencies — reads ~/.claude/projects in place.
npx ccspan # run without installing
npm install -g ccspan # or install globallyRequires Node.js ≥ 18.
On a real terminal, ccspan launches a full-screen interactive app:
ccspan # project list → Enter opens its timeline tree
ccspan <project-name> # jump straight into a project's timelineIt's a unified app: a project list, then a collapsible timeline tree per project. Keys:
| Key | Action |
|---|---|
↑/↓ or j/k |
Move |
Enter / → / Space |
Open project · expand agent |
← / h |
Collapse · go back |
Esc |
Back to the project list |
q / Ctrl-C |
Quit |
Sub-agent trees start collapsed (▸); expand the ones you care about (▾).
When the output is piped, or you pass --json or --plain, you get the text
report instead — so ccspan <project> --plain --timeline | less and
ccspan --json still work for scripting.
# Picker — show all projects, newest first
ccspan --plain [--all]
# Single project — tokens, cost, duration, per-day table
ccspan <project-name> --plain
# With flags
ccspan <project-name> --plain --sessions # add top sessions table
ccspan <project-name> --plain --timeline # add prompt-cascade timeline
ccspan <project-name> --json # machine-readable JSON
# Date filters
ccspan <project-name> --from 2026-06-01 --to 2026-06-30
# Skip cost lookup (faster; no CodeBurn required)
ccspan --no-cost
ccspan <project-name> --no-cost
# Tune idle gap (default 300s)
ccspan <project-name> --idle 120Flags:
| Flag | Description |
|---|---|
--from YYYY-MM-DD |
Only include sessions on or after this UTC date |
--to YYYY-MM-DD |
Only include sessions on or before this UTC date |
--idle <sec> |
Gap threshold between active/idle (default: 300) |
--sessions |
Show top sessions by cost and compute time |
--timeline |
Show per-day prompt-cascade timeline |
--all |
Show all projects in picker (default: top 20) |
--json |
Emit JSON instead of formatted output |
--plain |
Force the text report instead of the interactive TUI |
--no-cost |
Skip CodeBurn cost lookup |
-v, --version |
Print version |
CLAUDE CODE SESSIONS · 18 projects · tokens+duration from logs, cost from CodeBurn
# project last active sess cost active
1 ccspan 2026-06-26 1 n/a 50m
2 Medgneering.AgenticPlatform 2026-06-26 24 n/a 7h15m
3 spine 2026-06-26 52 n/a 11h35m
4 Medgneering.Portal 2026-06-26 1 n/a 30m
5 coolify 2026-06-25 6 n/a 8h01m
6 dayofai 2026-06-25 3 n/a 2h40m
...
18 total. Run `ccspan <name>` to analyze a project.
ccspan · /Users/username/Developer/refo/tmp/ccspan
1 sessions · cost: CodeBurn (LiteLLM pricing)
TOKENS
input 31.4k
output 116.9k
cache-create 187.3k
cache-read 8.98M
─────────────────────
total 9.32M
COST
n/a (codeburn unavailable — run: npm i -g codeburn)
DURATION
wall 2h35m calendar span across sessions
active 50m at-keyboard time (gaps within idle)
compute 12m measured engine time
idle 1h44m waiting / away
PER DAY
date input output cache-cr cache-rd cost compute
2026-06-26 31.4k 116.9k 187.3k 8.98M n/a 12m
tip: --timeline for the per-day agent cascade · --sessions for top sessions
(Token totals are de-duplicated by (message.id, requestId), the same way
ccusage counts, so replayed usage from resumed sessions is not double-counted.)
The timeline is a prompt cascade: each ▸ row is a user prompt (slash
commands shown as /cmd), and the sub-agents it spawned are drawn as a tree
beneath it. Sub-agents that spawn their own sub-agents are nested recursively
(read from each agent's transcript under <session>/subagents/), so a deep flow
like /integrate shows its full tree. Each agent is labeled with the Agent
tool's description; duration and tokens align in a right-hand gutter so you can
scan a column. Session markers (/clear, caveats) collapse to one dim line.
AgenticPlatform — TIMELINE
2026-06-23 16h28m 537.7M tok
· 3 session markers (/clear, <local-command-ca…, …)
▸ Base directory for this skill: ~/Developer… 16h30m 45.8k tok
Bash ×11
├─ general-purpose Integrate plan gw 2h03m 177.1k tok
│ ├─ maestro:developer GW Wave 1: seam + host… 9m 69.9k tok
│ ├─ maestro:developer GW Wave 2: errors, auth… 35m 201.4k tok
│ ├─ maestro:reviewer Review GW sprint diff 5m 114.0k tok
│ └─ maestro:security Security scan GW sprint 4m 66.4k tok
└─ general-purpose Integrate plan platform 3h09m 162.2k tok
The --json output carries the same tree under each timeline group's agents[],
nested recursively, with both description and promptHead per agent.
Tokens are summed from every model call in ~/.claude/projects/ — including
sub-agent transcripts (<session>/subagents/), so token totals account for work
done inside sub-agents, not just the main thread. Duplicate usage records
(replayed when a session is resumed) are de-duplicated by (message.id, requestId), the same way ccusage counts.
Duration is read from the main-thread events only (sub-agents run concurrently, so counting their wall time would double-count). Three metrics:
- wall — total elapsed calendar time across all events (includes idle gaps)
- active — time within the configured idle threshold (default 5 min); approximates at-keyboard time
- compute — sum of
turn_durationmeasurements from Claude Code's engine; the most precise measure of actual LLM compute
There is intentionally no $/hr metric: wall time is a poor proxy for productivity, and mixing compute time with total cost would produce misleading numbers.
Cost requires CodeBurn (npm i -g codeburn). When unavailable, tokens and duration are still shown. Set --no-cost or CCSPAN_NO_COST=1 to skip the cost lookup entirely.
Project matching — the project argument is a case-insensitive substring match on your project paths. If multiple paths match, ccspan lists them and asks you to be more specific.
All data stays local. ccspan reads ~/.claude/projects/*.jsonl in place and never writes, copies, or transmits anything.