Technical Blog
Claude Code Hooks: What They Can (and Can't) Do for Cost Control
If you already use Claude Code hooks, you probably have the behavioral side of governance covered. The missing part is spend.
I like Claude Code hooks because they give me a clean way to attach policy to agent behavior. If I want to log every shell command, block risky tool calls, or run validation after file edits, hooks are the right mechanism. They are simple, local, and close to the agent workflow.
But after using them for a while, I ran into a limit that matters in real projects: hooks do not tell me what the session is costing. They run around tool calls, not around the Anthropic API requests themselves. So if my goal is “stop this session when it burns through $10,” hooks alone cannot do that.
That is the gap agent-bill-guard fills. I still use hooks for behavioral governance, and I put agent-bill-guard in front of the Anthropic API for cost governance. The combination is what I wanted all along.
What Claude Code hooks are good at
Claude Code supports lifecycle hooks in settings.json. The events include PreToolUse, PostToolUse, Notification, Stop, and SubagentStop. That makes them useful for things like:
- blocking dangerous shell commands before they run
- logging tool usage for audit
- running formatters or checks after edits
- adding local guardrails without changing the app code
Here is a real working hook example that logs every Bash tool invocation before it runs:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \"No description\")\"' >> ~/.claude/bash-command-log.txt"
}
]
}
]
}
}
That is useful. I can inspect ~/.claude/bash-command-log.txt later and see what the agent tried to do. I can also replace that logger with a validator that denies commands matching a pattern.
If your problem is “what files or commands did the agent touch?”, hooks are exactly the right abstraction.
Where hooks stop helping
The problem is that API spend is not a tool event. Claude Code might make multiple Anthropic API requests during a session, and hooks do not sit on that path. They do not intercept request payloads, response usage fields, token counts, or cumulative dollar cost.
Important limitation: Claude Code hooks can govern agent behavior, but they cannot reliably answer “how much has this session spent so far?” and they cannot enforce a hard budget cap on Anthropic API usage.
That distinction matters. Logging every Bash call does not tell me whether a long reasoning loop just consumed another few dollars. Blocking rm -rf is useful, but it does nothing if my main failure mode is runaway model usage.
What I use for cost governance instead
agent-bill-guard solves the missing part by sitting between Claude Code and the Anthropic API as a local proxy. Because it sees every API request and response, it can do the things hooks cannot:
- track cumulative token cost for the session
- show real-time cost in the terminal
- write an append-only
ledger.jsonl - block new API requests once a budget cap is hit
That is cost governance, not behavioral governance. It answers a different question: not “what did the agent try to do?” but “how much model spend did this session accumulate, and should the next request be allowed?”
Running hooks and agent-bill-guard together
This is the setup I actually want:
- Claude Code hooks for file, command, and tool governance
- agent-bill-guard for API spend tracking and budget enforcement
Start the local proxy first:
agent-bill-guard --listen 127.0.0.1:8787 --budget-usd 10
Then point Claude Code at it with ANTHROPIC_BASE_URL:
export ANTHROPIC_BASE_URL=http://127.0.0.1:8787
claude
That is the trick. Claude Code still behaves normally, your hooks still fire, but the API traffic now goes through a local process that can meter and enforce spend. When the session hits the configured cap, agent-bill-guard blocks the next request before more money is spent.
The split is clean: hooks handle behavioral governance, agent-bill-guard handles cost governance.
Why I prefer the split
I would rather keep these concerns separate than force one system to do both badly. Hooks are a good fit for “don’t let the agent run this command.” A proxy is a good fit for “don’t let the session exceed this budget.” Mixing those concepts usually produces partial visibility and awkward policy.
There are limits, of course. Hooks still matter because cost control does not tell me whether the agent touched a sensitive file. And a proxy still matters because command logs do not tell me what the Anthropic invoice will look like. I need both views.
If you already rely on Claude Code hooks, I would not replace them. I would keep them, then add agent-bill-guard in front of the API. That gives you two separate controls that line up with two separate risks: agent behavior and API spend.