Limits adapter

Claude.ai Subscription Quota

Opt-in Claude.ai quota gauges stored in the OS keychain and shown with Claude Code usage.

Claude.ai Subscription Quota

tokenuse can optionally show Claude.ai subscription-quota gauges (5-hour / 7-day / 7-day Opus / 7-day Sonnet / Extra Usage) next to your Claude Code spend. It is opt-in, user-triggered, and gated behind the quota-sync Cargo feature (on by default).

Status: implemented (limits-only adapter, no session ingestion).

How it works

  1. You add your sessionKey cookie from https://claude.ai to the OS keychain — see Adding the cookie.

  2. From the Config page, you select Claude.ai subscription quota → Sync and confirm.

  3. src/tools/claude_subscription/limits.rs::refresh_sidecar reads the cookie from the keychain, calls Claude.ai’s web-app usage endpoints with browser-style headers, and writes a sidecar JSON to:

    <config dir>/tokenuse/limits/claude_subscription.json
  4. The adapter’s discover() picks up that sidecar on the next ingest pass and emits LimitSnapshot rows tagged with tool = "claude-code" so the gauges appear inside the existing Claude Code section.

flowchart TD A["sessionKey cookie in OS keychain"] --> B["Config page Sync action"] B --> C["GET claude.ai/api/organizations"] C --> D["GET claude.ai/api/organizations/{uuid}/usage"] C --> E["GET claude.ai/api/organizations/{uuid}/overage_spend_limit"] D --> F["limits/claude_subscription.json"] E --> F F --> G["LimitSnapshot rows tagged tool='claude-code'"]

The cookie never leaves your machine. It is stored in:

PlatformStorage
macOSKeychain (Security framework)
WindowsCredential Manager (wincred)
LinuxSecret Service over D-Bus (gnome-keyring / KWallet / KeePassXC). Headless servers without a Secret Service daemon are not supported.

Service dev.tokenuse, account claude_subscription.session.

From the terminal (in-app modal)

  1. Open https://claude.ai/settings/usage in your browser and log in.
  2. Open dev tools → Application → Cookies → https://claude.ai.
  3. Copy the value of the sessionKey cookie.
  4. Launch the dashboard (tokenuse), press c to open the Config page, scroll to Claude.ai subscription quota and press Enter.
  5. In the cookie modal, paste the value (Cmd/Ctrl+V — bracketed paste is enabled, so long cookies arrive as a single chunk). The input is masked to and shows a character count next to it.
  6. Use ←/→ to choose Save & sync and press Enter. The status bar shows “Syncing…” while the request runs on a worker thread; on success the Usage page gauges populate.
  7. The modal also offers Sync with stored cookie (re-run against the already-saved cookie) and Clear stored cookie (delete from the OS keychain).

Esc closes the modal at any time; an in-flight sync continues in the background and its result still updates the status bar.

From the terminal (one-shot CLI)

The non-interactive flags are still supported for scripted set-up:

tokenuse --set-claude-cookie 'sk-ant-sid01-...'
tokenuse --clear-claude-cookie

--set-claude-cookie <value> is visible in shell history. Use read -s or a similar pattern if that’s a concern for your environment. The in-app modal does not leak to history.

From the desktop app

The Config page offers the equivalent Subscription cookie modal — see docs/guides/desktop-usage.md. Underneath it uses the same set_claude_session_cookie / clear_claude_session_cookie Tauri commands.

Sidecar format

tokenuse writes the sidecar as a wrapper object with the upstream usage and overage payloads inlined:

{
  "observed_at": "2026-05-11T12:00:00Z",
  "organization_uuid": "abc-def-...",
  "organization_name": "Personal",
  "source_usage": "https://claude.ai/api/organizations/abc-def-.../usage",
  "source_overage": "https://claude.ai/api/organizations/abc-def-.../overage_spend_limit",
  "usage": {
    "five_hour":      { "utilization": 42.5, "resets_at": "2026-05-11T18:00:00Z" },
    "seven_day":      { "utilization": 17.0, "resets_at": "2026-05-18T00:00:00Z" },
    "seven_day_opus":   { "utilization": 0,    "resets_at": null },
    "seven_day_sonnet": { "utilization": 25.0, "resets_at": "2026-05-18T00:00:00Z" }
  },
  "overage": {
    "is_enabled": true,
    "monthly_limit": 5000,
    "used_credits": 1250.0,
    "currency": "USD",
    "out_of_credits": false
  }
}

The parser also accepts a raw usage object (no wrapper) for manual snapshots.

LimitSnapshot rowSource fieldNotes
five_hourusage.five_hour.utilization / resets_atwindow 300 min
seven_dayusage.seven_day.utilization / resets_atwindow 10 080 min
seven_day_opususage.seven_day_opus.utilization / resets_atwindow 10 080 min — skipped if utilization is 0 and resets_at is null
seven_day_sonnetusage.seven_day_sonnet.utilization / resets_atwindow 10 080 min — same zero-skip
extra_usageoverage.monthly_limit, overage.used_creditsused % derived; balance in dollars ((limit − used) / 100); out_of_creditsrate_limit_reached_type

Errors and re-auth

HTTP / payloadBehaviour
401Status bar shows “Claude session expired or unauthorized” — reopen the cookie modal on the Config page (or re-run --set-claude-cookie) and paste a fresh sessionKey.
403 or HTML responseStatus bar shows “Cloudflare challenge” — usually means the user-agent/header fingerprint is stale; report an issue.
429Status bar shows “rate limited” — wait and retry.
overage endpoint 403/404Treated as “Extra Usage not enabled”; the rest of the sync still succeeds.

The sidecar is overwritten on every successful sync. There is no historical archive; integrating that is a follow-up.

Browser fingerprint

The header set in src/tools/claude_subscription/config.rs mimics Chrome 131 on macOS, including anthropic-client-platform: web_claude_ai, referer: https://claude.ai/settings/usage, and the sec-fetch-* triplet. Anthropic may change Cloudflare rules at any time; if syncs start failing with 403 / HTML responses, bump the UA in USER_AGENT and re-test.

Privacy posture

  • Cookie is stored in the OS keychain only — never in plaintext on disk, never sent anywhere except claude.ai over HTTPS.
  • No telemetry. No background polling — only the explicit Config-page Sync action triggers a network call.
  • Disable the feature entirely with cargo build --no-default-features (or omit quota-sync from your feature list); the Config row falls back to a “sync unavailable in this build” status.
  • This feature accesses your own Claude.ai account using your own credentials. It is for personal monitoring of your subscription quota and does not extract or share account data. Anthropic’s Terms of Service govern your use of the underlying endpoints.