Skip to content

feat: Limit auto-claude window usage based on budget #1907

Open
eyalk11 wants to merge 2 commits intoAndyMik90:developfrom
eyalk11:budget
Open

feat: Limit auto-claude window usage based on budget #1907
eyalk11 wants to merge 2 commits intoAndyMik90:developfrom
eyalk11:budget

Conversation

@eyalk11
Copy link
Copy Markdown

@eyalk11 eyalk11 commented Feb 28, 2026

  • Add budgetCapPercent setting: a single unified slider that caps both session and weekly thresholds, preventing usage beyond the configured percentage of the plan (e.g. 80% budget cap).
    • Add noExtraUsage toggle: marks an account unavailable once either usage limit hits 100%, preventing Anthropic extra-usage (pay-per-use overage) from being consumed.
    • Apply both settings in profile-scorer (availability checks, fallback scoring, unified account scoring, proactive switch logic) and in usage-monitor threshold checks.
    • Add UI controls (budget cap slider + toggle) in AccountSettings below the weekly threshold slider, visible when proactive monitoring is on.
    • Add i18n keys for both new controls in en/fr settings locales.
    • Move budget cap and noExtraUsage controls into a dedicated "Usage Limits" section visible regardless of account count (no longer gated by totalAccounts > 1).
    • Budget cap and noExtraUsage now work independently of the auto-switch master toggle, so single-account users can also enforce plan limits.
    • When a budget limit is hit and no alternative account is available, emit budget-exhausted from UsageMonitor → initializeUsageMonitorForwarding calls agentManager.killAll() to stop all running agents immediately.
    • Pass agentManager into initializeUsageMonitorForwarding in index.ts (both the primary and fallback init paths).

Base Branch

  • [ X] This PR targets the develop branch (required for all feature/fix PRs)
  • This PR targets main (hotfix only - maintainers)

Description

It makes auto-claude stop when reaches X% of allowed tokens in the 5-hours window . Also, make auto-claude not consume extra-usage even if available.

Looks like that :

image

Related Issue

Closes #

Type of Change

  • 🐛 Bug fix
  • [X ] ✨ New feature
  • 📚 Documentation
  • ♻️ Refactor
  • 🧪 Test

Area

  • [ X] Frontend
  • Backend
  • Fullstack

Commit Message Format

Follow conventional commits: <type>: <subject>

Types: feat, fix, docs, style, refactor, test, chore

Example: feat: add user authentication system

AI Disclosure

  • [X ] This PR includes AI-generated code (Claude, Codex, Copilot, etc.)

Tool(s) used:
Testing level:

  • Untested -- AI output not yet verified

  • [ X ] Lightly tested -- ran the app / spot-checked key paths . I checked that it works.

  • Fully tested -- all tests pass, manually verified behavior

  • [ X] I understand what this PR does ** but not how the underlying code works**

Checklist

  • [X ] I've synced with develop branch
  • I've tested my changes locally
  • I've followed the code principles (SOLID, DRY, KISS)
  • [X ] My PR is small and focused (< 400 lines ideally)

Platform Testing Checklist

CRITICAL: This project supports Windows, macOS, and Linux. Platform-specific bugs are a common source of breakage.

  • [ X] Windows tested (either on Windows or via CI)
  • macOS tested (either on macOS or via CI)
  • Linux tested (CI covers this)
  • Used centralized platform/ module instead of direct process.platform checks
  • No hardcoded paths (used findExecutable() or platform abstractions)

If you only have access to one OS: CI now tests on all platforms. Ensure all checks pass before submitting.

CI/Testing Requirements

  • All CI checks pass on all platforms (Windows, macOS, Linux)
  • All existing tests pass
  • New features include test coverage
  • Bug fixes include regression tests

Screenshots

Before After

Feature Toggle

  • Behind localStorage flag: use_feature_name
  • Behind settings toggle
  • Behind environment variable/config
  • N/A - Feature is complete and ready for all users
  • New Features

    • Added Usage Limits settings section with a budget cap slider to constrain plan usage across all accounts and a no extra usage toggle to prevent overage
    • Agents automatically stop when budget limits are exhausted and no alternative accounts are available
  • Documentation

    • Added localization strings in English and French for new usage limits controls

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Usage Limits section in account settings with a budget cap slider to limit plan usage across all accounts
    • Added "no extra usage" toggle to prevent overage usage
    • App stops running tasks when budget limit is reached with no alternative accounts available
  • Localization

    • Added French translations for new budget limit settings

    - Add `budgetCapPercent` setting: a single unified slider that caps both
      session and weekly thresholds, preventing usage beyond the configured
      percentage of the plan (e.g. 80% budget cap).
    - Add `noExtraUsage` toggle: marks an account unavailable once either
      usage limit hits 100%, preventing Anthropic extra-usage (pay-per-use
      overage) from being consumed.
    - Apply both settings in profile-scorer (availability checks, fallback
      scoring, unified account scoring, proactive switch logic) and in
      usage-monitor threshold checks.
    - Add UI controls (budget cap slider + toggle) in AccountSettings below
      the weekly threshold slider, visible when proactive monitoring is on.
    - Add i18n keys for both new controls in en/fr settings locales.
    - Move budget cap and noExtraUsage controls into a dedicated "Usage Limits"
      section visible regardless of account count (no longer gated by totalAccounts > 1).
    - Budget cap and noExtraUsage now work independently of the auto-switch master
      toggle, so single-account users can also enforce plan limits.
    - When a budget limit is hit and no alternative account is available, emit
      budget-exhausted from UsageMonitor → initializeUsageMonitorForwarding calls
      agentManager.killAll() to stop all running agents immediately.
    - Pass agentManager into initializeUsageMonitorForwarding in index.ts (both
      the primary and fallback init paths).
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Feb 28, 2026

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 28, 2026

📝 Walkthrough

Walkthrough

Adds an optional unified budget cap and a noExtraUsage hard-stop to Claude auto-switching: settings now include budgetCapPercent and noExtraUsage, effective thresholds are computed and enforced across scoring, proactive swapping, usage monitoring, agent startup, IPC handling, and the settings UI.

Changes

Cohort / File(s) Summary
Profile scoring & types
apps/frontend/src/main/claude-profile/profile-scorer.ts, apps/frontend/src/shared/types/agent.ts, apps/frontend/src/main/claude-profile/profile-storage.ts
Adds budgetCapPercent?: number and noExtraUsage: boolean to auto-switch settings; computes effective weekly/session thresholds by clamping to budgetCapPercent and treats noExtraUsage as a 100% hard stop. Replaces raw-threshold checks with effective thresholds in availability, scoring, and reason messages.
Usage monitoring & proactive swap
apps/frontend/src/main/claude-profile/usage-monitor.ts
Implements budget-cap-aware threshold checks, a cached isBudgetExceeded(profileId) helper returning explanatory reason, updated checkThresholdsExceeded signature, performProactiveSwap accepting stopIfExhausted, emits budget-exhausted when no alternatives exist, and logs enriched warnings.
Agent lifecycle & IPC forwarding
apps/frontend/src/main/agent/agent-manager.ts, apps/frontend/src/main/ipc-handlers/terminal-handlers.ts, apps/frontend/src/main/index.ts
Pre-flight budget check in AgentManager.startSpecCreation aborts task start if budget exceeded. initializeUsageMonitorForwarding now accepts optional AgentManager; on budget-exhausted the main process attempts agentManager.killAll() before forwarding budget_exhausted event to renderer. Call sites updated to pass agentManager.
UI & i18n
apps/frontend/src/renderer/components/settings/AccountSettings.tsx, apps/frontend/src/shared/i18n/locales/en/settings.json, apps/frontend/src/shared/i18n/locales/fr/settings.json
Adds a Usage Limits section exposing budgetCapPercent (slider, with "off" state) and noExtraUsage toggle tied to auto-switch settings; includes new English and French localization keys. Note: the React file contains duplicated Usage Limits blocks.

Sequence Diagram(s)

sequenceDiagram
    participant UsageMonitor as Usage Monitor
    participant ProfileScorer as Profile Scorer
    participant ProactiveSwap as Proactive Swap
    participant AgentManager as Agent Manager
    participant TerminalHandlers as Terminal Handlers
    participant Renderer as Renderer

    UsageMonitor->>ProfileScorer: compute effective thresholds<br/>(weekly, session, budgetCapPercent, noExtraUsage)
    ProfileScorer-->>UsageMonitor: threshold evaluation & reason
    alt Budget exceeded & no alternatives
        UsageMonitor->>ProactiveSwap: performProactiveSwap(stopIfExhausted=true)
        ProactiveSwap-->>UsageMonitor: no alternative found
        UsageMonitor->>TerminalHandlers: emit budget-exhausted event (main)
        TerminalHandlers->>AgentManager: agentManager.killAll()
        AgentManager-->>TerminalHandlers: agents killed
        TerminalHandlers->>Renderer: forward budget_exhausted payload
    else Alternatives available
        UsageMonitor->>ProactiveSwap: performProactiveSwap(stopIfExhausted=false)
        ProactiveSwap-->>UsageMonitor: switched account
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

area/frontend, size/M

Poem

🐰 A tiny rabbit hops and sees,
Caps and limits in the breeze,
When budgets peak and options fade,
Agents rest and plans are made,
Hooray—safe switching, quiet peace!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding budget-based usage limits for auto-claude window. It accurately reflects the primary feature introduced across multiple files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch budget

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.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the Claude profile management system by introducing robust usage limit controls. It allows users to define a budget cap for both session and weekly usage and to prevent extra usage beyond their plan limits. These new settings are deeply integrated into the system's logic for determining profile availability and proactive switching, and are exposed through a new, dedicated section in the user interface. The changes ensure that agents are stopped if budget limits are hit and no alternative accounts are available, providing better cost control and preventing unexpected overages.

Highlights

  • Usage Limit Controls: Introduced a budgetCapPercent setting, a unified slider that caps both session and weekly usage thresholds, and a noExtraUsage toggle to prevent consumption beyond 100% of the plan, avoiding pay-per-use overage.
  • Core Logic Integration: Integrated the new budgetCapPercent and noExtraUsage settings into profile-scorer for availability checks, fallback scoring, and unified account scoring, and into usage-monitor for threshold checks and proactive switching logic.
  • User Interface Enhancements: Added dedicated UI controls for the budget cap slider and no extra usage toggle in the AccountSettings page, now grouped under a new 'Usage Limits' section that is visible independently of the number of accounts.
  • Independent Operation: Ensured that the budget cap and no extra usage controls function independently of the auto-switch master toggle, allowing single-account users to also enforce plan limits.
  • Agent Termination on Budget Exhaustion: Implemented logic to emit a budget-exhausted event from UsageMonitor which, when no alternative account is available, triggers agentManager.killAll() to immediately stop all running agents.
  • Agent Manager Integration: Modified initializeUsageMonitorForwarding in index.ts and terminal-handlers.ts to accept and utilize the agentManager for agent termination upon budget exhaustion.
  • Internationalization: Added new i18n keys for the budget cap and no extra usage controls in both English and French locales.
Changelog
  • apps/frontend/src/main/claude-profile/profile-scorer.ts
    • Updated availability checks to incorporate noExtraUsage and budgetCapPercent.
    • Modified fallback scoring to use effective thresholds based on budgetCapPercent.
    • Adjusted unified account scoring to respect noExtraUsage and budgetCapPercent.
  • apps/frontend/src/main/claude-profile/profile-storage.ts
    • Added budgetCapPercent and noExtraUsage with default values to DEFAULT_AUTO_SWITCH_SETTINGS.
  • apps/frontend/src/main/claude-profile/usage-monitor.ts
    • Revised handleUsageUpdate to consider budget policies independently of proactive swap settings.
    • Updated checkThresholdsExceeded to calculate effective session and weekly thresholds based on budgetCapPercent and noExtraUsage.
    • Modified performProactiveSwap to include a stopIfExhausted parameter and emit a budget-exhausted event when no alternative profile is found under budget policy.
  • apps/frontend/src/main/index.ts
    • Updated calls to initializeUsageMonitorForwarding to pass the agentManager instance.
  • apps/frontend/src/main/ipc-handlers/terminal-handlers.ts
    • Imported AgentManager type.
    • Modified initializeUsageMonitorForwarding to accept an optional agentManager parameter.
    • Added an event listener for budget-exhausted to kill all running agents via agentManager.
  • apps/frontend/src/renderer/components/settings/AccountSettings.tsx
    • Added a new 'Usage Limits' section with a slider for budgetCapPercent and a switch for noExtraUsage.
    • Implemented logic to update auto-switch settings based on user interaction with the new controls.
    • Moved the 'Usage Limits' section to be always visible, independent of the number of accounts.
  • apps/frontend/src/shared/i18n/locales/en/settings.json
    • Added new translation keys for 'usageLimits' title and description.
    • Added new translation keys for 'budgetCap', 'budgetCapOff', 'budgetCapDescription', 'noExtraUsage', and 'noExtraUsageDescription' under 'autoSwitching'.
  • apps/frontend/src/shared/i18n/locales/fr/settings.json
    • Added new French translation keys for 'usageLimits' title and description.
    • Added new French translation keys for 'budgetCap', 'budgetCapOff', 'budgetCapDescription', 'noExtraUsage', and 'noExtraUsageDescription' under 'autoSwitching'.
  • apps/frontend/src/shared/types/agent.ts
    • Extended the ClaudeAutoSwitchSettings interface to include budgetCapPercent and noExtraUsage properties with their respective JSDoc comments.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

🎉 Thanks for your first PR!

A maintainer will review it soon. Please make sure:

  • Your branch is synced with develop
  • CI checks pass
  • You've followed our contribution guide

Welcome to the Auto Claude community!

@sentry
Copy link
Copy Markdown

sentry Bot commented Feb 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Comment on lines +1113 to +1118
const effectiveSession = settings.budgetCapPercent !== undefined
? Math.min(baseSession, settings.budgetCapPercent)
: baseSession;
const effectiveWeekly = settings.budgetCapPercent !== undefined
? Math.min(baseWeekly, settings.budgetCapPercent)
: baseWeekly;

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a budget cap feature to limit token usage by auto-claude. It adds budgetCapPercent and noExtraUsage settings, which are correctly implemented across the profile scoring, usage monitoring, and UI components. The logic to stop agents when the budget is exhausted and no alternative accounts are available is also well-implemented. My main feedback is to refactor some duplicated code for calculating effective thresholds into a shared helper function to improve maintainability.

Comment on lines +73 to +79
// Effective thresholds: budget cap (if set) acts as a ceiling on both thresholds
const effectiveWeeklyThreshold = settings.budgetCapPercent !== undefined
? Math.min(settings.weeklyThreshold, settings.budgetCapPercent)
: settings.weeklyThreshold;
const effectiveSessionThreshold = settings.budgetCapPercent !== undefined
? Math.min(settings.sessionThreshold, settings.budgetCapPercent)
: settings.sessionThreshold;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

To improve maintainability and adhere to the DRY (Don't Repeat Yourself) principle, consider extracting the logic for calculating effective thresholds into a helper function. This logic is duplicated in several places in this file (calculateFallbackScore, scoreUnifiedAccount, shouldProactivelySwitch) and also in apps/frontend/src/main/claude-profile/usage-monitor.ts in the checkThresholdsExceeded function.

A shared utility function could look like this:

function getEffectiveThresholds(settings: ClaudeAutoSwitchSettings) {
  const baseSession = settings.sessionThreshold ?? 95;
  const baseWeekly = settings.weeklyThreshold ?? 99;

  const effectiveSessionThreshold = settings.budgetCapPercent !== undefined
    ? Math.min(baseSession, settings.budgetCapPercent)
    : baseSession;
  const effectiveWeeklyThreshold = settings.budgetCapPercent !== undefined
    ? Math.min(baseWeekly, settings.budgetCapPercent)
    : baseWeekly;

  return { effectiveSessionThreshold, effectiveWeeklyThreshold };
}

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/frontend/src/main/claude-profile/usage-monitor.ts (1)

1927-1979: ⚠️ Potential issue | 🔴 Critical

Budget exhaustion can be missed because alternatives aren’t policy-filtered.

At Line 1928-Line 1959, alternatives are collected by auth/availability only. If every alternative is already over budget/no-extra limits, unifiedAccounts.length is still non-zero, so the budget-exhausted branch at Line 1965 may never run.

Suggested fix
   private async performProactiveSwap(
@@
   ): Promise<void> {
     const profileManager = getClaudeProfileManager();
+    const settings = profileManager.getAutoSwitchSettings();
     const excludeIds = new Set([currentProfileId, ...additionalExclusions]);
@@
     for (const profile of oauthProfiles) {
       if (!excludeIds.has(profile.id)) {
+        if (stopIfExhausted && profile.usage) {
+          const session = profile.usage.sessionUsagePercent;
+          const weekly = profile.usage.weeklyUsagePercent;
+          const budgetCap = settings.budgetCapPercent;
+          const overBudgetCap = budgetCap !== undefined && (session >= budgetCap || weekly >= budgetCap);
+          const overNoExtra = !!settings.noExtraUsage && (session >= 100 || weekly >= 100);
+          if (overBudgetCap || overNoExtra) {
+            continue;
+          }
+        }
         const unifiedId = `oauth-${profile.id}`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/src/main/claude-profile/usage-monitor.ts` around lines 1927 -
1979, After collecting oauth and api alternatives into unifiedAccounts (from
profileManager.getProfilesSortedByAvailability and loadProfilesFile), filter
unifiedAccounts by the same budget/policy check used for the current profile so
accounts that are over-budget or have "no extra limits" are excluded; e.g. call
the existing budget-check helper (create or reuse a helper like
isAccountWithinBudget or isProfileAllowedByPolicy) for each
unifiedAccount.unifiedId or id and only keep those that pass before checking
unifiedAccounts.length, then if filtered list is empty follow the
stopIfExhausted -> emit('budget-exhausted', ...) or
emit('proactive-swap-failed', ...) branches accordingly (also reference
excludeIds and additionalExclusions when emitting).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/frontend/src/main/claude-profile/usage-monitor.ts`:
- Around line 1105-1124: The function checkThresholdsExceeded currently seeds
baseSession/baseWeekly to 95/99 which causes noExtraUsage-only mode to trigger
before 100%; change the baseline when settings.noExtraUsage is true so
thresholds default to 100 instead of 95/99. Concretely, in
checkThresholdsExceeded adjust how baseSession and baseWeekly are computed (or
override effectiveSession/effectiveWeekly) to use 100 when settings.noExtraUsage
is true, then apply the budgetCapPercent ceiling (Math.min) only afterwards if
budgetCapPercent is provided; keep the rest of the
sessionExceeded/weeklyExceeded checks unchanged and reference the existing
symbols baseSession, baseWeekly, effectiveSession, effectiveWeekly, and
settings.noExtraUsage.

---

Outside diff comments:
In `@apps/frontend/src/main/claude-profile/usage-monitor.ts`:
- Around line 1927-1979: After collecting oauth and api alternatives into
unifiedAccounts (from profileManager.getProfilesSortedByAvailability and
loadProfilesFile), filter unifiedAccounts by the same budget/policy check used
for the current profile so accounts that are over-budget or have "no extra
limits" are excluded; e.g. call the existing budget-check helper (create or
reuse a helper like isAccountWithinBudget or isProfileAllowedByPolicy) for each
unifiedAccount.unifiedId or id and only keep those that pass before checking
unifiedAccounts.length, then if filtered list is empty follow the
stopIfExhausted -> emit('budget-exhausted', ...) or
emit('proactive-swap-failed', ...) branches accordingly (also reference
excludeIds and additionalExclusions when emitting).

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60c4890 and a5c6f5e.

📒 Files selected for processing (9)
  • apps/frontend/src/main/claude-profile/profile-scorer.ts
  • apps/frontend/src/main/claude-profile/profile-storage.ts
  • apps/frontend/src/main/claude-profile/usage-monitor.ts
  • apps/frontend/src/main/index.ts
  • apps/frontend/src/main/ipc-handlers/terminal-handlers.ts
  • apps/frontend/src/renderer/components/settings/AccountSettings.tsx
  • apps/frontend/src/shared/i18n/locales/en/settings.json
  • apps/frontend/src/shared/i18n/locales/fr/settings.json
  • apps/frontend/src/shared/types/agent.ts

Comment on lines 1105 to +1124
private checkThresholdsExceeded(
usage: ClaudeUsageSnapshot,
settings: { sessionThreshold?: number; weeklyThreshold?: number }
settings: { sessionThreshold?: number; weeklyThreshold?: number; budgetCapPercent?: number; noExtraUsage?: boolean }
): { sessionExceeded: boolean; weeklyExceeded: boolean; anyExceeded: boolean } {
const sessionExceeded = usage.sessionPercent >= (settings.sessionThreshold ?? 95);
const weeklyExceeded = usage.weeklyPercent >= (settings.weeklyThreshold ?? 99);
const baseSession = settings.sessionThreshold ?? 95;
const baseWeekly = settings.weeklyThreshold ?? 99;

// Budget cap acts as a ceiling on both thresholds
const effectiveSession = settings.budgetCapPercent !== undefined
? Math.min(baseSession, settings.budgetCapPercent)
: baseSession;
const effectiveWeekly = settings.budgetCapPercent !== undefined
? Math.min(baseWeekly, settings.budgetCapPercent)
: baseWeekly;

// noExtraUsage: also flag when hitting 100%
const sessionExceeded = usage.sessionPercent >= effectiveSession ||
(!!settings.noExtraUsage && usage.sessionPercent >= 100);
const weeklyExceeded = usage.weeklyPercent >= effectiveWeekly ||
(!!settings.noExtraUsage && usage.weeklyPercent >= 100);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Budget-only mode is still enforcing proactive thresholds.

Line 1109 and Line 1110 always seed 95/99 (or configured) thresholds, so noExtraUsage-only mode can trigger exhaustion flow before 100%. That contradicts the “stop at 100%” behavior.

Suggested fix
-  private checkThresholdsExceeded(
+  private checkThresholdsExceeded(
     usage: ClaudeUsageSnapshot,
-    settings: { sessionThreshold?: number; weeklyThreshold?: number; budgetCapPercent?: number; noExtraUsage?: boolean }
+    settings: { sessionThreshold?: number; weeklyThreshold?: number; budgetCapPercent?: number; noExtraUsage?: boolean },
+    useProactiveThresholds: boolean
   ): { sessionExceeded: boolean; weeklyExceeded: boolean; anyExceeded: boolean } {
-    const baseSession = settings.sessionThreshold ?? 95;
-    const baseWeekly = settings.weeklyThreshold ?? 99;
+    const baseSession = useProactiveThresholds ? (settings.sessionThreshold ?? 95) : 100;
+    const baseWeekly = useProactiveThresholds ? (settings.weeklyThreshold ?? 99) : 100;
-        const thresholds = this.checkThresholdsExceeded(usage, settings);
+        const thresholds = this.checkThresholdsExceeded(usage, settings, isProactiveEnabled);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/src/main/claude-profile/usage-monitor.ts` around lines 1105 -
1124, The function checkThresholdsExceeded currently seeds
baseSession/baseWeekly to 95/99 which causes noExtraUsage-only mode to trigger
before 100%; change the baseline when settings.noExtraUsage is true so
thresholds default to 100 instead of 95/99. Concretely, in
checkThresholdsExceeded adjust how baseSession and baseWeekly are computed (or
override effectiveSession/effectiveWeekly) to use 100 when settings.noExtraUsage
is true, then apply the budgetCapPercent ceiling (Math.min) only afterwards if
budgetCapPercent is provided; keep the rest of the
sessionExceeded/weeklyExceeded checks unchanged and reference the existing
symbols baseSession, baseWeekly, effectiveSession, effectiveWeekly, and
settings.noExtraUsage.

Previously the budget check only ran on the periodic usage monitor poll,
meaning an agent could wake up and start doing work before the next poll
cycle detected the overage. Now startSpecCreation checks cached usage
against the budget policy before spawning — if the limit is already
exceeded it emits an error immediately and refuses to start.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@AndyMik90 AndyMik90 self-assigned this Mar 2, 2026
Comment on lines +251 to +261
try {
const activeProfile = profileManager.getActiveProfile();
const budgetCheck = UsageMonitor.getInstance().isBudgetExceeded(activeProfile.id);
if (budgetCheck.exceeded) {
console.warn(`[AgentManager] Refusing to start task "${taskId}": budget limit already exceeded — ${budgetCheck.reason}`);
this.emit('error', taskId, `Budget limit reached: ${budgetCheck.reason}. Adjust the budget cap in Settings > Accounts to continue.`);
return;
}
} catch {
// getActiveProfile can throw if no profiles exist; auth check above already handles that case.
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: The startTaskExecution function lacks a pre-flight budget check, allowing tasks to start even when the user's budget is exceeded.
Severity: MEDIUM

Suggested Fix

Add a pre-flight budget check to the startTaskExecution function, similar to the one implemented in startSpecCreation. This will prevent tasks from starting if the user's budget is already exceeded, ensuring consistent budget enforcement and avoiding unnecessary resource consumption.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: apps/frontend/src/main/agent/agent-manager.ts#L249-L261

Potential issue: The `startTaskExecution` function does not perform a pre-flight budget
check before initiating a task. This allows a user to run an existing task even if their
budget is already depleted. While the `startSpecCreation` function includes this check,
its absence in `startTaskExecution` means an agent can be spawned and begin consuming
resources, only to be terminated by the periodic budget monitor shortly after. This
bypasses the intended budget enforcement for pre-existing tasks.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/frontend/src/main/claude-profile/usage-monitor.ts (1)

930-979: ⚠️ Potential issue | 🟠 Major

Separate proactive thresholds from hard budget exhaustion.

budgetCapPercent !== undefined treats 100% as an active cap even though the UI says it disables the cap, and checkThresholdsExceeded() always starts from 95/99. That means budget-only or no-extra-usage-only mode can block startup or emit budget-exhausted before 100%, especially because stopIfExhausted is passed as hasBudgetPolicy instead of “hard budget limit actually exceeded.” The label also reports noExtraUsage (100%) when a lower budget cap caused the hit.

Suggested direction
-        const hasBudgetPolicy = settings.budgetCapPercent !== undefined || settings.noExtraUsage;
+        const hasBudgetCap = settings.budgetCapPercent !== undefined && settings.budgetCapPercent < 100;
+        const hasBudgetPolicy = hasBudgetCap || !!settings.noExtraUsage;
         const isProactiveEnabled = settings.enabled && settings.proactiveSwapEnabled;
-        const thresholds = this.checkThresholdsExceeded(usage, settings);
+        const budgetThresholds = this.checkThresholdsExceeded(usage, settings, false);
+        const proactiveThresholds = isProactiveEnabled
+          ? this.checkThresholdsExceeded(usage, settings, true)
+          : { sessionExceeded: false, weeklyExceeded: false, anyExceeded: false };
+        const thresholds = budgetThresholds.anyExceeded ? budgetThresholds : proactiveThresholds;
-            hasBudgetPolicy
+            budgetThresholds.anyExceeded
   private checkThresholdsExceeded(
     usage: ClaudeUsageSnapshot,
-    settings: { sessionThreshold?: number; weeklyThreshold?: number; budgetCapPercent?: number; noExtraUsage?: boolean }
+    settings: { sessionThreshold?: number; weeklyThreshold?: number; budgetCapPercent?: number; noExtraUsage?: boolean },
+    useProactiveThresholds: boolean
   ): { sessionExceeded: boolean; weeklyExceeded: boolean; anyExceeded: boolean } {
-    const baseSession = settings.sessionThreshold ?? 95;
-    const baseWeekly = settings.weeklyThreshold ?? 99;
+    const hasBudgetCap = settings.budgetCapPercent !== undefined && settings.budgetCapPercent < 100;
+    const baseSession = useProactiveThresholds ? (settings.sessionThreshold ?? 95) : 100;
+    const baseWeekly = useProactiveThresholds ? (settings.weeklyThreshold ?? 99) : 100;
 
     // Budget cap acts as a ceiling on both thresholds
-    const effectiveSession = settings.budgetCapPercent !== undefined
+    const effectiveSession = hasBudgetCap
       ? Math.min(baseSession, settings.budgetCapPercent)
       : baseSession;
-    const effectiveWeekly = settings.budgetCapPercent !== undefined
+    const effectiveWeekly = hasBudgetCap
       ? Math.min(baseWeekly, settings.budgetCapPercent)
       : baseWeekly;
-    const hasBudgetPolicy = settings.budgetCapPercent !== undefined || settings.noExtraUsage;
+    const hasBudgetPolicy = (settings.budgetCapPercent !== undefined && settings.budgetCapPercent < 100) || !!settings.noExtraUsage;
     const thresholds = this.checkThresholdsExceeded(
       { sessionPercent, weeklyPercent } as ClaudeUsageSnapshot,
-      settings
+      settings,
+      false
     );

Also applies to: 1105-1124, 1147-1175

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/src/main/claude-profile/usage-monitor.ts` around lines 930 -
979, The code treats any budget setting presence as a hard budget policy and
passes hasBudgetPolicy into performProactiveSwap, and also shows misleading
labels; update logic around hasBudgetPolicy/HardBudgetExceeded so
budgetCapPercent === 100 is treated as "no cap", compute a boolean (e.g.,
hardBudgetExceeded) that is true only when the exceeded threshold is actually
due to a hard cap (settings.noExtraUsage OR (settings.budgetCapPercent !==
undefined && settings.budgetCapPercent < 100 && limitPercent >=
settings.budgetCapPercent)), use that boolean for stopIfExhausted in
performProactiveSwap, and build capLabel from the actual cap that caused the
exceed (use 'noExtraUsage (100%)' only when noExtraUsage triggered it, or
`budgetCap (${settings.budgetCapPercent}%)` only when budgetCapPercent < 100
triggered it); references: checkThresholdsExceeded, settings.budgetCapPercent,
settings.noExtraUsage, hasBudgetPolicy, thresholds.anyExceeded, limitPercent,
capLabel, and performProactiveSwap.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/frontend/src/main/agent/agent-manager.ts`:
- Around line 249-261: The budget pre-flight gate (emitBudgetExceededIfNeeded /
UsageMonitor.getInstance().isBudgetExceeded via profileManager) is only applied
when creating specs but not when starting existing tasks, allowing
startTaskExecution to call spawnProcess(...) and bypass budget checks; add a
call to the existing helper (emitBudgetExceededIfNeeded) immediately after the
auth/profile check inside startTaskExecution and return early if it signals
budget exceeded so startTaskExecution cannot proceed to spawnProcess when budget
is exceeded.

---

Duplicate comments:
In `@apps/frontend/src/main/claude-profile/usage-monitor.ts`:
- Around line 930-979: The code treats any budget setting presence as a hard
budget policy and passes hasBudgetPolicy into performProactiveSwap, and also
shows misleading labels; update logic around hasBudgetPolicy/HardBudgetExceeded
so budgetCapPercent === 100 is treated as "no cap", compute a boolean (e.g.,
hardBudgetExceeded) that is true only when the exceeded threshold is actually
due to a hard cap (settings.noExtraUsage OR (settings.budgetCapPercent !==
undefined && settings.budgetCapPercent < 100 && limitPercent >=
settings.budgetCapPercent)), use that boolean for stopIfExhausted in
performProactiveSwap, and build capLabel from the actual cap that caused the
exceed (use 'noExtraUsage (100%)' only when noExtraUsage triggered it, or
`budgetCap (${settings.budgetCapPercent}%)` only when budgetCapPercent < 100
triggered it); references: checkThresholdsExceeded, settings.budgetCapPercent,
settings.noExtraUsage, hasBudgetPolicy, thresholds.anyExceeded, limitPercent,
capLabel, and performProactiveSwap.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: edb410ff-9afd-4d5e-a05d-31e99c94999e

📥 Commits

Reviewing files that changed from the base of the PR and between a5c6f5e and f1e720a.

📒 Files selected for processing (2)
  • apps/frontend/src/main/agent/agent-manager.ts
  • apps/frontend/src/main/claude-profile/usage-monitor.ts

Comment on lines +249 to +261
// Pre-flight budget check: Refuse to start if cached usage already exceeds configured budget cap.
// This prevents agents from waking up and doing work that the periodic monitor would immediately kill.
try {
const activeProfile = profileManager.getActiveProfile();
const budgetCheck = UsageMonitor.getInstance().isBudgetExceeded(activeProfile.id);
if (budgetCheck.exceeded) {
console.warn(`[AgentManager] Refusing to start task "${taskId}": budget limit already exceeded — ${budgetCheck.reason}`);
this.emit('error', taskId, `Budget limit reached: ${budgetCheck.reason}. Adjust the budget cap in Settings > Accounts to continue.`);
return;
}
} catch {
// getActiveProfile can throw if no profiles exist; auth check above already handles that case.
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Apply the budget pre-flight gate to startTaskExecution too.

This check only protects spec creation. Starting an existing task through startTaskExecution still reaches spawnProcess(...) without consulting cached budget usage, so budget/no-extra-usage can be bypassed until the next monitor poll.

Suggested refactor to reuse the gate in both start paths
+  private emitBudgetExceededIfNeeded(taskId: string, profileManager: ClaudeProfileManager): boolean {
+    try {
+      const activeProfile = profileManager.getActiveProfile();
+      const budgetCheck = UsageMonitor.getInstance().isBudgetExceeded(activeProfile.id);
+      if (!budgetCheck.exceeded) {
+        return false;
+      }
+
+      console.warn(`[AgentManager] Refusing to start task "${taskId}": budget limit already exceeded — ${budgetCheck.reason}`);
+      this.emit('error', taskId, `Budget limit reached: ${budgetCheck.reason}. Adjust the budget cap in Settings > Accounts to continue.`);
+      return true;
+    } catch {
+      return false;
+    }
+  }
+
   async startSpecCreation(
-    try {
-      const activeProfile = profileManager.getActiveProfile();
-      const budgetCheck = UsageMonitor.getInstance().isBudgetExceeded(activeProfile.id);
-      if (budgetCheck.exceeded) {
-        console.warn(`[AgentManager] Refusing to start task "${taskId}": budget limit already exceeded — ${budgetCheck.reason}`);
-        this.emit('error', taskId, `Budget limit reached: ${budgetCheck.reason}. Adjust the budget cap in Settings > Accounts to continue.`);
-        return;
-      }
-    } catch {
-      // getActiveProfile can throw if no profiles exist; auth check above already handles that case.
-    }
+    if (this.emitBudgetExceededIfNeeded(taskId, profileManager)) {
+      return;
+    }

Also call the helper after the auth check in startTaskExecution:

if (this.emitBudgetExceededIfNeeded(taskId, profileManager)) {
  return;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/src/main/agent/agent-manager.ts` around lines 249 - 261, The
budget pre-flight gate (emitBudgetExceededIfNeeded /
UsageMonitor.getInstance().isBudgetExceeded via profileManager) is only applied
when creating specs but not when starting existing tasks, allowing
startTaskExecution to call spawnProcess(...) and bypass budget checks; add a
call to the existing helper (emitBudgetExceededIfNeeded) immediately after the
auth/profile check inside startTaskExecution and return early if it signals
budget exceeded so startTaskExecution cannot proceed to spawnProcess when budget
is exceeded.

@eyalk11
Copy link
Copy Markdown
Author

eyalk11 commented Apr 23, 2026

If you plan to work on it, some new commits on docker branch related to auto resume budget-waiting tasks. which is also a needed feature..

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants