Moving to a new machine
This is the end-to-end guide: everything you do on the old machine before you wipe it or hand it back, and everything you do on the new one to get your setup back.
There are three ways to carry your setup. Pick one:
| Way | Best when | What you need |
|---|---|---|
| One encrypted file (recommended) | You are moving once, from one machine to another | A USB drive, cloud storage, or any way to copy one file |
| Private GitHub repo | You want every machine backed up somewhere you can reach from anywhere | A GitHub account |
| chezmoi repo | You already use, or want, chezmoi to keep machines in sync | chezmoi, an age key, a private git repo |
The first two carry the same backup: your config, your credentials, the list of apps you had, and your macOS settings. The chezmoi way carries config files and an install script, but not macOS settings.
dothaven with no arguments. The first group, Moving to a new Mac (“machine” on Linux), walks through the same five steps as Way 1. Its Pack everything into one encrypted file entry does all of the old-machine part in one go, and checks that the file opens before you wipe anything. See Interactive mode.Way 1: one encrypted file
On the old machine
Check that nothing exists only here
dothaven readyConfig can be rebuilt. Uncommitted changes, unpushed commits and stashes cannot, and neither can the .env file a fresh git clone will not bring back. ready looks through your home folder (up to 5 folders deep) for git repositories and reports:
- repositories with no remote at all: every commit in them exists only on this machine;
- repositories with uncommitted files, commits on no remote, or stashes;
- gitignored files a clone won’t bring back:
.envfiles, keys and keystores, cloud credentials, Terraform state; - how old your newest backup is.
1 repository with no remote. These exist ONLY on this machine:
✗ ~/code/prototype 12 commits, 1 file uncommitted
1 repository with gitignored files a fresh clone won't bring back:
⚠ ~/code/api .env
✗ Not safe to wipe yet: 2 repositories hold work that exists nowhere else.Fix what it lists: add a remote and push, commit and push (a stash is not pushed by pushing a branch), and copy ignored files you need. For a gitignored file you want in your backup, dothaven include ~/code/api/.env carries it in the encrypted backup.
Nothing is fetched, so ready is fast and works offline, but it judges “pushed” against the remote state git last saw. It exits with code 2 while anything is at risk, or when you have no backup newer than 7 days.
Catch config dothaven does not know about
dothaven include --listThis lists files and folders in your home folder that look like config but are in no backup. Add the ones you want:
dothaven include ~/.config/raycast ~/binYou can skip this step: on a terminal, backup offers these paths once anyway.
Make the encrypted backup
Write it straight to where it needs to end up, such as a USB drive:
dothaven backup --encrypt -o /Volumes/MyDriveOn a terminal it first shows the category picker with everything selected (press Enter to keep it that way) and offers any config nothing covers yet. Then it asks for a passphrase twice (at least 10 characters). You will need it on the new machine, and nothing can open the file without it, so put it in your password manager now.
The result is one file, backup-<host>-<timestamp>.tar.gz.age, holding:
- every config file dothaven tracks, plus your includes;
- your credentials:
~/.sshkeys, cloud logins, tokens, GnuPG keys; - the list of installed apps and packages, with a script to reinstall them;
- your macOS settings: trackpad, keyboard, Finder, hot corners, keyboard shortcuts and layouts, language order, and the apps in your Dock.
✓ Encrypted backup saved: 194 files, 3.1 MB
/Volumes/MyDrive/backup-mymac-20260927232938.tar.gz.age
ai (58), cloud (6), editor (97), git (9), npm (1), shell (14), ssh (5), terminal (4)
+ installed apps & packages list, 214 macOS settings
Next:
Copy this file off this machine: to a USB drive, cloud storage or another computer.
It lives on the disk you are about to replace.
On the new machine: dothaven restore backup-mymac-20260927232938.tar.gz.age
You will need the passphrase. Nothing can open this file without it.Why this is safe to carry: the file is encrypted as it is written. Your keys and tokens never touch the disk in plaintext, not even as a temporary file. It is a standard age file, so age -d can also open it; dothaven itself needs nothing extra installed.
DOTHAVEN_PASSPHRASE instead of typing it. It must also be at least 10 characters. The prompt is the default because an environment variable is visible to every program the shell starts.Get the file off the machine, and check it opens
If you did not write it to a drive, copy it to one, or to cloud storage, or to another computer. Then prove it opens with your passphrase without changing anything:
dothaven restore --dry-run /Volumes/MyDrive/backup-mymac-20260927232938.tar.gz.ageIt asks for the passphrase and lists what it would restore. (The menu’s Pack everything flow does this check for you.)
On the new machine
Install dothaven
On a fresh Mac, the installer script is quickest. It does not need Homebrew:
curl -fsSL https://raw.githubusercontent.com/doguyilmaz/dothaven/main/scripts/install.sh | shSee Installation for other ways.
Put your files back
Plug in the drive, then:
dothaven restoreWith no path on a terminal, restore looks for backups in ~/.local/share/dothaven, the current folder, Downloads, Desktop, Documents and mounted drives, and lets you pick one (or type a path). You can also name the file:
dothaven restore /Volumes/MyDrive/backup-mymac-20260927232938.tar.gz.ageIt asks for the passphrase (three tries on a terminal), then asks what to restore:
What should be restored?
Already-applied files are not listed again.
> Everything new or updated (194)
Choose categories e.g. only ai, shell and git
Choose files type / to filter
Show me the list first
CancelOn a new machine almost everything is new, so the first choice is usually right. If a file already exists and differs (say, a default .zshrc), you are asked about it on its own, with a diff, and whatever you replace is saved to a pre-restore-<timestamp> folder first. Details are in Backup & restore.
Put your macOS settings back
When the restore finishes on a Mac, it offers:
Also put back your macOS settings (trackpad, keyboard, Dock, Finder)?Say yes, or do it later with dothaven defaults import <file>. Settings already set on this Mac are shown as done, not offered again. The Dock is rebuilt from the apps installed here, so it is worth doing again after the next step.
Reinstall your apps and packages
The restore then offers to reinstall. You can also run it yourself:
dothaven reinstall /Volumes/MyDrive/backup-mymac-20260927232938.tar.gz.ageIt compares the backup’s list with this machine, shows what is already installed, and installs only what is missing: everything, some groups, or packages you pick. It runs attached to your terminal with no time limit, so Homebrew and sudo can ask for your password and a long brew bundle is not cut off.
On a fresh Mac, install Homebrew first. If brew is missing, reinstall warns you, skips the Homebrew part, and prints the official install command:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"Then run dothaven reinstall again. Each step skips itself if its tool is missing, so running it twice is safe.
Check what is still missing
dothaven missing /Volumes/MyDrive/backup-mymac-20260927232938.tar.gz.ageThis lists what the old machine had installed that this one does not, grouped by package manager, with the command that installs each group:
Missing on this machine:
npm globals (2)
typescript@5.6.2, @biomejs/biome@1.9.4
fix: npm install -g typescript @biomejs/biome
2 items missing across 1 group.
Install them (all, or the ones you pick): dothaven reinstall /Volumes/MyDrive/backup-….tar.gz.ageIt matches on names, not versions. It exits with code 1 while anything is missing, and prints ✓ Nothing missing when you are done.
Sign back in to things
Some things cannot be copied and need you: see What does not travel below.
Way 2: a private GitHub repo
Instead of a file, keep the backup in a private repository on your GitHub account. No git is needed on either machine.
On the old machine:
dothaven ready # same check as above
dothaven github login # once per machine
dothaven github push # creates <you>/dothaven-backup (private) the first timepush makes the same backup as backup --encrypt and commits it to machines/<this machine>/ in the repo. It is encrypted by default. Other modes keep config readable on GitHub; see GitHub sync.
On the new machine:
dothaven github login
dothaven restore githubIf the repo holds several machines, it asks which one (or pass dothaven github pull --machine <name>). From there it is the same as Way 1: pick what to restore, then settings, reinstall and missing. Those commands accept github in place of a file, too:
dothaven reinstall github
dothaven missing githubWay 3: a chezmoi repo
If you want chezmoi to own your dotfiles and keep machines in sync, dothaven can hand them over. This path needs chezmoi and an age key set up for chezmoi, and it does not carry macOS settings.
On the old machine:
dothaven init # checks chezmoi, the age key and the source repo; prints what to fix
dothaven chezmoi-export # shows what would be added and encrypted, then asks
dothaven chezmoi-export --apply # adds the files to your chezmoi source
chezmoi cd # then commit and push the source repo (keep it private)chezmoi-export adds files one by one. Files with a secret in them are added encrypted; config that names your home folder is added as a template so it works under a different username. It also writes an install script that chezmoi runs on the new machine to reinstall your packages.
On the new machine, put your age key back first (for example at ~/.config/chezmoi/key.txt), then:
chezmoi init <your-private-repo>
dothaven migrate # checks the prerequisites, then runs chezmoi applyDetails are on Encryption & chezmoi.
What does not travel
dothaven leaves these out on purpose. Deal with them by hand:
- Data. Databases, Docker volumes, anything a local service stores. Dump and copy what you need. (
dothaven services exportcarries the config of Homebrew services such as nginx and MySQL, not their data.) - System config outside your home folder, such as
/etc/hosts. - Keychain items: code-signing certificates, provisioning profiles, saved passwords. Re-import or re-download them.
- Sign-ins: browser sync, the App Store, licensed apps, anything behind two-factor login. (CLI logins in files, such as
~/.awsorgh, do travel in an encrypted backup.) - Large downloads: Ollama models, simulator runtimes, Android emulators. The inventory records their names; pull them again.
- Project-level config (a repo’s
.claude/,.mcp.json,.vscode/). It travels with the project’s own repository. Make sure it is pushed (dothaven ready). - Unsaved work: save and quit your editors before the final backup. A backup carries files on disk, not open buffers.
If something goes wrong
- Wrong passphrase: dothaven cannot recover it, and neither can anyone else. Try the one in your password manager.
- A redacted file was not restored: it came from a plain backup, which masks secret values. Restore from an encrypted backup instead.
- Anything else: run
dothaven doctor, then see Doctor & troubleshooting.