Claude Code logs each session as JSONL under ~/.claude/projects/, with input, output, cache-write, and cache-read token counts on every assistant turn. Codex does the same under ~/.codex/sessions/. The four counts price at different multipliers (cache reads at 0.1x base input, 5-minute cache writes at 1.25x, 1-hour writes at 2x), so summing them at one rate is the classic mistake. Five methods get you a number: /usage in-session, a status line, ccusage, OpenTelemetry export, and the vendor analytics APIs.
- Session history lives at
~/.claude/projects/for Claude Code and~/.codex/sessions/for Codex. Plain local files, not telemetry. - Each assistant turn records input, output, cache-write, and cache-read tokens separately. They price at different multipliers.
- Cache reads are 0.1x the base input rate. They usually dominate the token count and barely register on the bill.
- Deduplicate on message ID plus request ID or retried turns quietly inflate your totals.
- On a subscription the dollar figure is notional: it is what the work would have cost on the API, which is the number that tells you whether the plan is good value.
ccusageis the reference open-source CLI, and it now covers Codex and a dozen other agents, not just Claude.
Five ways to get a number
Pick by what you actually need. Most people want the third row and reach for the first two by accident.
Claude Code cost-tracking methods, August 2026.
| Method | Scope | Effort | Good for |
|---|---|---|---|
/usage in a session | This machine, current session plus plan bars | Zero | Am I about to get cut off, and what is eating the window |
| Custom status line | Live, continuous, current session | One shell script | Watching cost and context while you work |
ccusage | All local history, all providers | One npx command | Daily, weekly, monthly, per-session, per-window totals |
| OpenTelemetry export | Per user, near real time, any provider | A collector to run | Team dashboards across Bedrock, Vertex, or Foundry |
| Vendor analytics API | Per user, org-wide, authoritative | An admin key | Finance and per-seat reporting |
Where the data lives
Both major CLIs keep a full local transcript. This is not telemetry sent somewhere, it is a file on your machine.
# Claude Code: one directory per project, JSONL per session
ls ~/.claude/projects/
# -Users-you-code-myapp/ -Users-you-code-otherapp/
# Codex: flat directory of rollout files
ls ~/.codex/sessions/
# How much history have you accumulated?
du -sh ~/.claude/projects ~/.codex/sessions
# A second Claude account lives wherever CLAUDE_CONFIG_DIR pointed
ls "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/projects"
One more trap worth knowing before you write anything: if you run a second Claude account under its own CLAUDE_CONFIG_DIR, its history is not under ~/.claude. Any tool that hardcodes the default path silently under-reports your real spend by whatever the second account did.
Reading the token counts
Every assistant message in the JSONL carries a usage object. The four counts bill at different multipliers, so summing them into one number gives you a wrong answer, usually by an order of magnitude.
{
"type": "assistant",
"message": {
"id": "msg_01ABC...",
"model": "claude-sonnet-5",
"usage": {
"input_tokens": 1204,
"output_tokens": 892,
"cache_creation_input_tokens": 18340,
"cache_read_input_tokens": 96210
}
},
"requestId": "req_01XYZ..."
}
Multipliers relative to the model's base input rate, from the Claude platform pricing page, checked 7 August 2026.
| Count | What it is | Multiplier |
|---|---|---|
input_tokens | Fresh prompt tokens | 1x base input |
output_tokens | What the model generated | Base output rate, typically 5x input |
cache_creation_input_tokens | Tokens written into the prompt cache | 1.25x for a 5-minute cache, 2x for a 1-hour cache |
cache_read_input_tokens | Tokens served from cache | 0.1x base input |
The JSONL does not tell you which cache duration was used, so a parser has to pick a convention. Most tools assume the 5-minute write at 1.25x, which is right for interactive sessions on the default. If you set 1-hour caching deliberately, your real cost is higher than any generic tool will report.
A working calculation
Here is a minimal version that gets the shape right. It is not production quality, but it produces a defensible number in a few seconds.
Group the raw counts by model
cat ~/.claude/projects/*/*.jsonl \
| jq -s '
map(select(.type == "assistant" and .message.usage))
| unique_by(.message.id + ":" + (.requestId // ""))
| map({
model: .message.model,
i: .message.usage.input_tokens,
o: .message.usage.output_tokens,
cw: (.message.usage.cache_creation_input_tokens // 0),
cr: (.message.usage.cache_read_input_tokens // 0)
})
| group_by(.model)
| map({
model: .[0].model,
input: (map(.i) | add),
output: (map(.o) | add),
cacheW: (map(.cw) | add),
cacheR: (map(.cr) | add)
})
'
Apply the per-bucket rates
As of August 2026: Opus 5 is $5 per million input and $25 output, Sonnet 5 is $2 and $10 on introductory pricing through 31 August 2026 (then $3 and $15), Haiku 4.5 is $1 and $5. Cache writes are 1.25x input, cache reads 0.1x input.
cost = (input * in_rate
+ output * out_rate
+ cacheW * in_rate * 1.25
+ cacheR * in_rate * 0.10) / 1e6
Price each event at its own timestamp
Rates change. Sonnet 5 alone moves on 1 September 2026. If you reprice your whole history at today's rate, every historical total silently shifts. Serious tools keep dated rate windows and resolve each event against the rate that was live when it happened.
The deduplication trap
Retried and streamed turns can appear more than once in the transcript. Deduplicate on message ID plus request ID before summing, or your totals drift upward over time in a way that is very hard to notice, because nothing ever looks obviously wrong.
cat ~/.claude/projects/*/*.jsonl \
| jq -s 'map(select(.message.usage))
| { raw: length,
deduped: (unique_by(.message.id + ":" + (.requestId // "")) | length) }'
Using ccusage
You do not have to write this yourself. ccusage by ryoppippi is the established open-source tool for exactly this. It handles the path encoding, the dedup, and the pricing table, and it now reports across a long list of agent CLIs, not only Claude.
npx ccusage@latest daily # spend per day
npx ccusage@latest weekly # roll up by week
npx ccusage@latest monthly # roll up by month
npx ccusage@latest session # per session
npx ccusage@latest blocks # by 5-hour billing window
# Per-source reports: codex, opencode, gemini, copilot and more
npx ccusage@latest codex daily
When you need per-user numbers instead
Local parsing answers "what did this machine do". For a team you need attribution, and there are three official routes depending on how you buy Claude Code.
| Your setup | Per-user reporting |
|---|---|
| Claude for Teams | Spend report CSV in org analytics, updated daily |
| Claude for Enterprise | Enterprise Analytics API, with a read:analytics key |
| Claude Console (API) | Console dashboard plus the Claude Code Analytics API, with an Admin API key |
| Bedrock, Google Cloud, or Microsoft Foundry | OpenTelemetry export, or a gateway that tracks spend per key |
OpenTelemetry is the only option that works on every setup and streams per-user token and cost metrics into your own stack in near real time.
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_METRIC_EXPORT_INTERVAL=60000 # ms, this is the default
The metrics it emits are claude_code.session.count, claude_code.token.usage, claude_code.cost.usage, claude_code.lines_of_code.count, claude_code.commit.count, claude_code.pull_request.count, claude_code.code_edit_tool.decision, and claude_code.active_time.total. Cost is in USD; tokens are counted per type.
What the number means on a subscription
If you are on Pro, Max, or a Team seat, you are not billed per token, so a dollar figure derived from API rates is not an invoice. It is still the most useful number you can compute, for three reasons.
- It tells you whether your plan is good value. If a $100 Max 5x plan does $600 of notional API work a month, that is a clear answer. Anthropic's own published average is around $13 per developer per active day on metered billing, so a full-time month lands around $150 to $250.
- It attributes consumption. "This one repo is 70% of my usage" is actionable in a way that "I hit my limit again" is not.
- It prices habits. Seeing that running full test suites through the agent costs more than the rest of the session combined changes the habit within a day.
Common mistakes
| Mistake | Effect | Fix |
|---|---|---|
| Summing all four token counts at one rate | Wildly overstated cost | Price each bucket at its own multiplier |
| Skipping deduplication | Slow upward drift nobody notices | Unique on message ID plus request ID |
| Using today's rates for old sessions | Whole history shifts after a repricing | Price each event at its own timestamp |
| Bucketing by UTC day | Totals disagree with your calendar near midnight | Bucket by local calendar day, as ccusage does |
| Ignoring the newest file | Missing the session you are in right now | Always re-read the most recently modified file |
Reading only ~/.claude | A second account's spend vanishes | Also read every CLAUDE_CONFIG_DIR you use |
Trusting /usage as a bill | Off by any discount you negotiated | Use the Console usage page for authoritative billing |
Questions people ask
In ~/.claude/projects/, one directory per project with JSONL files per session. Codex uses ~/.codex/sessions/. Both are plain local files you can read. A second account under CLAUDE_CONFIG_DIR keeps its own projects directory under that root.
Yes, but with caveats. /usage shows a session cost computed locally at standard list rates, so it ignores promotional pricing and contracted discounts. On a subscription it is a measurement, not a bill. cost.total_cost_usd in the status line JSON is the same figure.
An open-source CLI by ryoppippi that parses local agent session history and reports token usage and cost by day, week, month, session, or 5-hour billing window. It covers Claude Code, Codex, opencode, Gemini, Copilot and more, and is the de facto reference implementation.
Cache reads. In a long agent session they dominate the raw count and bill at 0.1x the base input rate. A session showing a million tokens of traffic can still cost under a dollar.
It is notional: what the same work would have cost on the API. That is exactly the number that tells you whether your subscription is good value and which project is consuming it.
Yes. Codex writes equivalent rollout files to ~/.codex/sessions/ with token counts, so the same approach works, and ccusage codex daily does it for you. The record shapes differ, so a homemade parser needs a branch per provider.
On Teams, export the spend report CSV from org analytics. On Enterprise, use the Enterprise Analytics API. On the Console, use the Claude Code Analytics API with an Admin key. On Bedrock, Google Cloud, or Foundry, export OpenTelemetry metrics, which is the only route that works everywhere.
1.25x the base input rate for a 5-minute cache write and 2x for a 1-hour write. The JSONL does not record which duration was used, so most tools assume 5 minutes, which is right for default interactive sessions.
Sources
Every figure above was read from these pages on August 2026. Vendors reprice without notice; if you find a stale number, tell us.
- ccusage reference implementation for parsing session history
- Claude platform pricing token rates and cache multipliers
- Claude Code: manage costs effectively /usage, per-user reporting routes
- Claude Code: monitoring usage OpenTelemetry metric names and env vars