Managed with chezmoi. Covers Homebrew packages, shell config, macOS defaults, Dock, and editor extensions (VS Code + Cursor).
sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply ffrizzo/dotfilesThis installs chezmoi, clones this repo, and applies everything: Xcode CLI tools, Homebrew plus every package in Brewfile, zinit (zsh plugin manager), macOS system/user defaults, fonts, browser extension stubs, Dock layout, and VS Code/Cursor extensions. See .chezmoiscripts/ for exactly what runs and in what order.
A couple of things chezmoi apply can't do for you, run once afterward:
rustup default stable— finishes the Rust toolchain setup.mise install— installs the Terraform versions pinned indot_config/mise/config.toml- Browser bookmarks and other home-only state — back them up and restore them with
home-state.shbelow.chezmoi applyinstalls that script as~/scripts/home-state.sh.
chezmoi edit ~/.zshrc— edit a managed file (opens the source file, e.g.dot_zshrc).chezmoi diff— preview whatchezmoi applywould change before changing anything.chezmoi apply— apply the source state to$HOME.chezmoi re-add— pull a file you edited directly (e.g.~/.zshrc) back into the source state, so it's ready to commit.chezmoi cd— cd into the source directory to commit/push changes.
chezmoi apply can reinstall packages and rewrite dotfiles. It cannot recreate browser bookmarks or anything else that only exists under your home directory. scripts/home-state.manifest lists those paths. Add a file or dir line there for anything else you want carried to a new machine.
# From this repo, or ~/scripts/home-state.sh after chezmoi apply:
scripts/executable_home-state.sh backup /Volumes/Backup/home-state
scripts/executable_home-state.sh restore /Volumes/Backup/home-statebackup replaces the snapshot in that folder. Pass a different folder to keep an older copy. Quit the apps before restore. Firefox stores bookmarks in places.sqlite, which also contains browsing history, so that file is part of the snapshot. Reading Safari bookmarks needs Full Disk Access for the terminal app running the script.
VS Code and Cursor settings.json, keybindings.json, and extensions already come back from chezmoi apply. The manifest adds the configs that do not: MCP servers, Cursor launch flags and CLI preferences, Claude Code settings, and the Claude desktop MCP config. Sign in to Claude again on the new Mac. The login files also contain a machine id, so they are left out.
Brewfile— Homebrew formulae, casks, and VS Code extensions, installed viabrew bundle..chezmoiscripts/— install/setup scripts, run in order bychezmoi apply(numeric prefix = order;run_once_= once ever per machine;run_onchange_= re-runs when its own rendered content changes, e.g. the Brewfile install and Cursor extension scripts re-run wheneverBrewfilechanges). macOS defaults and the Dock layout re-run when the macOS version changes.dot_*— dotfiles, applied to$HOME(e.g.dot_zshrc→~/.zshrc;dot_config/mise/config.toml→~/.config/mise/config.toml;dot_warp/settings.toml→~/.warp/settings.toml).Library/— editor settings applied under~/Library(VS Code and Cursor). Warp's preference plist and iTerm2 are unmanaged.fonts/— bundled fonts, installed by.chezmoiscripts/run_once_after_23-fonts.sh.tmpl.scripts/—executable_home-state.shandhome-state.manifest.chezmoi applyinstalls them as~/scripts/home-state.shand~/scripts/home-state.manifest.
After editing Brewfile, run brew bundle check --verbose --no-upgrade --file=Brewfile locally to catch renamed/removed formulas and casks before committing — CI only checks that the file parses, not that every entry still resolves (see the comment in run_onchange_before_10-packages.sh.tmpl for why).