Blog

Tool output is eating your context: compress test logs, diffs and grep results

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.

67.7%
of spend is re-reading cached history
0.2%
is fresh, uncached input
+15.2%
cost per pass with a shell filter, one run

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.

OutputInstead ofAsk for
Test runsThe full suite, verbosepytest path/test_x.py -x -q --tb=short
Builds and lintersEvery warning and progress lineErrors only, or | tail -n 40 after a failure
Diffsgit diff of the whole treegit diff --stat, then git diff -- path
SearchUnbounded grep over the reporg -l or rg -c, then a scoped search
JSON and API responsesThe full payloadFields via jq, or the first few items
File readsWhole generated files and lockfilesThe relevant range, or a symbol search
LogsThe entire logA 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 goMust reach the agent verbatim
Passing testsFailing test name
Already-triaged warningsThe assertion and exact message
Repeated linesThe stack trace with file and line

Make it the default

The agent picks its own commands, so tell it which ones to use.

  1. 1
    Write it in CLAUDE.md

    Targeted test and lint commands, git diff --stat first, no lockfiles. Keep it short: it is sent every request.

  2. 2
    Delegate broad searches

    A subagent searches in its own context and hands back a short answer.

  3. 3
    Clear between tasks

    /clear drops old output; /context shows 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.

ToolActs onHowTrade-off
rtkShell output, before contextFailures only, grep grouped by fileRaised cost per solved task in one Terminal-Bench run
condenseThe request, every turnTrims the newest turn verbatim; packs finished tool loops and keeps the pack fixed for cachingHosted; 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.

All posts