Compare what your Claude Code subscription costs against what the same token usage would have cost at API rates.
Claude Code prunes its local transcripts after roughly 30 days. This tool ingests those transcripts into SQLite before they disappear, prices every assistant response at per-model API rates, and shows the result next to your plan price — so "is the subscription worth it?" becomes a number instead of a guess.
Screenshot rendered from synthetic sample data, not real usage.
- Ingests token usage from Claude Code (
~/.claude/projects) and omp (~/.omp/agent/sessions) JSONL transcripts. - Deduplicates on
(message_id, request_id). This matters: resumed and forked sessions rewrite earlier history into new transcript files, so a naive scan roughly doubles every total. - Prices input, output, cache reads, 5-minute and 1-hour cache writes, and
server-tool (web search) requests separately, using
Decimalthroughout. - Compares the API-equivalent total against your plan price, with a 30-day projection derived from the days actually covered by data.
- Lets you edit every rate in the browser — models, date windows, multipliers, server-tool prices, and plan prices — with a one-click reset back to the shipped defaults.
With devbox:
devbox run setup # uv venv + editable install with dev extras
devbox run ingest # scan transcripts into SQLite
devbox run serve # dashboard on http://127.0.0.1:8420
devbox run testWith uv directly:
uv venv
uv pip install -e '.[dev]'
uv run python -m claude_spend.ingest
uv run uvicorn claude_spend.app:app --reload --port 8420
uv run pytest -qRequires Python 3.12+. Ingest is idempotent — run it as often as you like. You can also trigger it from the dashboard's ingest button instead of the CLI.
| Variable | Default | Purpose |
|---|---|---|
CLAUDE_SPEND_DB |
~/.claude-spend-tracker/spend.db |
Usage database location |
CLAUDE_PROJECTS_DIR |
~/.claude/projects |
Claude Code transcript root |
OMP_SESSIONS_DIR |
~/.omp/agent/sessions |
omp session root |
The database deliberately defaults to a user data directory outside the
repository, so deleting or git cleaning the checkout never takes your usage
history with it.
Rates are date-windowed, not a flat per-model number. Each rate row has an
optional effective_from and effective_until; either may be open (NULL),
meaning unbounded on that side. A model whose price changed is therefore
represented as two adjacent rows that tile the timeline with no gap and no
overlap:
| model | from | until | input | output |
|---|---|---|---|---|
claude-sonnet-5 |
open | 2026-08-31 | 2.00 | 10.00 |
claude-sonnet-5 |
2026-09-01 | open | 3.00 | 15.00 |
Each row is priced by the window containing its own usage date, so historical
usage keeps its historical price when a rate changes. Overlapping windows and
from > until are rejected when saving.
Multipliers apply to a model's input rate: cache reads at 0.10x, 5-minute
cache writes at 1.25x, 1-hour cache writes at 2.00x. Web search is billed
per request. Plans default to Pro $20, Max 5x $100, Max 20x $200.
A model with usage but no matching rate is reported as unpriced rather than
silently costed at $0 — a missing rate should be loud, not a quiet
underestimate.
The shipped default rates are a starting point, not authoritative. Check
them against Anthropic's published pricing and edit them on the /rates page
to match what you are actually billed.
| Route | Purpose |
|---|---|
GET / |
Dashboard: totals, plan comparison, daily chart, per-model tokens |
POST /ingest |
Run both ingesters, then redirect back with counts |
GET /rates |
Rate and settings editor |
POST /rates/save, POST /rates/delete/{id} |
Add, edit, remove a rate |
POST /rates/settings |
Save multipliers, tool rates, plan prices |
POST /rates/reset/{rates|multipliers|tool_rates|plans} |
Restore defaults |
GET /api/summary |
The dashboard's data as JSON |
Everything is local. There are no network calls, no telemetry, and no
credentials — the tool only reads transcript files already on your disk and
writes to a local SQLite file. Your usage database is not part of this
repository and is excluded by .gitignore.
uv run pytest -qThe suite covers the pricing engine (multipliers, date-window resolution, unpriced models), both ingesters (deduplication across runs and files, cache breakdown handling, malformed-line tolerance), and rate validation including window-overlap rejection and idempotent default seeding.
MIT — see LICENSE. You are free to use, copy, modify, and redistribute this, including commercially.