Guides
History & Undo
Time-machine for destructive ops: every optimize/convert/resize/remove-bg/caption is snapshotted locally and reversible via `localpress undo`.
Every destructive op writes a snapshot of the pre-change state. Walk it back with
localpress undo. Pairs naturally with the MCP server so agents can self-correct.
localpress ships with a time-machine that captures the state of every attachment before any destructive op writes new data to WordPress. If something goes wrong — a bad bulk optimize, a model swap that ruined the lighting, an agent that ran the wrong command — you can walk back to the previous state.
What gets snapshotted
| Operation | Kind | Captures |
|---|---|---|
optimize | binary | source file bytes + WP metadata |
convert | binary | source file bytes + WP metadata |
resize | binary | source file bytes + WP metadata |
remove-bg | binary | source file bytes + WP metadata |
caption | metadata-only | alt-text before-state |
Idempotent skips (when the source hasn't changed since the last op) don't create snapshots — they're truly free.
Interactive commands (edit, watch) aren't snapshotted: edit keeps the original locally during the round-trip, and watch would create too many redundant snapshots in normal use.
Where snapshots live
~/.config/localpress/sites/<site-name>.db ← session + snapshot rows
~/.config/localpress/snapshots/<site>/<session>/ ← blob storage
Each session corresponds to one command invocation. Each snapshot inside a session corresponds to one attachment that was changed.
The commands
Browse history
# List recent sessions (default action)
localpress history
# Filter
localpress history --session a1b2c3d4
localpress history --attachment 123
localpress history --operation optimize
# Interactive TUI (mirrors `list -i` UX)
localpress history -i
Show details
# By session prefix (8 chars is enough)
localpress history show a1b2c3d4
# By snapshot ID
localpress history show 42
Undo
# Undo the last session — dry-run by default, requires --apply
localpress undo
localpress undo --apply
# Undo a specific session
localpress undo a1b2c3d4 --apply
# Undo one specific snapshot (single-target, executes immediately)
localpress undo --snapshot 42
# Undo the most recent op on a specific attachment (single-target)
localpress undo --attachment 123
Safe-by-default: bulk (session-targeted) undos dry-run unless you pass --apply. Single-target modes (--snapshot / --attachment) execute immediately, matching the rest of the CLI's "explicit IDs execute" pattern.
Retention
# Apply the configured retention policy now
localpress history prune
# One-off overrides
localpress history prune --max-size 1073741824 # 1 GB cap
localpress history prune --older-than 30 # drop >30 days old
localpress history prune --max-sessions 50 # keep last 50 sessions
# Nuclear option
localpress history clear --yes
By default, snapshots are auto-pruned at the end of every destructive op — you don't normally need to run prune manually.
Retention policy
The default is 2 GiB per site, drop oldest first. Configure per site:
# 4 GiB cap
localpress config set history.maxSizeBytes 4294967296
# Disable snapshotting entirely
localpress config set history.enabled false
Both keys are also readable:
localpress config get history.maxSizeBytes
localpress config get history.enabled
Stats integration
localpress stats includes a "History (undo)" block:
History (undo):
Snapshots: 147 across 12 sessions
Storage used: 842.3 MB / 2.0 GB (41.1%)
Oldest snapshot: Apr 12, 2026
Retention policy: size-capped, 2.0 GB
The --json shape extends accordingly:
{
"site": "production",
"stats": { ... },
"history": {
"snapshotCount": 147,
"sessionCount": 12,
"totalBytes": 882903960,
"oldestSnapshotAt": 1744473600000,
"newestSnapshotAt": 1746979200000,
"maxSizeBytes": 2147483648,
"enabled": true
}
}
Restore mechanics
When undo runs, it reverses the original op:
- Binary snapshots: load the blob from disk, replace-in-place via the adapter. If WP-CLI is configured (SSH), the file is replaced atomically. Otherwise localpress falls back to uploading a new attachment and warning you about manual reference updates.
- Metadata-only snapshots (caption): call
updateMetadatawith the before-state alt-text/title/caption.
Snapshots aren't deleted on restore — they're marked restored_at so you can see the history. Pruning still applies normally.
Use with the MCP server
If you're driving localpress through the MCP server, four tools cover the time-machine surface:
| Tool | What it does |
|---|---|
history_list | Browse sessions and snapshots |
history_show | Details for a session ID or snapshot ID |
undo | Restore from snapshot(s); dry-run unless apply: true |
history_prune | Apply retention policy with per-call overrides |
Plus a read-only resource at localpress://history for proactive context-loading.
Combined with the MCP server's safe-by-default bulk ops, this means an agent can confidently run optimize --unoptimized --apply knowing that if anything goes wrong, undo walks it back.
When NOT to rely on the time-machine
Some scenarios fall outside what snapshots can capture:
- Snapshots are local-only. If your machine dies, the snapshots die with it. For long-term archival, use
localpress export. - Snapshots don't cover schema-level changes like deleting an attachment via
wp_delete_postor moving uploads between WP installs. Those aren't localpress operations. - Reference rewrites done via
localpress references --update-toaren't snapshotted (yet). If you bulk-rewrite content URLs, that's not reversible throughundo.
Performance and disk
- Binary snapshots cost ~the same as the original file. Bulk ops on a 500 MB library produce ~500 MB of snapshots until pruned.
- Metadata-only snapshots are essentially free (~200 bytes each).
- Snapshot writes happen before the WP mutation, so if WP fails or the network drops mid-op, the snapshot is still on disk and
undostill works for items that already changed. - Auto-prune runs at the end of every destructive command, so disk usage stays bounded.
See also
- Commands Reference — full command list
- MCP Setup — first-party MCP server
- Configuration — config keys including
history.*
Sourced from the GitHub Wiki. Updates on each deploy.