uhoh

ctrl-z for AI agents

Local filesystem snapshots that let you undo anything an AI agent does to your code.

fluffypony@qubes: ~/
$  

Install in 10 seconds

curl -fsSL https://uhoh.it/install.sh | sh
Copied!

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

Blob store

BLAKE3 content-addressed, tiered storage (reflink → hardlink → copy), optional zstd compression.

SQLite database

WAL mode, transactional snapshots, FTS5 search index, tamper-evident event ledger with BLAKE3 hash chain.

Localhost server

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.

Subsystem manager

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.

Most tuned settings: 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