uhoh
ctrl-z for AI agents
Local filesystem snapshots that let you undo anything an AI agent does to your code.
Install in 10 seconds
Or build from source: cargo install uhoh
1. Watch
uhoh monitors your project using OS-native file watchers. It respects the full .gitignore chain plus .uhohignore files for project-specific exclusions.
2. Snapshot
Changed files are BLAKE3-hashed and stored in a deduplicated blob store. uhoh tries reflink (copy-on-write) first, then hardlink, then full copy, so on APFS or btrfs snapshots can cost almost no extra disk space.
3. Recover
Restore any snapshot, export to git stash, diff between any two points, or undo entire AI operations.
Automatic Snapshots
Background daemon creates snapshots on file changes with smart debouncing.
Operation-Level Undo
Run uhoh mark before an agent session, then uhoh undo to revert everything it changed in one command.
Emergency Snapshot Retention
Configurable thresholds for emergency snapshot retention. Storage limit enforcement automatically prunes old snapshots when blob storage grows past the per-project cap.
Local Only
Everything stays on your machine. No cloud, no accounts, no telemetry. Snapshots live in ~/.uhoh with a SQLite database and a local blob store.
MCP Integration
Both STDIO and HTTP MCP transports let AI agents create snapshots, list history, restore files, and send pre-action notifications. Works with Claude Desktop, Cursor, and any MCP-compatible client out of the box.
uhoh mcp
Database Guardian
Monitor PostgreSQL, SQLite, and MySQL for dropped tables, mass deletes, and schema changes. Automatic baselines and encrypted recovery artifacts so you can undo database mistakes, not just file mistakes.
Agent Monitoring
MCP proxy interception classifies agent tool calls before they execute. Dangerous actions can be paused for human approval. Session-log tailing as fallback, fanotify audit on Linux as opt-in.
AI summaries (optional)
When enabled, uhoh uses a local Qwen 3.5 model (via llama.cpp or MLX on Apple Silicon) to generate one-line change summaries for each snapshot. Everything runs on your machine — no API calls, no data leaves your disk. Skips automatically on battery or low RAM.
How it works
BLAKE3 content-addressed, tiered storage (reflink → hardlink → copy), optional zstd compression.
WAL mode, transactional snapshots, FTS5 search index, tamper-evident event ledger with BLAKE3 hash chain.
REST API, WebSocket events, Time Machine UI, MCP HTTP endpoint — all on 127.0.0.1:22822. The built-in Time Machine UI at http://127.0.0.1:22822 lets you browse snapshots, view diffs, and search history in a browser.
Daemon coordinates file watcher, database guardian, agent monitor, AI sidecar, and maintenance tasks with automatic restart on failure.
MCP integration
uhoh exposes four MCP tools (create_snapshot, list_snapshots, restore_snapshot, uhoh_pre_notify) over both STDIO and HTTP transports. restore_snapshot defaults to dry-run mode and requires explicit confirm: true for actual restore — agents can't accidentally restore without confirmation.
Claude Desktop configuration:
{
"mcpServers": {
"uhoh": {
"command": "uhoh",
"args": ["mcp"]
}
}
}
Event forensics
All subsystem events — filesystem changes, database guard triggers, and agent actions — land in a single unified timeline. Each event is chained with a BLAKE3 hash of the previous entry, making the ledger tamper-evident.
Navigate the ledger with: uhoh trace to walk causal chains, uhoh blame to trace backward from a file path, uhoh timeline for a unified chronological view, and uhoh ledger verify to verify hash chain integrity.
CLI Reference
Getting Started
(none)
uhoh
▼
Usage: uhoh
If unregistered, registers current directory and takes initial snapshot. If registered, shows status and tips.
uhoh +
uhoh add [path]
▼
Usage: uhoh + [path]
Register a folder for watching (defaults to current directory). Creates marker file and initial snapshot.
uhoh -
uhoh remove [target]
▼
Usage: uhoh - [path-or-hash]
Unregister a folder. Removes marker file and all metadata.
uhoh l
uhoh list
▼
Usage: uhoh l
List all registered projects with status (✓/✗), snapshot count, and hash prefix.
(none)
uhoh status
▼
Usage: uhoh status
Show daemon state, project count, total snapshots, blob storage size, and AI status. Warns about inception loops.
Snapshots & History
uhoh suhoh snapshots [target]
▼
Usage: uhoh s [target]
List snapshots for a project with timestamps, IDs, trigger types, per-file storage methods.
uhoh cuhoh commit [message]
▼
Usage: uhoh c "before refactor"
Create a manual snapshot with an optional message. Messages get minimum daily retention during compaction.
uhoh duhoh diff [id1] [id2]
▼
Usage: uhoh d or uhoh d <id1> <id2>
Unified diff with syntax highlighting. No args = latest snapshot vs working tree. Two IDs = diff between those snapshots.
uhoh puhoh cat <file> <id>
▼
Usage: uhoh p src/main.rs <id>
Print a file's contents at a point in time. Accepts base58 IDs, RFC 3339 timestamps, or YYYY-MM-DDTHH:MM:SS.
uhoh ouhoh log <file>
▼
Usage: uhoh o src/main.rs
Show the change history of a specific file across all snapshots.
Recovery
uhoh ruhoh restore <id>▼
Usage: uhoh r <id> [--dry-run] [--force]
Restore working tree to a snapshot. Takes a pre-restore snapshot first. --dry-run previews changes. --force skips confirmation when deleting >10 files.
uhoh guhoh gitstash <id>▼
Usage: uhoh g <id>
Push a snapshot into a git stash entry without touching working tree or index. Preserves executable bits and symlink modes.
(none)uhoh mark <label>▼
Usage: uhoh mark "implement search"
Mark the start of an AI-agent operation. Auto-closes any previously active operation.
(none)uhoh undo [target]▼
Usage: uhoh undo
Close active operation (if any), find last completed operation, restore to the snapshot just before it started.
(none)uhoh operations [target]▼
Usage: uhoh operations
List recorded operations with status (active/completed), labels, and snapshot ranges.
Git Integration
uhoh hook install▼
Usage: uhoh hook install
Add a pre-commit hook that snapshots before each git commit. Appends to existing hooks with BEGIN/END markers.
uhoh hook remove▼
Usage: uhoh hook remove
Remove only the uhoh block from the pre-commit hook. Deletes the file if nothing else remains.
Daemon & Maintenance
uhoh start▼
Usage: uhoh start [--service]
Start the background daemon. --service runs in foreground (for service managers).
uhoh stop▼
Usage: uhoh stop
Stop the daemon via PID file.
uhoh restart▼
Usage: uhoh restart
Stop + start. Required for most config changes.
uhoh config▼
Usage: uhoh config
Usage: uhoh config edit
Usage: uhoh config set watch.debounce_quiet_secs 5
Usage: uhoh config get ai.enabled
Print full current config as TOML, open ~/.uhoh/config.toml in $EDITOR, set a config value, or read a config value.
uhoh gc▼
Usage: uhoh gc
Manual garbage collection of unreferenced blobs (15-minute grace period).
uhoh update▼
Usage: uhoh update
Check for new version, verify Ed25519 signature + DNS TXT fallback, atomically replace binary.
uhoh doctor▼
Usage: uhoh doctor [--fix] [--restore-latest] [--verify-install]
Run integrity checks on DB and blob store. --fix removes orphans, quarantines corrupt blobs. --restore-latest restores DB from backup. --verify-install checks binary hash against DNS.
uhoh service-install▼
Usage: uhoh service-install
Install auto-start service (launchd on macOS, systemd on Linux, scheduled task on Windows).
uhoh service-remove▼
Usage: uhoh service-remove
Remove auto-start service.
Event Forensics
uhoh traceuhoh trace <event-id>▼
Usage: uhoh trace <event-id>
Walk the causal chain in the event ledger starting from a specific event.
uhoh blameuhoh blame <path>▼
Usage: uhoh blame <path>
Trace backward from a file path to find which events modified it.
uhoh timelineuhoh timeline [--source ...] [--since ...]▼
Usage: uhoh timeline [--source filesystem|database|agent] [--since 1h]
Unified chronological view of all events. Filter by source subsystem or time range.
uhoh ledger verify▼
Usage: uhoh ledger verify
Verify the BLAKE3 hash chain integrity of the event ledger. Reports any tampered or missing entries.
Database Guardian
uhoh db adduhoh db add <dsn>▼
Usage: uhoh db add <dsn>
Register a database for monitoring. Supports PostgreSQL, SQLite, and MySQL DSNs.
uhoh db list▼
Usage: uhoh db list
List all registered database guards with status and last baseline time.
uhoh db eventsuhoh db events [name]▼
Usage: uhoh db events [name]
Show events for a specific database guard or all guards.
uhoh db recoveruhoh db recover <event-id>▼
Usage: uhoh db recover <event-id>
Inspect or apply recovery artifacts from a database guard event.
uhoh db baselineuhoh db baseline <name>▼
Usage: uhoh db baseline <name>
Force a baseline snapshot for a named database guard.
uhoh db testuhoh db test <name>▼
Usage: uhoh db test <name>
Test connectivity to a named database guard.
Agent Monitor
uhoh agent init▼
Usage: uhoh agent init
Initialize the agent profiles directory for agent monitoring configuration.
uhoh agent adduhoh agent add <name>▼
Usage: uhoh agent add <name>
Register a named agent for monitoring.
uhoh agent loguhoh agent log [name]▼
Usage: uhoh agent log [name]
Show events for a specific agent or all agents.
uhoh agent undouhoh agent undo --cascade <event-id>▼
Usage: uhoh agent undo --cascade <event-id>
Cascade undo of an agent action and all dependent changes.
uhoh agent approve▼
Usage: uhoh agent approve
Approve a pending dangerous action that was paused for human review.
uhoh runuhoh run -- <command>▼
Usage: uhoh run -- <command>
Launch a command with uhoh runtime controls and monitoring.
MCP
uhoh mcp▼
Usage: uhoh mcp
Run the MCP server over STDIO. Exposes create_snapshot, list_snapshots, restore_snapshot, and uhoh_pre_notify tools to MCP-compatible clients.
Configuration
Located at ~/.uhoh/config.toml
Edit with uhoh config edit or uhoh config set <key> <value>. Settings marked ✓ hot-reload take effect immediately; all others require uhoh restart.
ai.enabled to turn on AI summaries, storage.max_binary_blob_bytes if your project has binary assets, and watch.debounce_quiet_secs to tune responsiveness.
# Snapshot timing [watch] debounce_quiet_secs = 2 # ✓ hot-reload | seconds of quiet after last file change min_snapshot_interval_secs = 5 # restart | minimum gap between snapshots max_debounce_secs = 30 # restart | force snapshot after continuous changes emergency_delete_threshold = 0.30 # restart | fraction deleted to trigger emergency snapshot emergency_delete_min_files = 5 # restart | minimum deleted files before threshold applies # Blob storage limits [storage] max_binary_blob_bytes = 1_048_576 # restart | binary cap (raise to recover binary assets) max_text_blob_bytes = 52_428_800 # restart | text blob cap (50 MB) max_copy_blob_bytes = 52_428_800 # restart | hard cap for copy fallback storage_limit_fraction = 0.15 # restart | per-project storage fraction limit storage_min_bytes = 524_288_000 # restart | minimum 500 MB floor compress = false # restart | zstd compression (compression feature build required) compress_level = 3 # restart | zstd level 1-22 # Retention policy [compaction] keep_all_minutes = 60 # restart | keep every snapshot in this window keep_5min_days = 14 # restart | keep one per 5-minute bucket keep_hourly_days = 30 # restart | keep one per hour keep_daily_days = 180 # restart | keep one per day keep_weekly_beyond = true # restart | keep one per week beyond daily window # Local AI summaries [ai] enabled = false # restart | automatically uses llama-server sidecar, or MLX on Apple Silicon skip_on_battery = true # restart recommended | skip inference on battery min_available_memory_gb = 4 # restart recommended | minimum available RAM max_context_tokens = 8192 # restart recommended | max diff context tokens idle_shutdown_secs = 300 # restart recommended | AI sidecar idle shutdown # Auto-updates [update] auto_check = true # restart | enable periodic update checks check_interval_hours = 24 # ✓ hot-reload | hours between checks # Notifications [notifications] desktop = true # restart | desktop notifications webhook_url = "" # restart | webhook endpoint webhook_events = ["mass_delete", "drop_table", "dangerous_agent_action", "mlx_update_failed"] cooldown_seconds = 60 # restart | minimum gap between notifications # Database guardian [db_guard] enabled = false # restart | enable database monitoring mass_delete_row_threshold = 100 # restart | rows deleted to trigger alert baseline_interval_hours = 6 # restart | hours between automatic baselines encrypt_recovery = true # restart | encrypt recovery artifacts # Agent monitor [agent] enabled = false # restart | enable agent monitoring mcp_proxy_port = 22823 # restart | MCP proxy interception port on_dangerous_change = "none" # restart | "none" or "pause" pause_timeout_seconds = 300 # restart | timeout for paused actions # Localhost server [server] enabled = true # restart | enable REST API and Time Machine UI port = 22822 # restart | server port bind_address = "127.0.0.1" # restart | bind address require_auth = true # restart | require authentication