csb restore: recover sessions from external backup directories (not just git history)
Problem
csb restore currently only recovers sessions from git history. But there are real-world scenarios where session transcripts (.jsonl files) exist in external backup copies of ~/.claude/ that were never committed to git:
C:\Users\Extreme\.claude_ORIG\ # Pre-session-logger era backup
C:\Users\Extreme\.claude - Copy (2)\ # Manual backup before upgrade
C:\Users\Extreme\.claude - Copy\ # Another manual backup
A recent incident illustrates the problem: after a git stash + git switch + git stash pop on the ~/.claude repo, we discovered 137 broken symlinks in sesslogs/ pointing to missing .jsonl files. Cross-referencing with external backups revealed that 654 jsonl files exist in backups but are missing from current ~/.claude/projects/.
Many of these predate the session logger (no symlinks were ever created), and Claude Code purged them from projects/ before any git backup captured them. The only copies that survive are in these manual filesystem backups.
Current csb restore can't help because:
- It only searches git history (
git log + git show)
- These files were never committed (
.gitignore was blocking .jsonl files at the time)
- The backup directories use different project folder names than the current structure (e.g.
C--code-claude-code-task-manager/ in ORIG vs C--code/ in current)
Proposed solution
Add a --source flag to csb restore (or a new csb recover subcommand) that searches external directories for missing session transcripts and copies them to the correct location.
# Recover from a specific backup directory
csb recover --source "C:\Users\Extreme\.claude_ORIG"
# Recover from multiple sources (searches all, deduplicates by UUID)
csb recover --source "C:\Users\Extreme\.claude_ORIG" \
--source "C:\Users\Extreme\.claude - Copy (2)" \
--source "C:\Users\Extreme\.claude - Copy"
# Dry-run to preview what would be recovered
csb recover --source "C:\Users\Extreme\.claude_ORIG" --dry-run
# Recover a specific session by UUID
csb recover --source "C:\Users\Extreme\.claude_ORIG" --session 833a100e
Recovery logic
The key insight is that .jsonl filenames are UUIDs -- they're unique regardless of which project subdirectory they live in. Recovery should:
- Scan source: Walk
<source>/projects/ recursively for *.jsonl files
- Scan current: Walk
~/.claude/projects/ for existing .jsonl files
- Diff by UUID filename: Find jsonl files in source that don't exist anywhere in current
- Determine target path: Use current project directory structure, not source's (project dirs may have been renamed/reorganized by Claude Code)
- Copy with metadata: Preserve timestamps from the source file
- Fix broken symlinks: After recovery, optionally re-link
sesslogs/*/transcript.jsonl symlinks that now have valid targets
- Update index: Re-scan and update
session-backup.db with recovered sessions
Edge cases
- UUID collision across project dirs: Same UUID shouldn't appear in multiple project dirs, but if it does, prefer the larger file (more complete transcript)
- Subagent jsonls: Files like
<uuid>/subagents/agent-*.jsonl should be recovered alongside their parent session
- Target project dir doesn't exist: Create it (Claude Code may have pruned empty project dirs)
- Source has older version of a file that current also has: Skip -- don't overwrite current with older backup
Acceptance criteria
Related issues
csb restore: recover sessions from external backup directories (not just git history)
Problem
csb restorecurrently only recovers sessions from git history. But there are real-world scenarios where session transcripts (.jsonlfiles) exist in external backup copies of~/.claude/that were never committed to git:A recent incident illustrates the problem: after a
git stash+git switch+git stash popon the~/.clauderepo, we discovered 137 broken symlinks insesslogs/pointing to missing.jsonlfiles. Cross-referencing with external backups revealed that 654 jsonl files exist in backups but are missing from current~/.claude/projects/.Many of these predate the session logger (no symlinks were ever created), and Claude Code purged them from
projects/before any git backup captured them. The only copies that survive are in these manual filesystem backups.Current
csb restorecan't help because:git log+git show).gitignorewas blocking.jsonlfiles at the time)C--code-claude-code-task-manager/in ORIG vsC--code/in current)Proposed solution
Add a
--sourceflag tocsb restore(or a newcsb recoversubcommand) that searches external directories for missing session transcripts and copies them to the correct location.Recovery logic
The key insight is that
.jsonlfilenames are UUIDs -- they're unique regardless of which project subdirectory they live in. Recovery should:<source>/projects/recursively for*.jsonlfiles~/.claude/projects/for existing.jsonlfilessesslogs/*/transcript.jsonlsymlinks that now have valid targetssession-backup.dbwith recovered sessionsEdge cases
<uuid>/subagents/agent-*.jsonlshould be recovered alongside their parent sessionAcceptance criteria
csb recover --source <dir>scans external backup for missing.jsonlfiles--sourceflags supported (searched in order, first match wins)--dry-runpreviews recoverable files without copying~/.claude/projects/session-backup.dbupdated after recoveryRelated issues