A VS Code status bar extension that reads your local Claude Code
transcript files (~/.claude/projects/**/*.jsonl) and shows accurate,
real-time context-window usage, cache hit rate, and cost. On a Claude
subscription (Pro/Max/Team) it also shows your 5-hour and weekly rate-limit
gauges (5h:34% · w:53%) — the limits that actually govern a subscription,
where dollars don't. These gauges update the moment Claude Code finishes a
turn, not on a blind polling schedule — see
How the rate-limit gauges stay fresh
below. Transcript-derived numbers stay fully offline; the rate-limit gauges
are the one deliberate, disclosable exception — see
Network access.
Not affiliated with, endorsed by, or sponsored by Anthropic. This is an independent, community-built tool. "Claude Code" is referenced only to describe compatibility.
Installation
Install from the VS Code Marketplace: Context and Usage Monitor for Claude Code.
Why this exists
This project started as a rewrite of claude-cache-watcher by Shivaraj (MIT licensed — see LICENSE-THIRD-PARTY.md), after running into a few real bugs:
- Wrong context window. A model-resolution bug caused Claude Sonnet 5 to
silently fall back to a 200K window instead of its real 1M, with cost
shown as
$?. <synthetic>in the status bar. Claude Code writes local zero-token bookkeeping records (e.g. "No response requested.") tagged with the model id<synthetic>. Counting them tanked the cache-hit reading to 0% and painted the status bar item black.- Broken workspace scoping. Claude Code encodes a project's path into its
transcript directory name by replacing
/,., and_with-. The original only replaced/, so any path containing a dot or underscore (e.g.claude_context_monitor) would silently fall back to showing whichever project's transcript was touched most recently — not necessarily the current one. - Cache-write pricing conflation. 5-minute and 1-hour cache writes are priced differently (1.25x vs. 2x input token price) but only one rate was ever tracked.
- Network-fetched pricing. Pricing was scraped from a marketing page at runtime, which is exactly what caused the model-resolution bug above. Pricing here is a built-in, offline table you can override in settings — this stays true even with rate-limit gauges enabled (see below); it's pricing that's offline, not literally everything the extension does.
This is a clean rewrite (not a fork) — see CHANGELOG.md for what changed. Context, cache, and cost numbers are derived only from files already on your disk. The 5-hour/weekly rate-limit gauges are the one exception, described in full in Network access.
Features
- Correct context-window % and token counts, per model, with no network call.
- An explicit "unknown model" state (never a silently wrong number) when a
model isn't in the registry — add it yourself via
pricing.models. - Per-turn, per-session, and monthly-to-date cost, with separate 5m/1h cache-write pricing.
- A configurable local monthly spend total (see Scope below).
- On a subscription plan: 5-hour and weekly rate-limit gauges right in the
status bar (
5h:34% · w:53%), on by default. They refresh the instant a new Claude Code turn is detected — not on a fixed timer — so the number you see reflects what you actually just did, with a lightweight 15-minute backstop check purely so the gauge doesn't go stale if you leave the editor open and idle through a reset. See How the rate-limit gauges stay fresh and Network access. Silently absent on API-key/Bedrock/ Vertex/Foundry billing, where these limits don't apply. - Every status bar segment and tooltip section is independently toggleable.
- Commands: Show Usage Report, Recalculate Monthly Usage, Open Anthropic Pricing Page, Copy Diagnostics (for bug reports), Refresh Rate Limits Now.
Settings
All settings live under contextUsageMonitor.*:
| Setting | Default | Description |
|---|---|---|
statusBar.enabled |
true |
Show the status bar item. |
statusBar.alignment |
right |
left or right. |
statusBar.priority |
100 |
Higher = further left/right within its alignment. |
statusBar.segments |
["model","context","turnCost"] |
Ordered list from: model, context, contextTokens, cacheHit, turnCost, sessionCost, idleState. |
statusBar.separator |
· |
Just the character — spaces are added automatically around it when rendering. |
statusBar.colorMode |
none |
none, cacheHit (warn on low hit rate), contextFill (warn/error as context fills up), or rateLimit (warn/error as 5-hour/weekly usage climbs). |
statusBar.showIcon |
true |
Show the leading icon. |
statusBar.showEffort |
true |
Show the reasoning-effort level (low/medium/high) in parentheses after the model name, when Claude Code recorded one. |
statusBar.showMonthlyCost |
false |
Show month-to-date cost, appended at the end. Renders even while idle — it's a background total, not tied to the current turn. |
tooltip.sections |
all | Ordered list from: turn, context, cache, rateLimits, cost, monthly, links. |
pricing.models |
{} |
Per-model input/output/cacheRead/cacheWrite5m/cacheWrite1h ($/token) and contextWindow overrides, merged over the built-in defaults. |
pricing.currencySymbol |
$ |
Currency symbol for formatted costs. |
usage.billingCycleStartDay |
1 |
Day of month (1–28) your monthly total resets on. |
filters.modelPattern |
^claude- |
Regex a model id must match to count at all. |
filters.includeSidechainsInContext |
false |
Include subagent turns in the context gauge (they always count toward cost). |
contextWindowOverrides |
{} |
Shortcut for pricing.models.<id>.contextWindow. |
rateLimits.enabled |
true |
Show the 5-hour/weekly gauges. Makes a network request — see Network access. |
rateLimits.refreshSeconds |
900 (15 min) |
Minimum interval between network checks (30–3600s) — the floor below which the on-new-turn trigger won't re-fetch, and the scheduled backstop's own interval. |
rateLimits.scheduledCheckEnabled |
true |
Also check on a refreshSeconds schedule, in addition to checking on every new turn. Turn off for zero idle-time network use — see How the rate-limit gauges stay fresh. |
rateLimits.showWeekly |
true |
Show the weekly (w:) gauge alongside the 5-hour one. |
rateLimits.showPerModelWeekly |
false |
Show per-model weekly gauges (Opus/Sonnet) in the tooltip, when your plan reports them (Max only). |
rateLimits.colorThresholds |
{"warning":80,"error":90} |
Thresholds for statusBar.colorMode: "rateLimit". |
How the rate-limit gauges stay fresh
Most extensions that show this kind of thing poll on a fixed timer — showing
a number that's up to N seconds stale even while you're actively working,
and still polling every N seconds even when you've stepped away and
nothing is happening. This one is event-driven instead:
- On every new turn. The same lightweight transcript scan this extension
already does every 10 seconds to update context/cost also notices when a
genuinely new Claude Code record has appeared. The instant it does, the
rate-limit gauge refreshes — so right after you finish a turn, the number
you see is the number that turn actually produced, not a stale reading
from up to
refreshSecondsago. - A 15-minute backstop, not the main driver.
rateLimits.refreshSeconds(default900= 15 min) now exists only to catch the case where you leave the editor open and idle for a long stretch spanning a 5-hour or weekly reset — with no new turn to trigger a check, the gauge would otherwise keep showing a stale percentage indefinitely. SetrateLimits.scheduledCheckEnabled: falseto disable this entirely: the gauge then updates only when you're actually using Claude Code, at the cost of possibly showing a stale number if a window resets while you're away. - Both paths share one safety net. Whichever one fires, the actual
network call still only happens if the on-disk cache is older than
refreshSeconds— a burst of records from one busy agentic turn (many tool calls in a row) can trigger the check repeatedly without causing a burst of requests; it just resolves from cache until the interval is actually up.
Net effect: on a typical active session, this is more responsive than a 120s timer ever was, while making meaningfully fewer requests overall — during any stretch where you're not generating new turns, it makes none.
Network access
Everything above — context, cache, and cost — comes only from files already on disk. The 5-hour/weekly rate-limit gauges are the one exception:
- Two
GETrequests toapi.anthropic.com(/api/oauth/usageand/api/oauth/profile), using the same local Claude Code OAuth token Claude Code itself already stores (in~/.claude/.credentials.jsonor the macOS Keychain) — no separate API key, no new credential. - Only fires when you're on a subscription plan (Pro/Max/Team/Enterprise via Claude.ai login). If Claude Code is configured for API-key, Bedrock, Vertex, or Foundry billing, the request is never made and the gauges are silently hidden — those don't have 5-hour/weekly limits.
- Triggered by a new turn or the 15-minute backstop (see above), but never
more than once per
rateLimits.refreshSecondsper machine, shared across every open VS Code window through a local cache file (~/.claude/.context-usage-monitor/rate-cache.json) — opening more windows doesn't multiply the request rate. - No telemetry, no third-party endpoint, nothing beyond the two Anthropic URLs above. The token itself never appears in the tooltip, "Copy Diagnostics" output, or any cache file.
- Turn it off entirely with
contextUsageMonitor.rateLimits.enabled: false, or keep the gauges but drop the idle-time backstop withrateLimits.scheduledCheckEnabled: false.
Scope
Monthly usage is computed locally, by scanning your own
~/.claude/projects directory on this machine — it does not require, and
does not use, an Anthropic Admin API key, and it cannot see usage from other
machines or other members of an organization. If you work across multiple
machines, each one tracks its own total.
Installing
Install from the
VS Code Marketplace,
or from a .vsix file:
- Download the
.vsixfile. - In VS Code: Extensions view →
...menu → Install from VSIX...
License
MIT © 2026 Viktor Moyseyenko. Third-party notices in LICENSE-THIRD-PARTY.md.