resume-budget-guard
Enforce a cumulative spend cap across Claude Code resumes.
claude --print --max-budget-usd N enforces the cap per invocation only —
spend from before a --resume / --continue does not count toward the cap on
the resumed run (Gotcha #7;
the official fix is to "track cumulative spend externally"). A $5 cap resumed
four times can silently spend ~$20.
resume-budget-guard (rbg) is that external tracker, plus teeth: it keeps a
cumulative spend ledger and wraps your claude invocations so a resume can
never reset the budget. If the cap is already spent, it refuses to launch.
pip install resume-budget-guard
rbg init --cap 5.00
# wrap your normal claude calls -- resume-aware from here on
rbg run -- claude -p --resume <session-id> "keep building the feature"
# spent $4.20 / cap $5.00 -> launching with --max-budget-usd 0.80 (sess-abc)
rbg run -- claude -p --resume <session-id> "one more thing"
# BLOCKED: budget exhausted -- spent $5.00 of $5.00 cap on sess-abc.
# Resume would have reset the cap; refusing to launch.
Why: hard budget caps, please, now
Simon Willison has been making the case that agents need hard budget caps,
not advisory ones — when a coding agent can spend your money, "trust me" is
not a control. claude --max-budget-usd was the obvious answer, but it has a
hole: the cap is per invocation. Resume a session four times under a $5 cap
and you can silently spend ~$20. This tool closes that hole: the cap is
cumulative, enforced from outside the agent, and a resume can never reset
it. Enforcement lives in a wrapper the agent cannot argue with — if the money
is gone, the process never starts.
Quota-aware auto-wake
Rate limits pause work; budgets shouldn't have to. Point rbg at your quota
reset time and wait blocks until the window reopens, so a cron job or
orchestrator can pick up exactly where the cap left off:
rbg init --cap 20.00 --reset-at 2026-10-12T07:00:00Z
# keep a nightly build loop alive across quota resets:
rbg wait --until-reset --timeout 21600 --poll-interval 60 \
&& rbg run -- claude -p --resume <session-id> "continue the nightly build"
# waiting for quota reset at 2026-10-12T07:00:00+00:00 (timeout 21600s)
# quota resets in ~5:59:59; checking again in 60s
# ...
# quota reset reached (2026-10-12T07:00:00+00:00).
# spent $0.00 / cap $20.00 -> launching with --max-budget-usd 20.00 (sess-abc)
The reset time can come from --reset-at (on init or on wait), the
RBG_RESET_AT environment variable, or config. wait exits 0 when the quota
resets, 1 on --timeout, 2 when no reset time is configured — plain exit
codes a scheduler can branch on:
# cron: resume the build loop as soon as the quota window reopens
0 2 * * * cd ~/jobs/nightly && rbg wait --until-reset --timeout 18000 && rbg run -- claude -p --resume $SESSION "continue"
How it works
- Ledger (
~/.resume-budget-guard/ledger.jsonl): one JSON record per invocation —{ts, session_key, kind, cost_usd}. Cumulative spend is computed on read; no daemon needed. - Wrap:
rbg runreads the ledger, computesremaining = cap - spent, and rewrites--max-budget-usdtomin(your value, remaining)before launchingclaude. At zero remaining it exits 3 without launching. - Record: after the run, it parses
total_cost_usdfrom claude's--output-format jsonresult and appends it to the ledger. - Sync:
rbg sync --session <id>parses the session transcript (~/.claude/projects/**/<id>.jsonl) and records a usage-derived baseline — for interactive (non--p) sessions.
Two cap modes: --session-key session (default — cap applies per session id)
and --session-key day (cap applies to all spend today).
Commands
| Command | What it does |
|---|---|
rbg init --cap 5.00 [--reset-at ISO] |
set the spend cap (+ optional quota reset time) |
rbg run [--cap N] [--session-key day] -- claude ... |
guarded invocation |
rbg sync --session <id> |
baseline a session from its transcript |
rbg status [--session <id>] |
spend vs cap |
rbg wait --until-reset [--timeout S] [--poll-interval S] |
block until the quota reset time (exit 0 on reset, 1 on timeout) |
rbg reset |
archive the ledger (daily rollover) |
Interop with subagent-budget
subagent-budget (pip install subagent-budget) guards per-agent token and spend budgets; rbg guards the
cumulative cap across resumes. The two share one ledger contract: every
ledger.jsonl record carries ts (ISO-8601 UTC), kind, and cost_usd
— subagent-budget 0.1.0 was built ledger-compatible with rbg on purpose, so
either tool can read the other's history.
To read subagent-budget's ledger from rbg (its default home is
~/.config/subagent-budget/ledger.jsonl), point the env override at it:
RBG_LEDGER_PATH=~/.config/subagent-budget/ledger.jsonl rbg status
Spend recorded by either tool accumulates under the same ts/kind/
cost_usd fields, so a combined spend picture is one rbg status away.
(rbg's own records add session_key/session_id, which subagent-budget
ignores — both directions stay readable.)
How this differs from agentcost-cli
agentcost-cli is excellent
observability: it profiles what drives token spend (report, watch,
list, outcome). It does not enforce anything — its hook-session-end
only observes, and --fail-on-waste fires on waste patterns, not spend caps.
resume-budget-guard is the opposite side of the coin: it doesn't analyze
why you spent, it stops you from spending more than the cap — including
across resumes, which is exactly the hole --max-budget-usd leaves open.
Notes
- Cost source priority: claude's own
total_cost_usd(exact) → transcriptusage× bundled rate table (estimates;PRICING_AS_OFstamped in code). - Single-user CLI; no locking, no network, no auth. Your ledger never leaves your machine.
- One file, stdlib only, Python 3.9+. 13/13 tests pass (
python3 -m unittest discover -s tests). - Install:
pip install resume-budget-guard— entry pointrbg.
License
MIT
Metadata
Release files for resume-budget-guard 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| resume_budget_guard-0.2.0.tar.gz | 12.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| resume_budget_guard-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.1 kB
Release files / resume_budget_guard-0.2.0.tar.gz
| Download URL | resume_budget_guard-0.2.0.tar.gz |
|---|---|
| Size | 12.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ecf24b04cf806553140457d3f2f87e1e63910e31cefb324cfe21a92b7f2890d9
|
|
BLAKE2b-256 checksum How to use checksums |
7fe2eb17ea3c76611c07150f61ac8c3e903d78a756f1e6a5b7ef9d4a3d21f9f0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / resume_budget_guard-0.2.0-py3-none-any.whl
| Download URL | resume_budget_guard-0.2.0-py3-none-any.whl |
|---|---|
| Size | 10.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b83a3a342169440db5cf75f4dd2f623b4fdc366c5be76df70a9a2576e85fee78
|
|
BLAKE2b-256 checksum How to use checksums |
6467237dc65f4247595ba209fd6d76f243869d13d2e44588e88fcb73a79806b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|