Findings from building full-content session search for Oh My Pi (session format v3, sessions in ~/.omp/agent/sessions/<encoded-cwd>/*.jsonl).
Built-in search is far narrower than it looks:
- The /resume picker's fuzzy search haystack is
id + title + cwd + firstMessage + allMessagesText + path, butallMessagesTextis parsed from only the first 4096 bytes of each file (SESSION_LIST_PREFIX_BYTESinpackages/coding-agent/src/session/session-listing.ts). Anything past the first ~4KB of a transcript is invisible to /resume search. ~/.omp/agent/history.db(SQLite FTS5) indexes user-submitted prompts only — no assistant text, no tool output (history-storage.ts).matchingSessionIds(query)is the only transcript-level search hook, and it can't find things the assistant said.
Raw grep over session JSONL is useless for content search. Measured on a real corpus (920 sessions, 578MB): rg -l -i vlc "matched" 795/920 files, because base64 blobs, tool outputs, and embedded system prompts byte-match nearly any short substring. Correct approach: use rg only as a candidate shortlist (full-corpus scan measured at 0.86s — no index needed at this scale), then JSON-parse candidate files and match only structured text: message entries with role user/assistant (text is entry.message.content as string, or the concatenation of content[].text where block.type == "text"), plus header/title-slot titles and compaction.summary / branch_summary.summary.
Two practical gotchas:
- Self-match: the in-progress session's JSONL already contains your search terms (the prompt asking for the search is persisted immediately), so any session search tool must exclude the current session file or every search returns itself. In an extension tool,
ctx.sessionManager.getSessionFile()andgetSessionDir()are available on the read-onlyReadonlySessionManagersurface — no need to replicate the cwd->dirname encoding. - Subagent transcripts live in a sibling directory named after the parent file (
<timestamp>_<id>/<agentId>.jsonl), so a depth-1 glob of*.jsonlnaturally scopes to top-level sessions.
Dir encoding and toolCall/toolResult block shapes are covered in Oh My Pi session-history globbing and tool_use extraction discrepancies.