Claude Lens
Real-time Claude usage intelligence for VS Code — know your session limits before they hit you.
"See the wall before you run into it."
A VS Code extension that shows your actual Claude Pro/Max subscription usage (session %, weekly %), live in the sidebar — the same numbers on claude.ai/settings, without switching windows. Adds budget caps, model ROI scoring, and real-time model switching capability.
Everything runs locally. Zero telemetry.

What it does
| Pillar |
What you get |
| Plan Quota |
Live session % and weekly % from Anthropic's API — same data as claude.ai/settings. Proactive toasts at 80% and 90% so you're never blindsided. |
| API Cost Estimate |
Per-session, daily, and weekly spend vs. configurable caps, using public API pricing. Useful for API-key users; shown collapsed for Pro/Max. |
| Model ROI Scoring |
Heuristic engine scores whether the active Claude model is appropriately matched to each task. Nudges when Sonnet or Opus is used for a simple question. |
| Model Switching |
Switch between Claude models (Haiku, Sonnet, Opus) from the Config section without restarting Claude Code — preference persists in ~/.claude/settings.json. |
What it is NOT
- Not a token counter (five already exist)
- Not a Claude Code replacement
- Not a cloud sync tool — your data never leaves your machine (except one read-only call to Anthropic's API)
Architecture
Claude Lens is a stateful polling extension with four independent data providers and a unified UI layer:
┌─────────────────────────────────────────────────────────────────┐
│ VS Code Extension │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──── DATA INGESTION (polling) ────┐ │
│ │ │ │
│ ├─ ClaudeCodeProvider (primary) │ Discovers ~/.claude/ │
│ │ └─ Polls JSONL every 2s │ projects/<hash>/ │
│ │ (local token counts) │ <session>.jsonl │
│ │ │ │
│ ├─ AnthropicUsageProvider │ Requires API key, │
│ │ └─ Polls API every 60s │ hits /v1/usage │
│ │ (workspace billing) │ │
│ │ │ │
│ ├─ ClaudeAiLimitsProvider │ Reads OAuth token, │
│ │ └─ Polls every 5 min │ hits /api/oauth/ │
│ │ (real subscription usage) │ usage (rate-limited) │
│ │ │ │
│ └─ ManualProvider │ User input via CLI │
│ └─ On-demand │ │
│ │ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──── STATE MACHINES ────────────────┐ │
│ │ │ │
│ ├─ SessionTracker │ Maintains: │
│ │ • Session ID + start time │ • 5-hour rolling window│
│ │ • Token counts (input/output) │ • Current turn count │
│ │ • Cost aggregation (all sources) │ • Reset boundaries │
│ │ │ │
│ ├─ BudgetEngine │ Evaluates: │
│ │ • Session / daily / weekly spend │ • Against caps │
│ │ • Status flags (ok/warn/over) │ • Stored daily/weekly │
│ │ • Alert thresholds (80% / 100%) │ totals from disk │
│ │ │ │
│ └─ RoiScorer │ Scores: │
│ • Effective context (tokens) │ • Model fit per turn │
│ • Complexity heuristic (0-100) │ • Overkill detection │
│ • Model tier mapping │ • Nudge suggestions │
│ │ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──── UI LAYER (EventEmitter) ────────┐ │
│ │ │ │
│ ├─ StatusBar │ • Cost / quota info │
│ │ └─ Refreshes on sessionTracker │ • Model indicator │
│ │ update or limitsProvider tick │ • Timer │
│ │ │ │
│ └─ SidebarProvider (TreeView) │ • Plan Quota section │
│ └─ Refreshes on any state change │ • API Cost section │
│ │ • ROI section │
│ │ • Session detail │
│ │ • Config section │
│ │ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──── STORAGE & CONFIG ────────────────┐ │
│ │ │ │
│ ├─ LocalStore (VS Code globalState) │ • Daily spend │
│ │ │ • Weekly spend │
│ │ │ • Reset timestamps │
│ │ │ │
│ ├─ WorkspaceConfig (.claudelens) │ • Budget caps │
│ │ │ • Alert thresholds │
│ │ │ • ROI settings │
│ │ │ │
│ └─ SecretStorage (VS Code) │ • Anthropic API key │
│ │ (if using provider 2)│
│ │ │
└─────────────────────────────────────────────────────────────────┘
Data Flow: Single Turn
User sends prompt via Claude Code
│
▼
ClaudeCodeProvider sees JSONL entry
│
├──▶ processEntry() in extension.ts
│ ├──▶ sessionTracker.ingestEntry() [updates cost]
│ ├──▶ roiScorer.scoreTurn() [complexity analysis]
│ └──▶ limitsProvider.refreshNow() [15s rate-limited]
│
├──▶ refreshUI()
│ ├──▶ budgetEngine.evaluate()
│ ├──▶ statusBar.update()
│ └──▶ sidebarProvider.update()
│
└──▶ User sees updated cost/quota in real-time
Initialization Sequence
1. activate() called by VS Code
│
├─ loadPriceTable() from resources/
├─ WorkspaceConfig.load() [.claudelens]
├─ LocalStore() [restore daily/weekly totals]
├─ SessionTracker() [ready for entries]
│
└─ claudeProvider.discoverSessionDir()
│
├─ Found? → loadCurrentSession() + startWatching()
│ [Source: Claude Code logs]
│
└─ Not found? → tryAnthropicApiProvider()
│
├─ Has API key? → fetchAndIngest() + startPolling()
│ [Source: Anthropic Usage API]
│
└─ No key? → Show "No data source" in sidebar
[Source: none]
2. ClaudeAiLimitsProvider.load()
│
├─ Reads ~/.claude/.credentials.json [OAuth token]
├─ Makes one API call to /api/oauth/usage [seed subscription type]
└─ startPolling() [5-min cadence, 300s initial wait]
└─ Updates sidebar + status bar with real quota %
Model Switching
Model preference is stored in ~/.claude/settings.json under modelPreference:
{
"modelPreference": "claude-opus-4-6"
}
When user clicks "Model: sonnet — click to switch" in Config section:
- Opens QuickPick with available models
- Writes selection to settings.json via
modelSwitcher.setModel()
- User starts new Claude Code session
- Claude Code reads settings.json and activates the model
- New JSONL entries use selected model
The Status Bar and sidebar update immediately to show active model.
ROI Scoring Algorithm
For each completed turn, roiScorer.scoreTurn() assigns a complexity score (0–100):
base = 10 // minimum
// Context size contribution (0–50 pts)
effective_context = input_tokens + cacheCreation_tokens + cacheRead_tokens
if effective_context < 500: score -= 15 // likely simple question
if effective_context > 100_000: score += 40 // complex context
// Response length contribution (0–20 pts)
if output_tokens > 2000: score += 15
// Architecture/complexity keywords in prompt (0–15 pts)
keywords = ["design", "architecture", "refactor", "algorithm", ...]
score += 5 * num_keywords_found
// Multi-turn context (0–10 pts)
if turn_count > 5: score += 5
// Recency bonus (0–5 pts)
if first_turn_in_session: score += 3
score = max(0, min(100, score)) // clamp
Model recommendation:
- Haiku (0–30): Simple Q&A, debugging, boilerplate
- Sonnet (31–65): Feature work, moderate refactoring
- Opus (66–100): Complex architecture, novel algorithms, deep reasoning
If user's active model is higher than recommended tier, flagged as overkill and nudged (max once per 10 minutes).
Installation
From the VS Code Marketplace
Search Claude Lens by shouvikm, or:
ext install shouvikm.claude-lens
## Setup
### 1. Open a workspace folder
Claude Lens is a per-project tool. Open your project folder in VS Code.
### 2. Create a `.claudelens` config
Run from the Command Palette (`Ctrl+Shift+P`):
Claude Lens: Create .claudelens
Scaffolds a config at your workspace root. Edit to set budget caps.
### 3. Start Claude Code
Claude Lens auto-discovers your active session. Sidebar and status bar update as you work.
**No API key required** for Claude Code users — token data comes from the local JSONL logs.
> Not using Claude Code? Run `Claude Lens: Set Anthropic API Key` for API billing accounts, or `Claude Lens: Manual Token Entry` for claude.ai-only usage.
---
## The `.claudelens` config file
Safe to commit — contains no secrets.
```json
{
"version": "1.0",
"project": "my-project-name",
"budget": {
"session": 0.50,
"daily": 2.00,
"weekly": 10.00,
"currency": "USD"
},
"alerts": {
"soft_threshold": 0.80,
"hard_stop": false,
"notify_on_reset": true
},
"model_roi": {
"enabled": true,
"preferred_model": "sonnet",
"nudge_on_overkill": true,
"nudge_cooldown_min": 10
}
}
Config fields
budget — applies to API cost estimates (most relevant for direct API users)
| Field |
Default |
Description |
session |
0.50 |
Max API-equivalent spend per session |
daily |
2.00 |
Max spend per calendar day |
weekly |
10.00 |
Max spend per 7-day window |
currency |
"USD" |
Display currency |
alerts
| Field |
Default |
Description |
soft_threshold |
0.80 |
Fraction of budget cap at which the amber warning fires |
hard_stop |
false |
Show a blocking modal at 100% |
notify_on_reset |
true |
Toast when the session window resets |
model_roi
| Field |
Default |
Description |
enabled |
true |
Enable/disable ROI scoring |
preferred_model |
"sonnet" |
Baseline for overkill detection |
nudge_on_overkill |
true |
Toast nudges when a more powerful model than needed is detected |
nudge_cooldown_min |
10 |
Minimum minutes between nudge toasts |
UI guide
Status bar
Always visible at bottom-right. Click to focus the Claude Lens sidebar.
⬡ 42% ⏱3h 48m sonnet-4-6
| Segment |
Meaning |
42% |
Plan quota usage — green < 80%, amber 80–89%, red ≥ 90% |
⏱3h 48m |
Time until session window resets on claude.ai |
sonnet-4-6 |
Active Claude model |

Click the Claude Lens icon in the activity bar.
CLAUDE LENS
│
├── 🌐 Plan Quota (pro) ← REAL data from Anthropic API
│ ├── Session 95% [█████████░] resets in 3h 48m
│ ├── Weekly 57% [█████░░░░░] resets Fri 07:00 PM
│ └── 🔗 View on claude.ai
│
├── 💰 API Cost Estimate — {project} ← collapsed by default for Pro/Max
│ ├── Session $0.12 / $0.50 [██░░░░░░░░] 24%
│ ├── Daily $0.84 / $2.00 [████░░░░░░] 42%
│ ├── Weekly $4.32 / $10.00 [████░░░░░░] 43%
│ └── Status: ✓ comfortable
│
├── 🎯 Model ROI
│ ├── Active model: sonnet-4-6 ✓ good fit
│ ├── This session: 4 turns — 3 optimal, 1 overkill
│ └── Overkill cost est: ~$0.04 this session
│
├── 📊 Session Detail
│ ├── Tokens in: 1,038
│ ├── Tokens out: 81,624
│ ├── Cache created: 2,177,040
│ ├── Cache read: 47,714,641
│ ├── API cost est.: $11.52 (gross, excl. cache savings)
│ ├── Cache savings: -$128.83
│ ├── Net API cost: $0.00
│ └── JSONL window: started 6:38 PM (elapsed — check claude.ai for current window)
│
└── ⚙ Config
├── Data source: ✓ Claude Code logs (local, exact)
├── .claudelens: ✓ found
├── Model: sonnet-4-6 — click to switch
├── 🔄 Switch Model
└── ✏ Edit .claudelens
Toast notifications
| Trigger |
Type |
Message |
| Plan quota hits 80% |
Info |
⬡ Claude session at 80% — resets in Xh Ym |
| Plan quota hits 90% |
Warning |
⬡ Claude session at 90% — resets in Xh Ym |
| API cost estimate hits soft threshold |
Warning |
⬡ Budget Alert — approaching cap |
| API cost estimate hits 100% |
Warning |
⬡ Budget Limit — cap reached |
| Model overkill detected |
Info |
⬡ ROI Nudge — Sonnet recommended, nudges every 10 min |
| Session resets |
Info |
⬡ Session window reset — token counters cleared |
Model Switcher
Click Model: sonnet-4-6 — click to switch in the Config section to open a QuickPick:
> sonnet-4-6 (← active)
opus-4-6
haiku-4-5-20251001
Reset to default (Claude Code decides)
Select a model to update ~/.claude/settings.json. Takes effect on the next Claude Code session. The status bar and sidebar update immediately to reflect your selection.
A note on session timers
Claude Lens shows two different time values:
| Value |
Source |
Meaning |
| Plan Quota "resets in" |
Anthropic API (api/oauth/usage) |
The real claude.ai session window — accurate |
| Status bar ⏱ timer |
JSONL file first-entry timestamp + 5h |
The current JSONL file boundary — may differ from the claude.ai window |
Claude Code writes one JSONL file per workspace session, but the claude.ai usage window is managed server-side and may have started at a different time. The Plan Quota section is the authoritative source for when your session resets.
Commands
(Ctrl+Shift+P → Claude Lens: ...)
| Command |
Description |
Open HUD |
Focus the Claude Lens sidebar |
Reset Session |
Clear current session counters (not Plan Quota) |
Clear Local History |
Wipe all stored session data from VS Code globalState |
Edit .claudelens |
Open the config file in the editor |
Create .claudelens |
Scaffold a new config at the workspace root |
Manual Token Entry |
Enter token counts manually (for claude.ai-only users) |
Set Anthropic API Key |
Store API key in SecretStorage for Usage API provider |
Clear Anthropic API Key |
Remove stored API key |
Switch Claude Code Model |
QuickPick to change active model (writes to ~/.claude/settings.json) |
View Usage on claude.ai |
Open https://claude.ai/settings/usage in browser |
Pricing reference
Bundled in resources/priceTable.json. Never fetched from the network.
| Model |
Input $/1M |
Output $/1M |
Cache Write $/1M |
Cache Read $/1M |
| claude-opus-4-6 |
$5.00 |
$25.00 |
$6.25 |
$0.50 |
| claude-sonnet-4-6 |
$3.00 |
$15.00 |
$3.75 |
$0.30 |
| claude-haiku-4-5-20251001 |
$1.00 |
$5.00 |
$1.25 |
$0.10 |
| claude-3-5-haiku-20241022 |
$0.80 |
$4.00 |
$1.00 |
$0.08 |
To override pricing, add to VS Code settings.json:
"claudeLens.priceOverrides": {
"claude-sonnet-4-6": {
"inputPerMillion": 3.00,
"outputPerMillion": 15.00,
"cacheWritePerMillion": 3.75,
"cacheReadPerMillion": 0.30
}
}
Privacy & Security
| Principle |
Implementation |
| Minimal network calls |
Two outbound calls: (1) api.anthropic.com/api/oauth/usage — read-only, using your existing Claude Code token. (2) Anthropic Usage API only if you explicitly provide an API key. All other data is local. |
| No telemetry |
Zero usage tracking, crash reporting, or analytics |
| API key in SecretStorage only |
If you provide an Anthropic API key, stored in VS Code SecretStorage — never in settings or .claudelens |
| OAuth token never stored by us |
The Claude Code token is read from disk each poll and never written anywhere by Claude Lens |
| Local state only |
Session data in VS Code globalState — never in the cloud |
.claudelens is safe to commit |
Contains no secrets or credentials |
| No hardcoded credentials |
All secrets are read from secure sources at runtime |
Development
Prerequisites
node >= 18.0.0
npm >= 9.0.0
Build and run
git clone https://github.com/shouvikm2/claude-lens
cd claude-lens
npm install
npm run compile
# Launch Extension Development Host
code --extensionDevelopmentPath=$(pwd)
# Or press F5 in VS Code
Run tests
npm test
Test suites:
test/suite/budgetEngine.test.ts — 7 tests
test/suite/workspaceConfig.test.ts — 6 tests
Watch mode
npm run watch
# Ctrl+Shift+P → Developer: Reload Window
Lint
npm run lint
Package
npm run compile
npx @vscode/vsce package
# Produces claude-lens-0.1.0.vsix
Publish
VS Code Marketplace:
npx @vscode/vsce publish
# Requires token with marketplace:publish scope
Open VSX (VSCodium, Gitpod, Theia):
npx ovsx publish claude-lens-0.1.0.vsix -p <token>
Roadmap
✅ Phase 1 — Core (shipped)
- JSONL log reader + polling watcher
- Session state machine
- Budget engine — session / daily / weekly caps
- Alert system — soft and hard thresholds
- Status bar — live cost + model + timer
- Sidebar — budget, session detail, config
✅ Phase 2 — Differentiation (shipped)
- ROI scorer — heuristic model-fit engine with cache-aware context sizing
- Anthropic Usage API provider (API billing users)
- Plan Quota from Anthropic's OAuth endpoint
✅ Phase 2.5 — Model Switching (shipped)
- Real session % and weekly % from
api.anthropic.com/api/oauth/usage
- Proactive toasts at 80% and 90%
- Auto-refresh OAuth token from disk on every poll
- API Cost Estimate collapsed by default for Pro/Max subscribers
- Model switcher — change active model from Config section
- Re-enabled ROI — now actionable with model switching
- Immediate quota refresh after each turn (15s rate-limited)
🔲 Phase 3 — HUD (future)
- Floating webview with Chart.js charts
- Burn rate sparkline (last 60 minutes)
- Session reset countdown ring
- Cost analytics by model and complexity
FAQ
Q: Is my data stored in the cloud?
A: No. Session data lives only in VS Code's local globalState. Plan Quota data comes from a read-only Anthropic API call. Nothing is stored on our servers.
Q: What if I switch models mid-session?
A: Claude Lens tracks the model active when each turn starts. If you switch in the Config section, the change applies to the next Claude Code session. Current session continues with the old model.
Q: Why is the status bar timer different from Plan Quota?
A: Claude Code's JSONL file starts from when you opened the editor. Claude.ai's session window is server-managed and may have started at a different time. The Plan Quota "resets in" is authoritative.
Q: Can I use Claude Lens with claude.ai directly (not Claude Code)?
A: Yes, with limitations. Set your Anthropic API key (for Usage API) or use Manual Token Entry. You'll see API cost estimates. Plan Quota requires the OAuth token from Claude Code.
Q: Does Claude Lens work offline?
A: Claude Code logs are local — yes. Plan Quota and Anthropic Usage API require internet — no. Sidebar gracefully shows "Fetching usage..." if offline.
License
MIT — see LICENSE.
Built for developers who want to ship more without hitting the wall.