Skip to content

feat: display provider usage limits in settings#1732

Open
Aditya190803 wants to merge 74 commits intopingdotgg:mainfrom
Aditya190803:feat/provider-usage-limits
Open

feat: display provider usage limits in settings#1732
Aditya190803 wants to merge 74 commits intopingdotgg:mainfrom
Aditya190803:feat/provider-usage-limits

Conversation

@Aditya190803
Copy link
Copy Markdown

@Aditya190803 Aditya190803 commented Apr 4, 2026

Fixes #228.

What Changed

Added provider usage limits to the settings flow end to end for all 4 providers (Codex, Claude, Cursor, OpenCode):

  • the shared contract now includes the usage-limits schema
  • the server persists and exposes provider usage limits
  • the web app renders the limits in Settings

Note: For OpenCode, only the official OpenCode-managed providers (OpenCode Go, OpenCode Zen) are shown.

Why

Users need a visible place to confirm provider usage limits without digging through logs or backend state. This keeps the value available across sessions and makes the current limits easy to inspect from the UI.

UI Changes

The Settings panel now shows provider usage limits in the provider section.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Adds a new usageLimits field to the provider contract and wires it through multiple provider probes plus a new runtime state tracker; mistakes could surface incorrect quota info or add latency (notably Claude PTY probing) but does not touch auth/permissions logic.

Overview
Provider snapshots now include quota/usage metadata. The ServerProvider contract gains optional usageLimits (session/weekly windows, reset timestamps, availability + reason), and snapshot building/caching is updated to persist and hydrate this field.

Server-side usage sourcing is added per provider. Codex fetches rate-limit windows during probe, OpenCode derives usage from managed upstream providers, Cursor converts ACP usage_update notifications into thread.token-usage.updated, and Claude can probe usage via a PTY-driven /status/usage flow; a new ProviderUsageStateLive service listens to runtime events (Cursor token usage + Claude rate-limit telemetry) and exposes the latest per-provider/instance usage back into status checks.

UI surfaces usage in Settings and reduces noise elsewhere. ProviderInstanceCard renders usage progress bars with threshold coloring and reset times, and the work log filters out account quota telemetry activities; minor React hook dependency fixes and new tests cover parsing/mapping and rendering behavior.

Reviewed by Cursor Bugbot for commit 94ba4ac. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Display provider usage limits with progress bars in settings panel

  • Adds usageLimits to the ServerProvider contract with session/weekly usage windows, availability status, and optional reset timestamps, sourced from Codex, Claude, Cursor, and OpenCode providers.
  • Introduces ProviderUsageStateLive, a new in-memory service that tracks per-provider usage by consuming runtime events (thread.token-usage.updated for Cursor, account.rate-limits.updated for Claude).
  • Probes Claude usage limits via a PTY-driven /status+/usage CLI flow (probeClaudeUsageLimits), parsing ANSI terminal output into normalized session/weekly windows.
  • Renders usage progress bars in ProviderInstanceCard with threshold-based colors (warning at 70%, destructive at 90%) and optional reset timestamps.
  • Filters account quota telemetry events (account.rate-limits.updated, account quota updated) from the session work log.
  • Behavioral Change: provider probes now fetch and expose usage data, which may increase probe latency for Claude (PTY spawn) and Codex (additional rate limits API call).

Macroscope summarized 94ba4ac.


Open in Devin Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0fd3598e-6121-4eac-bef8-200867e2239d

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Apr 4, 2026
@Aditya190803
Copy link
Copy Markdown
Author

For now, I’ve added two images to illustrate the UI:

1. Free tier view

This screenshot reflects my current setup. I don’t have subscriptions to Codex or Claude Code, I’m using Copilot Pro (available to me as a student). It shows how the weekly usage limit appears in the interface.

Free Tier Screenshot

2. Pro tier (mocked example)

This second screenshot uses dummy data to demonstrate how the UI could look for users on a Pro plan (Codex or Claude Code). It includes both session-based limits and weekly limits for clarity.

Pro Tier Mock Screenshot

Comment thread apps/server/src/persistence/Layers/ProviderUsageLimits.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 80515efa38

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +574 to +578
state?.usageLimits
? usageLimitsRepository
.upsert({
provider: PROVIDER,
usageLimits: state.usageLimits,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stop re-persisting stale cached Codex usage limits

This Effect.tap writes the accountProbeCache value back into provider_usage_limits on every Codex status check. Because the probe cache is valid for 5 minutes, a newer usage-limit update persisted from runtime events (via ProviderService's account.rate-limits.updated handling) can be overwritten by this older cached snapshot, causing limits to regress in storage and UI until cache expiry. Please avoid upserting cached probe data unconditionally (or at least reject older timestamps).

Useful? React with 👍 / 👎.

Comment on lines +494 to +496
const usageLimits = isResolvedCodexAccountState(account)
? (account.usageLimits ?? cachedUsageLimits)
: cachedUsageLimits;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prefer persisted usage limits over account-probe cache

When both values exist, this branch prioritizes account.usageLimits from the 5-minute accountProbeCache and ignores cachedUsageLimits loaded from persistence. That means even after a fresh runtime usage-limit event is stored, provider refreshes keep serving stale probe data instead of the latest persisted snapshot. Reversing this precedence prevents stale limits from being shown after updates.

Useful? React with 👍 / 👎.

@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented Apr 4, 2026

Approvability

Verdict: Needs human review

New feature introducing provider usage limit display across multiple providers with new service infrastructure. Multiple unresolved P1 review comments identify potential issues with cache/persistence precedence that need resolution before merging.

You can customize Macroscope's approvability policy. Learn more.

Comment thread apps/server/src/provider/codexAppServer.ts Outdated
@Aditya190803
Copy link
Copy Markdown
Author

Hey @juliusmarminge, could you take a look at this PR when you get a moment? Thanks!

@Marve10s
Copy link
Copy Markdown
Contributor

Marve10s commented Apr 6, 2026

Randomly found this PR because wanted to add usage to T3. I think this is great as a user but also I think the UI should match the Codex App usage,it's minimal and clean, would be better than AI tabs
image

You would need to redo the settings button though,something Julius needs to approve. I genuinely think settings button should match Codex App, would love to open PR for that.

@Marve10s
Copy link
Copy Markdown
Contributor

Marve10s commented Apr 6, 2026

A few concerns after checking the code:

  1. Codex can prefer stale persisted usage over freshly probed usage in the same refresh path.
    checkCodexProviderStatus() reads cachedUsageLimits first, then later resolves account state, but ultimately uses cachedUsageLimits ?? accountUsageLimits. That means a refresh can still emit an older persisted value even when the same refresh just fetched newer limits from the provider probe. If the goal is to show the freshest available snapshot, I think the precedence likely needs to be reversed, or persisted data should only be used when no fresh usage was fetched.
  2. The persisted cache looks too coarse-grained for account/config changes.
    The new table is keyed only by provider_name, and the repo API is also getByProvider only. That seems risky if the user changes auth state, swaps Codex homePath, changes binary path, or otherwise changes the effective account behind a provider. In those cases we can still surface previously persisted usage for the provider even though it may belong to a different account/config. Is that safe, or should this cache be scoped more tightly (for example by provider + account/config fingerprint) or suppressed when provider health/auth no longer matches the cached source?
  3. A usage-limit update currently looks like it can trigger full provider refresh work.
    ProviderService persists account.rate-limits.updated, then ProviderRegistry listens to repository changes and calls refresh(change.provider). That refresh path eventually reruns the provider's checkProvider flow rather than just updating already-known snapshot state. For a quota-bar style UI update, this feels heavier than necessary and could add extra CLI churn to a hot path. Would it be simpler to keep usage attached to the provider snapshot/update flow directly instead of going through persistence -> repository stream -> provider refresh?

I can test further and commit to this PR if you're okay with it, @Aditya190803. Genuinely want to see this merged - it would be super useful

@juliusmarminge
Copy link
Copy Markdown
Member

this is on my list to review still! Just dealing with some larger prep work so haven't had time yet.

As for the "it must be more visible and sjhould be 1:1 like codex app":

How often do you guys check your limits to warrant it being one click ??? I check it at most a few times a week, so hiding it in settings next to the provider status is fine!

@Marve10s
Copy link
Copy Markdown
Contributor

Marve10s commented Apr 6, 2026

this is on my list to review still! Just dealing with some larger prep work so haven't had time yet.

As for the "it must be more visible and sjhould be 1:1 like codex app":

How often do you guys check your limits to warrant it being one click ??? I check it at most a few times a week, so hiding it in settings next to the provider status is fine!

I've been checking usage a lot in Codex - a couple of times daily since I was on the $20 plan with 2x limits till April, so I was curious how it was going. My take is that the current settings are genuinely fine, but I think it'll get crowded soon. With usage, OpenCode and Cursor support, and I'm sure there are PRs that extend the settings further it's going to contain a lot of content before long.
Codex shows a small tab with everything you need: usage, general info, and language (something I'd tuck away in settings). I think the Cursor settings approach is a good reference here too.

image

@juliusmarminge
Copy link
Copy Markdown
Member

Yes when the single settings page gets too large we'll split it to subpages. We already did the work adding the sidebar when adding the archive

@juliusmarminge
Copy link
Copy Markdown
Member

can't see claude limits:
CleanShot 2026-04-06 at 15 21 34@2x

Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

implementation seems way overcomplicated.

why cache the data? the provider check runs once per minute. we can get fresh data on every tick?

how i imaagined this working:

  • extend the checkProvider probe in ServerProvider to include a new usageLimits property.
  • on the auth check probes (app server / claude), extract usage data
  • stream it down to client as part of the normal provider snapshot
  • render the UI on settings page

given i haven't looked into exactly what's possible to probe and not, why is this PR so much more than that?

@github-actions github-actions Bot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Apr 7, 2026
Comment thread apps/server/src/provider/Layers/ClaudeProvider.ts
Comment thread apps/server/src/server.ts
Berkay2002 added a commit to Berkay2002/bcode that referenced this pull request Apr 16, 2026
Cherry-picked from upstream pingdotgg#1732
Conflicts resolved manually.
@Aditya190803 Aditya190803 force-pushed the feat/provider-usage-limits branch from f9aabcd to 171df70 Compare April 17, 2026 06:07
@github-actions github-actions Bot added size:XL 500-999 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Apr 17, 2026
Comment thread apps/server/src/provider/Layers/ClaudeProvider.ts Outdated
Comment thread apps/server/src/provider/providerUsageLimits.ts Outdated
@github-actions github-actions Bot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Apr 17, 2026
Comment thread apps/server/src/provider/codexAppServer.ts Outdated
Comment thread apps/server/src/provider/Layers/ClaudeProvider.ts Outdated
…d union and simplify usage limit label generation
- Refactor claudeUsageProbe to use shared PtyAdapter instead of ad-hoc node-pty
- Add parseClaudeRuntimeUsageLimits for SDK rate-limit event parsing
- Add ProviderUsageState layer with tests
- Integrate usage state into ClaudeDriver and ClaudeProvider
- Add migration 029 for auth session compatibility columns (keep 021 intact)
- Update server and tests for usage limits wiring
Comment thread apps/server/src/provider/Layers/CursorProvider.ts Outdated
Comment thread apps/server/src/provider/Layers/ProviderUsageState.ts
Comment thread apps/server/src/persistence/Migrations/029_AuthCompatibilityColumns.ts Outdated
Comment thread apps/server/src/provider/claudeUsageProbe.ts Outdated
Comment thread apps/server/src/server.ts Outdated
Comment thread apps/web/src/components/settings/ProviderInstanceCard.tsx
Comment thread apps/web/src/components/settings/SettingsPanels.tsx Outdated
Comment thread apps/server/src/provider/providerUsageLimits.ts
Comment thread apps/web/src/components/settings/ProviderInstanceCard.tsx Outdated
Comment thread apps/server/src/persistence/Migrations/030_AuthCompatibilityColumns.ts Outdated
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fee4110. Configure here.

Comment thread apps/server/src/provider/Layers/ClaudeProvider.ts Outdated
Comment thread apps/server/src/server.ts Outdated
@Aditya190803
Copy link
Copy Markdown
Author

@juliusmarminge
Could you review it once more.

Resolved merge conflicts and fixed typecheck errors introduced by
origin/main's stricter Effect lint rules (importFromBarrel, globalDate,
globalDateInEffect). Migrated barrel imports to subpath imports and
replaced Date.now()/new Date() with Effect DateTime/Clock APIs.
Comment thread apps/server/src/provider/Layers/ClaudeAdapter.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ 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.

feat: add usage / quota visibility for Codex sessions and accounts

4 participants