Problem
When the preCompact hook is installed, running /compact in Claude Code returns immediately without compacting. The hook fires, blocks with a save instruction, but Claude Code treats the block as a cancellation rather than a pause-then-proceed. Compaction never resumes.
The result is the opposite of the hook's intent: instead of preventing data loss before compaction, it makes compaction impossible — guaranteeing eventual data loss as context fills up.
Root cause
Claude Code's PreCompact hook type has no retry/resume mechanism. A block decision means cancel, not defer. The current hook design assumes Claude Code will retry compaction after Claude acts on the save instruction — but it doesn't.
Why a shell-side fix is non-trivial
The obvious workaround — have the hook save to MemPalace directly and exit 0 — is blocked by a transport limitation: the MCP server uses stdio transport exclusively (no REST/HTTP API). Shell scripts cannot call MCP tools; those are LLM-only. The hook can only use the mempalace CLI.
Proposed fix
Rewrite the preCompact hook to:
- Call
mempalace mine <transcript_path> --mode convos --since <last_save_offset> using the transcript path from the hook's stdin JSON
- Exit
0 — compaction proceeds normally, no Claude involvement required
This requires a new --since flag on mempalace mine --mode convos to support incremental ingestion (avoiding re-processing the entire transcript on every compaction). The Stop hook already tracks save state per session in ~/.mempalace/hook_state/ — the same mechanism could be used here.
Alternatives considered
- Remove
preCompact hook entirely — the Stop hook fires every 15 messages and already provides protection against context loss. This is the minimal viable fix if --since is too much scope.
- Add HTTP/REST transport to MCP server — would allow hooks to call MCP tools directly; likely out of scope for this issue.
Related
Environment
- mempalace 3.2.0 (installed via uv)
- macOS
Problem
When the
preCompacthook is installed, running/compactin Claude Code returns immediately without compacting. The hook fires, blocks with a save instruction, but Claude Code treats the block as a cancellation rather than a pause-then-proceed. Compaction never resumes.The result is the opposite of the hook's intent: instead of preventing data loss before compaction, it makes compaction impossible — guaranteeing eventual data loss as context fills up.
Root cause
Claude Code's PreCompact hook type has no retry/resume mechanism. A
blockdecision means cancel, not defer. The current hook design assumes Claude Code will retry compaction after Claude acts on the save instruction — but it doesn't.Why a shell-side fix is non-trivial
The obvious workaround — have the hook save to MemPalace directly and
exit 0— is blocked by a transport limitation: the MCP server uses stdio transport exclusively (no REST/HTTP API). Shell scripts cannot call MCP tools; those are LLM-only. The hook can only use themempalaceCLI.Proposed fix
Rewrite the
preCompacthook to:mempalace mine <transcript_path> --mode convos --since <last_save_offset>using the transcript path from the hook's stdin JSON0— compaction proceeds normally, no Claude involvement requiredThis requires a new
--sinceflag onmempalace mine --mode convosto support incremental ingestion (avoiding re-processing the entire transcript on every compaction). The Stop hook already tracks save state per session in~/.mempalace/hook_state/— the same mechanism could be used here.Alternatives considered
preCompacthook entirely — the Stop hook fires every 15 messages and already provides protection against context loss. This is the minimal viable fix if--sinceis too much scope.Related
Environment