subagent-budget
Hard budget caps for subagents — token and dollar limits enforced by hooks, not just displayed on a dashboard.
The problem
Subagents are the silent half of your Claude Code bill. In one real-world measurement (aidiveyt), a month of usage — 455 sessions, 2,631 subagent runs — showed subagents consuming 48.1% of all tokens, with the median subagent's first request alone weighing in at 47,117 tokens. Nobody asked for that spend; it just happened in the background.
Simon Willison put it bluntly: "hard budget caps, please, now."
Dashboards don't fix this. If a cap can't stop a launch, it's a suggestion.
subagent-budget wires into Claude Code's hook system so an over-budget
subagent is refused at launch — non-zero exit, reason on stderr, the
agent sees exactly why.
How it differs
| subagent-ledger | subagent-budget | |
|---|---|---|
| Dimensions | tokens only | tokens + dollars |
| History | cleared when the session ends | cross-session JSONL ledger |
| Enforcement | none — display only | hooks hard-block the launch |
| Pricing | — | built-in model price table (overridable) |
| Resume-aware | — | imports resume-budget-guard ledgers |
Install
pip install subagent-budget
Stdlib only, zero dependencies. Python 3.9+.
Quickstart
# 1. Create the config (~/.config/subagent-budget/config.json)
subagent-budget init --default-tokens 1000000 --default-usd 50
# 2. Cap expensive agent types (glob matched against name AND subagent type)
subagent-budget set-budget --pattern "Explore*" --tokens 200000 --usd 10
subagent-budget set-budget --pattern "researcher" --tokens 500000 --usd 25
# 3. Backfill usage from Claude Code transcripts
subagent-budget sync
# 4. Record an exact run (e.g. from --output-format json)
subagent-budget record --agent "Explore auth code" --type Explore --tokens 47117
# 5. See where every agent stands
subagent-budget report
AGENT RUNS TOKENS COST REMAINING STATUS
Explore auth code 3 141351 $0.93 58649 tok, $9.07 ok
deep research dive 9 423000 $2.79 OVER (researcher)
Claude Code hooks setup
This is the part that makes caps hard. Add to your Claude Code settings
(~/.claude/settings.json):
{
"hooks": {
"PreToolUse": [
{
"matcher": "Task",
"hooks": [
{
"type": "command",
"command": "subagent-budget hook --event pre"
}
]
}
]
}
}
Claude Code pipes the hook input JSON (tool name, subagent_type,
description) into the command's stdin. subagent-budget looks up the
cumulative usage for the matching budget rule; if a limit is exceeded it
exits with code 2 (Claude Code's blocking-hook signal) and the reason
goes to stderr, which Claude sees:
subagent-budget blocked launch of 'Explore auth code' (Explore):
token budget exceeded: used 210,441 / 200,000 tokens
Optional: record exact post-run usage with a PostToolUse hook on Task:
{
"matcher": "Task",
"hooks": [
{ "type": "command", "command": "subagent-budget hook --event post --tokens $USAGE" }
]
}
(--tokens there is whatever your accounting pipeline measured; without it
the hook records 0 and sync/record remain the sources of truth.)
Manual check without hooks:
subagent-budget check --agent "Explore auth code" --type Explore
# exit 3 = over budget
Budgets
- Rules are glob patterns matched (case-insensitively) against both the
agent's description and its subagent type. First match wins — put
specific patterns before broad ones (
--position first). - A named rule's usage accumulates across all agents matching its pattern (a shared pool). The default budget accumulates per agent name.
- Either dimension may be left unlimited:
--tokensor--usdalone. - Config lives at
~/.config/subagent-budget/config.json; the ledger at~/.config/subagent-budget/ledger.jsonland is never cleared at session end.
Working with resume-budget-guard
The ledger format is intentionally compatible with
resume-budget-guard
(records carry ts, kind, cost_usd). If you already track resume spend
there, fold it into the same budgets:
subagent-budget import-rbg
# imports ~/.resume-budget-guard/ledger.jsonl as agent "rbg:<session-key>"
Imported spend counts toward the matching budget rules, so a resume can no longer silently reset what a subagent cap was guarding. Idempotent — re-run anytime.
Honest limitations
- Transcript sync is estimated. A parent transcript does not contain a
subagent's own token usage, so
syncrecords one ledger entry per Task invocation usingsync_estimate_tokens(default 47,117 — the measured median first-request size). Override it in config, or userecord --tokensfor exact figures. - Dollar amounts are estimates from a built-in price table (as of
2026-10-01). Override
model_ratesin config; pass--costto record an exact figure. - A hook can only block what it sees. The
prehook reads Claude Code's hook stdin; identity comes fromdescription/subagent_type. If you spawn subagents outside Claude Code's Task tool, record them manually. - Enforcement is per-machine (local ledger). It won't stop a second machine from spending.
License
MIT
Metadata
Release files for subagent-budget 0.1.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 | |
|---|---|---|---|
| subagent_budget-0.1.0.tar.gz | 19.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| subagent_budget-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.1 kB
Release files / subagent_budget-0.1.0.tar.gz
| Download URL | subagent_budget-0.1.0.tar.gz |
|---|---|
| Size | 19.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
60ae21da153ffbe801164518b1cec2c13f5afdcc92017c98f7657e9ea4f16dc4
|
|
BLAKE2b-256 checksum How to use checksums |
0fefa945608e4c4663ca42b42e5dcfee5dbaae6303d89c46f6c3c5b1e17112c9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / subagent_budget-0.1.0-py3-none-any.whl
| Download URL | subagent_budget-0.1.0-py3-none-any.whl |
|---|---|
| Size | 15.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
116ead1f26a20d7cec0b79bc30c5a7cd2f987c1f267d17354aafc71fb00ec5ef
|
|
BLAKE2b-256 checksum How to use checksums |
aa34632188a9ab1c9a4f14cb872b4c44a63f880236dd48d658681ebdde7301e7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|