usagelens
v0.6.0
Published
Local dashboard for your AI coding usage across Claude Code, Codex CLI, Cursor and Antigravity. Reads your machine's local data and serves an interactive dashboard on localhost. Accurate per-model pricing, cost-per-shipped-code, and per-session drilldown.
Maintainers
Readme
usagelens
A local dashboard for your AI coding usage — unified across Claude Code, Codex CLI, and Cursor. It reads the usage data those tools already store on your machine, and serves an interactive dashboard on localhost. Read-only, offline, zero runtime dependencies.
npx usagelensThat's it — it scans your local data, starts a server on http://localhost:4319, and opens your browser.
What you get
- Tokens, est. cost, sessions, cache hit-rate, streak — with deltas vs the prior period
- Daily activity bar chart and a when-you-work hour × weekday heatmap (hover for details)
- Tool breakdown (Claude / Codex / Cursor / Antigravity) and model mix with per-model estimated cost
- Cost per shipped code — AI spend mapped to real git commits & lines (
$/commit,$/1K lines, per project) - Cost efficiency & model routing — premium (Opus) share, output/input leverage, and estimated savings if routine turns were routed to a cheaper tier
- Tool usage — how often Bash / Edit / Read / etc. are called
- Top projects, session shape, cache effectiveness, and code authorship (Cursor)
- Budgets — month-to-date spend vs a configured monthly budget, with straight-line projection
- Most expensive sessions — the top sessions by estimated cost; click any row to open a detail drawer with the spend curve, token composition, models, tool calls, stop reasons, priciest turns, and session metadata (CLI version, git branch, sandbox, reasoning effort…)
- Plans — your plan for Claude / Codex / Cursor, read from local files (offline, always on)
- Live quota (opt-in) — your real 5-hour and 7-day Claude quota, with reset times
- Accurate pricing — per-model list prices synced from models.dev, version-aware
- Custom date ranges — 7d / 30d / 90d presets, or any
from → towindow - Live refresh — re-scan your data without restarting; multi-account aware
CLI
usagelens [--port <n>] [--no-open] [--no-cache] # start the dashboard (default command)
usagelens report [--json] [--range <r>] # print a usage report to stdout, then exit
usagelens sync-pricing [--write] # refresh model prices from models.dev
usagelens clear-cache # drop the incremental parse cacheusagelens — start the dashboard
Scans your local AI data, starts an HTTP server bound to 127.0.0.1, and opens the dashboard in your browser.
| Flag | Default | Description |
| --- | --- | --- |
| --port <n> | 4319 | Port to listen on (loopback only). |
| --no-open | off | Start the server but don't auto-open the browser. |
| --no-cache | off | Re-parse every transcript instead of using the incremental cache. |
usagelens # start on http://localhost:4319 and open the browser
usagelens --port 8080 # use a custom port
usagelens --no-open # headless (e.g. remote box, or you'll open it yourself)The first scan parses every transcript; afterwards results are cached per file and only changed files are re-read (typically ~8s → ~0.1s).
usagelens report — headless report
Prints a report for the given range to stdout and exits (no server). Useful for CI, cron, piping to jq, or posting to Slack. Includes git cost-per-shipped-code.
| Flag | Default | Description |
| --- | --- | --- |
| --json | off | Emit the full data payload as JSON instead of Markdown. |
| --range <r> | 30d | Reporting window: 7d, 30d, 90d, or any <n>d. |
usagelens report # Markdown report for the last 30 days
usagelens report --range 7d # last 7 days
usagelens report --json # full JSON payload
usagelens report --json --range 90d # 90-day JSON, e.g. pipe to jq
usagelens report --json | jq '.summary.costUsd' # extract a single numberTip: from the running dashboard, the ↓ Export report button (top-right) downloads the same Markdown report for the selected range, and .json downloads the full payload — both include git cost-per-shipped-code.
usagelens sync-pricing — refresh model prices
Prices are per-model and version-aware, sourced from models.dev. A copy ships with the package; this command refreshes it into ~/.usagelens/pricing.json, which takes precedence.
| Flag | Default | Description |
| --- | --- | --- |
| (none) | — | Dry run: print the diff without saving. |
| --write | off | Save the fetched prices to ~/.usagelens/pricing.json. |
usagelens sync-pricing # show what would change
usagelens sync-pricing --write # update local pricesModels that aren't in the price list are flagged in the dashboard and the report rather than silently guessed at.
usagelens clear-cache
Deletes the incremental parse cache (~/.usagelens/cache.db). The next run does a full re-scan.
Config (optional) — ~/.usagelens.json
{
"sources": [
{ "tool": "claude", "dir": "~/.claude", "label": "[email protected]" },
{ "tool": "claude", "dir": "~/.claude-personal", "label": "[email protected]" }
],
"pricing": { "opus": { "input": 12, "output": 60 } },
"budget": { "monthlyUsd": 500, "monthlyTokens": 2000000000 },
"git": true,
"cache": true,
"allowSubscriptionAccess": false
}- sources — point at multiple config dirs to track multiple accounts (each labeled).
- pricing — override the synced per-model $/Mtoken rates (keys are matched as regexes).
- budget — enables the budget panel + projection.
- git — set
falseto skip the git correlation (cost-per-shipped-code). - cache — set
falseto disable the incremental parse cache. - allowSubscriptionAccess — set
trueto fetch your real plan & quota. See below.
Plans & quota
These are two different things, and only one of them uses the network.
Plans — offline, always on. Which plan you're on is already sitting in plain local files, so usagelens just reads it. No network, no Keychain, no opt-in:
| Tool | Read from |
| --- | --- |
| Claude | ~/.claude.json → oauthAccount.organizationType (e.g. max) |
| Codex | ~/.codex/auth.json → id_token claim chatgpt_plan_type (e.g. business) |
| Cursor | Cursor globalStorage/state.vscdb → cursorAuth/stripeMembershipType |
No token is read for this — only plan and tier names, which aren't secrets.
Live quota — opt-in, network. Your real 5-hour / 7-day utilisation and reset times only
exist server-side, so showing them needs one request. Click ⚡ Enable live quota in the
dashboard (or set "allowSubscriptionAccess": true yourself) and usagelens reads the OAuth
token Claude Code already stores (macOS Keychain, or ~/.claude/.credentials.json) and calls
https://api.anthropic.com/api/oauth/usage.
This is the only feature that touches the network, and it is off until you turn it on. The token goes only to its own issuer, is never logged, never written to disk, and never appears in any API response or exported report.
Changed your mind? The same panel has a Disable live quota button, which flips the flag back and stops all network calls. Plans keep working — they never needed the network.
Why not on by default? Because
npx usagelensshould never read a credential and phone home on a stranger's machine without them asking. One click is a small price for that.
Data sources
Read-only, from your machine:
~/.claude/projects/**/*.jsonl— Claude Code (tokens, models, projects, cache)~/.codex/sessions/**— Codex CLI (per-turn token usage)~/.cursor/ai-tracking/ai-code-tracking.db— Cursor (AI vs human code authorship)~/.gemini/antigravity/**— Antigravity (session & file activity; no token data)
Tools present but exposing no usable local usage data (GitHub Copilot, Ollama) are shown as detected-without-metrics rather than fabricated numbers.
Notes
- Cost is estimated — list price × tokens ("API-equivalent value"), not a bill. Prices come
from models.dev and are version-aware:
claude-opus-4-1andclaude-opus-4-5are priced differently, as they should be. Unpriced models are flagged, not guessed. - Never writes to your tool directories.
~/.claude,~/.codex,~/.cursorand~/.geminiare opened read-only. usagelens writes only to its own~/.usagelens/(parse cache + synced prices). - Offline by default. The server binds to loopback (127.0.0.1) only. The only outbound
requests are
sync-pricing(when you run it) and plan/quota (when you opt in). - Requires Node ≥ 22.5 (uses the built-in
node:sqlite).
License
MIT
