A local dashboard that reads the JSONL transcripts Claude Code writes to ~/.claude/projects/ and turns them into per-prompt cost analytics, tool/file heatmaps, subagent attribution, cache analytics, project comparisons, and a rule-based tips engine.
Everything runs locally. No data leaves your machine — no telemetry, no API calls for your data, no login.
- Seeing which of your prompts are expensive (surprise: they usually involve large tool results).
- Comparing token usage across projects you've worked on.
- Spotting wasteful patterns — the same file read twenty times in a session, a tool call returning 80k tokens.
- Understanding what a "cache hit" actually saves you.
- If you're on Pro or Max, confirming you're getting your money's worth in API-equivalent dollars.
- Python 3.8 or newer — already installed on macOS and most Linux. On Windows:
winget install Python.Python.3.12or download from python.org. - Claude Code — installed and with at least one session run. The dashboard reads those sessions. If you just installed Claude Code and haven't used it yet, run at least one prompt first.
- A web browser. Any modern one.
No pip install. No Node.js. No build step.
git clone https://github.com/nateherkai/token-dashboard.git
cd token-dashboard
python3 cli.py dashboardOn Windows, if
python3isn't on your PATH, substitutepy -3forpython3in every command below.
The command:
- Scans
~/.claude/projects/(first run can take 20–60 seconds on a heavy user's machine). - Starts a local server at http://127.0.0.1:8080.
- Opens your default browser to that URL.
Leave it running; it re-scans every 30 seconds and pushes updates live. Stop with Ctrl+C.
Claude Code writes one JSONL file per session here:
| OS | Path |
|---|---|
| macOS / Linux | ~/.claude/projects/<project-slug>/<session-id>.jsonl |
| Windows | C:\Users\<you>\.claude\projects\<project-slug>\<session-id>.jsonl |
The dashboard never modifies those files — it only reads them and keeps a local SQLite cache at ~/.claude/token-dashboard.db.
To point at a different location:
python3 cli.py dashboard --projects-dir /path/to/projects --db /path/to/cache.db| Var | Default | Purpose |
|---|---|---|
PORT |
8080 |
Port the local web server listens on |
HOST |
127.0.0.1 |
Bind address. Keep the default. Setting 0.0.0.0 exposes your entire prompt history to anyone on your local network — don't do this on any network you don't fully control (no coffee-shop Wi-Fi, no coworking spaces). |
CLAUDE_PROJECTS_DIR |
~/.claude/projects |
Where to scan for session JSONL files |
TOKEN_DASHBOARD_DB |
~/.claude/token-dashboard.db |
SQLite cache location |
Pricing lives in pricing.json. Edit it directly if model prices change or to add a new plan.
python3 cli.py scan # populate / refresh the local DB, then exit
python3 cli.py today # today's totals (terminal)
python3 cli.py stats # all-time totals (terminal)
python3 cli.py tips # active suggestions (terminal)
python3 cli.py dashboard # scan + serve the UI at http://localhost:8080
# dashboard flags
python3 cli.py dashboard --no-open # don't auto-open the browser
python3 cli.py dashboard --no-scan # skip the initial scan (use cached DB only)Change the port: PORT=9000 python3 cli.py dashboard.
The dashboard is a single page with a hash-router tab bar across the top. Each tab is backed by its own JSON API under /api/:
- Overview — all-time input/output/cache tokens, sessions, turns, estimated cost on your chosen plan, daily work and cache-read charts, tokens-by-project, token share by model, top tools by call count, and recent sessions. This is the landing tab.
- Prompts — your most expensive user prompts ranked by tokens. Click any row to see the assistant response, tool calls made, and the size of each tool result.
- Sessions — turn-by-turn view of any single session, with per-turn tokens and tool calls.
- Projects — per-project comparison: tokens, session counts, and which files were touched most.
- Skills — which skills you invoke most often, and (where we can measure them) their token cost. See limitations.
- Tips — rule-based suggestions for reducing token usage (repeated file reads, oversized tool results, low cache-hit rate, etc.).
- Settings — switch pricing between API / Pro / Max / Max-20x so cost figures everywhere else reflect your actual plan.
The Overview tab also has a built-in "What do these numbers mean?" panel that explains input/output/cache tokens in plain English.
"No data" or empty charts. Run python3 cli.py scan once to populate the DB, then reload.
Port 8080 already in use. PORT=9000 python3 cli.py dashboard.
Numbers look wrong / stuck. The DB lives at ~/.claude/token-dashboard.db. Delete it and re-run python3 cli.py scan to rebuild from scratch.
Running the dashboard twice at the same time. Don't — both processes will fight over the SQLite DB. Stop all instances before starting a new one.
Claude Code writes each assistant response 2–3 times to disk while it streams (the same API message gets snapshotted as output grows). The dashboard dedupes these by message.id so the final tally matches what the API actually billed. If you compare against another tool that sums every JSONL row, expect this dashboard's numbers to be lower — and closer to reality.
Nothing leaves your machine. No telemetry. No remote calls for your data. The browser fetches its JSON from 127.0.0.1, and all JS/CSS/fonts are served from that same local server — ECharts is vendored into web/, and the UI falls back to system fonts rather than pulling from a font CDN. If you want to verify: grep -r "https://" token_dashboard/ web/ — you'll find nothing.
Python 3 (stdlib only) for the CLI, scanner, and HTTP server. SQLite for the local cache. Vanilla JS + ECharts for the UI, no build step. Dark theme, hash-based router, server-sent events for live refresh.
Data flow: cli.py → token_dashboard/scanner.py → SQLite DB; token_dashboard/server.py exposes /api/* JSON routes and serves web/.
CLAUDE.md— conventions and architecture overview (also picked up automatically by Claude Code)CONTRIBUTING.md— how to develop and testdocs/KNOWN_LIMITATIONS.md— rough edgesdocs/inspiration.md— prior art and how this project diverges
See CONTRIBUTING.md. Short version: fork, python3 -m unittest discover tests before opening a PR, keep it stdlib-only.
MIT.

