Usage Monitor
A VS Code extension that shows daily and weekly usage for Claude and Codex
inside the editor — read from your own signed-in browser session, with no API
keys and no telemetry.
How it works
Claude and ChatGPT/Codex put their usage data behind Cloudflare bot-protection,
so replaying cookies from Node.js does not work. Instead, Usage Monitor opens a
controlled browser window (your installed Chrome or Edge, reused via
Playwright — nothing is downloaded) where you sign in once. That login is
kept in a dedicated, isolated browser profile on disk. On refresh, the extension
navigates that browser to the provider's usage page and reads the provider's own
usage JSON response — no scraping of fragile HTML, no credentials handled by the
extension itself.
Features
- A sidebar view in its own activity-bar container with one card per
provider: usage bars, a status chip, last-refreshed time, and per-provider
Sign in / Refresh / Disconnect actions
- A status-bar summary (e.g.
Claude 42% · Codex 71%) that turns amber near
a limit
- First-class UI states: signed-out, expired-session, rate-limited, unsupported,
layout-changed, and error — never a silent zero
- No API keys; the extension never reads or stores your cookies or tokens (the
isolated browser profile holds the session)
- Strict webview CSP with nonced local scripts; no remote requests from the view
- Optional, conservative auto-refresh (off by default)
First run
- Open the Usage Monitor view from the activity bar (bar-chart icon).
- Click Sign in on the Claude and/or Codex card. A browser window opens —
log in to the provider as normal, then return to VS Code.
- Click Refresh. The extension reads your current usage.
You only sign in once per provider; the session persists.
Commands
| Command |
ID |
| Open Dashboard (focus the view) |
usageMonitor.openDashboard |
| Refresh Usage |
usageMonitor.refreshUsage |
| Sign in to Claude |
usageMonitor.signInClaude |
| Sign in to Codex |
usageMonitor.signInCodex |
| Clear Provider Session |
usageMonitor.clearSession |
Settings
usageMonitor.autoRefreshMinutes (default 0 = manual): refresh interval
while the view is visible.
usageMonitor.browserChannel (auto | chrome | msedge): which installed
browser the controlled window uses. auto tries Chrome, then Edge.
usageMonitor.captureTimeoutSeconds (default 30): how long to wait for a
provider's usage data before reporting a failure.
Architecture
src/
extension.ts activation, view + command wiring, status bar, output channel
types.ts shared usage/result types (windows[] model + UI states)
session/browserSession.ts Playwright persistent-context manager (per provider)
providers/
provider.ts UsageProvider interface + context
baseProvider.ts capture→parse template + error→status mapping
parseHelpers.ts defensive JSON→window helpers
claudeProvider.ts Claude adapter (claude.ai usage capture)
codexProvider.ts Codex adapter (backend-api/wham/usage capture)
registry.ts provider construction
webview/usageViewProvider.ts WebviewView sidebar + message bridge + auto-refresh
media/
activity-icon.svg activity-bar icon
dashboard.css / .js webview styles + renderer (CSP-safe)
Provider logic is isolated behind UsageProvider so Claude and Codex evolve
independently. Each adapter maps every failure onto a typed status the sidebar
renders as a distinct state.
Known limitations / honesty notes
- Usage window labels: neither provider exposes a clean calendar "day". They
expose rolling windows (a ~5-hour session window and a 7-day weekly window), so
the cards show those real windows rather than inventing a daily number.
- Undocumented payloads: the usage JSON shapes are internal and change-prone.
The parsers are defensive and report Layout changed (not zero) when a shape
is unrecognized. If you hit that, the raw response is logged to the Usage
Monitor output channel so the field mapping in
claudeProvider.ts / codexProvider.ts can be tightened against a real sample.
- The window is visible by design: a real, user-driven browser is what gets
past Cloudflare; headless/automated clicking gets challenged. You can minimize
the window between refreshes.
Develop
npm install
npm run compile # or: npm run watch
npm run lint
Press F5 (the "Run Extension" launch config) to open an Extension Development
Host, then open the Usage Monitor view.
Package
npm run package # writes dist/usage-monitor.vsix via @vscode/vsce
Requires Google Chrome or Microsoft Edge installed on the machine (reused by the
controlled browser; no browser binaries are bundled or downloaded).