You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
csb resume <pruned-uuid> resolves the UUID, calls claude --resume,
which fails because the JSONL doesn't exist on disk. User gets a
Claude Code error with no path forward.
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.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
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.
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.
--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.
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.
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).
Summary
csb resume <uuid>andcsb view <uuid>(the latter per #14) shouldgracefully handle pruned UUIDs (sessions with
deleted_atset inthe DB; JSONL no longer on disk; bytes still recoverable from git).
Today:
csb resume <pruned-uuid>resolves the UUID, callsclaude --resume,which fails because the JSONL doesn't exist on disk. User gets a
Claude Code error with no path forward.
csb view <pruned-uuid>(when CLI launcher for claude-code-history-viewer -- csb view (Alpha #3) #14 ships) would face the same gap.Proposed surface:
csb resume <pruned-uuid>: detect the pruned state, promptthe user once: "Session
<name>was pruned . Restore fromgit before resuming? [Y/n]". On
Y, runcmd_restore(the fullv0.3.12 implementation: jsonl + subagents + tool-results +
session-states + sesslogs), then launch
claude --resume. Onn,abort with a hint about
csb restore <uuid>for manual control.csb view <pruned-uuid>: temporary resurrection -- restoreto 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 shouldNOT reimplement restore logic.
Consolidation discipline (non-negotiable)
This project has a clear pattern of consolidating shared functionality
across
list/scan/search/resume/show/restore:ids.py:resolve_session_idcsb searchparity withlist/scanfor sort,-f/-fftranscript_walkerconsolidating JSONL parsing-d/-Ddir-scope CLI flags acrosslist/scan/searchThe new behaviors here MUST plug into the same machinery:
_resolve_session_or_exitincommands.py(usesids.py:resolve_session_id)list_sessions(show_deleted=True),cmd_show,cmd_restore-- needs extractionis_pruned(session_row) -> bool)cmd_restore(v0.3.12 -- multi-file withgit_ls_tree_for_uuid+ preserve-present policy)_restore_session(claude_dir, uuid, slug, commit, ...) -> RestoreResultfromcmd_restore; bothcmd_resumeandcmd_view(and futurecsb scan -d ... --restore) call it_confirm_destructiveor similar (probably new)--yes/--no-promptthroughThe implementation MUST extract these into shared helpers before
adding
cmd_resume/cmd_viewconsumers. Doing it inline (copyingrestore 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
csb viewtemporary location. Options:a. Restore to
~/.claude/then clean up on viewer exit. Risk:viewer crashes / user kills, leaves residue. Mitigation: stamp
a
.csb-view-tempmarker, 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.
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.
--yes/--restore/--no-restoreflags for non-interactive use.Cron / scripts shouldn't hang on a prompt. Default: prompt when TTY,
abort with hint when non-TTY.
deleted_atcould lagreality (e.g. user manually
rm'd a JSONL since lastcsb backup).Do we check the filesystem too, or trust the DB?
cmd_resumecurrently trusts the DB; should we add a stat() fallback?
Acceptance criteria
checks
deleted_atand every restore code path. Identify theduplication. Decide the extraction shape (
is_pruned,_restore_session, etc.) BEFORE writing new code._restore_session()fromcmd_restoreinto a callablehelper that returns a structured result (counts, conflicts,
preserve-list).
cmd_restorebecomes a thin wrapper around itthat handles CLI flag parsing + output formatting.
cmd_resumedetects pruned sessions, prompts (TTY) or abortswith hint (non-TTY), and invokes the shared
_restore_sessionon 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 prunedUUIDs via temporary restoration. Implementation per the
Decision-1 outcome above.
--yes/--no-restore/ equivalent)with consistent semantics across
resumeandview.detection, pruned + --yes, alive session (no prompt), restore
failure mid-resume, view + cleanup-on-success, view + cleanup-on-crash.
docs/maintenance.mdupdated to document the resume / viewflow for pruned sessions.
Out of scope (for this issue)
list/scan/searchSQL filter composition (thev0.3.12 UUID-prefix fix already started this; further consolidation
is a separate cleanup issue worth filing).
--deletedsemantics (separate from DB-derived;noted in the v0.2.8 design doc as Phase 2 of the deletion discovery).
Related
adds pruned-UUID support to it)
_restore_sessionextraction operates on the code that landed there)(search parity), v0.3.1 (shared transcript_walker), v0.3.5
(shared dir-scope flags)
Design references (filename only):
2026-06-03__03-36-19__csb-restore-completeness-design.md-- v0.3.12DWP describing the cmd_restore architecture that this issue extracts from