Post-Mac-Setup: One Script to Bootstrap a New Mac

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.

April 4, 20264 min read

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-SetupMIT

Quick Start

Bash
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.

What It Installs

CLI Tools

The script installs everything I need for hardware design, software development, and general productivity:

CategoryPackages
Shellsbash, zsh
Version Controlgit, git-lfs, gh
Languagespython@3, uv, node, pnpm, r, gcc, go, rustup
EDA / Hardwareicarus-verilog, yosys, verilator, verible, surfer, graphviz
File Navigationeza, fd, fzf, zoxide, tree
File Inspectionbat, ripgrep, jq, coreutils
System Monitoringhtop, bottom, dust
Benchmarkinghyperfine, difftastic
Networkingwget, curl
Referencetldr
Build Toolscmake, llvm, pandoc
Homebrew TUIbbrew

GUI Apps

CategoryApps
Editors & IDEsVS Code, CotEditor
GitGitHub Desktop
AIClaude
ProductivityMicrosoft Office, Setapp, Google Drive
LaTeXMacTeX, Texifier
ResearchZotero, Inkscape
TerminaliTerm2
NetworkingTailscale, 1Password, 1Password CLI
Browser & MessagingUlaa, WhatsApp
Window ManagementAltTab, Rectangle Pro
Menu BarBlip
FontsMesloLG 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: eza as ls, bat as cat, fd as find, dust as du, btm as top, difft as diff, plus git shortcuts
  • Config files: ~/.zshrc, ~/.zsh_paths, ~/.zsh_aliases (cleanly separated)

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:

Bash
### 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 for Flexibility

Bash
# See what would happen without making changes
./mac-setup.sh --dry-run
# Install only CLI tools (no GUI apps)
./mac-setup.sh --skip-casks
# Skip CLI tools, install only casks
./mac-setup.sh --skip-formulae
# Minimal run — just packages, no shell or macOS config
./mac-setup.sh --skip-shell --skip-macos
# Suppress log file output
./mac-setup.sh --no-log

How It Works

  1. Preflight — verifies internet connectivity, installs Xcode Command Line Tools and Homebrew
  2. Install — taps third-party repos, installs formulae, casks, and npm globals
  3. Configure — sets up shells in /etc/shells, configures Git, initializes Rust, fzf, and MacTeX
  4. Shell Config — writes config files using marker-based block injection
  5. macOS Defaults — applies .DS_Store prevention on network and USB volumes
  6. Cleanup — runs brew cleanup and exports a Brewfile snapshot

Post-Install

A few things still need manual steps after the script finishes:

  1. Restart your terminal (or exec zsh)
  2. Run p10k configure to set up the Powerlevel10k prompt
  3. Set iTerm2 font to MesloLGS Nerd Font (Preferences > Profiles > Text > Font)
  4. Verify Homebrew versions: which git, which python3, which zsh
  5. 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.

Try It

Clone it, swap in your own packages, and never manually set up a Mac again:

Bash
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
macosautomationbashtoolsproductivity
Was this helpful?