Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/coleam00/claude-memory-compiler/llms.txt

Use this file to discover all available pages before exploring further.

Claude Memory Compiler uses three Claude Code hooks to wire your conversations into the knowledge pipeline without any manual steps. Once configured, every session automatically injects your existing knowledge base at the start and queues a background extraction when the session ends or the context window compacts. The hooks themselves make no API calls — they do only local file I/O, so they complete in well under the timeout limits.

Hook configuration

Add the following to .claude/settings.json at the root of your project (create the file if it does not exist):
{
  "hooks": {
    "SessionStart": [{ "matcher": "", "hooks": [{ "type": "command", "command": "uv run python hooks/session-start.py", "timeout": 15 }] }],
    "PreCompact": [{ "matcher": "", "hooks": [{ "type": "command", "command": "uv run python hooks/pre-compact.py", "timeout": 10 }] }],
    "SessionEnd": [{ "matcher": "", "hooks": [{ "type": "command", "command": "uv run python hooks/session-end.py", "timeout": 10 }] }]
  }
}
Commands use relative paths from the project root. The empty matcher value ("") means the hook fires on every event of that type with no filtering. If your project already has a .claude/settings.json with other hooks, merge the "hooks" keys rather than replacing the file. Add SessionStart, PreCompact, and SessionEnd alongside any existing hook entries.

What each hook does

hooks/session-start.py runs when Claude Code opens a session. It performs pure local I/O — no API calls — and finishes in under one second.What it does:
  • Reads knowledge/index.md (the master catalog of all compiled articles)
  • Reads the last 30 lines of the most recent daily log (today or yesterday)
  • Outputs a JSON payload to stdout:
output = {
    "hookSpecificOutput": {
        "hookEventName": "SessionStart",
        "additionalContext": context,
    }
}
print(json.dumps(output))
Claude Code reads this payload and prepends the content to the session context. This means Claude always enters a session aware of your full knowledge base index and recent activity. The injected context is capped at 20,000 characters to stay within Claude Code’s context limits.
hooks/session-end.py fires when you close a Claude Code session. The hook itself completes immediately — it does not wait for the LLM extraction to finish.What it does:
  1. Reads the hook input JSON from stdin (session_id, transcript_path, cwd)
  2. Parses the raw JSONL conversation transcript into markdown turns (up to the last 30 turns, max 15,000 characters)
  3. Writes the extracted context to a temp file (e.g., scripts/session-flush-<id>-<timestamp>.md)
  4. Spawns flush.py as a fully detached background process using subprocess.Popen
  5. Returns immediately so Claude Code is not blocked
flush.py then calls the Claude Agent SDK to decide what from that conversation is worth preserving and appends the result to daily/YYYY-MM-DD.md.
hooks/pre-compact.py fires before Claude Code auto-compacts the context window. It has the same architecture as session-end.py and uses the same extraction logic.Why it exists: in a long session, Claude Code may trigger multiple auto-compactions before you ever close the session. Each compaction summarizes and discards detail from the context. Without this hook, intermediate context is permanently lost before SessionEnd ever fires.pre-compact.py has a higher minimum turn threshold (MIN_TURNS_TO_FLUSH = 5) than session-end.py (MIN_TURNS_TO_FLUSH = 1) to avoid flushing trivially short compaction checkpoints.It also guards against a known Claude Code bug (#13668) where transcript_path is sometimes empty in the PreCompact payload:
if not transcript_path_str or not isinstance(transcript_path_str, str):
    logging.info("SKIP: no transcript path")
    return

Recursion guard

Both session-end.py and pre-compact.py include a recursion guard as the very first executable statement:
if os.environ.get("CLAUDE_INVOKED_BY"):
    sys.exit(0)
flush.py sets CLAUDE_INVOKED_BY=memory_flush before it calls the Claude Agent SDK. The Agent SDK internally runs Claude Code, which would otherwise fire the hooks again — causing an infinite loop. The guard exits the hook process immediately when it detects it was invoked by a memory flush rather than a real user session.
Do not remove or move the recursion guard. In flush.py it is set as the very first line of the module, before any other imports, to ensure it takes effect before any code that could trigger Claude Code runs.

After hooks are active

Once .claude/settings.json is in place, the capture pipeline activates automatically the next time you open Claude Code in the project:
  1. Session openssession-start.py injects the knowledge index into the context
  2. You work normally → Claude has your accumulated knowledge available throughout
  3. Session ends (or context compacts) → session-end.py / pre-compact.py spawns a background flush.py
  4. flush.py runs silently → calls Claude Agent SDK, extracts key decisions and lessons, appends to daily/YYYY-MM-DD.md
  5. After 6 PM → if the daily log changed, flush.py also spawns compile.py in the background to promote the day’s log into structured knowledge articles
You can verify the background processes ran by checking scripts/flush.log, which both hooks and flush.py write to.

Build docs developers (and LLMs) love