[BUG] PreCompact hook output is added to the compaction instructions with no size limit
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?
The stdout of every successful PreCompact hook is added, in full, to the custom instructions of the compaction request. Nothing limits its size.
In 2.1.296, the PreCompact runner keeps each successful, non-blocking hook's trimmed output and joins all of them into newCustomInstructions. The auto, reactive and manual compaction paths all append that to the request's customInstructions. I found no truncation anywhere on that path. The same full output is also put into the message shown to the user ("PreCompact [cmd] completed successfully: <output>").
SessionStart output, by contrast, is shortened past 10,000 characters to a preview plus a file path. So the same command that is safe on SessionStart can break compaction when it is wired on PreCompact.
We hit this with bd prime (beads issue tracker). It was wired on both SessionStart and PreCompact, in project and user settings, and printed about 2.2 MB per run because it included a large memory store. Every compaction then carried about 4.4 MB of custom instructions. Sessions came back from compaction about 95% full and stopped with "Autocompact is thrashing". The compaction summaries also went stale; most likely the summarizer was reading the hook output more than the conversation (not verified).
The thrash message then blames "a file or tool output", which pointed us the wrong way (compare #85489).
What Should Happen?
PreCompact hook output added to the compaction instructions should be size-limited, as SessionStart output is: truncated with a note, or rejected with a visible warning that names the hook. A hook printing megabytes should not be able to fill the compacted context by itself.
Error Messages/Logs
Autocompact is thrashing: the context refilled to the limit within 3 turns of the previous compact, 3 times in a row.
In the session transcript, the compact_boundary rows' compactMetadata.preTokens / postTokens show post-compaction size near the limit whenever the PreCompact hook was large.
Steps to Reproduce
- Add a PreCompact hook that prints a large amount of text, for example
{"type": "command", "command": "head -c 2000000 /dev/zero | tr '\\0' x"}underhooks.PreCompactin.claude/settings.json. - Start a session, do some work, and run
/compact(or let auto-compact trigger). - From the code path above, the compaction request carries the full 2 MB in its custom instructions. We saw the downstream effect with the real hook (sessions coming back near the limit, then "Autocompact is thrashing"); this synthetic hook is the minimal form of it and has not been run on its own.
Claude Model
Opus
Is this a regression?
I don't know
Claude Code Version
2.1.296 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Other (tmux)
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗