Skip to main content
Open-source software

onbudget

Creator and maintainer

A free, MIT-licensed Claude Code plugin that gives a single task a spending limit, in dollars or as a share of the 5-hour or weekly usage window, and stops it before the limit runs out.

Overview

onbudget is a free, MIT-licensed plugin for Claude Code, released in October 2026. It gives one task a spending limit, either in dollars or as a share of the account's 5-hour or weekly usage window, and stops the task before the limit runs out.

It is built for long, unattended runs, where a task can otherwise overspend or be cut off in the middle of its work at a plan limit. It requires Claude Code 2.1.287 or later, runs entirely inside Claude Code, and sends nothing over the network.

The problem it addresses

Claude Code's own budget controls are limited. Its --max-budget-usd flag works only in print mode and the SDK, is checked after each response, and its documentation says spend can pass it. Claude Code provides no budget for an interactive terminal session and none for the weekly usage window.

onbudget gives the task a budget the model can see while it works, and enforces that budget before each model request rather than after it.

Demonstration

The exact wording of its notices

  ⚠ onbudget: tier MEDIUM · $0.21 left · budget $0.50

⏺ [onbudget] Stopped: $0.07 of $0.12 is used, and the next request could cost up
  to $0.07, so it was not sent.
  This notice comes from the onbudget plugin, not from Claude. The work was
  interrupted: treat anything Claude has not reported as complete and verified
  as unfinished.
  To go on: /onbudget off (no budget), or /onbudget <budget> <instructions> (a
  new budget).

⏺ onbudget: Claude ended the task with STATUS: COMPLETE, at $0.20 of
  $0.50. The budget is still open: a follow-up prompt draws on it, and
  /onbudget off removes it.

Installation

onbudget requires Claude Code 2.1.287 or later. Install it from the plugin marketplace:

claude plugin marketplace add sebastiandrazsky/onbudget
claude plugin install onbudget@onbudget

Type /onbudget. It should answer "onbudget: no budget is set" and name its version and the Claude Code builds it was tested on.

The budget meter and the pre-request stop

The stop comes before the request. onbudget sits on Claude Code's model-request hook. A request cannot be priced before it is sent, so the plugin holds back what the dearest request of the task has cost so far. When the spend so far, plus that reserve, would reach the budget, the next request is answered by the plugin with a notice and never reaches the API. Requests already running are not cancelled, and each one holds back its own reserve.

The meter. Claude is told the budget once, with the task, and shown a meter line after every tool result. The line carries a tier and what is left before the stop: HIGH from 70% left, MEDIUM from 30%, LOW from 10%, and CRITICAL below that. The protocol asks the model to stop adding scope at LOW and to leave the tree in its best verified state at CRITICAL, so the work usually lands before the stop. In the shipped evaluation the three onbudget runs ended by themselves at LOW with 19 to 25% of the budget unspent.

Dollar and usage-window budgets

Dollar budgets. /onbudget $3 Implement authentication sets a budget of three dollars for the task. The dollars are list-price dollars as Claude Code's /cost counts them, read from the session's own ledger, subagents included. onbudget does no pricing of its own.

Usage-window budgets. /onbudget 10% 5h Build this application sets a budget in whole points of the 5-hour window for the whole account, and /onbudget 5% week Fix these bugs does the same for the weekly window. A 5-hour percentage is converted to dollars using a rate learned from the account's own usage readings once three points of movement have been seen. A weekly budget is counted in the weekly window's own points unless usdPerPointWeek is set.

What a window has left. /onbudget 5h Refactor the parser sets the budget to the points between the window's reading and 99% when the command is given. A reset of the window during the task does not enlarge the budget.

Every budget is also bounded by what the account has left. While a budget is open, both usage windows count as limits, and onbudget stops short of either one with its own notice before Claude Code would end the session with its limit message.

/onbudget $3 Implement authentication
/onbudget 10% 5h Build this application
/onbudget week Write the migration

Evaluation results

The evaluation is published with its raw data. The benchmark is seven real bug fixes in Python libraries (boltons, falcon, markdown-it-py, pluggy, pydantic-settings and two in werkzeug), given in one prompt to one headless session and scored by upstream tests the model never saw. The model was Claude Opus 5.5 at medium effort. The harness and every run of data are at the tag v0.1.0; from version 0.1.1 they are not on main, so an install does not carry them.

Evaluation results by arm
ArmRunsTasks complete, of 7Within $2.47Ended by itself, with a reportCost, each run
onbudget35, 5, 53 of 33 of 3$2.00, $1.86, $1.97
Plain, --max-budget-usd 2.4725, 62 of 22 of 2$2.06, $2.25
Budget sentence in the prompt25, 52 of 2, one only because a safety cap refused its next request1 of 2$2.38, $2.10
  • No onbudget run has gone over its budget: 12 runs with the real model, on Claude Code 2.1.289 and 2.1.304 (10 seven-task sessions and 2 single tasks). 11 of the 12 ended by themselves with a report.
  • On 2.1.304 the result is parity: onbudget finished no more tasks than plain Claude Code under its own cap or a sentence in the prompt. With two or three runs per arm, a difference of a task or less is noise.
  • These results come from two or three runs per budget, on one model and one kind of task. They describe what happened in those runs and are not a guarantee of what a budget will do.

How it relates to Claude Code's own controls

Claude Code already offers several cost and usage controls. onbudget differs from each of them in what it enforces and when.

  • --max-budget-usd works in print mode and the SDK only, and is checked after each response; its documentation says spend can pass it. onbudget checks before each request and also works in a terminal session.
  • The token countdown is undocumented, set by the server and padded to 15 million tokens. It is not a task budget; while a budget is open onbudget leaves it out of new requests.
  • The warning at 85% of the session limit tells you the limit is near; onbudget acts on the model's requests.
  • Auto-continue at a reset carries on after the limit resets; a budget does not grow at a reset.
  • The Wrap-Up Allowance lets a response in progress finish at the 5-hour limit and does not apply to API keys. onbudget stops before either limit, including the weekly one.

None of these gives a task a budget in an interactive session, and none acts at the weekly limit.

Limitations

  • One request can pass the budget. The API cannot cap what one request costs, and a request can cost more than any before it, usually the first after a long idle period. That request overruns the budget, and the plugin stops at the next request with the real figure.
  • Claude Code's own requests are counted, not stopped. The next-prompt suggestion at the end of a turn and a compaction do not pass through the hook the plugin refuses requests on, so spend can end a few cents past the budget. In a test on Claude Code 2.1.289, a $0.07 budget stopped at $0.069 and finished at $0.115. Setting CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false removes that request.
  • A budget that fits only a few requests gives little warning. The first request of a session can cost about $0.03 to $0.07 and the next up to three times as much, so a very small budget can be reached before the meter has had a request at CRITICAL to show.
  • It lands early. The meter makes the model wrap up before the stop, so part of the budget usually goes unspent: 19 to 25% in the second round's three onbudget runs, which all ended at LOW.
  • The stop falls between requests. The plugin can refuse a request but cannot choose a good moment in the work, so if the model does not wrap up in time the stop can land in the middle of an edit. Parallel subagents make the stop come early, because each request in flight holds back a reserve.
  • Window readings are whole points for the whole account. Other sessions move the same readings, and a model-specific limit, which Claude Code does not report to a plugin, can end a task without onbudget seeing it coming.
  • The evaluation covered one model (Claude Opus 5.5), one kind of task, on macOS. Windows, the VS Code, desktop and mobile surfaces, other models, teammates and workflow agents were not tested, and no evaluated run used a weekly budget.
  • Completion claims are Claude's. The plugin measures spend, not whether the work is right. In the first round one of 42 completion claims made under onbudget was wrong.
  • Dollar figures are list prices. On a subscription these are the units Claude Code's ledger counts in, not an amount billed.

My role

I created onbudget and I maintain it. I designed it, wrote its code and tests, and ran the evaluation. The design decisions, the evaluation and each release are mine.

It is written in TypeScript as Claude Code function hooks, with no dependencies, no build step, and no network or model calls of its own.

What it reads, writes and sends

onbudget sends nothing anywhere: no network calls, no commands, no credentials. It reads the session's cost ledger and usage-window readings, its session id and model, three environment variables (none a secret), and its own store. It writes only its own store under ~/.claude/plugins/store, a status line, and, only with ONBUDGET_LOG=1, an event log in its own folder. With no budget set it changes no request.

Links and evidence