Snapshot and restore cmux workspaces with Claude Code session resumption.
When cmux crashes or is restarted, this tool recreates your workspace layout — splits, panels, working directories, Claude sessions, and optionally terminal commands — and resumes everything where it left off.
-
Snapshot reads cmux's session state file to capture all windows, workspaces, panels, and their layout (splits, orientations, working directories).
-
It cross-references running Claude processes (
ps) with their--session-idflags, mapping each Claude panel to its active session. For non-Claude terminal panels, it detects running foreground commands (dev servers, watchers, etc.) via process inspection. -
Restore recreates the workspace structure using
cmuxCLI commands, targeting each panel by surface ref to ensure commands land in the correct split. Claude sessions resume withclaude --resume <session-id>, and terminal panelscdto their original directories. With--run-commands, captured terminal commands are re-launched automatically.
# Take a snapshot of all workspaces
make snapshot
# List active Claude sessions
make list-active
# Show detailed info for a workspace
make show W=myproject
# After a crash — preview the restore plan
make restore-dry-run W=myproject
# Restore a workspace (auto-executes inside cmux, prompts for confirmation)
make restore W=myproject
# Respawn: snapshot + kill + restore in one step
make respawn W=myproject# See what you had running
make list-snapshots
# Inspect a specific snapshot to verify it has what you need
make show F=cmux-20260405-161401
# Preview the restore plan
make restore-dry-run
# Restore everything (requires typing 'yes' for multi-workspace)
make restore# Check current state
make show W=devops-work
# Snapshot, kill, and restore in one step
make respawn W=devops-work# List available snapshots
make list-snapshots
# Preview what it would do
make restore-dry-run W=devops-work F=cmux-20260405-161401
# Restore it
make restore W=devops-work F=cmux-20260405-161401# See which workspaces from the snapshot are active vs closed
make diff
# Restore only the ones that aren't currently running
make restore SA=1
# Combine with a specific snapshot
make restore SA=1 F=cmux-20260405-161401# Take a snapshot (captures running terminal commands)
make snapshot W=vibefocus
# Check what commands were captured
make show W=vibefocus F=latest
# Restore with commands auto-launched
make restore W=vibefocus RC=1# Quick overview — Claude sessions and panel counts
make list-active
# Deep dive into a specific workspace
make show W=vibefocus# Snapshot everything
make snapshot
# Verify it captured your workspaces
make list-snapshots
# After reboot, restore from inside cmux
make restoremake help Show all available targets
make list-active List active Claude sessions with git branches
make show Show detailed workspace info (W= workspace, F= snapshot)
make snapshot Capture state (W= workspace, N= name)
make list-snapshots List all saved snapshots with workspace names
make diff Compare snapshot vs live workspaces (F= snapshot)
make validate Check snapshot health before restoring (F= snapshot, W= workspace)
make prune Delete old snapshots, keep last N (KEEP=10)
make restore-dry-run Preview restore (W= workspace, F= snapshot, RC=1, SA=1)
make restore Restore from snapshot (W= workspace, F= snapshot, RC=1, SA=1)
make kill Close a workspace with confirmation (requires W=)
make respawn Snapshot, kill, and restore a workspace (requires W=)
make install Symlink cmux-sessions into ~/bin
| Variable | Description | Example |
|---|---|---|
W= |
Workspace name filter (case-insensitive substring) | W=devops-work |
F= |
Snapshot file (bare name, with .json, or full path) | F=cmux-20260405-161401 |
N= |
Named snapshot (instead of timestamp) | N=before-refactor |
RC=1 |
Re-run captured terminal commands on restore | RC=1 |
SA=1 |
Skip already-active workspaces on restore | SA=1 |
KEEP= |
Number of snapshots to keep when pruning (default: 10) | KEEP=5 |
cmux-sessions list Show Claude sessions with git branches
cmux-sessions show -w myproject Show detailed workspace info (live)
cmux-sessions show -w myproject -f snap.json Show detailed workspace info (snapshot)
cmux-sessions snapshot Save current state (all workspaces)
cmux-sessions snapshot -w myproject Snapshot only matching workspace
cmux-sessions snapshot -n before-refactor Save with a name instead of timestamp
cmux-sessions snapshots List all saved snapshots
cmux-sessions diff Compare snapshot vs live workspaces
cmux-sessions diff -f snap.json Compare specific snapshot vs live
cmux-sessions validate Check snapshot health before restoring
cmux-sessions validate -f snap.json -w proj Validate specific snapshot/workspace
cmux-sessions prune Delete old snapshots (keep last 10)
cmux-sessions prune --keep 5 Keep last 5 snapshots
cmux-sessions restore --dry-run Preview what would be restored
cmux-sessions restore -w myproject Restore only matching workspace
cmux-sessions restore --skip-active Restore only closed workspaces
cmux-sessions restore --run-commands Re-run saved terminal commands
cmux-sessions kill -w myproject Close a workspace (with confirmation)
cmux-sessions kill -w myproject -y Close without confirmation
cmux-sessions respawn -w myproject Snapshot, kill, and restore in one step
make show W=myproject displays every panel with its type, working directory, and session/command info:
Workspace: myproject
Directory: ~/Development/myproject
Panels: 3
Panel 1: [claude] Implement auth middleware
cwd: ~/Development/myproject
session: a1b2c3d4-5678-90ab-cdef-1234567890ab
pid: 12345
status: running
Panel 2: [terminal] Terminal
cwd: ~/Development/myproject
command: npm run dev
Panel 3: [terminal] Terminal
cwd: ~/Development/myproject/docs
Works with -f to inspect snapshot contents: make show W=myproject F=cmux-20260405-161401
Snapshots detect foreground processes running in non-Claude terminal panels (dev servers, watchers, REPLs, etc.) and save them as lastCommand. On restore:
- Default: commands are shown as hints but not executed — panels just
cdto the correct directory RC=1/--run-commands: commands are re-launched automatically
Restore auto-detects whether you're inside cmux:
- Inside cmux: shows the plan, prompts for confirmation, then executes directly
- Outside cmux: generates a restore shell script to run from a cmux terminal
Safety checks before restoring:
- Duplicate detection: warns if target workspaces are already open, requires typing
forceto continue - Multi-workspace guard: restoring all workspaces (no
W=filter) requires typingyes - Single workspace: standard
y/Nconfirmation
make respawn W=myproject is the all-in-one workflow:
- Snapshots the workspace
- Prompts for confirmation
- Kills it via
cmux close-workspace - Restores from the fresh snapshot
Claude session IDs are resolved in priority order:
- Running process with
--session-idor--resumeflag sessions-index.jsonin~/.claude/projects/- Most recent
.jsonlsession file by modification time (fallback when index is missing)
Give snapshots meaningful names instead of timestamps:
make snapshot W=devops N=before-refactor
# Saves as ~/.cmux-snapshots/cmux-before-refactor.json
# Restore from it later
make restore W=devops F=before-refactorCheck that a snapshot is still valid before restoring:
make validate F=cmux-20260405-161401Output shows PASS/FAIL for each panel's directory and Claude session:
WORKSPACE TYPE DIRECTORY DIR SESSION
--------- ---------- -------------------------- ---- -------
myproject [claude] ~/Development/myproject PASS PASS
myproject [terminal] ~/Development/myproject PASS -
myproject [terminal] ~/Development/myproject/api PASS -
Snapshots accumulate over time. Clean up old ones:
make prune # Keep last 10
make prune KEEP=5 # Keep last 5make list-active includes a BRANCH column showing the current git branch for each Claude session's working directory.
make install # Symlinks to ~/bin/cmux-sessionsOr add to your PATH manually:
export PATH="$HOME/Development/cmux-sessions:$PATH"| Path | Purpose |
|---|---|
~/.cmux-snapshots/ |
Snapshot storage directory |
~/.cmux-snapshots/latest.json |
Most recent snapshot (used by default restore) |
~/.cmux-snapshots/restore.sh |
Generated restore script (outside cmux fallback) |
~/Library/Application Support/cmux/session-com.cmuxterm.app.json |
cmux's live session state (read-only) |
~/.claude/projects/ |
Claude Code session index and history files |
To take periodic snapshots, add a cron job or launchd plist:
# Every 30 minutes
*/30 * * * * python3 ~/Development/cmux-sessions/cmux-sessions.py snapshot 2>/dev/null- Kill/respawn must be run from inside cmux —
cmux close-workspacerequires a socket connection only available to cmux child processes. Snapshot, list, and show work from anywhere. - Layout is approximate — complex nested splits are flattened into sequential split operations. Split directions and panel order are preserved, but exact divider positions may shift.
- Terminal command capture is best-effort — it detects foreground child processes of shell sessions. Idle shells (at a prompt) have no command to capture. Background jobs and piped commands may not be detected.
- Session IDs are point-in-time — if a Claude session is ended and a new one started between snapshot and restore, the old session ID will be used. Take fresh snapshots regularly.
- Python 3.8+
- cmux (macOS)
- Claude Code CLI