feat(usage): show subscription limits - #8327
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
There was a problem hiding this comment.
One finding in apps/web/src/components/usage/UsagePage.tsx: the loading skeleton was not updated alongside the reshaped provider summary row, so the page still shifts when data lands. Details inline.
Posted via Macroscope — UI Consistency
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This is a substantial new subscription-quota capability spanning provider subprocess/API probes, transcript reads, caching, shared contracts, and web/mobile UI behavior. The broad production runtime and cross-component surface require human review despite backward-compatible schema handling and focused tests. You can add or adjust custom eligibility rules. Learn more. |
There was a problem hiding this comment.
Reviewed the web usage UI changes (UsagePage.tsx, UsageProviderChart.tsx, UsagePage.test.tsx) for shared-primitive use, Tailwind ownership, and layout/skeleton parity.
The skeleton reshape from the previous round now matches the loaded provider rows (mark size, gap-6/gap-1.5/gap-0.5, second summary line, meter grid, min-h-60 chart), so that earlier finding is resolved. Two smaller items remain, both in apps/web/src/components/usage/UsagePage.tsx; neither blocks the feature.
Posted via Macroscope — UI Consistency
|
Note 🤖 Claude Fable 5 responding on behalf of Theo Thanks for this. The shape is right: probe only on Usage page loads, cache server side, degrade to no meters on failure. We compared it against CodexBar, ccusage, Claude-Code-Usage-Monitor, CCSeva, and the codex TUI itself. Four things need to change before merge, and a few follow-ups are worth tracking. Must fix
Worth doing, your call whether here or in the follow-up you already offered
For what it is worth, we verified the earlier review findings are genuinely fixed at head (contract stays v4 with a decoding default, the mobile date crash, the cache-miss respawn churn, the blocking join), and the page-view-only trigger makes this the most conservative fetch cadence of any tool we compared. No evidence anywhere of accounts banned for polling these endpoints; the failure mode is 429, which is why item 1 is the one that matters most. |
|
For auth-independent visual review, run: T3CODE_DEV_USAGE_LIMITS_FIXTURE=review vp run devThis fixture is deliberate. Theo mentioned that CLIProxyAPI makes the native probes difficult to exercise on his machine, so the PR includes a development-only path for reviewing the UI without provider credentials. It is accepted only when the server has a Vite development URL and renders representative Codex weekly and Claude five-hour, weekly, and Fable windows. Normal builds do not use it. |
|
Addressed the stream review in Must fixes
Follow-ups included here
The development fixture remains intentional for CLIProxyAPI review: T3CODE_DEV_USAGE_LIMITS_FIXTURE=review vp run devIt is gated on the Vite development URL and does not ship as a production path. It renders representative Codex weekly and Claude five-hour, weekly, and Fable windows without touching provider auth. Verification at head: 50 focused tests passed, targeted server/contracts/shared/web/mobile typechecks passed, targeted lint passed, and live Claude/Codex values matched their CLIs. The separate cross-environment multi-account identity problem remains follow-up work; this commit does not claim to solve it. |
There was a problem hiding this comment.
UI consistency review of the new Usage subscription-limit meters. Two small issues in apps/web/src/components/usage/UsagePage.tsx, both in the new UsageLimitMeters markup; the rest of the reshaped provider rows, the skeleton, and the chart flex geometry look consistent with the loaded layout.
Posted via Macroscope — UI Consistency
…scription-limits # Conflicts: # apps/server/src/usage/UsageService.ts # packages/shared/src/usageMerge.test.ts # packages/shared/src/usageMerge.ts
There was a problem hiding this comment.
One finding: the per-provider chart color swatch was dropped from the summary rows, leaving the provider chart with no color legend when a provider has no quota meters. Previously flagged items (label overflow in the fixed 2.25rem track, window-agnostic aria-valuetext, duplicated meter geometry, skeleton shape) look addressed.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
Effect service conventions: one finding — the new subscription-limits code inside UsageService.make reads the process environment from the module global process.env instead of the HostProcessEnvironment reference the same constructor already binds (hostEnvironment, line 154, used at line 387). Everything else in the diff (namespace subpath imports, make/layer shape, Context.Service tag, dependency acquisition via yield*, no new runtimes or runPromise, no new error classes) matches the conventions.
Posted via Macroscope — Effect Service Conventions
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 67b7533. Configure here.
The transcript snapshot parser required `payload.info.rate_limits`, but codex-rs persists `rate_limits` as a sibling of `info`, so no real rollout ever matched and every cold read still spawned the app-server probe. Read the real shape and ignore model-scoped buckets (any `limit_id` other than `codex`, or absent on older builds) on both the transcript and probe paths so a Spark turn cannot present its windows as the account limit. Only short-circuit the page's wait when every enabled provider has settled, so a fast Codex snapshot no longer ships the page without Claude's meters. Verified against live rollouts in ~/.codex/sessions: the account line parses and the codex_bengalfox line is rejected.
|
@t3dotgg I believe all feedback is addressed and this is ready for your eyes again. One known major gap: when the CLIs route through a proxy or otherwise aren't signed into a single real account, both probes return nothing and the meters are omitted. The empty state is honest, but it means this feature is invisible on setups like yours, as you mentioned on stream last night that your auth doesn't go through the standard login. The pipeline (probe → normalize → cache → contract) can take another source as an adapter; what's missing is an account identity on I'd be excited by the opportunity to take that as the follow-up, but I'd rather design it against your real configuration than guess. If you're open to it, could you describe how exactly your auth is set up so I can replicate locally and think it over? Happy to take that in a live discussion instead of this thread if that's easier, or more secure for you to talk about privately. |
|
Note 🤖 GPT-5.6 Sol responding on behalf of Theo We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together. We are continuing with #1732 as the provider-limit source and #8445 as its separate composer follow-up. This branch has useful decoder, cache, and backoff work, but keeping its alternate ingestion and UI path would split ownership. If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed. |

What changed
T3 Code's Usage page showed API-equivalent spend and tokens, but subscription users could not see how close they were to provider limits.
This PR reads the structured quota windows exposed by the local Claude Code and Codex runtimes and shows compact meters beside each provider's existing cost and token summary. Web, desktop, and mobile show the same windows and reset countdowns. Providers without supported quota data keep the existing summary without meters.
The server performs this work only when the Usage page requests a summary. Successful values are cached for 180 seconds. Failures back off for 10 minutes instead of repeatedly spawning a CLI. A failed refresh keeps the last successful values visible with their age.
Claude reports five-hour, weekly, and model-scoped weekly windows such as Fable. Codex reuses an account-accurate rate-limit snapshot from a session transcript when one is less than 180 seconds old. It starts the native app-server probe only when no fresh snapshot or cache entry exists. Codex labels five-hour, daily, weekly, monthly, and annual windows with the same 5% duration tolerance used by the Codex TUI. It does not invent an unlimited window that the provider did not report.
Review fixture
Theo noted that CLIProxyAPI authentication makes the native probes hard to exercise on his machine. This development-only fixture keeps the UI reviewable without provider credentials:
The fixture is accepted only when the server has a Vite development URL. It renders representative Codex weekly and Claude five-hour, weekly, and Fable windows. Normal builds continue to use fresh local snapshots and native provider probes.
UI changes
Before:
After:
Verification
vp test run apps/server/src/usage/usageSubscriptionLimits.test.ts apps/server/src/usage/usageTranscriptReader.test.ts packages/shared/src/usageFormat.test.ts packages/shared/src/usageMerge.test.ts apps/web/src/components/usage/UsagePage.test.tsx(50 tests)t3,@t3tools/web,@t3tools/mobile,@t3tools/contracts, and@t3tools/shared~/.codex/sessionsrollouts: the accountrate_limitsline parses and model-scopedlimit_idbuckets (Spark) are rejectedChecklist
Built with GPT-5.6 Sol in the Codex harness through T3 Code.
Note
Add subscription limits to usage page with per-provider quota meters
probeClaudeUsageandprobeCodexRateLimits, with in-memory caching, TTL/backoff, and background refresh under a single-permit semaphore inUsageService.makeUsageSummaryschema withsubscriptionLimitsfield (defaults to empty array on decode) and merges newest per-provider limits across environments inmergeUsagereadFreshCodexRateLimitsSnapshot) as a local recovery path when probe fails or cache is staleUsageLimitMeters) and mobile (UsageRouteScreen) with progress bars, live reset countdowns updated every minute, observation-age text, and tooltips; loading skeletons match the new layoutformatUsageResetCountdown,formatUsageResetDateTime, andformatUsageObservationAgein usageFormat.tsUsageSummarygains a newsubscriptionLimitsarray field; older payloads without it decode to[].UsageService.layerTeststub updated to returnsubscriptionLimits: [].Macroscope summarized c902fe1.
Note
Medium Risk
Touches usage summary contract v5, spawns provider CLIs during usage reads, and adds caching/concurrency logic; failures are isolated from transcript scans but probe or normalization bugs could misrepresent quotas.
Overview
Adds subscription quota visibility to the Usage page by extending the usage API with
subscriptionLimits(contract v5) and rendering per-provider limit meters on web, desktop, and mobile beside existing cost/token summaries.The server probes local Claude Code and Codex CLIs (plus a Codex transcript tail fallback when account snapshots are fresh), normalizes windows (5h, weekly, model-scoped, plan-specific Codex durations), and returns limits through a cached refresh path (3m success / 10m failure TTL, last-known-good with stale age, ~5s wait budget) without blocking transcript usage if probes fail. Clients show progress bars, reset countdowns, and stale “last updated” copy; a dev-only
T3CODE_DEV_USAGE_LIMITS_FIXTURE=reviewfixture supports UI review.Reviewed by Cursor Bugbot for commit c902fe1. Bugbot is set up for automated code reviews on this repo. Configure here.