How to save tokens in Claude Code: my agent team ate my usage limit in an hour
How to save tokens in Claude Code: what I found when my Claude Max limit suddenly ran out in an hour, and the skills, subagents and briefing rules that stopped my agents reading everything three times.
On Monday of this week something strange happened. I’m on a Claude Max 20x subscription, and on a normal day I can work four hours or more in one usage window without thinking about it. On Monday my session hit the limit after about an hour. The next one too. One lasted twenty minutes.
Since yesterday everything is back to normal. Yesterday I worked the whole day in one session on Fable, the biggest model, without hitting anything. My own transcripts don’t explain the drop either. On the days I hit the limit, my sessions used fewer tokens than on several days the week before, when I worked for hours without a problem. The Sunday before, a single session of mine wrote 42 million tokens into the cache without hitting any limit.
The timing is interesting too. The limits went strange in the same days Anthropic released Opus 5.5, and the day after the worst of it, Claude Code suddenly offered me a one-time “reset limit” button, one per account, which I had never seen before. Anthropic hasn’t said anything went wrong. But put together, I’m pretty sure it wasn’t only me.
Still, when your tool suddenly stops working, you look at what you’re doing with it. And what I found was worth fixing whether Anthropic had a bug or not.
The project and the pattern
The project is a Flutter app with a Serverpod backend. I’m the only developer, Claude Code is my daily tool, and the project rules live in a CLAUDE.md.
For larger features I use an agent team. A lead session on Opus splits the feature into lanes. Each lane gets its own git worktree and its own implementing agent. An independent reviewer agent reviews each lane’s diff before merge, and the lead integrates. For a redesign of the app’s start page that was four lanes and five reviewers.
Compared with my other projects, this one had grown differently. It had no specialized subagents and no skills. Every agent was the generic general-purpose type, and everything the agents needed to know sat in CLAUDE.md or was repeated in each brief.
Measure before you guess
Claude Code writes every session as a JSONL transcript under ~/.claude/projects/<project>/. Every assistant message carries its token counts: cache creation, cache read, input, output. I had Claude read them back and sum them.
The lead session of the run that failed:
- 355 messages
- 21.8 million cache-creation tokens, about 61k per message
- 74 turns that each wrote more than 100k tokens into the cache
My first theory was the prompt cache going cold while I waited for agents and then being rebuilt. That explained 1.9 million of the 21.8 million. My first guess was wrong by a factor of ten.
The agents come on top. Subagent transcripts are stored separately, under <session-id>/subagents/, so if you only sum the top-level files you miss them. For that run, ten subagent transcripts added another 10.2 million cache-creation tokens and 254 million cache-read tokens.
Where the tokens went: the same text, again and again
To be clear up front: none of what follows explains why my limit suddenly dropped. I had worked with this exact setup for weeks without any trouble. But it was waste all the same, and in a team you pay for waste nine times.
The team didn’t get expensive because the agents did a lot of work. It got expensive because the same text entered a context window three, four, nine times. Biggest first:
- Every report reached the lead three times. The lane agent’s final message, the harness notification echoing that same text, and then the lead copying it into a file. Three copies of a multi-thousand-token report, per lane, per round.
- The full test suite ran about four times per round. Lane, lane fix round, reviewer, lead. About 500 Flutter tests, each time with full progress output streaming into a context.
- Reviewers worked out every change again from the repo. Each reviewer read
CLAUDE.md, the working conventions, the UX concept, the brief, the lane’s report, and then whole source files to find out what had changed. Five reviewers, five full re-reads. - Shared rules were read by all nine agents. A 2.4 KB rules file plus
CLAUDE.md. Small per agent, but nine times, and again on every restart. - The lead re-read files the agents had already reported on, and re-read a design index before every publish, although it only matters when there is a conflict.
The fixes
Reports go to a file, the reply is DONE
A lane writes its report to a file and answers with one word. The lead reads the file once, when it needs it. No echo, no relay.
Run your own tests, piped
Lanes and reviewers run only the tests for their own area, piped through | tail -5. The full suite runs once, at integration, by the lead.
Reviewers get a diff, not a repo
The reviewer gets git diff main...<branch> and reviews that, instead of finding the change on its own. A fix round checks only the findings that were named. To make that possible, lanes now commit on their own branch. They never push and never merge. That has a nice side effect: tearing down a worktree can no longer lose work.
Put the rules in agent definitions, not in briefs
This was the biggest structural change. Project agent types under .claude/agents/:
app-lane: Sonnet, edit tools, no web accessapp-reviewer: Opus, read-onlyapp-git: Sonnet, git plumbing onlyapp-backlog: Sonnet, read-only
The rules every agent has to follow (use the fvm SDK, never commit to main, stay in your worktree, write your report to a file) live in the agent definition. A brief now only describes the lane’s actual scope. And the reviewer is never the agent that wrote the brief.
Rules in a prose brief are suggestions. Rules in an agent definition are always there, and the tool list makes some of them impossible to break. A read-only reviewer cannot “just quickly fix” something.
Why smaller models for helper agents
Pinning helper agents like app-git or app-backlog to Sonnet helps in two ways:
- The work is cheaper. A smaller model uses up less of the limit for the same amount of text, and git housekeeping doesn’t need the strongest model.
- The lead’s context stays small. A subagent works in its own context window. All the noisy output of
git log, merge conflicts or a backlog search stays there, and the lead gets back a short conclusion. Every later turn of the lead doesn’t have to carry that noise along.
A subagent isn’t free, though. Each one starts with a fresh context: its own system prompt, tool definitions and project instructions. For a single git status that overhead costs more than running the command inline. A git agent pays off for multi-step work with a lot of output: merging several lanes, resolving conflicts, cleaning up worktrees. The same goes for broad code searches: hand them to a cheap Explore agent that returns a conclusion instead of file dumps.
Skills instead of an ever-growing CLAUDE.md
The other thing my other projects already had and this one didn’t: skills. Knowledge like how to deploy the backend, how to access the staging database correctly, or how to manage backlog tickets had slowly piled up in CLAUDE.md.
The problem is that CLAUDE.md is loaded in full into every session and into every agent that reads it, whether the task has anything to do with deployment or not. Every line is paid for on every run. With nine agents, nine times.
A skill works differently. Until it’s used, only its name and a one-line description sit in the context. The full instructions load when a task actually needs them. So the deploy procedure costs tokens only when you deploy.
My rule of thumb now: CLAUDE.md holds what is true for every task in the repo. Procedures that only matter for some tasks become skills.
Lead-side habits
- Don’t re-read what an agent has already reported.
- Re-read shared indexes only on a conflict.
- Every “just to be safe” re-read is paid for in full, and in a team it’s paid nine times.
A smaller version of the same problem
Even without a team, a single long session can read too much. The day after, I had Claude run a 60-scenario coaching benchmark many times, and it read the full logs right in the session to sort out the failures. The benchmark itself costs the session nothing, because it runs on our staging server. But every log Claude read went straight into the context. The cheaper way follows the same principle: an agent that reads the logs and returns only the failing replies.
Measure it yourself
- Transcripts are in
~/.claude/projects/<project-path-with-dashes>/*.jsonl, and subagent transcripts are in<session-id>/subagents/*.jsonlnext to them. - Each line is a JSON object. Assistant turns carry
message.usagewithcache_creation_input_tokens,cache_read_input_tokens,input_tokensandoutput_tokens. - Sum per session, look at the distribution per turn, and look for turns whose cache creation is far above the median. Those are the “something big just got pasted in” turns. Then read what got pasted.
You don’t need a tool for this. Ask Claude Code to do it. It’s a five-minute job.
What I take away
- Cost is a context-hygiene problem before it’s a model-choice problem.
- Rules in prose briefs aren’t enforced. Rules in agent definitions are.
- Keep
CLAUDE.mdfor what’s always true, and move procedures into skills. - Measure from the transcripts before changing anything.
And if your limit suddenly drops by a factor of four overnight, it may not be your fault. But it’s still a good reason to look.