Daeseon Yoo
Back to project
·Tech retro·3 min

Real AI usage gauges — from a ccusage estimate to the OAuth endpoint Claude Code itself uses

An always-on top-right strip shows current usage/limits for Claude, Codex, and Antigravity, with a click-to-open detail popup. Codex is read straight from the local rollout JSONL (real, zero-network). Claude started as a ccusage-style local estimate — but the estimate didn't match claude.ai's real 5%/9%, so we found the actual endpoint Claude Code uses (api/oauth/usage, authed by the OAuth token in the macOS Keychain) and switched to real numbers with the estimate as fallback. Every path is a usage *query* — zero tokens, no inference, BYO-clean.

The goal

One always-visible strip (top-right) with a tiny color gauge per provider — Claude · Codex · Antigravity — and a click-to-open popup with 5-hour + weekly bars, reset countdowns, and the plan label. The hard part was never the UI; it was: can we read each provider's real remaining limit locally, without spending a token?

What's actually readable, per provider (verified on the machine)

The estimate ≠ reality, so we went looking for the real endpoint

The gauge showed one thing; claude.ai → Settings → Usage showed 5% session / 9% weekly, Max (20x). The relative "vs your own peak" estimate is honest but it isn't the real quota. That screen exists, so something serves the real data.

It does: GET https://api.anthropic.com/api/oauth/usage, authed with the OAuth access token Claude Code stores in the macOS Keychain (security find-generic-password -s "Claude Code-credentials" → JSON with accessToken, subscriptionType: "max", rateLimitTier: "default_claude_max_20x"). The Keychain item also gives the plan label with zero network.

Before writing a parser against a guessed shape, we made one live call and read the actual response:

{ "five_hour":  { "utilization": 8.0,  "resets_at": "2026-06-07T23:00:00Z" },
  "seven_day":  { "utilization": 10.0, "resets_at": "2026-06-14T11:59:59Z" },
  "seven_day_sonnet": { "utilization": 0.0, "resets_at": "..." } }

Near 1:1 with the Settings UI. utilization is 0–100, resets_at is ISO. Bearer alone works.

What shipped

The lesson (Pattern)

Twice in this thread the cheap-but-wrong move was to assume — first "Claude limits aren't readable" (false: they are, via the OAuth endpoint), then the JSON shape. The fix both times was the same: make one real call and read the actual bytes before writing the code. Verify the endpoint, then implement.