Skip to content

Session search: find any coding-agent conversation by name or by what was said in it, and resume it #14731

Description

@samithaj

Problem

Once you have run more than a handful of coding-agent sessions there is no way to find one. The project rail can only show what fits in a sidebar — it caps discovered sessions per project — so conversations that exist on disk are simply unreachable. On this machine that is 73 project directories and several thousand Claude transcripts.

Two questions go unanswered: "which conversation was the one about X?" and, more painfully, "where is that thing I pasted?"

Proposal

A popup (Cmd+Shift+K, plus a magnifier in the rail header) over every known session — live tabs, stored session handles, and transcripts discovered on disk — deduped by (agent, session_id). Enter resumes: if that session's pane is still open in the right directory it activates that tab, otherwise it opens a new one with the resume command prefilled but not executed.

Results are staged, and the staging is the design:

  • Names match synchronously against data already in memory and render on the same frame as the keystroke.
  • Content matches inside transcript text and appends below, under its own header, with a one-line snippet and a progress readout. Name results never reorder.

Content search reads transcripts off the main thread into an in-memory digest keyed on (path, len, mtime) — the len component makes growth append-only, so a transcript that grew re-reads only [old_len, EOF). Matching is literal (memchr::memmem), never fuzzy, so an identifier like POA-2236 stays one token. What counts as content is decided structurally rather than by regex: a "type":"user" envelope whose blocks carry a tool_use_id is a tool result, not something the user typed — tool output and pasted file bodies are excluded, and the footer says so rather than letting a half-answer look complete.

Three constraints worth recording for anyone implementing this

  1. The mixer must stay synchronous. Registering an AsyncDataSource withholds all results — including the instant name matches — for up to INITIAL_RESULTS_TIMEOUT (500 ms) while the palette still shows the previous query's rows, and that is also why Enter is a no-op while loading (search_bar.rs). Feeding a sync source from a model that owns its own spawn avoids both.
  2. Section order is a tier, and the direction is counterintuitive: the mixer sorts ascending on (priority_tier, score, source_order) and the search bar then reverses for top-down, so a higher tier renders higher. This inverts silently with no compile error.
  3. SelectionUpdate::Top does not skip static separators. A section header at index 0 gets selected when the popup opens, and the user's first Enter does nothing at all.

Implementation (fork, reusing the existing command-palette view rather than a new modal): https://github.com/samithaj/warp/tree/samithaj/session-search — built on #14720.

Scope note

Content search covers Claude Code only, because Codex keeps no per-cwd transcript store — its sessions are date-keyed rollouts. Codex sessions still appear in name search via recorded handles.

Metadata

Metadata

Assignees

Labels

area:agentAgent workflows, conversations, prompts, cloud mode, and AI-specific UI.area:searchGlobal search, command palette, and content discovery.area:window-tabs-panesWindow, tab, pane, and workspace layout management.enhancementNew feature or request.needs-mocksrepro:highThe report includes enough evidence that the issue appears highly reproducible.triagedIssue has received an initial automated triage pass.warp:auto-triage-review

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions