Interactive macOS backup and restore CLI
macback backs up and restores your entire macOS environment: files, configs, Homebrew packages, system metadata, and more. It runs in an interactive terminal UI with smart defaults that exclude caches, build artifacts, and iCloud clutter automatically. Built entirely in Bash, powered by rclone.
- 🎛️ Interactive TUI: arrow keys, vim bindings (
j/k),/filtering, andSpacemulti-select - 📦 Modular components: back up files, Homebrew, keychain metadata, launchd metadata, and system snapshots independently
- 🧠 Smart defaults: iCloud paths, caches,
node_modules, build artifacts, and other rebuildables are excluded automatically - 🔄 rclone-powered: reliable file transfer with progress reporting and integrity verification
- 🛡️ Destination guard: supervises
rcloneand pauses the backup if the selected volume disappears, remounts elsewhere, or no longer matches the original mount identity - 🔒 SHA256 checksums:
rclone checkverifies that backups are complete and correct - 📋 JSON manifests: spec versioning for structured metadata and forward compatibility
- ⏸️ Resume support: pick up interrupted backups without re-copying transferred files
- 🎯 Granular restore: choose which components, paths, and individual app configs to restore
- 🏥 Doctor command: diagnose and fix backup health, permissions, and integrity issues
- 🧪 Comprehensive tests: unit + integration + PTY coverage powered by BATS
- 🔐 Runs as root: full access to system files and Library data, with automatic user detection
| Component | Contents |
|---|---|
| Files | Projects, Documents, Desktop, Downloads, SSH keys, GPG keys, shell configs, dotfiles, Library preferences, Mail, Messages, LaunchAgents |
| Homebrew | Brewfile, formula/cask lists, taps, leaves, services. Everything needed to reconstruct your dev environment |
| Keychain metadata | Keychain discovery and locations (metadata only, no secrets exported) |
| Launchd metadata | User LaunchAgents and custom system LaunchDaemons/LaunchAgents |
| System snapshot | macOS version, machine serial, hostname, full application inventory |
macback skips things you can rebuild:
- ☁️ iCloud: Mobile Documents, CloudStorage, iCloud app support
- 🗑️ System caches:
.DS_Store, Library Caches/Logs/WebKit, Xcode DerivedData - 📦 Package caches:
node_modules,.pnpm-store,.yarn/cache,.bun/install/cache - 🔨 Build artifacts:
__pycache__,.pytest_cache,.gradle,target/,.terraform - 🔌 Socket files:
.gnupg/S.*,*.sock, agent sockets
All defaults are customizable through the interactive rules editor during backup.
- macOS (tested on macOS 13+)
- Bash 4+ (ships with macOS or install via Homebrew)
- rclone:
brew install rclone - Homebrew (optional, only needed for the Homebrew component)
git clone https://github.com/gastonmorixe/macback.git
cd macback
make bootstrap # checks for shellcheck and bats-coresudo bash ./macbackOpens the TUI main menu:
macback
macOS backup and restore
Mode Interactive
Primary user youruser
Primary home /Users/youruser
❯ Backup Create a new backup run
Restore Restore from an existing backup
Inspect View backup metadata and verification state
Doctor Check and fix backup health and permissions
Help Usage information
Quit Exit the tool
sudo bash ./macback backup # guided backup flow
sudo bash ./macback restore # guided restore flow
sudo bash ./macback inspect # inspect an existing backup
sudo bash ./macback doctor # check and fix backup health
sudo bash ./macback help # show usage information| Key | Action |
|---|---|
↑ / k |
Move up |
↓ / j |
Move down |
Enter |
Select / Confirm |
Space |
Toggle selection (multi-select) |
a |
Select all visible |
u |
Unselect all visible |
/ |
Filter / Search |
q |
Cancel / Back |
For local-disk backups, rclone only sees a filesystem path. It does not know that /Volumes/My Disk is supposed to remain bound to the same physical external drive for the entire run. Because of that, macback wraps the file-copy/check steps with a parallel destination guard.
- Before
rclonestarts, macback records the selected destination mount root, filesystem device id, and volume UUID when available. - While
rcloneruns, a watcher checks that identity every 2 seconds. - If the destination disappears or remounts under a different
/Volumes/...path, macback stopsrcloneand pauses the backup instead of trusting the stale pathname. - If the same volume UUID comes back under a new mount path, macback can offer to continue the same run on the remounted volume.
- Stale
/Volumes/...directories that are not real mounted volumes are rejected before a run is created or resumed. - File backups use
rclone --inplaceto avoid.partial -> finalrename failures on external filesystems. - Backup asks you to choose a speed profile:
Normal: safer defaults, fullrclone checkon new runsFast: more parallelism, skips the long post-copyrclone checkUltrafast: highest parallelism, skips full verification and compares by size only
- When you resume an existing backup run, macback always skips the full post-copy
rclone checkso the restart path focuses on copying what is still missing.
This is a strong supervisory guard, not a per-write guarantee. Writes already in flight when the destination changes may still complete or fail before the watcher stops rclone.
macback # main entrypoint
lib/
common.sh # environment detection, utilities, manifest discovery
ui.sh # terminal UI framework (colors, selectors, widgets)
templates.sh # backup rule template expansion (@HOME@ tokens)
filter.sh # rclone filter generation
destination.sh # destination volume selection, mount identity capture, remount lookup
manifest.sh # manifest creation, validation, integrity checks
components.sh # backup components plus the rclone destination watcher/pause flow
restore.sh # restore workflows, path remapping, permission reconciliation
templates/
include-paths.txt.template # default paths to back up
exclude-patterns.txt.template # default exclusion patterns
Backups are stored on the destination volume under macback/<machine-id>/<timestamp>/:
meta/
run.json # run metadata (timestamps, source info, versions)
manifest.json # component flags and restore defaults
include-paths.txt # resolved include rules
exclude-patterns.txt # resolved exclude patterns
integrity/ # SHA256 checksums and rclone verification results
components/
files/rootfs/ # filesystem backup (mirrored directory tree)
brew/ # Brewfile, formula/cask lists, taps
system/ # system facts, app inventory
keychain/ # keychain metadata
launchd/ # launchd plist inventory
make bootstrap # check dev dependencies (shellcheck, bats-core)
make lint # run shellcheck on all scripts
make test # run full BATS test suite (unit + integration)
make check # lint + testMIT. Gaston Morixe 2026
