Skip to content

csb resume / csb view: handle pruned UUIDs (prompt-to-restore + temporary resurrection) #34

@djdarcy

Description

@djdarcy

Summary

csb resume <uuid> and csb view <uuid> (the latter per #14) should
gracefully handle pruned UUIDs (sessions with deleted_at set in
the DB; JSONL no longer on disk; bytes still recoverable from git).

Today:

Proposed surface:

  • csb resume <pruned-uuid>: detect the pruned state, prompt
    the user once: "Session <name> was pruned . Restore from
    git before resuming? [Y/n]". On Y, run cmd_restore (the full
    v0.3.12 implementation: jsonl + subagents + tool-results +
    session-states + sesslogs), then launch claude --resume. On n,
    abort with a hint about csb restore <uuid> for manual control.
  • csb view <pruned-uuid>: temporary resurrection -- restore
    to a sandboxed location, launch the viewer against it, clean up
    on exit. The on-disk ~/.claude/ is never touched.

Both features build on top of v0.3.12's cmd_restore -- they should
NOT reimplement restore logic.

Consolidation discipline (non-negotiable)

This project has a clear pattern of consolidating shared functionality
across list / scan / search / resume / show / restore:

  • v0.2.7 -- short-UUID resolver shared via ids.py:resolve_session_id
  • v0.2.10 -- csb search parity with list/scan for sort, -f/-ff
  • v0.3.1 -- shared transcript_walker consolidating JSONL parsing
  • v0.3.5 -- shared -d/-D dir-scope CLI flags across list/scan/search

The new behaviors here MUST plug into the same machinery:

Concern Existing shared call-site New use
UUID resolution (prefix/suffix accepted) _resolve_session_or_exit in commands.py (uses ids.py:resolve_session_id) Reused unchanged
"Is this session pruned?" detection scattered between list_sessions(show_deleted=True), cmd_show, cmd_restore -- needs extraction Single helper (proposed: is_pruned(session_row) -> bool)
Restore execution (file-level + UUID-keyed) cmd_restore (v0.3.12 -- multi-file with git_ls_tree_for_uuid + preserve-present policy) Extract _restore_session(claude_dir, uuid, slug, commit, ...) -> RestoreResult from cmd_restore; both cmd_resume and cmd_view (and future csb scan -d ... --restore) call it
User prompt UX _confirm_destructive or similar (probably new) Shared; one place to thread --yes / --no-prompt through

The implementation MUST extract these into shared helpers before
adding cmd_resume / cmd_view consumers. Doing it inline (copying
restore logic into each cmd_) would compound bug surface across the
expanding tool set -- exactly what the consolidation arc has been
trying to avoid.

Open design questions

  1. csb view temporary location. Options:
    a. Restore to ~/.claude/ then clean up on viewer exit. Risk:
    viewer crashes / user kills, leaves residue. Mitigation: stamp
    a .csb-view-temp marker, sweep on next csb invocation.
    b. Restore to %TEMP%/csb-view-<uuid>/ mirroring the ~/.claude/
    structure. Viewer must accept arbitrary paths.
    claude-code-history-viewer's current path assumption: TBD --
    check CLI launcher for claude-code-history-viewer -- csb view (Alpha #3) #14's design.
    c. Stream JSONL bytes directly to a viewer's stdin. Eliminates
    filesystem residue but limits to viewers that accept stdin.
  2. Cleanup on resume-after-prompt. If user says Y to restore-then-resume,
    should the post-resume state be:
    a. Permanent (csb restore + claude --resume + done; user has the
    session back). RECOMMENDED.
    b. Temporary (restore + claude --resume + clean up on claude exit).
    Surprising; users probably want it to stick.
  3. --yes / --restore / --no-restore flags for non-interactive use.
    Cron / scripts shouldn't hang on a prompt. Default: prompt when TTY,
    abort with hint when non-TTY.
  4. Pruned-state cache staleness. The DB's deleted_at could lag
    reality (e.g. user manually rm'd a JSONL since last csb backup).
    Do we check the filesystem too, or trust the DB? cmd_resume
    currently trusts the DB; should we add a stat() fallback?

Acceptance criteria

  • Investigation pass: catalog every existing call-site that
    checks deleted_at and every restore code path. Identify the
    duplication. Decide the extraction shape (is_pruned,
    _restore_session, etc.) BEFORE writing new code.
  • Extract _restore_session() from cmd_restore into a callable
    helper that returns a structured result (counts, conflicts,
    preserve-list). cmd_restore becomes a thin wrapper around it
    that handles CLI flag parsing + output formatting.
  • cmd_resume detects pruned sessions, prompts (TTY) or aborts
    with hint (non-TTY), and invokes the shared _restore_session
    on confirmation. Reuses existing _resolve_session_or_exit.
  • cmd_view (or its v0.3.x equivalent under CLI launcher for claude-code-history-viewer -- csb view (Alpha #3) #14) handles pruned
    UUIDs via temporary restoration. Implementation per the
    Decision-1 outcome above.
  • Non-interactive flags (--yes / --no-restore / equivalent)
    with consistent semantics across resume and view.
  • Tests cover: pruned + Y prompt, pruned + n prompt, pruned + TTY
    detection, pruned + --yes, alive session (no prompt), restore
    failure mid-resume, view + cleanup-on-success, view + cleanup-on-crash.
  • docs/maintenance.md updated to document the resume / view
    flow for pruned sessions.

Out of scope (for this issue)

  • The viewer implementation itself (that's CLI launcher for claude-code-history-viewer -- csb view (Alpha #3) #14).
  • Refactoring list/scan/search SQL filter composition (the
    v0.3.12 UUID-prefix fix already started this; further consolidation
    is a separate cleanup issue worth filing).
  • Filesystem-derived --deleted semantics (separate from DB-derived;
    noted in the v0.2.8 design doc as Phase 2 of the deletion discovery).

Related

Design references (filename only):

  • 2026-06-03__03-36-19__csb-restore-completeness-design.md -- v0.3.12
    DWP describing the cmd_restore architecture that this issue extracts from

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions