Skip to content

burn limits: quota-window tracking across providers #5

@willwashburn

Description

@willwashburn

Why

Spend has two axes: dollars and quota consumption. Many users are on Claude Pro/Max plans where hitting the 5-hour wall matters more than the dollar total. Burn today reports only $; adding quota windows completes the picture and directly serves the meta-goal of "is my current harness/model choice efficient?"

Endpoints

Reverse-engineered by TokenTracker — see their src/lib/usage-limits.js:55-588. Reusing, not re-deriving.

Provider Endpoint / method Auth Returns
Claude GET https://api.anthropic.com/api/oauth/usage OAuth token from Claude Code state five_hour, seven_day, seven_day_opus, extra_usage — each with percent_used, reset_at
Codex GET https://chatgpt.com/backend-api/wham/usage ChatGPT session primary_window, secondary_window (Auto / API lanes)
Cursor SQLite auth extract + CSV fetch State DB plan.totalPercentUsed, on-demand cents
Gemini Per-model remaining-token budget endpoint API key Remaining-fraction per model

MVP scope

Claude only in this issue. File follow-ups for Codex / Cursor / Gemini when those readers land (currently Codex is scaffolded, others deferred).

CLI

burn limits                # one-shot snapshot
burn limits --watch [5s]   # refresh loop, default 5s interval
burn limits --json         # programmatic

Output shape (TTY):

Claude
  5-hour      34% used  resets in 2h 14m
  7-day       12% used  resets in 4d 6h
  7-day Opus   8% used  resets in 4d 6h

Constraints

  • Don't log or persist OAuth tokens; read from Claude Code's existing state on each invocation.
  • Cache responses for ≤ 30s in-process to support --watch without hammering the endpoint.
  • If the OAuth token is absent or expired, print one clear line explaining where it should be and how to refresh — no stack trace.
  • No background daemon. burn limits is a foreground command.

Acceptance

  • burn limits prints Claude's 5-hour and 7-day windows with correct percent-used and a human-friendly time-to-reset.
  • --watch refreshes in-place without flicker and exits cleanly on Ctrl-C.
  • Token-missing case produces a one-line actionable message, exit code 2.
  • Unit test mocks the endpoint and asserts parsing + formatting for each window type.

Depends on

Nothing. Independent of #1 / #2 / #3.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions