Skip to content

fix(usage): show Claude spending budgets on the Limits view - #14911

Open
Mnigos wants to merge 8 commits into
pingdotgg:mainfrom
Mnigos:claude-spend-budget
Open

Mnigos wants to merge 8 commits into
pingdotgg:mainfrom
Mnigos:claude-spend-budget

Conversation

@Mnigos

@Mnigos Mnigos commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #10155.

Resubmission of #10160, which was closed on 2026-09-19 while the provider layer was frozen for V2 ("If this is still an issue once V2 lands, please reopen (or open a fresh PR against the new code)"). The branch is rebuilt on the new main and verified there; claudeUsageLimits.ts and the usage contract came through #2829 without conflicts. One part is new since #10160: the pooled Limits card that landed on main in the meantime now shows the amount too.

Problem

Claude Enterprise accounts, and any plan with a spending budget instead of rolling quotas, answer get_usage with five_hour and seven_day null and a populated rate_limits.spend / rate_limits.extra_usage. claudeUsageResponseToLimits only maps the rolling windows and the model-scoped weeklies, so the snapshot has no windows and both the Limits view and /usage-limits say "No limits reported." for an account with an enabled monthly budget.

Change

  • The Claude mapper reads the budget and adds a monthly_spend window ("Monthly spend"). spend wins when enabled, otherwise extra_usage when is_enabled; they describe the same budget, so one row is drawn. Rolling windows stay beside it when they exist. The percent is computed from the amounts (9.262% is not collapsed to the provider's rounded 9). A budget with an unknown used amount, a blank currency or an impossible exponent draws no row.
  • ServerProviderUsageWindow gains an optional spend (usedMinor, limitMinor, currency, exponent) carrying the provider's minor units unchanged. Older clients ignore it and still get the bar.
  • formatSpend in @t3tools/shared/usageLimits renders $46.31 of $500.00 in the budget's currency and precision. Web shows it in the usage row and bar tooltip (Limits view, /usage-limits), and on the pooled card: under the percent when one account reports the budget, and per account (segment popover, narrow legend, accessible label) when several do. Amounts from different accounts are never summed, since the pooled percent is an average. Mobile shows the amount in the row's detail line; its pooled view stays percent only.
  • User docs: the "Track subscription limits" paragraph mentions the bar, because without it the paragraph says such accounts report nothing.

spend and decimal_places are read structurally: the pinned SDK typings do not have spend yet and type extra_usage without decimal_places.

Scope and approval

Accepted bug #10155 (labels bug, accepted, via-triage). Touches the Claude usage mapper, one optional contract field, the shared formatter, and the web and mobile usage rows. Other providers are unaffected: none of them sets spend.

Verification

Real web client on V2, before and after. Headless Chromium 153 at 1400×900 (one capture at 700×900) against vp run dev, main at e9298af versus this branch, each with its own empty state. The provider is a stand-in claude binary that answers the SDK's initialize and get_usage with the payload from the issue (null rolling windows, USD budget 4631 of 50000 minor units), so the budget travels through the real probe, mapper, contract and client. No real account, credentials or model call.

Before (main) After
Before: the Limits view says Claude: No limits reported After: the Limits view shows Monthly spend, 91% left and $46.31 of $500.00 used
Before: the composer usage panel says No limits reported After: the composer usage panel shows Monthly spend, 91% left and the amount
What Observed on this branch
Segment popover, one account Left 91%, Spent $46.31 of $500.00 (capture)
Narrow layout (700 px) Amount under the percent and in the legend row (capture)
Two accounts ($46.31 of $500.00 and $120.00 of $1,000.00) Card shows 89% left with no amount; each segment shows its own (first, second)

No reset countdown or pace marker appears for the budget in any capture.

Tests. claudeUsageLimits.test.ts: the Enterprise payload yields the monthly window at 9.262%; the extra_usage fallback keeps the session window beside the budget; a disabled or unlimited budget, an unknown used amount, a blank currency and an out-of-range exponent draw nothing, while a reported 0 draws the zero-spend row. usageLimits.test.ts: currency and precision formatting including a code Intl does not know, and singleAccountSpend for one account, several accounts in the same and different currencies, no members, and a budget beside a rolling window. 60 tests pass. Typecheck for contracts, shared, server, web and mobile, targeted lint, format and knip are clean.

Not checked: a live Enterprise account (the payload shape is the one captured in the issue), the mobile app in a simulator and the packaged desktop app (mobile is typechecked; desktop renders the web code), and currencies other than USD in a client.

Implemented with Claude Code (Claude Fable 5.1 and Claude Opus 5.5); tests, independent review and evidence capture by GPT-6 Astra via Codex.

Mnigos and others added 7 commits October 3, 2026 00:01
Clients format at most twenty fraction digits and no currency has more than
four, so a wilder exponent from Claude's spend or extra_usage payload is a
malformed budget: skip the row instead of scaling it to Infinity.
The spend contract wants a trimmed, non-empty currency code. Read it once
for both the spend and extra_usage payloads: trim it, skip the budget when
it is blank, and keep dollars as the credits default.
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Oct 2, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This change adds automatic Claude spending-budget support end to end, including a new usage contract shape, provider parsing, currency formatting, pooled-account handling, and web/mobile presentation. The behavior is additive and well tested, but its multi-surface production impact exceeds a small self-contained fix.

Notes:

  • Diff unchanged. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 2, 2026 — with ChatGPT Codex Connector
@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Important

Review skipped

We couldn't safely recover the incremental review. No full review was started, and the last reviewed checkpoint was preserved. Retry later, or explicitly request a full review by commenting @coderabbitai full review.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: pingdotgg/t3code/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 294a1ea2-d1f2-4791-b20c-9ad409381bf7

📥 Commits

Reviewing files that changed from the base of the PR and between bf7121d and 2a35cb7.

📒 Files selected for processing (9)
  • apps/mobile/src/features/usage/UsageLimitsSection.tsx
  • apps/server/src/provider/Layers/claudeUsageLimits.test.ts
  • apps/server/src/provider/Layers/claudeUsageLimits.ts
  • apps/web/src/components/usage/UsageLimits.tsx
  • apps/web/src/components/usage/UsageLimitsPooled.tsx
  • docs/user/usage.md
  • packages/contracts/src/providerUsageLimits.ts
  • packages/shared/src/usageLimits.test.ts
  • packages/shared/src/usageLimits.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

Adds support for Claude monthly spending budgets through provider mapping, shared spend utilities, and web and mobile usage displays. Also updates usage documentation and adds tests for spend mapping, formatting, and pooled-account behavior.

Changes

Claude monthly spend limits

Layer / File(s) Summary
Provider spend contract and mapping
packages/contracts/src/providerUsageLimits.ts, apps/server/src/provider/Layers/claudeUsageLimits.ts, apps/server/src/provider/Layers/claudeUsageLimits.test.ts
Adds spend data to the usage-window contract. The Claude mapper validates spend and legacy extra_usage data, then adds a monthly spend window for valid budgets. Tests cover precedence, fallback, and invalid or missing budget values.
Spend formatting and pool extraction
packages/shared/src/usageLimits.ts, packages/shared/src/usageLimits.test.ts
Adds currency- and exponent-aware spend formatting and a helper that returns spend only for a single pool member. Tests cover formatting and pooled-account cases.
Spend details in usage views
apps/web/src/components/usage/UsageLimits.tsx, apps/web/src/components/usage/UsageLimitsPooled.tsx, apps/mobile/src/features/usage/UsageLimitsSection.tsx, docs/user/usage.md
Shows formatted spend in web, mobile, and pooled usage views when available. Documents the monthly spend bar and where the amount used appears.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Low

Sequence Diagram(s)

sequenceDiagram
  participant Claude as Claude_get_usage
  participant Mapper as claudeUsageResponseToLimits
  participant Window as ServerProviderUsageWindow
  participant Formatter as formatSpend
  participant Views as Usage_limit_views
  Claude->>Mapper: rate_limits.spend and extra_usage
  Mapper->>Window: valid monthly_spend window with spend details
  Window->>Formatter: amounts, currency, and exponent
  Formatter->>Views: formatted spend
Loading

Possibly related PRs

  • pingdotgg/t3code#10160: Implements the same Claude spend mapping, contract, formatting, and usage-view changes.

Suggested reviewers: juliusmarminge

Merge Risk: ⚪ Minimal · up to 2a35c

The reviewed monthly-budget behavior is ready to merge after normal checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 2a35c

The change is display-oriented and adds budget amounts to existing usage views. No new privilege or budget-enforcement operation was identified. Risk appears low, but older-client compatibility and refresh recovery are not fully established.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — Financial amounts inherit the environment configuration’s provider-list exposure, rather than being restricted by whichever account row is selected in the UI. The supported exposure scope is the provider accounts returned for that environment to configuration readers; no additional tenant or service reachability was established.

Trust Boundaries and Controls

  • observed — Configuration retrieval requires orchestration-read scope and passes through an authorization wrapper that checks the current session’s scopes. Configuration subscription is mapped to the same required scope. No spend-specific privilege is added to these inspected contracts.
  • observed — Provider-derived spend and currency values terminate as formatted React or native text and accessible labels in the inspected displays, not as evaluated code or spend-derived navigation targets.

Resilience and Maintainability Implications

  • observed — Each mapper invocation constructs a fresh window array and appends at most one selected budget row. This establishes deterministic local construction, but not the concurrency, cancellation, or recovery invariants of downstream snapshot publication.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 21 functions across 8 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description covers the Problem, Change, Scope and approval, and Verification sections. It identifies issue #10155, explains the implementation, documents test and manual verification results, incl…
Title check ✅ Passed The title is concise, uses the conventional commit format, and clearly identifies the main change: displaying Claude spending budgets in the Limits view.
Linked Issues check ✅ Passed The changes meet the coding requirements in [#10155]. claudeUsageResponseToLimits reads enabled spend data and falls back to enabled extra_usage. It creates one monthly_spend window when rolli…
Out of Scope Changes check ✅ Passed The changes stay within [#10155]. The contract field, Claude mapper, regression tests, shared formatter, pooled-account handling, web and mobile displays, and usage documentation directly support prov…
Full details: Docstring Coverage

Explanation

Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 21 functions across 8 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Claude Enterprise spending budget is ignored, showing “No limits reported”

2 participants