Wiring a Per-Session Spend Ceiling Into Claude Code on an Aggregator Key
A conceptual walkthrough for enforcing a per-session USDC spend ceiling when running Claude Code against an LLM API aggregator key: where spend actually accrues, which layer to intercept at, how to translate a USDC budget into a session guardrail, and what clean and messy mid-session ceiling hits look like in practice.
Why cap a session at all
Claude Code is an agentic client: one human task can turn into many model calls as it reads files, plans, edits, and re-checks. On a metered aggregator key, that means one session can spend far more than you expect. A per-session ceiling in USDC gives every working session a hard boundary, so a single runaway loop or an over-long debugging detour can't quietly drain a balance.
The goal is not to throttle normal work. It is to make the maximum downside of any one session a number you chose in advance.
Understand where the money is actually spent
Before choosing a place to intercept, be clear about the flow:
- Claude Code sends model requests to the aggregator's base URL using your API key.
- The aggregator authorizes the key and routes the request to the selected model.
- Usage is billed against your prepaid USDC balance at the aggregator's published price for that model.
So the spend signal lives at the aggregator, not inside Claude Code. Claude Code knows how many tokens it has sent and received (it shows context and cost estimates), but the authoritative number is the balance movement on your account.
On an aggregator that charges official price × 1.3 to users, your per-session budget is expressed in the same USDC units as your top-up. Contributors to the platform instead receive a credit back at official price × 1.1 (× 1.2 for premium tiers) in USDC, which affects net economics over time but does not change how you meter a session — you still cap against what the request costs you.
Pick your interception layer
There are three practical places to enforce a ceiling. Each has different fidelity and different failure behavior.
1. Session wrapper around Claude Code
You launch Claude Code from a script that owns the session. The wrapper is responsible for the budget: it snapshots the balance at session start, and a companion loop or hook checks spend after each tool turn.
- Pros: no changes to how Claude Code talks to the API; one script gives you one budget per session.
- Cons: the check is periodic, not instantaneous. You know you overspent only on the next poll.
2. Proxy in front of the aggregator
The client points at a local proxy, which forwards to the aggregator with your key and counts cost per request as responses stream back.
- Pros: you see every request and can reject the next one the moment the budget is exhausted; you can log per-request cost for later analysis.
- Cons: one more process to run and keep healthy; streaming and tool-call responses must be passed through faithfully.
3. Aggregator-side budgets
If the aggregator supports per-key spending limits or balance alerts, use them as a backstop. They are the most authoritative limit, but they are typically coarse — a daily or per-key cap, not a per-session one — so they complement, rather than replace, the two layers above.
A robust setup uses the proxy for the tight in-session limit and the aggregator limit as the outer fence.
Turn a USDC budget into a session guardrail
Do not equate "tokens" with "money" — they are not proportional across models and turns. Instead:
- Snapshot the starting balance (or a proxy-side counter starting at zero) when the session opens.
- Record a per-session budget in USDC, e.g. the most you are willing to spend on one task.
- Compute session spend as
starting value − current value(balance-based) or as the running sum of per-request cost (proxy-based). - Define a soft threshold and a hard ceiling. At the soft threshold, warn or pause for confirmation. At the hard ceiling, stop.
Because usage is billed at the aggregator's price — official price × 1.3 for pay-as-you-go users — the per-request cost you accumulate in the proxy should be the same priced usage the aggregator applies, so your counter and the balance movement agree.
What happens when the ceiling is hit mid-edit
This is the part people underestimate. An agent session is stateful: Claude Code may be halfway through a plan, with files read, edits staged, and tools queued. Cutting the money mid-stream has consequences beyond "the request fails."
Clean stop (recommended)
The soft threshold triggers a controlled pause: the current tool call finishes, Claude Code is told to stop taking new actions, and you get a summary of unfinished work. Token cost stops growing because no new requests are issued. Work-in-progress is left in a readable state — partial edits on disk, a to-do list you can resume from next session.
Hard stop (what a blunt cut looks like)
The hard ceiling rejects the next request outright. The model call fails, and Claude Code surfaces an error. Depending on where the cut landed:
- Mid-edit: you may have a partially applied patch. Most editors and Claude Code's own diff view make this inspectable, but you should review the working tree before resuming.
- Mid-tool-loop: the agent may retry the failed call, which itself costs nothing if rejected before routing, but generates error churn in the transcript.
- Mid-plan: the plan is not lost, but the agent loses the thread of what it was doing; a fresh session picks up more cleanly than a resumed one.
Either way, no further spend occurs once the next request is blocked — the ceiling holds. The cost of a hard stop is workflow disruption, not budget leakage.
Keep the ceiling from being a nuisance
- Size the budget to the task class, not to a fixed number for everything. A refactor and a one-line bug fix are not the same session.
- Reserve headroom for the resume. If you plan to continue after a pause, the resume is itself a new session with its own budget.
- Log spend per session so you can see which task types approach the ceiling. That is your tuning data.
- Watch config drift. If a proxy rewrites the base URL or key for some tools but not others, some traffic escapes the counter. A single egress point avoids this.
A minimal pattern to copy
The shape that works in practice:
BUDGET_USDCset per session.- A wrapper (or proxy) that records start value and current value.
- A check after each assistant/tool turn:
spend = start − current. if spend >= BUDGET_USDC: block next request, print session summary.- The aggregator-side limit set a bit above the wrapper limit as a backstop.
With that in place, a Claude Code session becomes a bounded unit of work: you can launch it, walk away, and know the most it can cost is the ceiling you set in USDC — while still paying the aggregator's straightforward price × 1.3 and, for contributors, receiving the × 1.1/× 1.2 credit as usual.