Part of #26.
Problem
As conversations get longer, Claude Code compacts older messages to stay within the context window. The compaction summary frequently drops:
- The user's original ask (the why)
- Hard constraints declared early ("don't touch the database layer", "preserve behavior")
- CLAUDE.md rules that were loaded once and never re-loaded
Result: Claude drifts from the original intent. anthropics/claude-code#22638 documents this exact failure mode — Claude ignored CLAUDE.md rules mid-session and executed a destructive git command. Community writeups (Fortune, The Register, dev.to "Feb-Mar 2026 regression") cite instruction drop-off as one of the top complaints.
Proposed solution
Add a PreCompact hook (released v2.1.105, Apr 13 2026) that:
- Reads the original user prompt(s) and any explicit constraints from the conversation
- Re-injects them as
additionalContext immediately after compaction so they survive into the post-compaction window
- Optionally returns
{"decision":"block"} if the constraints would be lost and the user has opted into strict mode
File changes
- New:
scripts/preserve-context.py — PreCompact hook handler
- Update:
hooks/hooks.json — register the new event
- Update:
README.md — document the new behavior + opt-out
- New tests:
tests/test_precompact_hook.py
Implementation sketch
# scripts/preserve-context.py
import json, sys
data = json.load(sys.stdin)
# Walk transcript_path; find first user message + any "constraint markers"
# (lines containing "must", "do not", "preserve", "only", "never")
preserved = extract_constraints(data["transcript_path"]) # truncated to budget
print(json.dumps({
"hookSpecificOutput": {
"hookEventName": "PreCompact",
"additionalContext": f"<original-goal-and-constraints>\n{preserved}\n</original-goal-and-constraints>"
}
}))
Token budget
- Total injected on compaction: ≤200 tokens, comprising:
- Original first user prompt: ≤120 tokens (truncate with ellipsis if longer)
- Detected hard constraints: ≤80 tokens (keep highest-priority first; drop overflow)
- Zero tokens injected when no compaction is occurring (hook fires only on PreCompact event)
- Zero tokens injected if no constraints detected and original goal already lives in retained context (skip injection entirely)
- Constraint extraction runs in <50ms; no LLM calls
Acceptance criteria
References
Part of #26.
Problem
As conversations get longer, Claude Code compacts older messages to stay within the context window. The compaction summary frequently drops:
Result: Claude drifts from the original intent. anthropics/claude-code#22638 documents this exact failure mode — Claude ignored CLAUDE.md rules mid-session and executed a destructive git command. Community writeups (Fortune, The Register, dev.to "Feb-Mar 2026 regression") cite instruction drop-off as one of the top complaints.
Proposed solution
Add a
PreCompacthook (released v2.1.105, Apr 13 2026) that:additionalContextimmediately after compaction so they survive into the post-compaction window{"decision":"block"}if the constraints would be lost and the user has opted into strict modeFile changes
scripts/preserve-context.py— PreCompact hook handlerhooks/hooks.json— register the new eventREADME.md— document the new behavior + opt-outtests/test_precompact_hook.pyImplementation sketch
Token budget
Acceptance criteria
…markers)PROMPT_IMPROVER_PRESERVE=0)References