nono can take filesystem snapshots before and after sandboxed execution, allowing you to review and reverse any changes an agent made. The rollback system uses content-addressable storage with SHA-256 deduplication and Merkle tree integrity verification.
The idea is that if an agent makes unintended changes to your filesystem, you can easily see what changed and restore any modified or deleted files back to their original state. This provides a safety net when running powerful agents that have write access to your files.
How It Works
When you run a command with --rollback, nono:
- Takes a baseline snapshot of all files in tracked directories before the command starts
- Runs the command inside the sandbox
- Takes a final snapshot after the command exits
- Shows an interactive diff of all changes, offering to restore any modified or deleted files
# Enable rollback snapshots
nono run --rollback --profile claude-code -- claude
--rollback automatically selects supervised execution because the parent process needs to remain unsandboxed to write snapshots to ~/.nono/rollbacks/.
Snapshot Architecture
Content-Addressable Object Store
Files are stored by their SHA-256 hash, so identical content is never stored twice. On macOS with APFS, nono uses clonefile() for copy-on-write storage - snapshots consume minimal additional disk space when files haven’t changed.
Merkle Tree Integrity
Each snapshot builds a Merkle tree over all tracked files. The root hash provides a cryptographic commitment to the exact filesystem state at that point in time. This allows:
- Verifying that no snapshot data has been tampered with
- Detecting corruption in stored objects
- Efficient comparison between snapshots (only recompute changed subtrees)
Session Structure
Sessions are stored in ~/.nono/rollbacks/ with the following layout:
~/.nono/rollbacks/
<session-id>/
manifest.json # Session metadata, Merkle roots, timestamps
objects/ # Content-addressable file store
ab/cd1234... # Files stored by SHA-256 hash
snapshots/
0/ # Baseline snapshot
1/ # Final snapshot (or intermediate)
Session IDs use the format YYYYMMDD-HHMMSS-PID (e.g., 20260214-143022-12345).
Exclusion Filters
Not every file needs tracking. The rollback system respects:
- Profile-defined patterns: Common build artifacts like
node_modules, .next, __pycache__, target
- Profile-defined globs: Patterns like
*.tmp.[0-9]*.[0-9]*
- gitignore integration: Reads
.gitignore patterns from the working directory
These exclusions keep snapshots fast and storage efficient.
Commands
nono rollback list
List past sessions grouped by project directory.
# Show recent sessions (grouped by project)
nono rollback list
# Filter to a specific project
nono rollback list --path ~/dev/my-project
# Show only the 5 most recent
nono rollback list --recent 5
# Include sessions with no file changes
nono rollback list --all
# Machine-readable output
nono rollback list --json
Example output:
[nono] 10 session(s)
~/dev/sprockets (7 sessions)
20260219-092017-8117 just now claude ~2 modified
20260219-091403-90291 7m ago claude ~2 modified
20260218-134433-28210 19h ago claude +5 files
...
~/dev/widgets (3 sessions)
20260219-100000-1234 5m ago claude +2 files
20260218-120000-5678 1d ago claude ~1 modified
...
nono rollback show
Inspect the changes made during a session.
# Show summary of changes
nono rollback show 20260214-143022-12345
# Show unified diff (git-style)
nono rollback show 20260214-143022-12345 --diff
# Side-by-side diff
nono rollback show 20260214-143022-12345 --side-by-side
# Show full file content from snapshot
nono rollback show 20260214-143022-12345 --full
# Machine-readable output
nono rollback show 20260214-143022-12345 --json
nono rollback restore
Restore files from a past session to their pre-change state.
# Restore all files to baseline state
nono rollback restore 20260214-143022-12345
# Restore to a specific snapshot (0 = baseline, 1 = final)
nono rollback restore 20260214-143022-12345 --snapshot 0
# Preview what would change without modifying files
nono rollback restore 20260214-143022-12345 --dry-run
Restoration uses atomic rename per file to prevent partial restores.
nono rollback verify
Verify the integrity of a stored session by recomputing Merkle tree hashes and checking all objects in the store.
nono rollback verify 20260214-143022-12345
Reports any missing objects, hash mismatches, or corrupted metadata.
nono rollback cleanup
Remove old sessions to reclaim disk space.
# Keep only the 10 most recent sessions
nono rollback cleanup --keep 10
# Remove sessions older than 30 days
nono rollback cleanup --older-than 30
# Preview what would be deleted
nono rollback cleanup --dry-run
# Remove all sessions (requires confirmation)
nono rollback cleanup --all
Interactive Post-Exit Flow
When a --rollback command exits and file changes are detected, nono presents an interactive review:
- Shows a summary of all changes (created, modified, deleted files)
- Offers to show diffs for individual files
- Asks whether to restore some or all files
Use --no-rollback-prompt to suppress the interactive UI while still taking snapshots (useful for scripting).
Storage Management
| Setting | Default | Description |
|---|
| Max sessions | 10 | Oldest sessions pruned automatically |
| Max storage | 5 GB | Total storage limit for all sessions |
Configure these in your nono config file or use nono rollback cleanup for manual management.
Profile Rollback Configuration
Profiles can customize rollback behavior:
[rollback]
exclude_patterns = ["node_modules", ".next", "__pycache__", "target"]
exclude_globs = ["*.tmp.[0-9]*.[0-9]*"]
These exclusions are combined with gitignore patterns from the working directory.