Guide
Tracking Claude Code costs, honestly
Everything you need is already in the session logs. Most of the wrong numbers people quote come from two specific counting mistakes.
Where the numbers live
Claude Code doesn’t report spend, but it records the raw material: every assistant record in
~/.claude/projects/…/*.jsonl carries a usage object — input tokens,
output tokens, and the cache traffic (cache_read_input_tokens,
cache_creation_input_tokens). What the logs do not contain is a price.
Anything that turns tokens into dollars multiplies by a rate table it brought along — which is why
every honest tool labels its output an estimate, and why numbers differ slightly between
tools and your invoice. (Subscription users have no marginal invoice at all; the estimate then
answers “what would this have cost on the API,” which is still the useful comparison
number.)
Trap one: the repeated usage object
One API response is written as several JSONL lines — one per content block — and each line
repeats the same message.id with an identical usage object. Sum
naively and you overcount by whatever the average block count is. This isn’t hypothetical:
an early Turnlog release summed per line, ran roughly 2.7× hot, and shipped
the correction as its 0.2.0 headline fix — count once
per message.id, and existing indexes rebuilt themselves. If your homegrown script has
never been checked for this, check it today.
Two smaller honesty rules that follow from the same logs:
- Cache tokens have their own prices. Cache reads bill at a fraction of the input rate and cache writes at a premium that depends on TTL. A heavy Claude Code session is mostly cache reads — price them as input and you overstate; drop them and you understate.
- Resumed sessions duplicate history. A resume copies the whole conversation into a new file. Aggregate per file and a three-part conversation’s shared prefix bills three times — count each message once per conversation, on the day it actually ran.
Trap two: Codex’s cumulative counters
Running Codex CLI too? Its rollouts under ~/.codex/sessions/ log
token_count events that carry both a running cumulative total for the session
and last_token_usage for just-finished response. Sum the cumulative field
across rows — the natural first attempt — and long sessions explode quadratically. Sum
last_token_usage only, and remember OpenAI’s input_tokens includes
the cached share. Details on both formats are in
the JSONL guide.
For usage reports: use ccusage
If what you want is usage reporting — daily and monthly rollups, per-model splits, billing-window views, a wide set of supported agents — ccusage is the standard and this page happily sends you there. It parses the same local logs, it’s fast, and it exports JSON. Turnlog doesn’t replace it and doesn’t try.
The question dashboards can’t answer
Every usage tool slices spend by time, model, and project — dimensions that sit in each record’s metadata. The question they structurally cannot answer is about content: “what has the websocket work cost me?” “What do I spend on CI babysitting?” Answering that means finding the sessions whose text matches, then pricing exactly those — a full-text index problem wearing a cost-report costume.
npx turnlog demo.)The indexed way
Turnlog prices the work, not just the days
Turnlog is a free, MIT-licensed CLI that indexes the content
of your Claude Code and Codex history locally — with usage counted once per response, resumes
billed once, cache traffic priced by its own rates, and every figure labeled the estimate it is.
The spend screen takes the full search language, so reconnect,
tool:Bash, or agent:codex each become a costed slice of your actual
work. All on your machine; nothing leaves it.
Related: the format and its traps · searching your history · how the tools compare