Episode 4: Lifecycle Hooks — How Claude-Mem Takes Notes Behind Your Back
This episode's scenario: You ask Claude to fix a comment bug in the blog project. In those 5 minutes, Claude-Mem fires hooks dozens of times and records multiple Observations. How does it know when to act?
4.1 What's a Lifecycle Hook?
A Lifecycle Hook is a mechanism in Claude Code's plugin system:
When a specific event occurs inside Claude Code, automatically run a registered script.
Like phone automation shortcuts — when you arrive home (event) → lights turn on (script). In Claude-Mem, when Claude performs an action (event) → notes are taken (script).
4.2 The Five Lifecycle Events
graph TD
subgraph "Session Lifecycle"
A["🟢 SessionStart"] -->|"You open Claude Code"| B["📝 UserPromptSubmit"]
B -->|"You send a message"| C["🔧 PostToolUse"]
C -->|"Claude uses a tool"| C
C --> D["⏸ Stop"]
D -->|"Claude stops activity"| E["🔴 SessionEnd"]
end
F["⚙️ Smart Install
(helper script)"] -.->|"Runs at install"| A
style A fill:#10b981,color:#fff
style B fill:#6366f1,color:#fff
style C fill:#f59e0b,color:#000
style D fill:#94a3b8,color:#000
style E fill:#ef4444,color:#fff
style F fill:#64748b,color:#fff1️⃣ SessionStart — Session Opens
Triggers when: You launch Claude Code
What it does:
- Sends
GET /api/contextto the Worker - Worker queries SQLite for Observations and Summaries from the last 10 sessions
- Injects those historical notes into Claude's initial context
Effect: Claude "recalls" your previous work before you even say your first word.
2️⃣ UserPromptSubmit — You Send a Message
Triggers when: Every time you press Enter to send a message
What it does: Sends your prompt to the Worker, which stores it in the user_prompts table.
3️⃣ PostToolUse — After Tool Execution (🔑 The Most Important Hook!)
Triggers when: Every time Claude uses a tool (Read, Write, Bash, Search, etc.)
What it does:
- Captures tool input and output
- POSTs raw data to the Worker
- Worker uses Claude Agent SDK for AI compression
- Generates a structured Observation (title, narrative, facts, concepts, type)
- Stores in SQLite + ChromaDB
This is Claude-Mem's core engine.
4️⃣ Stop — Pause
Triggers when: Claude stops active work (waiting for your next message)
What it does: Lightweight state sync to ensure all in-flight Observations are committed.
5️⃣ SessionEnd — Session Closes
Triggers when: You close Claude Code or end the session
What it does:
- Notifies Worker the session is ending
- Worker reviews all Observations from this session
- Generates a Session Summary (request, investigated, completed, next_steps)
- Stores in
session_summariestable
Key: The next_steps field gets read and injected at the next SessionStart — that's the secret to cross-session continuity.
4.3 Hook Script Locations
~/.claude/plugins/marketplaces/thedotmack/plugin/hooks/
├── session-start.sh
├── user-prompt.sh
├── post-tool-use.sh
├── stop.sh
├── session-end.sh
└── pre-hook.sh # Smart Install (helper)
4.4 Complete Call Chain
This sequence diagram is Claude-Mem's most important reference. It traces the entire data flow from session open to session close:
sequenceDiagram
participant User as 👤 User
participant CC as 💻 Claude Code
participant Hook as 🪝 Hook Script
participant Worker as ⚙️ Worker (37777)
participant SDK as 🤖 Claude Agent SDK
participant DB as 💾 SQLite + ChromaDB
Note over User,DB: ── Session Start ──
User->>CC: Open Claude Code
CC->>Hook: Trigger SessionStart
Hook->>Worker: GET /api/context
Worker->>DB: Query last 10 sessions
DB-->>Worker: Return Observations + Summaries
Worker-->>Hook: Return context data
Hook-->>CC: Inject history into Claude
Note over User,DB: ── User Starts Working ──
User->>CC: "Fix the comment bug"
CC->>Hook: Trigger UserPromptSubmit
Hook->>Worker: POST /api/prompt
Worker->>DB: Store in user_prompts
Note over User,DB: ── Claude Operates ──
CC->>CC: Read src/api/comments.ts
CC->>Hook: Trigger PostToolUse (tool=Read)
Hook->>Worker: POST /api/observation (raw file content)
Worker->>SDK: Compress & distill
SDK-->>Worker: {title, narrative, facts, type}
Worker->>DB: INSERT observation + update vector index
CC->>CC: Modify src/api/comments.ts
CC->>Hook: Trigger PostToolUse (tool=Write)
Hook->>Worker: POST /api/observation (changes)
Worker->>SDK: Compress & distill
SDK-->>Worker: {title:"Fix comment FK", type:"bugfix"}
Worker->>DB: INSERT observation + update vector index
CC->>CC: Run npm test
CC->>Hook: Trigger PostToolUse (tool=Bash)
Hook->>Worker: POST /api/observation (test output)
Worker->>SDK: Compress & distill
Worker->>DB: INSERT observation
Note over User,DB: ── Session End ──
User->>CC: Close Claude Code
CC->>Hook: Trigger SessionEnd
Hook->>Worker: POST /api/session/end
Worker->>Worker: Review all session Observations
Worker->>SDK: Generate Session Summary
SDK-->>Worker: {request, investigated, completed, next_steps}
Worker->>DB: INSERT session_summary4.5 Why Async Compression?
Won't AI compression after every tool call be slow?
No, because it's asynchronous.
graph LR
A["Claude acts"] --> B["Hook sends HTTP"]
B --> C["Worker receives"]
C --> D["Returns 200 OK immediately"]
D --> E["Claude continues working
(doesn't wait)"]
C --> F["Background async compression
(Agent SDK)"]
F --> G["Done → store in DB"]
style D fill:#10b981,color:#fff
style E fill:#6366f1,color:#fff
style F fill:#f59e0b,color:#000The Hook fires and returns immediately — never blocks Claude's workflow. The Worker compresses and stores in the background.
Hands-On Exercise
- Start a new Claude Code session on the blog project
- Have Claude: read a file, modify a file, run a command
- In another terminal, watch Worker logs in real time:
tail -f ~/.claude-mem/logs/worker.log
- Observe processing records appearing after each Claude action
- After ending the session, check
session_summariesfor the generated summary
Coming Up Next
Hooks capture data, but the Worker handles compression, storage, and search. Next episode, we go inside the Worker — running on localhost:37777, powered by Bun, serving 10 API endpoints.