Claude Code Token Tracker
Live token usage and estimated API-equivalent cost for Claude Code, in the VS Code status bar.
Claude Code's own status line is a terminal-TUI feature and does not render in the VS Code extension. This fills that gap by reading the same data the CLI writes.
What it shows
A status bar item that updates as you work — current chat tokens, cost, and how full its
context window is:
2.8M · $3.61 · ctx 30%
Click it for a panel led by the current chat: its cost, model, message count, when it
started, subagent share, and a context-window meter that turns amber at 50% and red at 80%.
Below that:
- Recent chats — the last 12 sessions with per-session tokens and cost, current one marked
- Today / last 7 days / all time summary cards
- Last 14 days as a bar chart
- Per-project breakdown, including what share of tokens went to subagents
- Per-model token classes — input, output, cache write, cache read — and cost
How it works
Claude Code appends every assistant message to ~/.claude/projects/<encoded-cwd>/<session>.jsonl,
each carrying a usage object. This extension watches that tree and aggregates it. No network
calls, no API key — everything is read from disk.
Two details matter for correctness:
De-duplication. Claude Code writes each assistant message to the transcript more than once.
Naively summing every usage object roughly doubles the totals, so records are de-duplicated on
message.id (falling back to requestId).
The context window is not recorded. message.model on disk is the bare id
(claude-opus-5) even for a 1M-context session — the [1m] suffix exists only in the CLI's
status-line payload. So the window is inferred: the largest context ever seen for a model,
including the preTokens a compaction records, decides whether that model is on the 200K or 1M
tier. Since the 1M window is an account-level setting rather than a per-session one, one session
seen above 200K establishes it for all of them. Without this the meter reads over 100%.
Cache tiers. Cache reads dominate real usage — often 95%+ of all tokens — and they bill at a
fraction of the input rate. Treating all tokens equally overstates cost by roughly 5×. Rates used:
| Token class |
Rate |
| Input |
1× input |
| Output |
1× output |
| Cache write, 5-minute TTL |
1.25× input |
| Cache write, 1-hour TTL |
2× input |
| Cache read |
0.1× input (0.025× on Fable/Mythos 5.1) |
Costs are estimated at API list prices. On a Claude Pro/Max subscription this is not what you
are billed — use /usage in Claude Code for actual plan consumption. The figure is useful as
a measure of how much work you are pushing through, and as what the same work would cost on the API.
Transcripts grow into the tens of megabytes, so a full re-parse per update is not viable. The
extension caches per file, keyed on size and mtime, and parses only newly appended bytes. Files
untouched for a week are sealed: totals frozen, de-duplication set dropped. Warm updates are
effectively free.
Parsing stops at the last newline in the file, so a half-flushed line is never consumed — it gets
picked up once the write completes.
Settings
| Setting |
Default |
Description |
claudeTokenTracker.claudeHome |
~/.claude |
Claude Code config directory |
claudeTokenTracker.statusBar.enabled |
true |
Show the status bar item |
claudeTokenTracker.statusBar.scope |
chat |
chat, project, today, or allTime |
claudeTokenTracker.statusBar.showTokens |
true |
Include the token count |
claudeTokenTracker.statusBar.showCost |
true |
Include the estimated cost |
claudeTokenTracker.statusBar.showContext |
true |
Append the context-window percentage |
claudeTokenTracker.statusBar.alignment |
right |
Status bar side (needs reload) |
claudeTokenTracker.refreshIntervalSeconds |
20 |
Safety-net rescan; 0 uses the watcher alone |
claudeTokenTracker.sealAfterDays |
7 |
When to freeze an idle transcript's totals |
claudeTokenTracker.pricing |
{} |
Per-model rate overrides, USD per million tokens |
Accuracy
Claude Code writes its own totalCostUSD into a cost-state record when a session ends. On a
session carrying one, this extension's independently computed figure matched it to the cent
($1.71 vs $1.7071). The scanner was also checked against a separate Python implementation over a
frozen snapshot of the transcripts — identical on every token class, message count, and cost.
Scopes: chat is the single conversation you are in; project sums every chat in the current
workspace folder; today and allTime span all projects. (session still works as a deprecated
alias for chat.)
The current chat resolves to the most recent transcript for the current workspace folder, matched
by Claude Code's directory encoding (non-alphanumerics replaced with dashes) and by the cwd
recorded inside the transcript. With no match it falls back to the most recent session overall and
says so in the tooltip.
Price overrides
Built-in rates go stale when pricing changes. Override them without touching the code:
"claudeTokenTracker.pricing": {
"claude-opus-5": { "input": 5, "output": 25, "cacheRead": 0.5, "cacheWrite": 6.25 }
}
Anything omitted falls back to the built-in rate. The cache stores token counts only, never money,
so a rate change takes effect immediately with no rebuild.
Commands
- Claude Token Tracker: Show Usage Details
- Claude Token Tracker: Refresh Now
- Claude Token Tracker: Rebuild Cache From Scratch
- Claude Token Tracker: Copy Usage Summary
Building
Requires Node (build-time only; the extension runs on VS Code's bundled Node).
npm install
npm run package # typecheck, bundle, and produce the .vsix
code --install-extension claude-token-tracker-0.3.0.vsix
For development, press F5 to launch an Extension Development Host.
License
MIT