RoninForge / Tutorials / Hard spend cap on Claude Code
Tutorial
Anthropic does not ship a hard $/day cap. Set one in 5 minutes with BudgetClaw: per-project and per-branch attribution, SIGTERM on breach, optional phone push. Zero keys, zero prompts, zero latency added.
Problem
Surprise bill from a stuck agent loop
Time
5 minutes
Output
Working hard cap with kill on breach
Claude Code can spend a lot in a hurry. A single agentic refactor on Opus 4.7 ($5 input / $25 output per MTok) can burn $20 to $50 in one task. Two parallel sessions on different branches, an overnight run, a stuck loop reading the same file 200 times -- and the morning bill is $200 you did not plan to spend.
Anthropic's console shows lifetime and monthly usage after the fact. The /cost slash command tells you the current session spend. Neither stops a session that has already gone off the rails.
BudgetClaw is the missing piece: a local Go binary that reads the JSONL session logs Claude Code already writes to ~/.claude/projects/, prices each event against the published Anthropic rates, and SIGTERMs the process the moment a per-project, per-branch, daily/weekly/monthly cap is breached. It is not a proxy: it never sits between your editor and the API, never sees your prompts, and never holds a key.
One install script drops a single static Go binary on your PATH. No runtime, no Python, no Node. Roughly 5 MB.
Or via Homebrew:
Verify:
$ budgetclaw version --short 0.1.5
Creates the XDG config + state directories and writes a default config.toml. Idempotent: re-running never overwrites your config.
budgetclaw initialized. Directories: config: ~/.config/budgetclaw state: ~/.local/state/budgetclaw data: ~/.local/share/budgetclaw cache: ~/.cache/budgetclaw Next steps: 1. Edit the config: budgetclaw config path 2. Set a budget: budgetclaw limit set --period daily --cap 10 3. Start watching: budgetclaw watch
A starting point is your monthly target divided by 30. Some calibration anchors at current Anthropic rates:
| Monthly target | Daily cap | Roughly equals (Opus 4.7) |
|---|---|---|
| $50 | --cap 1.67 | ~330K input tokens or ~70K output |
| $100 | --cap 3.33 | ~660K input or ~130K output |
| $300 | --cap 10 | ~2M input or ~400K output |
| $1000 | --cap 33 | ~6.6M input or ~1.3M output |
Two actions to choose from:
--action warn sends a phone push when the cap is crossed but does not interrupt the session. Good when you want the data without the friction.--action kill SIGTERMs the Claude Code process and writes a lockfile so a silent relaunch is caught. Use when you actually want the safety floor.If you have never set a cap before, start with kill at a number that would feel painful. You can always raise it; the lockfile makes accidental overshoot impossible.
A global $5/day kill cap across every project:
added limit: project=* branch=* period=daily cap=$5.00 action=kill config: ~/.config/budgetclaw/config.toml
Per-branch is where this gets useful. A common pattern: generous on main, tight on feature branches where stuck loops happen:
Confirm with budgetclaw limit list:
# PROJECT BRANCH PERIOD CAP ACTION 1 * * daily $5.00 kill 2 myapp main daily $10.00 warn 3 myapp feature/* daily $2.00 kill
Rules are evaluated independently. The most specific rule fires first; in this example a feature branch on myapp can hit $2 and trigger a kill before the global $5 rule even applies.
Caps only fire when the watcher is running. Foreground (a tab in your terminal):
budgetclaw watching ~/.claude/projects (ntfy alerts not configured; run `budgetclaw alerts setup` to enable) press Ctrl-C to stop.
In production you want the watcher running permanently. Pick the right snippet:
Save as ~/Library/LaunchAgents/org.roninforge.budgetclaw.plist (replace YOU with your username), then load it:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.roninforge.budgetclaw</string>
<key>ProgramArguments</key>
<array>
<string>/Users/YOU/.local/bin/budgetclaw</string>
<string>watch</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/budgetclaw.log</string>
<key>StandardErrorPath</key>
<string>/tmp/budgetclaw.log</string>
</dict>
</plist>Save as ~/.config/systemd/user/budgetclaw.service, then enable:
[Unit] Description=BudgetClaw watcher After=default.target [Service] Type=simple ExecStart=%h/.local/bin/budgetclaw watch Restart=on-failure RestartSec=5 [Install] WantedBy=default.target
The whole tool stands or falls on this. Set a tiny test cap on a project, run a small Claude Code task in that project, and watch the SIGTERM fire.
In a fresh tab, set a $0.10 test cap (about 20 thousand input tokens on Opus 4.7 -- one small prompt):
Make sure the watcher is running in another tab. Then start a Claude Code session in a directory named test-cap (BudgetClaw uses the directory's basename as the project name) and ask it to do something small:
$ mkdir test-cap && cd test-cap && git init && claude In Claude: Read every file in this directory and write a one-paragraph summary.
Within seconds the watcher logs the breach and SIGTERMs the Claude process. Expected line in the watcher's tab:
time=2026-04-28T... level=INFO msg="kill breach" project=test-cap branch=main cap=0.1 current=0.12 pids=[12345]Claude Code exits. budgetclaw locks list now shows an active lock:
$ budgetclaw locks list PROJECT BRANCH PERIOD CURRENT CAP LOCKED test-cap main daily $0.12 $0.10 2026-04-28 14:23
If you try to relaunch claude in the same project, the watcher SIGTERMs it again immediately -- the lockfile blocks silent relaunches until the period rolls over. Clean up the test rule when done:
In production the kill is a useful pause, not a disaster. Walk the data first:
PROJECT BRANCH TODAY WEEK MONTH myapp main $1.42 $4.85 $28.30 myapp feature/auth $2.04 $2.04 $2.04 TOTAL $3.46 $6.89 $30.34
One branch responsible for the breach? Probably a stuck loop or an over-eager refactor. Stop, fix the prompt, resume tomorrow. Multiple branches contributed evenly? Cap is too tight; raise it with another budgetclaw limit set --cap <new>.
To resume work in the current period after a kill:
Or do nothing -- the lock auto-expires when the budget period rolls over. A daily cap with a kill at 23:59 unlocks itself at 00:00.
Get a push notification on your phone when warn or kill fires. Uses ntfy -- no signups, no vendor lock-in. Setup takes 60 seconds:
You should see a "budgetclaw test" notification on your phone. From now on, warn and kill breaches push automatically. Kill actions use max priority to bypass Do Not Disturb.
budgetclaw status shows zero spendThe watcher is what tallies events. If budgetclaw status looks suspiciously low, confirm budgetclaw watch is running (or the launchd / systemd service). Then run budgetclaw pricing diagnose -- it walks your local logs and flags any model the pricing table does not know about. If a model is missing, open an issue on GitHub; the daily pricing-audit workflow usually catches new models within 24 hours.
That is the lockfile working as designed. List it with budgetclaw locks list, decide whether to raise the cap, and resume with budgetclaw unlock <project>. Or wait until the period rolls over and the lock auto-expires.
Run budgetclaw alerts test. If that does not push, the topic in your config does not match what the ntfy app is subscribed to. Re-run budgetclaw alerts setup --topic "$TOPIC" with the exact same topic both places. Mobile carriers occasionally throttle ntfy.sh on the free tier; switching to --server https://ntfy.your-domain if you self-host fixes that.
Upgrade to the latest BudgetClaw release, then run budgetclaw backfill --rebuild. The --rebuild flag wipes the rollups and replays every event at the corrected rates; without it, idempotent inserts leave the old rate baked into existing rows.
Yes. BudgetClaw reads the JSONL session logs Claude Code writes locally, regardless of how billing works upstream. On Pro and Max, billing is flat-rate but token consumption is still tracked, so caps based on equivalent dollar cost still fire correctly. The dollar number on a flat-rate plan is informational rather than billed; the cap still shows you when a runaway agent is burning your share of the rate-limit budget.
No. BudgetClaw never sits between your editor and the Anthropic API. It reads files Claude Code already writes to ~/.claude/projects/ on your machine. Zero API keys, zero prompts captured, zero latency added to the inference path. Source is MIT-licensed Go and auditable in an afternoon.
The watcher sends SIGTERM to the running Claude Code process and writes a lockfile under the BudgetClaw lock directory. The lockfile prevents silent relaunches: if you start a new Claude session in the same project, the watcher SIGTERMs that one too until you explicitly run budgetclaw unlock or the budget period rolls over.
Yes. --branch accepts a glob (or * for all). Common pattern: a generous daily cap on main, a tight cap on feature branches where stuck loops tend to happen. BudgetClaw reads the gitBranch field Claude Code already records on every event, so attribution is exact.
Watcher works fine. It reads filesystem events from ~/.claude/projects/ and writes to a local SQLite database. The only outbound network call is the optional phone push to your ntfy server, which is best-effort and does not block enforcement.
v0.1.4 and later have the corrected $5 input / $25 output rates per MTok for Opus 4.5+. A daily pricing-audit GitHub Action cross-checks the embedded rates against Anthropic's /v1/models endpoint AND against BerriAI/litellm's community-maintained pricing data, so any future rate change opens a tracking issue within 24 hours. After a price correction lands, run budgetclaw backfill --rebuild to recompute historical rollups.
Walk through the day's rollups with budgetclaw status to see which branch consumed the most. If a single branch is responsible (a stuck agent loop, an over-eager refactor), the right call is usually to stop, fix the prompt, and resume tomorrow. If multiple branches contributed evenly, the cap may be too tight -- raise it with budgetclaw limit set --cap <new>. Either way, budgetclaw unlock <project> resumes work in the current period.
This tutorial is part of RoninForge. Read more about BudgetClaw, or browse the other tutorials.