Search and query past Claude Code session history.
Reactive: when the user asks "how did I fix X", "what did we do last time", "find the session where", "上次怎么修的", "之前的session", "历史记录".
Proactive: when the user references past work you lack context for, when you're about to modify a file with complex edit history, when the user says "继续之前的" or "continue where we left off", or when understanding prior decisions would improve your current response.
- Read `references/schema.md` before raw `sql()` unless the needed table/column relationship is already explicit here. Do this before running the SQL, not after a missing-column error.
- Read `references/query-patterns.md` before broad "how did X evolve / what did we do / what problems happened / what was the conclusion" synthesis, and for one-shot synthesis retrieval, workflow trees, failed tool counts or failure groups, file history synthesis, summary neighbors, subagent recall, raw windows, and empty-result handling.
- Read `references/pitfalls.md` when a scoped result is empty or tiny, when a query may over-fetch, when a term is hyphenated, when project scope is ambiguous, or when helper row fields are unclear.
- `trace(uuid)` -- parent chain from root to message.
- `thread(sessionId)` -- full session messages; last resort only.
- `raw(uuid, opts?)` -- windowed access to the original JSONL line.
## Retrieval Contract
Keep queries scoped, bounded, and structural.
- Preserve explicit project/session/file/time scopes. Empty or tiny scoped results are real results; do not broaden unless the user asks.
- Treat project scope as three distinct semantics: exact `sessions.project` slug, exact `sessions.project_path`, or fuzzy `LIKE` search. Use `sql()` for exact slug/path membership; helper `project` means fuzzy `LIKE`.
- Start with cheap locators: `sessions()`, `summaries()`, `search()`, or a small SQL query.
- Expand incrementally with `context()`, `trace()`, neighbor SQL, or `raw()` windows.
- Keep runtime JSON small, ideally under 10k-12k chars for synthesis tasks. Do not return all sessions, all summaries, all tool calls, complete workflow trees, full raw messages, or whole tool results.
- When counting or aggregating, compute counts in SQL or in the query script and return those counts. Do not hand-count from long rows in prose.
- For recent failures or "which tasks failed" questions, aggregate by session/task and return counts plus sparse examples. Do not return raw failure rows.
- For broad "how did X evolve / what did we do / what problems happened" history synthesis, use a bounded facet sweep from `references/query-patterns.md`. For concept recall, session lookup, or exact term recall, keep compact `search()` first.
High-frequency field contracts:
- `summaries()` uses `source` and `content`, not `summary_type` or `text`.
- `search().context` is temporal neighbor context, not causal or parent-chain context.
- `fileHistory()` includes `Read`; filter to `Edit`/`Write` for causal change history.
- `workflowTree()` may expose raw `script` and `result_json`; omit them unless the user asks for raw workflow details.
- `fileHistory()` is ordered oldest first. For recent file changes, use SQL with `ORDER BY m.timestamp DESC`.
- FTS5 tokenizes hyphens and treats `search(text)` as raw `MATCH` syntax. For `workflow-script`, search the quoted tokenized phrase such as `"workflow script"` or use SQL `LIKE` for exact hyphen matching.