Skip to content

csb restore: recover sessions from external backup directories #8

@djdarcy

Description

@djdarcy

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:

  1. It only searches git history (git log + git show)
  2. These files were never committed (.gitignore was blocking .jsonl files at the time)
  3. 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:

  1. Scan source: Walk <source>/projects/ recursively for *.jsonl files
  2. Scan current: Walk ~/.claude/projects/ for existing .jsonl files
  3. Diff by UUID filename: Find jsonl files in source that don't exist anywhere in current
  4. Determine target path: Use current project directory structure, not source's (project dirs may have been renamed/reorganized by Claude Code)
  5. Copy with metadata: Preserve timestamps from the source file
  6. Fix broken symlinks: After recovery, optionally re-link sesslogs/*/transcript.jsonl symlinks that now have valid targets
  7. 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

  • csb recover --source <dir> scans external backup for missing .jsonl files
  • Multiple --source flags supported (searched in order, first match wins)
  • --dry-run previews recoverable files without copying
  • Recovery copies files to correct project directory in current ~/.claude/projects/
  • Subagent jsonls recovered alongside parent sessions
  • Timestamps preserved from source files
  • session-backup.db updated after recovery
  • Summary report: N recovered, N already present, N skipped

Related issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions