◉CLAUDE LABJP
●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…
Articles/Claude Code
⟐ Claude Code/2026-07-17Advanced

My Nightly Subagents Ran, and I Couldn't Retrace Them — Trimming the Logs That --forward-subagent-text Unleashed

Subagent text and thinking can now flow into stream-json output, and unattended log volume climbs sharply with it. Here are measured numbers, a three-tier retention filter that keeps only what postmortems need, and a correlation ID design that survives missing fields.

Claude Code264Subagents8stream-jsonLog DesignAutomation45

✦ Premium Article

I opened the log from a failed nightly task and stopped short.

The parent session recorded two useful things: that it had launched four subagents, and that one of them never returned a result. What those four read, where they changed course, and why exactly one went quiet — none of it was there.

When a job runs unattended, the log is all you get. And mine was missing the part that mattered.

The July 17 update added the --forward-subagent-text flag (or CLAUDE_CODE_FORWARD_SUBAGENT_TEXT as an environment variable), which pushes subagent text and thinking into stream-json output. Exactly what I'd wanted.

Then I turned it on, ran one night, and hit a different wall the next morning. The logs were no longer a size a person reads.

What actually starts flowing

First I measured what the flag changes.

# Before: parent events only
claude -p "Validate article metadata across four categories" \
  --output-format stream-json > baseline.jsonl
 
# From July 17: subagent text and thinking included
claude -p "Validate article metadata across four categories" \
  --output-format stream-json \
  --forward-subagent-text > forwarded.jsonl

Output is JSON Lines, one event per line, so counting by type is straightforward.

# Break down the event types
jq -r '.type' forwarded.jsonl | sort | uniq -c | sort -rn

I ran the same prompt ten times each and took the medians. Four subagents plus one parent, on Sonnet 5.

MetricNo flag--forward-subagent-textRatio
Lines (events)2184,93022.6×
File size0.9 MB38.4 MB42.7×
From thinking blocks0 MB24.1 MB—
From assistant text0.4 MB11.8 MB29.5×
90-day total (3 runs/day)0.24 GB10.4 GB43.3×

The 42× headline mattered less to me than the breakdown. 63% of the growth is thinking. And thinking is enormously useful for diagnosing a failure, while a successful run's thinking is never opened at all.

So most of the new volume has an awkward shape: rarely read, indispensable when you need it. Dropping all of it is wrong. Keeping all of it is also wrong.

Three tiers, three fates

I settled on sorting every event into one of three tiers.

TierContentsRetentionPolicy
SkeletonParent/child start and stop, tool names, result statusForeverNever trimmed. Enough to reconstruct the shape of a run
BodyAssistant text, summarized tool input30 daysKeep head and tail, record the middle as a character count
ThinkingThinking blocks7 days / forever on failureDiscard for successful runs, keep for failed ones

"Keep only on failure" can't be decided while writing. You don't know a run failed until you reach the end of it.

So the filter writes everything first, then decides once the exit status is known. Deferring the judgment costs a little disk churn and buys correctness.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦Measured growth per run with --forward-subagent-text enabled, broken down by event type
✦A three-tier filter separating keep-everything, summarize, and discard (runnable Node.js)
✦Correlation ID design for matching parent sessions to child agents, including what to do when the field arrives null
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

⟐ Claude Code2026-07-18
Branch with /fork, Delegate with /subtask — Two Commands That Traded Jobs
In Claude Code 2.1.212, /fork now clones your conversation into a background session, and in-session subagents moved to /subtask. Here is how I decide between them, and the budgets worth setting before you start branching freely.
⟐ Claude Code2026-09-01
Drop the quotes on a heredoc and the prices in your log quietly change
An unquoted heredoc runs the variables and backticks inside its body. Here are the four ways my log got rewritten, how the three quoting forms compare, a safe placeholder-and-sed pattern, and a small script for auditing what you already have.
⟐ Claude Code2026-08-22
Handing a long job to another session — and the completion marker for when the notification never arrives
How to use notify_when_idle to hear when another Claude Code session finishes, and a small completion marker that keeps you from waiting forever when the notification is dropped.