Post-Mac-Setup: One Script to Bootstrap a New Mac
April 4, 2026·4 min read
An idempotent Bash script that bootstraps a complete macOS development environment — Homebrew, CLI tools, GUI apps, Oh My Zsh, and shell config from a fresh install.
Every time I set up a new Mac — or nuke and reinstall — I go through the same tedious ritual: install Homebrew, then brew install fifty packages one by one, download apps, configure the shell, set defaults. It takes hours and I always forget something.
So I wrote a single Bash script that does everything. One command, one file, fully idempotent.
Post-Mac-SetupMIT01. Quick Start
| chmod +x mac-setup.sh && ./mac-setup.sh |
Rerunning is safe — Homebrew skips already-installed packages, and shell configs are updated in-place using marker-based injection.
02. What It Installs
CLI Tools
The script installs everything I need for hardware design, software development, and general productivity:
| Category | Packages |
|---|---|
| Shells | bash, zsh (updated, replacing macOS system versions) |
| Version Control | git, git-lfs, gh |
| Languages | python@3, node, pnpm, r, gcc, go, rustup, uv |
| EDA / Hardware | icarus-verilog, yosys, verilator, verible, surfer, graphviz |
| Terminal Utilities | bat, eza, fd, fzf, ripgrep, zoxide, jq, tree, htop, tldr, dust, bottom, hyperfine, difftastic, coreutils, wget, curl |
| Build Tools | cmake, llvm, pandoc |
| Homebrew TUI | bbrew |
GUI Apps
| Category | Apps |
|---|---|
| Editors & IDEs | VS Code, CotEditor |
| Git | GitHub Desktop |
| AI | Claude |
| Productivity | Microsoft Office, Setapp, Google Drive |
| LaTeX | MacTeX, Texifier |
| Research | Zotero, Inkscape |
| Terminal | iTerm2 |
| Networking | Tailscale, 1Password, 1Password CLI |
| Browser & Messaging | Ulaa, WhatsApp |
| Window Management | AltTab, Rectangle Pro |
| Menu Bar | Blip |
| Fonts | MesloLG Nerd Font, JetBrains Mono Nerd Font |
Shell Environment
The script sets up Oh My Zsh with Powerlevel10k and configures:
- Plugins: zsh-autosuggestions, zsh-syntax-highlighting, zsh-completions, fzf
- Aliases:
ezaasls,batascat,fdasfind,dustasdu,btmastop,difftasdiff, plus git shortcuts - Config files:
~/.zshrc,~/.zsh_paths,~/.zsh_aliases(cleanly separated)
03. Design Decisions
Why a Single File?
No framework, no dotfile manager, no symlinks. Just one Bash script you can curl and run. The tradeoff is less modularity — but for a personal setup script, simplicity wins.
Marker-Based Injection
This is the part I'm most proud of. Shell config blocks are wrapped in markers:
| ### BEGIN BLOCK-ID (managed by mac-setup.sh — do not edit) | |
| # ... managed content ... | |
| ### END BLOCK-ID |
Anything you add outside these markers is preserved across reruns. This means you can customize your .zshrc freely and still rerun the script without losing your changes. It's idempotent in the truest sense.
CLI Flags
| --help, -h Show usage | |
| --dry-run Preview what would be installed (no changes made) | |
| --skip-casks Skip GUI app installation | |
| --skip-formulae Skip CLI tool installation | |
| --skip-macos Skip macOS .DS_Store defaults | |
| --skip-shell Skip shell configuration (.zshrc, etc.) | |
| --no-log Don't save output to a log file |
Examples:
| # See what would happen without making changes | |
| ./mac-setup.sh --dry-run | |
| # Install only CLI tools (no GUI apps) | |
| ./mac-setup.sh --skip-casks | |
| # Minimal run — just packages, no shell or macOS config | |
| ./mac-setup.sh --skip-shell --skip-macos |
04. How It Works
- Preflight — verifies internet connectivity, installs Xcode Command Line Tools and Homebrew
- Install — taps third-party repos, installs formulae, casks, and npm globals
- Configure — sets up shells in
/etc/shells, configures Git, initializes Rust, fzf, and MacTeX - Shell Config — writes
~/.zsh_paths,~/.zsh_aliases, and~/.zshrcusing marker-based block injection that preserves your own additions between runs - macOS Defaults — applies
.DS_Storeprevention on network and USB volumes - Cleanup — runs
brew cleanupand exports aBrewfilesnapshot
05. Post-Install
A few things still need manual steps after the script finishes:
- Restart your terminal (or
exec zsh) - Run
p10k configureto set up the Powerlevel10k prompt - Set iTerm2 font to MesloLGS Nerd Font (Preferences > Profiles > Text > Font)
- Verify Homebrew versions:
which git,which python3,which zsh - Sign in to apps: 1Password, Setapp, Tailscale, GitHub Desktop
Could these be automated too? Maybe. But they require GUI interaction or credentials, so I'm fine leaving them manual.
06. Try It
Clone it, swap in your own packages, and never manually set up a Mac again:
| git clone https://github.com/anirbanchakraborty-dev/Post-Mac-Setup.git | |
| cd Post-Mac-Setup | |
| ./mac-setup.sh --dry-run # preview first | |
| ./mac-setup.sh # full install |