These hook scripts make MemPalace save automatically. No manual "save" commands needed.
| Hook | When It Fires | What Happens |
|---|---|---|
| Save Hook | Every 15 human messages | Blocks the AI, tells it to save key topics/decisions/quotes to the palace |
| PreCompact Hook | Right before context compaction | Emergency save — forces the AI to save EVERYTHING before losing context |
The AI does the actual filing — it knows the conversation context, so it classifies memories into the right wings/halls/closets. The hooks just tell it WHEN to save.
Add to .claude/settings.local.json:
{
"hooks": {
"Stop": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "/absolute/path/to/hooks/mempal_save_hook.sh",
"timeout": 30
}]
}],
"PreCompact": [{
"hooks": [{
"type": "command",
"command": "/absolute/path/to/hooks/mempal_precompact_hook.sh",
"timeout": 30
}]
}]
}
}Make them executable:
chmod +x hooks/mempal_save_hook.sh hooks/mempal_precompact_hook.shAdd to .codex/hooks.json:
{
"Stop": [{
"type": "command",
"command": "/absolute/path/to/hooks/mempal_save_hook.sh",
"timeout": 30
}],
"PreCompact": [{
"type": "command",
"command": "/absolute/path/to/hooks/mempal_precompact_hook.sh",
"timeout": 30
}]
}Edit mempal_save_hook.sh to change:
SAVE_INTERVAL=15— How many human messages between saves. Lower = more frequent saves, higher = less interruption.STATE_DIR— Where hook state is stored (defaults to~/.mempalace/hook_state/)MEMPAL_DIR— Optional. Set to a conversations directory to auto-runmempalace mine <dir>on each save trigger. Leave blank (default) to let the AI handle saving via the block reason message.
The relevant commands are:
mempalace mine <dir> # Mine all files in a directory
mempalace mine <dir> --mode convos # Mine conversation transcripts onlyThe hooks resolve the repo root automatically from their own path, so they work regardless of where you install the repo.
User sends message → AI responds → Claude Code fires Stop hook
↓
Hook counts human messages in JSONL transcript
↓
┌─── < 15 since last save ──→ echo "{}" (let AI stop)
│
└─── ≥ 15 since last save ──→ {"decision": "block", "reason": "save..."}
↓
AI saves to palace
↓
AI tries to stop again
↓
stop_hook_active = true
↓
Hook sees flag → echo "{}" (let it through)
The stop_hook_active flag prevents infinite loops: block once → AI saves → tries to stop → flag is true → we let it through.
Context window getting full → Claude Code fires PreCompact
↓
Hook ALWAYS blocks
↓
AI saves everything
↓
Compaction proceeds
No counting needed — compaction always warrants a save.
Check the hook log:
cat ~/.mempalace/hook_state/hook.logExample output:
[14:30:15] Session abc123: 12 exchanges, 12 since last save
[14:35:22] Session abc123: 15 exchanges, 15 since last save
[14:35:22] TRIGGERING SAVE at exchange 15
[14:40:01] Session abc123: 18 exchanges, 3 since last save
Zero extra tokens. The hooks are bash scripts that run locally. They don't call any API. The only "cost" is the AI spending a few seconds organizing memories at each checkpoint — and it's doing that with context it already has loaded.