subagent-budget 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 hao li
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,190 @@
1
+ Metadata-Version: 2.4
2
+ Name: subagent-budget
3
+ Version: 0.1.0
4
+ Summary: Hard budget caps for subagents — token/$ limits enforced by hooks, not just displayed
5
+ Author-email: hao li <haoli5933@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/hahahahahahahahah6/subagent-budget
8
+ Project-URL: Repository, https://github.com/hahahahahahahahah6/subagent-budget
9
+ Keywords: claude-code,subagents,budget,tokens,cost-control,hooks
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Dynamic: license-file
23
+
24
+ # subagent-budget
25
+
26
+ Hard budget caps for subagents — token **and** dollar limits enforced by
27
+ hooks, not just displayed on a dashboard.
28
+
29
+ ## The problem
30
+
31
+ Subagents are the silent half of your Claude Code bill. In one real-world
32
+ measurement ([aidiveyt](https://github.com)), a month of usage — 455
33
+ sessions, 2,631 subagent runs — showed subagents consuming **48.1% of all
34
+ tokens**, with the median subagent's first request alone weighing in at
35
+ **47,117 tokens**. Nobody asked for that spend; it just happened in the
36
+ background.
37
+
38
+ Simon Willison put it bluntly: *"hard budget caps, please, now."*
39
+
40
+ Dashboards don't fix this. If a cap can't stop a launch, it's a suggestion.
41
+ `subagent-budget` wires into Claude Code's hook system so an over-budget
42
+ subagent is **refused at launch** — non-zero exit, reason on stderr, the
43
+ agent sees exactly why.
44
+
45
+ ## How it differs
46
+
47
+ | | subagent-ledger | **subagent-budget** |
48
+ |---|---|---|
49
+ | Dimensions | tokens only | **tokens + dollars** |
50
+ | History | cleared when the session ends | **cross-session JSONL ledger** |
51
+ | Enforcement | none — display only | **hooks hard-block the launch** |
52
+ | Pricing | — | built-in model price table (overridable) |
53
+ | Resume-aware | — | **imports resume-budget-guard ledgers** |
54
+
55
+ ## Install
56
+
57
+ ```bash
58
+ pip install subagent-budget
59
+ ```
60
+
61
+ Stdlib only, zero dependencies. Python 3.9+.
62
+
63
+ ## Quickstart
64
+
65
+ ```bash
66
+ # 1. Create the config (~/.config/subagent-budget/config.json)
67
+ subagent-budget init --default-tokens 1000000 --default-usd 50
68
+
69
+ # 2. Cap expensive agent types (glob matched against name AND subagent type)
70
+ subagent-budget set-budget --pattern "Explore*" --tokens 200000 --usd 10
71
+ subagent-budget set-budget --pattern "researcher" --tokens 500000 --usd 25
72
+
73
+ # 3. Backfill usage from Claude Code transcripts
74
+ subagent-budget sync
75
+
76
+ # 4. Record an exact run (e.g. from --output-format json)
77
+ subagent-budget record --agent "Explore auth code" --type Explore --tokens 47117
78
+
79
+ # 5. See where every agent stands
80
+ subagent-budget report
81
+ ```
82
+
83
+ ```
84
+ AGENT RUNS TOKENS COST REMAINING STATUS
85
+ Explore auth code 3 141351 $0.93 58649 tok, $9.07 ok
86
+ deep research dive 9 423000 $2.79 OVER (researcher)
87
+ ```
88
+
89
+ ## Claude Code hooks setup
90
+
91
+ This is the part that makes caps **hard**. Add to your Claude Code settings
92
+ (`~/.claude/settings.json`):
93
+
94
+ ```json
95
+ {
96
+ "hooks": {
97
+ "PreToolUse": [
98
+ {
99
+ "matcher": "Task",
100
+ "hooks": [
101
+ {
102
+ "type": "command",
103
+ "command": "subagent-budget hook --event pre"
104
+ }
105
+ ]
106
+ }
107
+ ]
108
+ }
109
+ }
110
+ ```
111
+
112
+ Claude Code pipes the hook input JSON (tool name, `subagent_type`,
113
+ `description`) into the command's stdin. `subagent-budget` looks up the
114
+ cumulative usage for the matching budget rule; if a limit is exceeded it
115
+ exits with code **2** (Claude Code's blocking-hook signal) and the reason
116
+ goes to stderr, which Claude sees:
117
+
118
+ ```
119
+ subagent-budget blocked launch of 'Explore auth code' (Explore):
120
+ token budget exceeded: used 210,441 / 200,000 tokens
121
+ ```
122
+
123
+ Optional: record exact post-run usage with a `PostToolUse` hook on `Task`:
124
+
125
+ ```json
126
+ {
127
+ "matcher": "Task",
128
+ "hooks": [
129
+ { "type": "command", "command": "subagent-budget hook --event post --tokens $USAGE" }
130
+ ]
131
+ }
132
+ ```
133
+
134
+ (`--tokens` there is whatever your accounting pipeline measured; without it
135
+ the hook records 0 and `sync`/`record` remain the sources of truth.)
136
+
137
+ Manual check without hooks:
138
+
139
+ ```bash
140
+ subagent-budget check --agent "Explore auth code" --type Explore
141
+ # exit 3 = over budget
142
+ ```
143
+
144
+ ## Budgets
145
+
146
+ - Rules are glob patterns matched (case-insensitively) against both the
147
+ agent's description and its subagent type. **First match wins** — put
148
+ specific patterns before broad ones (`--position first`).
149
+ - A named rule's usage accumulates across *all* agents matching its pattern
150
+ (a shared pool). The default budget accumulates per agent name.
151
+ - Either dimension may be left unlimited: `--tokens` or `--usd` alone.
152
+ - Config lives at `~/.config/subagent-budget/config.json`; the ledger at
153
+ `~/.config/subagent-budget/ledger.jsonl` and is **never cleared** at
154
+ session end.
155
+
156
+ ## Working with resume-budget-guard
157
+
158
+ The ledger format is intentionally compatible with
159
+ [resume-budget-guard](https://github.com/hahahahahahahahah6/resume-budget-guard)
160
+ (records carry `ts`, `kind`, `cost_usd`). If you already track resume spend
161
+ there, fold it into the same budgets:
162
+
163
+ ```bash
164
+ subagent-budget import-rbg
165
+ # imports ~/.resume-budget-guard/ledger.jsonl as agent "rbg:<session-key>"
166
+ ```
167
+
168
+ Imported spend counts toward the matching budget rules, so a resume can no
169
+ longer silently reset what a subagent cap was guarding. Idempotent — re-run
170
+ anytime.
171
+
172
+ ## Honest limitations
173
+
174
+ - **Transcript sync is estimated.** A parent transcript does not contain a
175
+ subagent's own token usage, so `sync` records one ledger entry per Task
176
+ invocation using `sync_estimate_tokens` (default 47,117 — the measured
177
+ median first-request size). Override it in config, or use
178
+ `record --tokens` for exact figures.
179
+ - **Dollar amounts are estimates** from a built-in price table (as of
180
+ 2026-10-01). Override `model_rates` in config; pass `--cost` to record an
181
+ exact figure.
182
+ - **A hook can only block what it sees.** The `pre` hook reads Claude Code's
183
+ hook stdin; identity comes from `description`/`subagent_type`. If you spawn
184
+ subagents outside Claude Code's Task tool, record them manually.
185
+ - Enforcement is per-machine (local ledger). It won't stop a second machine
186
+ from spending.
187
+
188
+ ## License
189
+
190
+ MIT
@@ -0,0 +1,167 @@
1
+ # subagent-budget
2
+
3
+ Hard budget caps for subagents — token **and** dollar limits enforced by
4
+ hooks, not just displayed on a dashboard.
5
+
6
+ ## The problem
7
+
8
+ Subagents are the silent half of your Claude Code bill. In one real-world
9
+ measurement ([aidiveyt](https://github.com)), a month of usage — 455
10
+ sessions, 2,631 subagent runs — showed subagents consuming **48.1% of all
11
+ tokens**, with the median subagent's first request alone weighing in at
12
+ **47,117 tokens**. Nobody asked for that spend; it just happened in the
13
+ background.
14
+
15
+ Simon Willison put it bluntly: *"hard budget caps, please, now."*
16
+
17
+ Dashboards don't fix this. If a cap can't stop a launch, it's a suggestion.
18
+ `subagent-budget` wires into Claude Code's hook system so an over-budget
19
+ subagent is **refused at launch** — non-zero exit, reason on stderr, the
20
+ agent sees exactly why.
21
+
22
+ ## How it differs
23
+
24
+ | | subagent-ledger | **subagent-budget** |
25
+ |---|---|---|
26
+ | Dimensions | tokens only | **tokens + dollars** |
27
+ | History | cleared when the session ends | **cross-session JSONL ledger** |
28
+ | Enforcement | none — display only | **hooks hard-block the launch** |
29
+ | Pricing | — | built-in model price table (overridable) |
30
+ | Resume-aware | — | **imports resume-budget-guard ledgers** |
31
+
32
+ ## Install
33
+
34
+ ```bash
35
+ pip install subagent-budget
36
+ ```
37
+
38
+ Stdlib only, zero dependencies. Python 3.9+.
39
+
40
+ ## Quickstart
41
+
42
+ ```bash
43
+ # 1. Create the config (~/.config/subagent-budget/config.json)
44
+ subagent-budget init --default-tokens 1000000 --default-usd 50
45
+
46
+ # 2. Cap expensive agent types (glob matched against name AND subagent type)
47
+ subagent-budget set-budget --pattern "Explore*" --tokens 200000 --usd 10
48
+ subagent-budget set-budget --pattern "researcher" --tokens 500000 --usd 25
49
+
50
+ # 3. Backfill usage from Claude Code transcripts
51
+ subagent-budget sync
52
+
53
+ # 4. Record an exact run (e.g. from --output-format json)
54
+ subagent-budget record --agent "Explore auth code" --type Explore --tokens 47117
55
+
56
+ # 5. See where every agent stands
57
+ subagent-budget report
58
+ ```
59
+
60
+ ```
61
+ AGENT RUNS TOKENS COST REMAINING STATUS
62
+ Explore auth code 3 141351 $0.93 58649 tok, $9.07 ok
63
+ deep research dive 9 423000 $2.79 OVER (researcher)
64
+ ```
65
+
66
+ ## Claude Code hooks setup
67
+
68
+ This is the part that makes caps **hard**. Add to your Claude Code settings
69
+ (`~/.claude/settings.json`):
70
+
71
+ ```json
72
+ {
73
+ "hooks": {
74
+ "PreToolUse": [
75
+ {
76
+ "matcher": "Task",
77
+ "hooks": [
78
+ {
79
+ "type": "command",
80
+ "command": "subagent-budget hook --event pre"
81
+ }
82
+ ]
83
+ }
84
+ ]
85
+ }
86
+ }
87
+ ```
88
+
89
+ Claude Code pipes the hook input JSON (tool name, `subagent_type`,
90
+ `description`) into the command's stdin. `subagent-budget` looks up the
91
+ cumulative usage for the matching budget rule; if a limit is exceeded it
92
+ exits with code **2** (Claude Code's blocking-hook signal) and the reason
93
+ goes to stderr, which Claude sees:
94
+
95
+ ```
96
+ subagent-budget blocked launch of 'Explore auth code' (Explore):
97
+ token budget exceeded: used 210,441 / 200,000 tokens
98
+ ```
99
+
100
+ Optional: record exact post-run usage with a `PostToolUse` hook on `Task`:
101
+
102
+ ```json
103
+ {
104
+ "matcher": "Task",
105
+ "hooks": [
106
+ { "type": "command", "command": "subagent-budget hook --event post --tokens $USAGE" }
107
+ ]
108
+ }
109
+ ```
110
+
111
+ (`--tokens` there is whatever your accounting pipeline measured; without it
112
+ the hook records 0 and `sync`/`record` remain the sources of truth.)
113
+
114
+ Manual check without hooks:
115
+
116
+ ```bash
117
+ subagent-budget check --agent "Explore auth code" --type Explore
118
+ # exit 3 = over budget
119
+ ```
120
+
121
+ ## Budgets
122
+
123
+ - Rules are glob patterns matched (case-insensitively) against both the
124
+ agent's description and its subagent type. **First match wins** — put
125
+ specific patterns before broad ones (`--position first`).
126
+ - A named rule's usage accumulates across *all* agents matching its pattern
127
+ (a shared pool). The default budget accumulates per agent name.
128
+ - Either dimension may be left unlimited: `--tokens` or `--usd` alone.
129
+ - Config lives at `~/.config/subagent-budget/config.json`; the ledger at
130
+ `~/.config/subagent-budget/ledger.jsonl` and is **never cleared** at
131
+ session end.
132
+
133
+ ## Working with resume-budget-guard
134
+
135
+ The ledger format is intentionally compatible with
136
+ [resume-budget-guard](https://github.com/hahahahahahahahah6/resume-budget-guard)
137
+ (records carry `ts`, `kind`, `cost_usd`). If you already track resume spend
138
+ there, fold it into the same budgets:
139
+
140
+ ```bash
141
+ subagent-budget import-rbg
142
+ # imports ~/.resume-budget-guard/ledger.jsonl as agent "rbg:<session-key>"
143
+ ```
144
+
145
+ Imported spend counts toward the matching budget rules, so a resume can no
146
+ longer silently reset what a subagent cap was guarding. Idempotent — re-run
147
+ anytime.
148
+
149
+ ## Honest limitations
150
+
151
+ - **Transcript sync is estimated.** A parent transcript does not contain a
152
+ subagent's own token usage, so `sync` records one ledger entry per Task
153
+ invocation using `sync_estimate_tokens` (default 47,117 — the measured
154
+ median first-request size). Override it in config, or use
155
+ `record --tokens` for exact figures.
156
+ - **Dollar amounts are estimates** from a built-in price table (as of
157
+ 2026-10-01). Override `model_rates` in config; pass `--cost` to record an
158
+ exact figure.
159
+ - **A hook can only block what it sees.** The `pre` hook reads Claude Code's
160
+ hook stdin; identity comes from `description`/`subagent_type`. If you spawn
161
+ subagents outside Claude Code's Task tool, record them manually.
162
+ - Enforcement is per-machine (local ledger). It won't stop a second machine
163
+ from spending.
164
+
165
+ ## License
166
+
167
+ MIT
@@ -0,0 +1,34 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "subagent-budget"
7
+ version = "0.1.0"
8
+ description = "Hard budget caps for subagents — token/$ limits enforced by hooks, not just displayed"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.9"
12
+ authors = [{ name = "hao li", email = "haoli5933@gmail.com" }]
13
+ keywords = ["claude-code", "subagents", "budget", "tokens", "cost-control", "hooks"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.9",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Topic :: Software Development",
24
+ ]
25
+
26
+ [project.urls]
27
+ Homepage = "https://github.com/hahahahahahahahah6/subagent-budget"
28
+ Repository = "https://github.com/hahahahahahahahah6/subagent-budget"
29
+
30
+ [project.scripts]
31
+ subagent-budget = "subagent_budget.cli:main"
32
+
33
+ [tool.setuptools.packages.find]
34
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,8 @@
1
+ """subagent-budget: hard budget caps for subagents.
2
+
3
+ Token/$ budgets enforced by hooks (block the launch), not just displayed.
4
+ Stdlib only. Python 3.9+.
5
+ """
6
+
7
+ __version__ = "0.1.0"
8
+ __all__ = ["__version__"]
@@ -0,0 +1,7 @@
1
+ """Allow `python -m subagent_budget`."""
2
+ import sys
3
+
4
+ from .cli import main
5
+
6
+ if __name__ == "__main__":
7
+ sys.exit(main())