Ask commands for less before they run: one test file, quiet flags, git diff --stat before full diffs, grep counts before matches, and jq for JSON. Keep whatever failed in full. Every tool result is re-sent on each later turn, so one 5,000-line test log is paid for again and again until you clear or compact.
Why tool output fills context
Passing tests, progress bars and unneeded JSON all join the conversation. Output read on turn 10 is still in the request on turn 200, and brings auto-compact closer.
Compress it by type
Locate before you read. A count or a stat line costs a few tokens and tells the agent where to look.
| Output | Instead of | Ask for |
|---|---|---|
| Test runs | The full suite, verbose | pytest path/test_x.py -x -q --tb=short |
| Builds and linters | Every warning and progress line | Errors only, or | tail -n 40 after a failure |
| Diffs | git diff of the whole tree | git diff --stat, then git diff -- path |
| Search | Unbounded grep over the repo | rg -l or rg -c, then a scoped search |
| JSON and API responses | The full payload | Fields via jq, or the first few items |
| File reads | Whole generated files and lockfiles | The relevant range, or a symbol search |
| Logs | The entire log | A level or time filter, or grep -n ERROR |
Keep the error intact
A last-20-lines filter can cut the failing assertion, and an agent that cannot see it reruns the command. Cut around failures, not through them.
| Can go | Must reach the agent verbatim |
|---|---|
| Passing tests | Failing test name |
| Already-triaged warnings | The assertion and exact message |
| Repeated lines | The stack trace with file and line |
Make it the default
The agent picks its own commands, so tell it which ones to use.
- 1Write it in CLAUDE.md
Targeted test and lint commands,
git diff --statfirst, no lockfiles. Keep it short: it is sent every request. - 2Delegate broad searches
A subagent searches in its own context and hands back a short answer.
- 3Clear between tasks
/cleardrops old output;/contextshows what fills the window. See /compact vs /clear.
Tools that do it automatically
rtk filters before output enters context. condense compresses what is already there, which command hygiene cannot remove. We build condense; the full comparison is in rtk vs Headroom vs condense.
| Tool | Acts on | How | Trade-off |
|---|---|---|---|
| rtk | Shell output, before context | Failures only, grep grouped by file | Raised cost per solved task in one Terminal-Bench run |
| condense | The request, every turn | Trims the newest turn verbatim; packs finished tool loops and keeps the pack fixed for caching | Hosted; leaves code, patches and error output untouched |
Frequently asked questions
Why does tool output use so many tokens in Claude Code?
Each tool result joins the conversation and is re-sent with every later request. A large log read early is billed on every turn after it until /clear or compaction.
How do I stop test output from flooding the agent's context?
Run the narrowest target, stop at the first failure, use short tracebacks, and run the full suite only once targeted tests pass. Put those commands in CLAUDE.md.
Can I compress tool output automatically?
Yes. rtk filters shell output on your machine; condense trims the newest turn and packs finished tool loops, keeping code, patches and errors intact.
Will compressing tool output make the agent miss errors?
It can, if a filter drops the failing lines or a summary paraphrases a trace. Keep errors verbatim and judge by tasks solved, not tokens removed.
Do subagents reduce tool output tokens?
Yes. A subagent searches in its own context and returns a short result, though its own tokens still count toward usage.