| Platform | |
| Stack | |
| Quality | |
| Meta |
From boxed Mac to working dev machine in one command. A phased, idempotent bootstrap script that installs your CLI tools, GUI apps, shell, prompt, terminal, editor, and macOS defaults — without leaking personal secrets or account state onto an employer-owned machine.
⭐ If this saved you a day, please star the repo — it helps other devs find it.
Why this kit?
- 🚀 One command, repeatable. Run
./bootstrap.sh, restart when prompted, rerun. Done. - 🧱 Phased & idempotent. Five clearly numbered phases with checkpoints; completed steps are skipped on rerun.
- 🔒 Secret-safe by default. SSH keys, npm tokens, browser profiles, and Keychain entries are explicitly not copied.
- 🧰 Curated, not bloated. A practical Brewfile of CLI + GUI tools real developers use, with personal apps cleanly separated.
- 🍎 Apple Silicon native. Built and tested on M-series Macs (M1 → M5); paths
to Homebrew (
/opt/homebrew) and miniforge are hardcoded.
On the new Mac, run the bootstrap once:
cd ~/new-mac-setup
./bootstrap.shThe bootstrap keeps step state in ./.state, so it is safe to rerun.
Completed steps are skipped.
Optionally override the hostname and Git identity when you run bootstrap:
MAC_HOSTNAME="your-mac-name" GIT_USER_NAME="Your Name" GIT_USER_EMAIL="you@example.com" ./bootstrap.shThe default hostname is mac-work. Git identity can also be set later:
git config --global user.name "Your Name"
git config --global user.email "you@example.com"The shell config honors an optional PERSONAL_MACOS_LIB environment variable.
If set to the absolute path of a directory containing personal executables,
that directory is prepended to PATH. Set it in ~/.zshenv or elsewhere in
your shell environment; leave it unset to no-op.
export PERSONAL_MACOS_LIB="$HOME/Dev/bin"The bootstrap runs in five phases. After each restart checkpoint, restart the
Mac and rerun ./bootstrap.sh. Completed steps are skipped.
Phase 1 — Hostname
- Sets the Mac
ComputerNameandLocalHostNamefromMAC_HOSTNAME, defaulting tomac-work. - Restart checkpoint.
Phase 2 — Xcode Command Line Tools
- Installs Xcode Command Line Tools if missing. If the installer is launched,
the script exits; finish the installer, then rerun
./bootstrap.sh. - Restart checkpoint.
Phase 3 — Shell and Homebrew
- Installs Oh My Zsh and custom plugins.
- Installs shell, Starship, and Ghostty configs.
- Installs Homebrew if missing.
- Restart checkpoint.
Phase 4 — Packages and system defaults
- Runs
brew bundleagainstBrewfile. - Configures Git LFS and line endings (and Git identity if
GIT_USER_NAME/GIT_USER_EMAILare set). - Applies macOS defaults.
- Restart checkpoint.
Phase 5 — Apps and finish
- Installs VS Code settings and extensions.
- Applies the Dock layout.
- Prints the manual checklist, including the canonical list of apps to open for first-run permissions and sign-in.
Existing config files are moved aside with a .backup.YYYYMMDDHHMMSS suffix
when their contents differ.
Useful state commands:
./bootstrap.sh --status
./bootstrap.sh --resetInstall personal apps by uncommenting entries at the bottom of Brewfile, then:
brew bundle --file BrewfileMirror additional macOS settings from an existing machine:
./settings-mirror/dump_current_settings.sh
./settings-mirror/compare_and_apply_settings.shThe canonical manual checklist (GitHub auth, SSH key, Node tooling, app
permissions, JetBrains setup, etc.) is printed by bootstrap.sh at the end of
phase 5. That output is the source of truth — rerun ./bootstrap.sh once all
phases are complete to print it again.
What this kit covers, and what it deliberately leaves to you.
Around 70–80% of a fresh Mac setup. Coverage by area:
| Area | Automation level | Notes |
|---|---|---|
| CLI tools and GUI apps | High | Brewfile installs work-appropriate defaults plus a personal/entertainment block; comment out anything that doesn't belong. |
| Shell and prompt | High | Installs Oh My Zsh, plugins, .zprofile, .zshrc, Starship and required fonts. |
| Ghostty config | High | Copies the current terminal config exactly. |
| Docker | Medium | App install and shell integration is automated; first launch, permissions, image/volume state are manual. |
| Node tooling | Low | Installs nvm through Homebrew only and provides the required defaults in .zshrc; Node versions and global packages are manual. |
| macOS defaults | Medium | Applies Finder, Dock, keyboard, screenshot, language, region, and timezone defaults. |
| Dock layout | Medium | Uses dockutil; only adds apps already installed. JetBrains IDEs are not pinned automatically; pin them manually after Toolbox installs them. |
| VS Code | High | Restores settings and extensions. |
| JetBrains IDEs | Low | Toolbox install is automated; IDE installs and account sync are usually interactive. |
| Raycast, Rectangle Pro, LuLu | Low | App install is automated; permissions, licenses, rules, and tokens need review. |
| Cloud storage | Low | Apps install automatically; account sign-in and folder hydration are manual. |
| Login items | Manual | Let each app create its own login/background item during first run or from its settings. |
| SSH, npm, browser profiles, Keychain secrets | Manual | Do not copy personal secrets blindly to an employer-owned Mac. |
| App Store apps | Manual | App Store app restore is not scripted. Install from AppStore after logging-in. |
Personal secrets and account-bound state — left to you on purpose:
~/.ssh/id_ed25519~/.npmrc~/.config/raycast/config.json- Personal Git identity from the old machine
- Browser profiles and saved sessions
- MacPass database location or passwords
- Docker images, containers, and volumes
- Personal Dropbox/Google Drive/Nextcloud state
- LuLu allow/block rules
- LinearMouse config
- Printer setup 😜