devsafe restore
Decrypt and restore a git bundle from your user-owned storage back to your local machine. Includes a drift check to confirm the roundtrip is perfect. Paid
Usage
$ devsafe restore <repo-id> [--target <dir>] [--file <path>] [--to <time>]
The restore command downloads your encrypted git bundle from user-owned storage, decrypts it locally with your key, and rebuilds the repository. Your key never leaves your machine during this process.
Before restoring, DevSafe saves your current state as a "pre-restore" checkpoint. If something goes wrong, you can restore back to that checkpoint.
Flags
| Flag | Description | Default |
|---|---|---|
--target <dir> | Stream a single-pass restore to a new directory instead of overwriting the current one. | Current directory |
--file <path> | Restore a single file from the backup instead of the entire repository. | All files |
--to <time> | Restore to a specific point in time. Accepts relative times like "1h ago" or absolute timestamps like "2026-04-29 14:00". | Latest snapshot |
--dry-run | Show what would be restored without making any changes. | Off |
Restore to current directory
The simplest restore. This downloads your latest encrypted git bundle, decrypts it, and replaces the current repository contents. DevSafe saves a checkpoint first, so you can undo the restore if needed.
$ devsafe restore api-server → downloading bundle from user-owned storage... → decrypting with nonce-unique AEAD (AES-256-GCM)... → saving current state as "pre-restore" checkpoint... → unbundling git objects... ✓ restored api-server (247 objects, 18.3 MB) ✓ drift: 0 files (perfect roundtrip)
The drift check at the end compares every file in the restored repo against the original snapshot. A perfect roundtrip means 0 files changed. This proves that the backup, encryption, storage, download, decryption, and unbundle cycle preserved every byte.
Restore to a new directory
Use --target to stream the restore into a fresh directory. This is useful when you want to compare the backup against your current working tree, or when you need to recover without disturbing your current state.
$ devsafe restore api-server --target ~/recovered/api-server → creating ~/recovered/api-server... → downloading bundle from user-owned storage... → decrypting with nonce-unique AEAD (AES-256-GCM)... → streaming single-pass restore... ✓ restored to ~/recovered/api-server (247 objects, 18.3 MB) ✓ drift: 0 files (perfect roundtrip)
The --target flag performs a single-pass restore. DevSafe streams the decrypted bundle directly into the new directory without writing any temporary files to disk.
Restore a single file
If you only need one file back (say you accidentally deleted or overwrote it), use --file to restore just that file from the latest backup.
$ devsafe restore api-server --file src/config/database.go → locating src/config/database.go in latest snapshot... → decrypting bundle... ✓ restored src/config/database.go (2.1 KB)
You can combine --file with --to to pull a specific file from a specific point in time.
Restore to a specific time
The --to flag lets you roll back to any snapshot. DevSafe finds the closest snapshot at or before the time you specify.
Relative time
$ devsafe restore api-server --to "1h ago" → resolving snapshot at 13:23:08... → saving current state as "pre-restore" checkpoint... → decrypting with nonce-unique AEAD (AES-256-GCM)... ✓ restored to snapshot from 13:23:08 (12 files changed, 0 conflicts) ✓ drift: 0 files (perfect roundtrip)
Absolute timestamp
$ devsafe restore api-server --to "2026-04-29 14:00" → resolving snapshot at 2026-04-29 14:00:00... → found snapshot from 2026-04-29 13:58:42 (closest match) → saving current state as "pre-restore" checkpoint... → decrypting with nonce-unique AEAD (AES-256-GCM)... ✓ restored to snapshot from 2026-04-29 13:58:42 ✓ drift: 0 files (perfect roundtrip)
If no snapshot exists at or before the requested time, DevSafe will tell you and show the earliest available snapshot.
The drift check
Every restore ends with a drift check. DevSafe compares the restored files byte-for-byte against the original snapshot metadata. This is how you know the entire cycle worked: backup, nonce-unique AEAD encryption, upload to user-owned storage, download, decryption, and unbundle.
- 0 files changed means a perfect roundtrip. Every byte survived the full cycle.
- N files changed means something in your working tree has changed since the snapshot was taken. DevSafe lists each changed file so you can inspect the difference.
# Perfect roundtrip ✓ drift: 0 files (perfect roundtrip) # Working tree had local changes since the snapshot ✓ drift: 3 files changed since snapshot modified src/main.go modified go.sum added src/config/new.go
Drift means files have changed since the snapshot, not that the restore failed. If you restore to "1h ago" and then kept working, the drift shows what you changed in that hour.
Combined examples
# Restore a single file from 2 hours ago $ devsafe restore api-server --file src/main.go --to "2h ago" # Restore to a new directory from a specific date $ devsafe restore api-server --target ~/compare/api-old --to "2026-04-29 14:00" # Preview what would be restored without changing anything $ devsafe restore api-server --dry-run --to "1h ago"