Claude-Session-Backup
Git-backed Claude Code session backup with timeline view, folder analysis, deletion detection, and session restore.
The Problem
Claude Code stores session data in ~/.claude/projects/ as JSONL files. These can be silently deleted during upgrades, lossy-compacted via /compact, or lost when session compatibility breaks between versions. Once gone, your conversation history (including debugging sessions, architectural decisions, and code review context) is unrecoverable.
csb preserves every session in your existing ~/.claude git repository, builds a searchable metadata index, detects deletions, and can restore lost sessions from git history.
[!NOTE] Beta (as of v0.6.0) -- feature-complete and in daily use. Everything on the original roadmap has shipped: backup, deletion detection, content search (JSONL+sesslogs+FTS5), full session restore (a deleted session's complete footprint recovered from git -- transcript, subagents, tool-results, logger sesslogs -- with original timestamps and symlinks, resumable in Claude Code), a viewer launcher (
csb view), a human-readable chat-log layer (csb distill), and guided onboarding (csb setup).Beta means the tool works well for real daily use, not that the interface is frozen. Breaking changes may still happen between versions when the design calls for it. Please file issues for anything rough. And, as with any backup tool, keep a second copy of anything truly irreplaceable.
Quick Start
Five commands install everything -- the CLI, the git store that holds the backups, the Claude Code plugin that fires backups automatically on PreCompact and SessionEnd, and the OS schedule that fires them when Claude Code doesn't run at all:
# 1. Install the csb CLI
pip install claude-session-backup
# 2. Guided setup -- detects/initializes the git backup store, hardens
# .gitattributes, and runs your first backup. (`csb setup --auto` for
# scripts; until setup completes, every csb run reminds you loudly.)
csb setup
# 3. Add the DazzleML marketplace (one-time)
claude plugin marketplace add "DazzleML/Claude-Session-Backup"
# 4. Install the plugin -- registers the PreCompact + SessionEnd hooks
claude plugin install claude-session-backup@dazzle-claude-session-backup
# 5. Schedule a recurring backup -- the hooks above fire only when you
# USE Claude Code; this protects the machine that sits idle while
# Claude Code's cleanup timer runs. Guided (24h default); verifies
# the scheduler works with an immediate prime run.
csb setup schedule
Then verify it works:
# Build the index from existing sessions (no git commits yet)
csb backup --no-commit
# See your session timeline
csb list
# Full backup with git commits (separate noise + user commits, unsigned)
csb backup
[!TIP] Pair with claude-session-logger for full searchable history. csb preserves Claude Code's session transcripts (
projects/<slug>/<uuid>.jsonl). The logger captures the richer per-session data alongside them -- tool calls, shell commands, agent dispatches -- written to~/.claude/sesslogs/. csb backs up those logger files too (it backs up everything under~/.claude/via the noise commits), andcsb restorebrings the whole footprint back together: transcript + subagents + tool-results + logger state + sesslogs. The two projects are independent (csb works fine without the logger) but they're designed to complement each other.
Features
- Findable sessions: hand-name each one with
/renameas you start it, usingPROJECT__DATE__topic--csb list/tree/resumethen become instant project views instead of content searches. See naming - Guided setup:
csb setupconfigures the git backup store (detects ancestor repos,--autofor scripts) and closes with a state-aware checklist -- running unprotected requires an explicit--index-onlysign-off, or csb reminds you on every run - Full session preservation: Every byte of JSONL, subagent data, tool results backed up via git
- Timeline view: Sessions sorted by last use with relative dates, start folder, and top N working directories
- Folder analysis: See where work actually happened -- the most-used folder is highlighted
- Deletion detection: Know when Claude Code removes a session you previously tracked
- Session restore: Recover deleted sessions from git history with
csb restore - Readable chat logs:
csb distillrenders any session as an IM-style log -- the full JSONL stays preserved regardless - Fork lineage:
csb treeshows which session spawned which as an indented tree -- including purged ancestors csb still remembers, so a chain never reads headless - Restart recovery:
csb set show lastreconstructs which sessions were active before the machine's last shutdown -- the Windows Update special (and theapt upgrade && rebootspecial: fences read from the Windows event log or journalctl/wtmp on POSIX), with a paste-able resume command per row. History is addressable too:csb set last~2, orcsb set 2026-7-15by date -- and membership reads each session's real activity timeline, so reopening an old session never erases it from the epochs it lived in - Live session tracking:
csb set show currentknows what is open right now -- csb's hooks register every session on start and erase the record on clean close, so leftovers are crash evidence,csb set new NAME --from currentfreezes the group, andcsb resume --set NAMElists what's left to reclaim - Two-commit model: Noise (transient state) and user (configs, skills) committed separately
- Scheduled backup:
csb setup scheduleregisters a recurring backup with the OS scheduler (Task Scheduler / cron / launchd) -- hooks only fire when you use Claude Code, and the purge countdown runs whether you do or not - Unattended operation:
--no-gpg-sign,--quiet, lock file -- designed for scheduler and hook contexts - Cross-platform: Works on Windows, Linux, macOS, BSD
Commands
The daily drivers:
csb setup # Guided onboarding (git store, first backup, checklist)
csb setup schedule # OS-scheduled backup -- protects machines you are NOT using
csb backup # Scan, index, git commit
csb list # Timeline of sessions (filter, sort, --deleted)
csb scan -d <path> --deleted # Find (and bulk-restore) what was purged in a folder
csb search "oauth callback" # Full-text search across every conversation
csb tree [filter] [path] # Fork lineage: which session spawned which
csb set show last # What was active before the last shutdown (restart recovery)
csb set show current # What is open right now (live registry)
csb distill <query> # Read a session as a chat log -> ~/.claude/distilled/
csb resume <query> # Reopen in Claude Code (UUID, prefix, name, keyword...)
csb resume last:3 # Reclaim member 3 of that epoch, in THIS terminal
csb view <query> # Open in Claude Code History Viewer
csb restore <session-id> # Recover a deleted session from git history
csb status # Summary stats
Every command, every flag, and the nitty-gritties live in docs/commands.md.
Naming sessions (do this on start)
Every csb lookup (list, scan, tree, resume) matches against the session name. Claude Code only assigns a UUID, so an unnamed vault is a wall of 3b0924e5-... that you can only search by content. Naming is what makes Claude Code sessions easily browsable, and it's the difference between finding old work in a second or two, versus having to excavate older sessions.
Hand-name it with /rename the moment you walk into a new session, before any work. Starting a new project you know what you've set out to do -- whereas nothing else in the system does yet, and nothing reconstructs it quite as well later. Claude Code then shows that name at the top-right of the text input bar, so it also helps distinguish which Claude window is which when several projects are open at once.
The convention that makes lookups easier and less painful later is this -- what, when, about:
PROJECT__DATE__topic-words
For example:
CLAUDE-SESSION-BACKUP__2026-7-26__add-tree-functionality
DAZZLECMD__2026-7-5__fiber-nuance-with-FQCN
The project leads so csb list DAZZLECMD and csb tree "DAZZLECMD*" anchor on it.
Renaming later is completely safe, so rename if the work drifts and name old sessions after the fact. The docs/naming.md file covers everything else: anti-patterns, the separator grammar, /renameAI for backlogs of older unclear sessions, the workflow that leaves a searchable trail, naming forks so csb tree reads as a narrative, and more.
Common workflows
The patterns that come up every day:
# "What was I working on before the restart / crash / weekend?" -- the
# boot epoch: every session active before the last shutdown, as a
# numbered roster with a paste-able resume command per row.
csb set show last
csb resume last:2 # reclaim member 2 of that roster
csb set show current # ...and what is open RIGHT NOW
csb list -n 5 # manual fallback: recent activity
# "What sessions touched THIS project?" -- cd into any folder you were
# working in and ask. The shortcut form needs no flags to remember.
cd ~/code/my-project
csb scan .
csb scan -D . # this folder exactly, no subfolders
csb scan -s . # only sessions that STARTED here
# "I remember discussing it, but in WHICH session?" -- search by content,
# then read the winner like a chat log.
csb search "rate limiter backoff"
csb distill <uuid-from-the-hit>
# "Pick up exactly where I left off" -- by name, prefix, or keyword.
csb resume MY-PROJECT__2026-6-6__that-refactor
# "Claude Code purged something I needed."
csb list --deleted
csb restore MY-PROJECT__2025-5-25__redesign #or <session-id / id-fragment>
csb scan --help groups its flags by what they do -- selection (which sessions match), display (how each match is shown), and limits. --top belongs to display and never changes what matches. How -d / -D / -s differ, and when to reach for -NI (--no-index, the escape hatch that reads transcripts instead of the database): docs/commands.md.
Searching conversations
csb search finds old sessions by what was discussed, not just by folder or name -- sub-second across tens of thousands of messages via per-project FTS5 indexes (run csb update build-fts5 once to build them).
csb search "oauth callback" # literal substring, case-insensitive
csb search -E "refresh.*token" -C 3 # regex, with 3 events of context
Full details (what's indexed, source channels, JSON output, freshness semantics): docs/commands.md.
Reading conversations (distill)
csb search finds the needle; csb distill lets you read the haystack comfortably, with an instant-messenger-style log with timestamped speaker turns (<User>, <Claude>, <Agent:explore>) and one-line tool calls instead of walls of tool output. Markdown-friendly (Typora) and editor-friendly (Vim / VSCode / etc).
csb distill <anything-that-identifies-a-session> # writes ~/.claude/distilled/<slug>/<uuid>.md
The distilled file is a reading layer -- the full JSONL remains the preserved record. Filters, channels, and the distill_policy config: docs/commands.md.
Fork lineage (tree)
Forking a session -- /branch, continuing a /rewind, or claude --fork-session -r -- mints a new session that inherits the old one's history. csb tree shows how they relate:
$ csb tree multi-term
CLAUDE-SESSION-BACKUP__adding-transcript-search 2 months ago
└── CLAUDE-SESSION-BACKUP__phase-1-grep-first 2 months ago forked 2026-05-18, at 09:12
├── CLAUDE-SESSION-BACKUP__phase-2-fts5-index 6 weeks ago forked 2026-05-24, at 14:03
│ └── CLAUDE-SESSION-BACKUP__fts5-escaping-fix 1 month ago forked 2026-06-21, at 17:11
└── CLAUDE-SESSION-BACKUP__multi-term-boolean 1 month ago forked 2026-06-21, at 19:03 *
1 tree | 5 sessions | 96 never forked (--orphans to list)
A filter renders the whole family around each match (*), so you see ancestors and descendants at once. csb tree . scopes to the folder you're standing in; csb tree search "C:\code\myproject" combines both. Purged ancestors still render, dimmed -- csb remembers chains Claude Code has already deleted, so a lineage never reads headless. Per-node detail (-f/-ff), --root, --orphans, --json: docs/commands.md.
Recovery
When Claude Code purges a session that you wanted to keep, csb recovers it from git history byte+metadata-exact. This includes the full footprint (transcript, subagents, tool-results, logger files), recreated symlinks, and original timestamps -- a recovered session is indistinguishable from one that was never deleted. resume/view/distill all offer the restore inline when they hit a pruned session.
csb list --deleted # what's gone?
csb restore <session-id> # bring one back
csb scan -d <path> --deleted --restore --dry-run # preview a bulk recovery
Single + bulk recovery, guarantees and limits, purge-TTL management: docs/commands.md. Maintenance verbs (csb update *): docs/maintenance.md.
How It Works
flowchart LR
subgraph GitRepo["~/.claude/ (your git repo)"]
direction TB
Data["projects/*.jsonl<br>session-states/<br>file-history/"]
end
subgraph CSB["csb Tool"]
direction TB
Scripts["scanner.py<br>metadata.py<br><i>(extract names, dates, folders)</i>"]
Restore["restore.py"]
end
DB[("session-backup.db<br>(rebuildable metadata cache)")]
Data -- "scan & read" --> Scripts
Scripts -- "upsert" --> DB
Scripts -- "git add + commit" --> Data
Data -- "git show {commit}:path" --> Restore
Key principle: Git is the source of truth. The SQLite database is a rebuildable index for fast queries. If the DB is lost or corrupted, csb update rebuild-index reconstructs it while preserving deleted-session metadata. See docs/maintenance.md for the csb update family of maintenance verbs.
Automation
Two layers, protecting different things. The Claude Code plugin (from Quick Start above) backs up the machine you are using: PreCompact fires before /compact, SessionEnd on exit. csb setup schedule backs up the machine you are not using -- hooks never fire on an untouched machine, while Claude Code's own cleanup deletes old transcripts on a timer regardless. The guided install picks an interval (24h default), verifies the scheduler actually works (prime run at install; a cron entry with no running daemon is refused, not faked), and csb setup schedule --status can tell you "INSTALLED BUT NOT RUNNING" instead of leaving a dead entry looking healthy. Details, interval guidance, and platform notes: docs/automation.md.
Requirements
- Python 3.10+
- Git (for backup storage)
~/.claude/initialized as a git repository --csb setupdoes this for you (guided;--autofor scripts). Required for backup/restore; running without one is an explicit exception (csb setup --index-only): the search index still works (list/scan/search), but nothing is protected, and csb reminds you on every run until you either set up or sign off- Moved your Claude directory? csb follows
CLAUDE_CONFIG_DIRautomatically;--claude-dir,CLAUDE_DIR, and theclaude_dirconfig key also work
Installation
# From PyPI (recommended)
pip install claude-session-backup
# Latest unreleased build from GitHub
pip install git+https://github.com/DazzleML/Claude-Session-Backup.git
# From source (development / contributing)
git clone https://github.com/DazzleML/Claude-Session-Backup.git
cd Claude-Session-Backup
pip install -e ".[dev]"
Full documentation index: docs/README.md.
Contributing
Contributions welcome! Please open an issue or submit a pull request.
See CONTRIBUTING.md for:
- Development setup (
pip install -e ".[dev]") - Running the test suite and human test checklists (
tests/checklists/) - Version management with
sync-versions.py - Pull request checklist
Like the project?
Related Projects
- claude-session-logger - Real-time per-session tool/conversation logging; csb backs up and restores its files, and its session naming + state-file conventions shaped csb's
- Claude-Code-Infinite-Perfect-Context (WIP) - Reverse compaction: search past turns and fork into them at full pre-compaction fidelity. csb preserves the pre-compaction transcript it reaches back into, and
csb treeshows the forks it creates - dazzle-claude-config - Sync Claude Code configuration across machines (
ccs). Complementary territory: csb backs~/.claudeup, ccs distributes it
Acknowledgements
- claude-vault by @kuroko1t -- Serendipitously started development on
csba week or so before kuroko1t's blog post laying out the problem. - claude-code-history-viewer by @jhlee0409 - GUI session reader that
csb viewlaunches.
License
Claude-Session-Backup, Copyright (C) 2026 Dustin Darcy
Licensed under the GNU General Public License v3.0 (GPL-3.0) -- see LICENSE
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file claude_session_backup-0.9.9.tar.gz.
File metadata
- Download URL: claude_session_backup-0.9.9.tar.gz
- Upload date:
- Size: 574.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ef465019edafe0b9a0e156cbafc2d2e32606520344aa7e2e3525cb5efa09535
|
|
| MD5 |
c523daf5d0d4649e19ca06220dab0cfa
|
|
| BLAKE2b-256 |
cfbbb613c9636f4dc2046d6666ad2346d668d40fc14e82087acff7b3c197aebd
|
Provenance
The following attestation bundles were made for claude_session_backup-0.9.9.tar.gz:
Publisher:
release.yml on DazzleML/Claude-Session-Backup
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_session_backup-0.9.9.tar.gz -
Subject digest:
4ef465019edafe0b9a0e156cbafc2d2e32606520344aa7e2e3525cb5efa09535 - Sigstore transparency entry: 2386645892
- Sigstore integration time:
-
Permalink:
DazzleML/Claude-Session-Backup@65c3a20a3dca68062f4206be8e88915f3c575055 -
Branch / Tag:
refs/tags/v0.9.9 - Owner: https://github.com/DazzleML
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@65c3a20a3dca68062f4206be8e88915f3c575055 -
Trigger Event:
release
-
Statement type:
File details
Details for the file claude_session_backup-0.9.9-py3-none-any.whl.
File metadata
- Download URL: claude_session_backup-0.9.9-py3-none-any.whl
- Upload date:
- Size: 343.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc38a64ec6eed761d23266768bf24164f02da91aa6c2ed07cf214ee63d58c005
|
|
| MD5 |
787905de7e5f0c2853400c4c9d2f4a0e
|
|
| BLAKE2b-256 |
e39ad179c29aefb777561354a31305b69318f92582c5b2a0ed55fdacc8ff411d
|
Provenance
The following attestation bundles were made for claude_session_backup-0.9.9-py3-none-any.whl:
Publisher:
release.yml on DazzleML/Claude-Session-Backup
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_session_backup-0.9.9-py3-none-any.whl -
Subject digest:
fc38a64ec6eed761d23266768bf24164f02da91aa6c2ed07cf214ee63d58c005 - Sigstore transparency entry: 2386645896
- Sigstore integration time:
-
Permalink:
DazzleML/Claude-Session-Backup@65c3a20a3dca68062f4206be8e88915f3c575055 -
Branch / Tag:
refs/tags/v0.9.9 - Owner: https://github.com/DazzleML
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@65c3a20a3dca68062f4206be8e88915f3c575055 -
Trigger Event:
release
-
Statement type: