# Flowchart: lifecycle-hooks
## Sources Consulted
- `src/cli/hook-command.ts:1-122`
- `src/cli/handlers/index.ts:1-72`
- `src/cli/handlers/context.ts:1-95` (SessionStart)
- `src/cli/handlers/session-init.ts:1-192` (UserPromptSubmit)
- `src/cli/handlers/observation.ts:1-86` (PostToolUse)
- `src/cli/handlers/summarize.ts:1-170` (Stop / Summary phase)
- `src/cli/handlers/session-complete.ts:1-66` (Stop / Completion phase)
- `src/cli/handlers/user-message.ts:1-54` (SessionStart parallel)
- `src/cli/adapters/claude-code.ts:1-45`
- `src/hooks/hook-response.ts:1-12`
- `src/shared/hook-constants.ts:1-35`
- `src/services/worker-service.ts:1-100`
- `src/supervisor/index.ts:1-100`
- `src/services/worker/http/routes/SessionRoutes.ts:1-330`
- `src/services/worker/http/routes/SearchRoutes.ts:1-150`
- `src/services/infrastructure/GracefulShutdown.ts:1-100`
- `src/supervisor/process-registry.ts:1-80`
- `src/services/worker-spawner.ts:1-150`
## Happy Path Description
Claude-Mem's lifecycle-hooks system intercepts Claude Code's session lifecycle events and routes them through specialized handlers that coordinate session tracking, tool observation capture, semantic context injection, and session summarization.
**SessionStart** fires immediately when a session begins. The **context handler** ensures the worker daemon is running, queries the Chroma vector database for relevant past observations, and returns them as `additionalContext` for injection into Claude's prompt. In parallel, **user-message** displays formatted context information to the user's terminal and broadcasts the worker's live dashboard URL. Both handlers gracefully degrade if the worker is unavailable.
**UserPromptSubmit** fires when the user submits their first prompt. The **session-init handler** calls `/api/sessions/init` to create a session record in the database, captures the prompt, checks privacy settings, and optionally starts the Claude SDK agent. If semantic injection is enabled, it fetches relevant observations via `/api/context/semantic` and injects them as additional context alongside the user's prompt.
**PostToolUse** fires after Claude executes each tool. The **observation handler** sends the tool usage (name, input, response) to `/api/sessions/observations` where the worker validates privacy rules, enriches the observation with cwd/platform metadata, stores it in SQLite, and queues an async Chroma embedding for semantic search.
**Stop** hook fires when a session ends. This is split into two phases with different timing guarantees: **summarize handler** queues the session's final assistant message to `/api/sessions/summarize` and then polls `/api/sessions/status` to wait (up to 110s) for the SDK agent to finish processing the summary, then calls `/api/sessions/complete`. The **session-complete handler** (phase 2) marks the session inactive in the sessions map.
## Mermaid Flowchart
```mermaid
flowchart TD
Start([Claude Code Session
Lifecycle Event]) --> Dispatch{Event Type?
hook-command.ts:88}
Dispatch -->|SessionStart| CtxSetup["ensureWorkerRunning
worker-spawner.ts:100"]
Dispatch -->|UserPromptSubmit| InitSetup["ensureWorkerRunning
worker-spawner.ts:100"]
Dispatch -->|PostToolUse| ObsSetup["ensureWorkerRunning
worker-spawner.ts:100"]
Dispatch -->|Stop| SumSetup["Check if subagent
summarize.ts:34"]
CtxSetup -->|Worker unavailable| CtxEmpty["Return empty context
context.ts:44-46"]
CtxSetup -->|Worker ready| CtxFetch["Fetch /api/context/inject
context.ts:54-56"]
CtxFetch --> CtxInject["Return additionalContext
context.ts:88-93"]
CtxInject --> UMsgStart["userMessageHandler parallel
user-message.ts:32"]
UMsgStart --> UMsgFetch["GET /api/context/inject (colors)
user-message.ts:13-29"]
UMsgFetch --> UMsgDisplay["Write formatted ctx to stderr
user-message.ts:24-28"]
InitSetup --> InitGuard["Validate session + cwd + project
session-init.ts:51-61"]
InitGuard --> InitCall["POST /api/sessions/init
session-init.ts:75-84"]
InitCall --> InitProcess["Receive sessionDbId + promptNumber
session-init.ts:97-106"]
InitProcess --> InitSDK["POST /sessions/{id}/init start SDK
session-init.ts:141-150"]
InitSDK --> InitSemantic["Semantic injection enabled?
session-init.ts:158-159"]
InitSemantic -->|Yes| SemanticFetch["POST /api/context/semantic
session-init.ts:164-165"]
SemanticFetch --> SemanticInject["Return additionalContext
session-init.ts:179-188"]
ObsSetup --> ObsGuard["Validate toolName + cwd + not excluded
observation.ts:40-62"]
ObsGuard --> ObsSend["POST /api/sessions/observations
observation.ts:65-77"]
ObsSend --> ObsDB["Worker stores + queues Chroma embed
SessionRoutes.ts:30"]
SumSetup -->|Not subagent| SumEnsure["ensureWorkerRunning
summarize.ts:44"]
SumEnsure --> SumValidate["Extract last assistant msg
summarize.ts:50-78"]
SumValidate --> SumQueue["POST /api/sessions/summarize
summarize.ts:86-104"]
SumQueue --> SumPoll["Poll /api/sessions/status 500ms up to 110s
summarize.ts:117-150"]
SumPoll --> SumComplete["POST /api/sessions/complete
summarize.ts:156-161"]
SumComplete --> SessionComplete["sessionCompleteHandler phase 2
session-complete.ts:32"]
SessionComplete --> SCSend["POST /api/sessions/complete
remove from active map
session-complete.ts:54"]
CtxEmpty --> Done([Exit code 0
hook-command.ts:106])
UMsgDisplay --> Done
SemanticInject --> Done
ObsDB --> Done
SCSend --> Done
```
## Side Effects
**HTTP Calls to Worker (port 37777):**
- `GET /api/context/inject` — returns markdown context for injection
- `POST /api/sessions/init` — creates session record, returns sessionDbId
- `POST /api/context/semantic` — semantic search on Chroma
- `POST /sessions/{sessionDbId}/init` — starts SDK agent
- `POST /api/sessions/observations` — stores tool usage observation
- `POST /api/sessions/summarize` — queues summary generation
- `GET /api/sessions/status` — polls queue length
- `POST /api/sessions/complete` — marks session inactive
**Database (SQLite via worker):**
- Inserts into `sdk_sessions`, `user_prompts`, `observations`
- Updates `sdk_sessions.summary` with `summary_stored` flag
**Process Management:**
- `ensureWorkerStarted` spawns worker daemon via `spawnDaemon` if not alive
- SDK agent subprocess spawned per session
- Summarize handler waits up to 110s for SDK agent to finish
**File I/O:**
- Worker PID file at `~/.claude-mem/worker.pid`
- Hook logs at `~/.claude-mem/logs/hook.log`
## External Feature Dependencies
**Calls into:**
- **context-injection-engine** (via `/api/context/inject`, `/api/context/semantic`)
- **sqlite-persistence** (all writes via worker HTTP)
- **vector-search-sync** (async Chroma embeds)
- **session-lifecycle-management** (session state, SDK subprocess)
- **privacy-tag-filtering** (observation content filtered before storage)
- **http-server-routes** (all HTTP communication)
**Called by:**
- Claude Code CLI plugin harness (registered hooks)
- Cursor IDE (routed through observation handler)
- Gemini CLI / OpenRouter adapters
## Confidence + Gaps
**High Confidence:** Hook lifecycle → handler mapping; HTTP endpoints + payloads; graceful degradation on worker unavailability; exit code 0 strategy.
**Medium Confidence:** Exact SDK agent lifecycle and crash recovery; Cursor hook integration paths.
**Gaps:** Hook installer (how hooks register in Claude Code settings); TypeScript build → CLI entry process.