Itemized cost breakdown for your Claude Code sessions. Reads local logs, no network, no config
TypeScript
9
18 commits
updated Oct 17, 2026
Where did my AI budget go?
Claude Code sessions cost real money and you get zero visibility into why.
tokenbill reads the session logs already on your disk and gives you the bill,
itemized. No network calls, no config, no account.
$ npx tokenbill
tokenbill - session 1d6eedb6 · 29m · claude-fable-5
TOTAL ESTIMATED COST $32.25
Where it went
──────────────────────────────────────────────────────────────────
System prompt & overhead ████████████████░░░░░░░░ 65% $21.04
Context compaction █████░░░░░░░░░░░░░░░░░░░ 20% $6.29
Model generation (output tokens) ██░░░░░░░░░░░░░░░░░░░░░░ 9% $3.04
Cache writes (premium) █░░░░░░░░░░░░░░░░░░░░░░░ 5% $1.66
──────────────────────────────────────────────────────────────────
Cache efficiency
──────────────────────────────────────────────────────────────────
Cache hit rate: 98% · saved ≈ $191 vs. uncached
Wasted on cache re-writes after prefix breaks: $3.14 (1 rebuild)
──────────────────────────────────────────────────────────────────
Recommendations
──────────────────────────────────────────────────────────────────
⚠ 1 cache prefix break cost you ≈ $3.14
→ usually mid-session config or system prompt changes; keep the prompt prefix stable
✓ cache hit rate 98% - healthy
Potential savings this project: ≈ $3.14
──────────────────────────────────────────────────────────────────
(Real output from a real session - yes, that half-hour cost $32 in API-equivalent terms, and $21 of it was re-reading the system prompt from cache on every request.)
cd your-project && npx tokenbill # every Claude Code session of this project, aggregated
npx tokenbill <project-dir> # same, for any project (source dir or log dir both work)
npx tokenbill <session.jsonl> # deep-dive report for one specific session
Run it from a project directory and you get the full bill for that project - per-session totals, combined categories, and the most expensive moments across all sessions. Run it anywhere else and it falls back to your most recent session. Zero configuration either way.
Options:
--json machine-readable output (schemaVersion 2)
--html [file] shareable single-file HTML report (default: tokenbill-report.html)
--md [file] GitHub Markdown report to stdout or a .md file (PR comments, job summaries)
--top <n> number of expensive turns to show (default 10)
--budget <usd> exit 2 if the total exceeds this amount (for CI)
--pricing <file> override the built-in price table with your own JSON
--no-color disable colored output (NO_COLOR env also respected)
tokenbill statusline reads the JSON Claude Code pipes to status line commands
and prints one line: this session's cost, today's spend across the project,
cache hit rate, and a warning when a cache prefix break cost you money.
tokenbill $4.12 · today $18.30 · cache 97% · ⚠ 1 prefix break ($3.14)
Install it globally (npx would add its startup time to every refresh), then
point ~/.claude/settings.json at it:
npm i -g tokenbill
{ "statusLine": { "type": "command", "command": "tokenbill statusline" } }
It only parses session files modified today, writes nothing to disk, and never
fails loudly: on any error it prints tokenbill - and exits 0.
--budget still prints the full report, then exits 2 if you're over.
Exit codes: 0 ok, 1 error, 2 budget exceeded.
CI runners have no ~/.claude, so point tokenbill at logs you commit to the
repo or download as an artifact. The bundled action writes the Markdown report
to the job summary and applies the guard:
- uses: emrehangorgec/[email protected]
with:
path: .agent-logs # a Claude Code log dir or a single .jsonl
budget: 25 # optional: fail the job above $25
Or call the CLI directly:
- run: npx tokenbill .agent-logs --md >> "$GITHUB_STEP_SUMMARY"
- run: npx tokenbill .agent-logs --budget 25
npx tokenbill --all
npx tokenbill --all --html all-projects.html
npx tokenbill --all --json
npx tokenbill --all --budget 100
--all combines every session under ~/.claude/projects into one report:
total estimated cost, per-session totals, model breakdown, daily spend trend,
and the most expensive turns across projects. Subagent logs are included through
their parent session, so they are not counted again as separate sessions.
Markdown output and the budget guard work too. The budget applies to the entire
recorded history, not a monthly allowance. You cannot combine --all with a
session or project path.
--md renders the same report as GitHub tables for PR comments and job summaries.--html writes the whole report as one self-contained dark-theme HTML file (no external requests, sortable turn table) you can open, screenshot, or send to your team.asOf date (printed in every report footer) and is refreshed with npm run pricing:sync - see CONTRIBUTING.md. Rates have effective dates, so a session is priced at the rate it was actually billed at - including promotional windows like Sonnet 5's introductory $2/$10. --pricing still overrides everything without waiting for a release.~unknown model, sonnet rates).usage.speed) is priced at its premium and the batch service tier at its discount. Priority tier is billed as standard - if you use it, the total is understated.tokenbill never makes a network call. It reads local files and prints text. The test fixtures in this repo are anonymized (same-length placeholder text; structure, token counts and tool names preserved) via scripts/anonymize.ts.
That holds even for pricing: scripts/sync-pricing.ts is run manually to refresh the table, and its output is committed as source. The published package contains dist only, so there is no fetch path at runtime, no cache directory, and nothing to opt out of.
Claude Code today. The parser is an adapter interface (src/adapters/) - Codex/Cursor/Aider adapters are welcome contributions.
npm install
npm test # vitest: unit + golden-file snapshot tests
npm run build # tsc → dist/
npm run dev # tsx src/cli.ts
npm run demo # regenerate assets/demo.svg from fixtures/basic.jsonl
npm run pricing:sync # refresh the price table from upstream (the only network call)
npm run pricing:audit # validate the shipped table offline
Type-checking is three projects, and CI runs all three - tsx and vitest both
transpile without checking, so the scripts and the test suite are only covered by
their own configs:
npx tsc --noEmit # src/ (the build project)
npx tsc --noEmit -p scripts/tsconfig.json # dev scripts
npx tsc --noEmit -p test/tsconfig.json # test suite
See CONTRIBUTING.md before touching prices -
src/cost/prices.generated.ts is generated, and hand-curated facts belong in
src/cost/pricing.overrides.json. CONTRIBUTING.md also covers
adapter contributions.
Licensed under the MIT License.
Itemized cost breakdown for your Claude Code sessions. Reads local logs, no network, no config
TypeScript
9
18 commits
updated Oct 17, 2026
Where did my AI budget go?
Claude Code sessions cost real money and you get zero visibility into why.
tokenbill reads the session logs already on your disk and gives you the bill,
itemized. No network calls, no config, no account.
$ npx tokenbill
tokenbill - session 1d6eedb6 · 29m · claude-fable-5
TOTAL ESTIMATED COST $32.25
Where it went
──────────────────────────────────────────────────────────────────
System prompt & overhead ████████████████░░░░░░░░ 65% $21.04
Context compaction █████░░░░░░░░░░░░░░░░░░░ 20% $6.29
Model generation (output tokens) ██░░░░░░░░░░░░░░░░░░░░░░ 9% $3.04
Cache writes (premium) █░░░░░░░░░░░░░░░░░░░░░░░ 5% $1.66
──────────────────────────────────────────────────────────────────
Cache efficiency
──────────────────────────────────────────────────────────────────
Cache hit rate: 98% · saved ≈ $191 vs. uncached
Wasted on cache re-writes after prefix breaks: $3.14 (1 rebuild)
──────────────────────────────────────────────────────────────────
Recommendations
──────────────────────────────────────────────────────────────────
⚠ 1 cache prefix break cost you ≈ $3.14
→ usually mid-session config or system prompt changes; keep the prompt prefix stable
✓ cache hit rate 98% - healthy
Potential savings this project: ≈ $3.14
──────────────────────────────────────────────────────────────────
(Real output from a real session - yes, that half-hour cost $32 in API-equivalent terms, and $21 of it was re-reading the system prompt from cache on every request.)
cd your-project && npx tokenbill # every Claude Code session of this project, aggregated
npx tokenbill <project-dir> # same, for any project (source dir or log dir both work)
npx tokenbill <session.jsonl> # deep-dive report for one specific session
Run it from a project directory and you get the full bill for that project - per-session totals, combined categories, and the most expensive moments across all sessions. Run it anywhere else and it falls back to your most recent session. Zero configuration either way.
Options:
--json machine-readable output (schemaVersion 2)
--html [file] shareable single-file HTML report (default: tokenbill-report.html)
--md [file] GitHub Markdown report to stdout or a .md file (PR comments, job summaries)
--top <n> number of expensive turns to show (default 10)
--budget <usd> exit 2 if the total exceeds this amount (for CI)
--pricing <file> override the built-in price table with your own JSON
--no-color disable colored output (NO_COLOR env also respected)
tokenbill statusline reads the JSON Claude Code pipes to status line commands
and prints one line: this session's cost, today's spend across the project,
cache hit rate, and a warning when a cache prefix break cost you money.
tokenbill $4.12 · today $18.30 · cache 97% · ⚠ 1 prefix break ($3.14)
Install it globally (npx would add its startup time to every refresh), then
point ~/.claude/settings.json at it:
npm i -g tokenbill
{ "statusLine": { "type": "command", "command": "tokenbill statusline" } }
It only parses session files modified today, writes nothing to disk, and never
fails loudly: on any error it prints tokenbill - and exits 0.
--budget still prints the full report, then exits 2 if you're over.
Exit codes: 0 ok, 1 error, 2 budget exceeded.
CI runners have no ~/.claude, so point tokenbill at logs you commit to the
repo or download as an artifact. The bundled action writes the Markdown report
to the job summary and applies the guard:
- uses: emrehangorgec/[email protected]
with:
path: .agent-logs # a Claude Code log dir or a single .jsonl
budget: 25 # optional: fail the job above $25
Or call the CLI directly:
- run: npx tokenbill .agent-logs --md >> "$GITHUB_STEP_SUMMARY"
- run: npx tokenbill .agent-logs --budget 25
npx tokenbill --all
npx tokenbill --all --html all-projects.html
npx tokenbill --all --json
npx tokenbill --all --budget 100
--all combines every session under ~/.claude/projects into one report:
total estimated cost, per-session totals, model breakdown, daily spend trend,
and the most expensive turns across projects. Subagent logs are included through
their parent session, so they are not counted again as separate sessions.
Markdown output and the budget guard work too. The budget applies to the entire
recorded history, not a monthly allowance. You cannot combine --all with a
session or project path.
--md renders the same report as GitHub tables for PR comments and job summaries.--html writes the whole report as one self-contained dark-theme HTML file (no external requests, sortable turn table) you can open, screenshot, or send to your team.asOf date (printed in every report footer) and is refreshed with npm run pricing:sync - see CONTRIBUTING.md. Rates have effective dates, so a session is priced at the rate it was actually billed at - including promotional windows like Sonnet 5's introductory $2/$10. --pricing still overrides everything without waiting for a release.~unknown model, sonnet rates).usage.speed) is priced at its premium and the batch service tier at its discount. Priority tier is billed as standard - if you use it, the total is understated.tokenbill never makes a network call. It reads local files and prints text. The test fixtures in this repo are anonymized (same-length placeholder text; structure, token counts and tool names preserved) via scripts/anonymize.ts.
That holds even for pricing: scripts/sync-pricing.ts is run manually to refresh the table, and its output is committed as source. The published package contains dist only, so there is no fetch path at runtime, no cache directory, and nothing to opt out of.
Claude Code today. The parser is an adapter interface (src/adapters/) - Codex/Cursor/Aider adapters are welcome contributions.
npm install
npm test # vitest: unit + golden-file snapshot tests
npm run build # tsc → dist/
npm run dev # tsx src/cli.ts
npm run demo # regenerate assets/demo.svg from fixtures/basic.jsonl
npm run pricing:sync # refresh the price table from upstream (the only network call)
npm run pricing:audit # validate the shipped table offline
Type-checking is three projects, and CI runs all three - tsx and vitest both
transpile without checking, so the scripts and the test suite are only covered by
their own configs:
npx tsc --noEmit # src/ (the build project)
npx tsc --noEmit -p scripts/tsconfig.json # dev scripts
npx tsc --noEmit -p test/tsconfig.json # test suite
See CONTRIBUTING.md before touching prices -
src/cost/prices.generated.ts is generated, and hand-curated facts belong in
src/cost/pricing.overrides.json. CONTRIBUTING.md also covers
adapter contributions.
Licensed under the MIT License.