[BUG] Session files grow to multi-GB due to normalizedMessages duplication in subagent progress entries
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Session .jsonl files grow to multi-GB sizes during long sessions with heavy subagent (Task tool) usage, eventually preventing Claude Code from starting.
Root cause: Every progress entry for subagents stores the full normalizedMessages array (complete conversation history at that moment). With many progress updates per subagent turn, session files grow exponentially.
Evidence from a 3.1GB session file:
- 3,620 progress entries with normalizedMessages
- 777,402 total messages stored (massive duplication)
- Largest single entry: 7.1MB (1,154 messages)
- Average ~200x duplication per message
- Session duration: ~10 hours
Entry structure causing bloat:
{
"type": "progress",
"data": {
"agentId": "a9b4d10",
"normalizedMessages": [/* FULL HISTORY */],
"prompt": "...",
"message": "..."
}
}
This is distinct from:
- #5034 (stream-json format issue)
- #9890/#10107 (FileHistory issues)
- #6394 (.claude.json bloat)
What Should Happen?
Progress entries should NOT store the full conversation history on every update. Options:
- Store message deltas/diffs only
- Reference previous entries by ID
- Don't include normalizedMessages in progress events (reconstruct from subagent files if needed)
Error Messages/Logs
No error messages - Claude Code simply fails to start when session files are too large. Had to manually move `~/.claude/projects/` to restore functionality.
Steps to Reproduce
- Start a Claude Code session in a project
- Use the Task tool (subagents) heavily throughout the session
- Continue for several hours with many subagent invocations
- Monitor
~/.claude/projects/{project-dir}/*.jsonlfile sizes - Observe exponential growth correlating with subagent usage
- Eventually Claude Code refuses to start due to file size
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.12 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
iTerm2
Additional Information
- This punishes exactly the workflow that makes Claude Code valuable: long-running sessions with heavy agent delegation for complex tasks
- I have the bloated session files preserved (~12GB total across multiple sessions) and can provide them for analysis
- The issue appears to persist in 2.1.12 but at smaller scale in current sessions (226KB max vs 7MB per entry in older sessions)
- Analysis commands used to identify root cause:
```bash
# Size by entry type
jq -c '{type, size: (. | tostring | length)}' session.jsonl | jq -s 'group_by(.type) | map({type: .[0].type, count: length, total_size: (map(.size) | add)})'
# normalizedMessages sizes
jq -c 'select(.type == "progress" and .data.normalizedMessages) | {nm_size: (.data.normalizedMessages | tostring | length)}' session.jsonl
```
11 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Additional data point from #19887:
| Metric | Value |
|--------|-------|
| Session file | 270 MB |
| Progress entries | 3,540 |
| Progress data | 250 MB (93% of file) |
| Subagents spawned | 23 |
| User-visible messages | 72 |
Trigger: ESC ESC → restore conversation (without code) during active session with compaction.
Symptoms:
claude -calso hangs---
Workaround: Slim progress entries by replacing
normalizedMessageswith just the count:Result: 257 MB → 17 MB, session resumes successfully. Metadata (agentId, prompt, timestamps) preserved.
Workaround Script
Here's an updated version of the workaround from the thread that works as both a manual script and a Claude Code hook.
Script
Save as
~/.claude/hooks/slim-session.py:Usage
Manual cleanup:
As a global Stop hook (runs after every conversation turn):
Add to
~/.claude/settings.json:As a skill-specific hook (add to skill frontmatter):
Results
Tested on a 343MB session file bloated by parallel subagent skills:
Session still loads and resumes correctly after slimming.
Conversation JSONL files in .claude/conversations/ grow without any limit. In my case, 79 conversation files totaled 2.5GB, with a single file reaching 1.1GB.
Root causes:
Impact:
Expected behavior:
Environment:
This is one of the biggest contributors to session bloat — normalizedMessages duplication in subagent progress entries compounds fast.
I built Cozempic to deal with this. The
progress-collapsestrategy specifically targets consecutive progress ticks (which account for 40-48% of file size), anddocument-dedupcatches the repeated normalizedMessages blocks:@Isoceth's workaround script is great for manual cleanup — Cozempic does something similar but with 13 composable strategies and automatic backups. Typical savings are 50-65% on subagent-heavy sessions.
Real-world impact: normalizedMessages bloat drove a 271 GB task output file
Adding a data point from v2.1.70 (macOS 15.7.5, M3 Max).
This issue's root cause —
normalizedMessagesduplication in progress entries — directly contributed to a 271 GB single.outputfile in/private/tmp/claude-501/. Details in my comment on #26911.The chain reaction
progressentry in JSONLnormalizedMessages(per this issue).outputfileThe
normalizedMessagesduplication described here is the force multiplier that turns a moderate-sized task output into a catastrophic disk-filler. Without the duplicated history in every progress entry, the same session would likely have produced single-digit GB of output.Supporting the proposed fix
Strongly agree with the proposal to not include normalizedMessages in progress events. Reconstructing from subagent files on demand is the right pattern. Even just storing a
normalizedMessages_countfield (as shown in the workaround script) would reduce file sizes by 93%+.This is not a theoretical concern — it nearly bricked a 1 TB MacBook Pro.
We've hit this too. Heavy subagent user — our workflow regularly spawns 3-6 parallel
Agenttool calls per investigation cycle across ~200 sessions on the same project. Session files on Windows grow noticeably over long sessions.Our mitigation has been architectural rather than patching the symptom:
PreCompacthook that snapshots active work state to a separate JSON file before compaction. This means we don't fight compaction (which helps control session file growth) but instead embrace it with state preservation.PreCompactsnapshot + MEMORY.md files make this nearly seamless.But these are all workarounds. The OP's analysis is spot-on — storing full
normalizedMessageson every progress entry is the root cause. Delta-only progress entries would fix this at the source. The exponential growth pattern (each progress entry contains all previous messages plus new ones) means a single long-running subagent can generate more data than the entire rest of the session.A Stop hook can clean up oversized session files:
The Stop hook removes oversized old sessions. Weekly cron prevents long-term disk bloat.
Multi-GB session files from normalizedMessages duplication in subagent progress is exactly what
progress-collapsein Cozempic v1.4.1 targets. It removes all progress tick messages, which include these duplicated normalized entries. Measured 92% savings on a session with 2,100+ progress ticks.pip install cozempic && cozempic initThe guard daemon runs this automatically. Also
file-history-dedupremoves duplicate file-history-snapshot entries that compound the problem.This was fixed in v2.1.16 — Subagent progress entries no longer duplicate the full message history into the session file, preventing multi-GB transcript growth. If you're still seeing this in the latest version, please comment with your version and repro and we'll reopen.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.