Skip to content

Resume + session search are inconsistent — sometimes show IDs, sometimes cwd names, sometimes prompts; needs to be reasoned through and redone #96

Description

@Juliusolsson05

What happened

Multiple surfaces let the user pick a past conversation (resume, prompt search, prompts list), and each one presents sessions differently. Some show a truncated provider session ID like `8d6926a5`, some show the cwd basename like `agent-code`, some show the first user prompt, some show some mixture depending on what's available. The result is that the same conversation shows up under different identities depending on where you're looking at it from, and there's no single way to ask "which past conversation am I looking at?".

`PromptSearchModal.tsx` itself acknowledges the friction inline:

// Session names are useless for recognizing conversations. This modal …

…but the rest of the surfaces don't share that conviction or the helpers around it. The display layer is fragmented across at least three modals, a shared helper module, two main-process IPC handlers, and two different transcript-listing primitives in the submodule packages.

Repro

  1. Open the command palette → "Search Conversation Prompts" — see one rendering shape (prompt-led).
  2. Open the resume picker (PathPickerModal → "Resume…" affordance, or whatever the current entrypoint is) — see a different rendering shape (cwd/id-led).
  3. Open "View Prompts" on a current session vs. "Rewind to Prompt" — different shapes again.

The exact disagreement varies by entry point and what fields are populated in the underlying transcript. The common failure mode: you remember a conversation by its content (the first prompt you sent, or the topic) but the picker is showing you a hex ID or a folder basename instead.

Where

The fragmentation surface:

Renderer modals (each renders the same conceptual thing differently):

  • `src/renderer/src/features/workspace/ui/PromptSearchModal.tsx` — currently the most thought-through (acknowledges the "names are useless" framing, displays prompt + cwd basename + provider glyph)
  • `src/renderer/src/features/workspace/ui/ViewPromptsModal.tsx` — list-prompts shape, different display
  • `src/renderer/src/features/workspace/ui/RewindToPromptModal.tsx` — rewind-target picker, different display again
  • PathPickerModal's resume affordance (`src/renderer/src/features/path-picker/ui/PathPickerModal.tsx`)

Shared display helpers (the right place to consolidate):

  • `src/renderer/src/features/workspace/lib/sessionDisplay.ts` — exists, used inconsistently
  • `src/renderer/src/features/workspace/lib/latestUserPrompts.ts` — feeds the rewind picker

Main-process IPC + indexing:

Provider-side primitives:

  • `packages/claude-code-headless/src/transcript/SessionList.ts` — `readSessionLite` returns head+tail snippets used to derive a display
  • `packages/codex-headless/src/transcript/SessionList.ts` — same shape for Codex

Output

N/A — UX-reliability issue, no crash.

State

Affects every surface that lets the user pick a past conversation. Worse on Codex sessions (rollout file names are timestamp-prefixed UUIDs) and on Claude sessions that don't have a meaningful first prompt (e.g. continuation sessions).

Sketch

This needs to be re-thought as a system, not patched per modal. Pieces:

  1. One canonical "display identity" for a past session. A typed record like:

    ```ts
    type SessionDisplayIdentity = {
    // Required
    providerSessionId: string // raw id, always present
    kind: 'claude' | 'codex'
    // Best-effort display fields, derived once at index time
    firstUserPrompt: string | null // null on continuations / empty sessions
    projectBasename: string | null // last segment of cwd
    lastActivityAt: number // mtime
    turnCount: number // user-prompt count
    }
    ```

    Built once in `sessionIndex.ts` (during the scan it already does — and which should become streaming per the open perf work). Served via a single IPC. No more `readSessionLite` head/tail re-derivation at the renderer.

  2. One renderer component for displaying a session row, consumed by every modal. Probably `SessionPickerRow` under `src/renderer/src/features/workspace/ui/`, fed by the identity record above. Locks in: provider glyph + first-prompt preview + project basename + relative "last activity" + turn count. Long-form. No truncated hex IDs in the primary line.

  3. One identity hierarchy when fields are missing. A continuation session with no first prompt should fall through to (most recent prompt) → (cwd basename) → (truncated id), in that order, never the other way around. The fallback should be visible (e.g. italicised) so the user knows they're looking at a fallback identity, not a real name.

  4. Drop the resume picker's separate codepath. Resume entry points should consume the same `SessionPickerRow` shape so a session looks identical whether the user found it via search, resume, or rewind.

  5. Migrate one modal at a time so the redesign doesn't merge as one giant unreviewable PR. Order: PromptSearchModal (already closest to the target shape) → resume picker → ViewPromptsModal → RewindToPromptModal.

The end state: there is one answer to "what does this past conversation look like in a picker?" and four modals that all answer the same way.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions