Output Spooling to Disk
A test suite prints 40,000 lines and fails on one of them. Run it directly and the whole dump enters the transcript, where it stays for the rest of the session and is re-sent on every subsequent turn. Spool it — pytest > /tmp/test.log 2>&1; tail -30 /tmp/test.log — and the context holds thirty lines, while the other 39,970 remain on disk, available to grep if they ever turn out to matter.
The asymmetry that makes this worth a rule: a tool result cannot be taken back. The agent chooses, before running the command, whether its output will be resident for the remainder of the session. There is no un-print.
Principle
Send verbose output to a file and read a deliberate slice of it. The file system is a context extension with zero token cost and full random access; the transcript is a write-once log that is re-read on every turn.
Why the Cost Is Not What It Looks Like
A 40,000-line dump is not a one-time charge. With T turns remaining in the session, it is charged T more times, minus whatever prompt-cache discount applies. The naive reading — "one big tool result, one big cost" — understates it by a factor of the remaining session length, which is exactly why the habit survives: the damage is invisible at the moment it is done.
Spooling also preserves what truncation destroys. A tool result clipped by the harness at some line limit loses the tail permanently; a spooled file loses nothing, because the bytes are still on disk under a path the agent knows.
Techniques
Redirect and Tail
The default move for any command whose output is unbounded: builds, test runs, installers, container logs, data dumps. Read the last N lines, which is where failures usually surface, and go looking only if that is not enough.
Query Instead of Read
Once the output is a file, it is searchable. grep -c, grep -n FAIL, awk over the summary line: the agent extracts the answer it actually needs — a count, a first failure, an exit status — rather than re-reading the material to find it. See Grep-Result Tool Output.
Exit Code First
Most of the time the question is "did it pass?", and the exit code answers it in one token. Read the log only on failure. See Fail Fast Validation.
Filter at the Source
| tail -30, --quiet, -q, --reporter=dot, 2>/dev/null: many tools can simply be told to say less. Cheaper than spooling, when available, because nothing has to be written or re-read.
Intermediate Artifacts Stay on Disk
Output that is only an input to the next command — a generated file, a JSON dump about to be queried, a diff about to be applied — never needs to pass through the context. The same logic on the generation side is Write-Path Delegation.
Trade-offs
- Two calls instead of one when the tail is not enough and a
grepfollows. Almost always cheaper than the dump, but not free. - A guess about where the signal is.
tail -30is a bet that failures print last; some tools print the summary first, or bury it mid-stream. - Files accumulate. Spool to a scratch directory, not into the repository, or the next
git statuspays for the mess. - Streaming is lost. A redirected command shows nothing until it finishes, which matters for a job the agent may want to abort early.
Anti-patterns
- Running a verbose command bare "just to see what happens" — that decision is irreversible.
- Spooling to a file and then
cat-ing the whole file, which reintroduces the entire dump with extra steps. - Printing a large file in order to reason about it, when a
grepwould answer the actual question. - Echoing content the agent just wrote, to confirm it was written.
- Spooling output that was small anyway, adding a round-trip to save nothing.
See Also
- Grep-Result Tool Output — the tool-author's side of the same goal; spooling is what the agent does when the tool does not cooperate.
- Write-Path Delegation — the generation-side counterpart: the artifact is written to disk without passing through the context.
- Fail Fast Validation — the exit code usually answers the question the log was going to be read for.
- Prompt Truncation — harness-level clipping loses the tail permanently; spooling keeps it retrievable.
- Token-Aware Formatting — reducing what a command emits in the first place.
- Event-Driven Waiting — the other source of permanently resident dead bytes.
- Compaction — what an unspooled log dump eventually forces.
Tools
- Claude Code Bash tool — shell redirection plus a session scratchpad directory make spooling the default for verbose commands.
pytest --tb=line -q— source-side output reduction for the most common offender.gh run view --log-failed— fetches only the failing job's log instead of the whole CI run.