Brewfile + mas-cli: reproducing your Mac’s app environment on a fresh install in 20 minutes

You’re getting a new Mac. Or your old one is going in for a battery replacement and you want a clean slate. Either way, the next two days are going to be a chore: install Chrome, install 1Password, install Slack, install Spotify, install Rectangle, install… 50 things, mostly by clicking through Cmd+Spaces and pkg installers, half of them needing licenses you have to dig out of email. Then the Mac App Store apps, which can’t be installed by Homebrew. Then the dev tools: brew install everything you remember, and accept that you’ll discover three more things you needed by month two.

Or: you have a Brewfile in your dotfiles repo, plus mas-cli for the App Store apps, and your fresh Mac is fully provisioned in 20 minutes while you make coffee. Here’s how that works in 2026.

What Brewfile is

A Brewfile is a plain-text declaration of every brew formula, cask, tap, and Mac App Store app you want installed. It’s the equivalent of requirements.txt for your Mac. The brew bundle command (built into Homebrew) reads it and installs everything that’s missing.

# ~/dotfiles/Brewfile
tap "homebrew/cask-fonts"

# Command-line tools
brew "git"
brew "tmux"
brew "neovim"
brew "fzf"
brew "ripgrep"
brew "bat"
brew "eza"
brew "jq"
brew "yq"
brew "wget"
brew "htop"
brew "mas"           # for Mac App Store apps below

# GUI apps via Homebrew Cask
cask "iterm2"
cask "1password"
cask "raycast"       # better Spotlight replacement
cask "rectangle"     # window snapping
cask "vlc"
cask "firefox"
cask "google-chrome"
cask "slack"
cask "spotify"
cask "the-unarchiver"
cask "alfred"
cask "discord"
cask "zoom"
cask "visual-studio-code"
cask "docker"
cask "obs"

# Fonts
cask "font-jetbrains-mono"
cask "font-fira-code"

# Mac App Store apps (need to be signed in to App Store first)
mas "Xcode", id: 497799835
mas "Things 3", id: 904280696
mas "Keynote", id: 409183694
mas "Pages",   id: 409201541
mas "Numbers", id: 409203825

Find the App Store IDs with mas search "Things 3" — the first column is the ID. Build the Brewfile up over time as you install things. After three months, you have a complete record of your Mac’s app environment.

Generating the Brewfile from your existing Mac

If you already have a Mac you’ve used for a while, generate the initial Brewfile in one command:

brew bundle dump --file=~/dotfiles/Brewfile --force --describe
# --force overwrites existing Brewfile
# --describe adds a comment per line with the package's description

This walks all currently-installed Homebrew formulae and casks, plus your installed Mac App Store apps (if mas is installed), and writes the Brewfile that would re-create your current state.

Important caveat: brew bundle dump includes everything currently installed, including transitive dependencies. The first time you run it, you might want to prune the list manually — only keep the packages you actually use, and let Homebrew pull dependencies. Otherwise the Brewfile becomes 200 lines and a chore to read.

The fresh-Mac install in 20 minutes

Fresh Mac. You’ve signed in with your Apple ID. The Mac App Store is logged in. Open Terminal:

# 1. Install Homebrew (this takes ~3 minutes — it pulls Xcode CLT)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# 2. Source Homebrew so it's in PATH right now
eval "$(/opt/homebrew/bin/brew shellenv)"

# 3. Clone your dotfiles
git clone https://github.com/yourusername/dotfiles.git ~/dotfiles

# 4. Install everything from the Brewfile
brew bundle --file=~/dotfiles/Brewfile

# Goes for ~15 minutes:
# - Installs every brew formula (mostly fast)
# - Downloads every cask (the slow part — Chrome, Slack, Discord are 200+ MB each)
# - Asks for sudo password 1-2 times for installers that need it (Rectangle, Docker)
# - Auto-installs MAS apps (signs into MAS automatically if you're already logged in)

While that’s running, brew shows progress per package. You can leave it alone and come back. The total time is bandwidth-bound — on a fast connection ~15 minutes; on slow ~45.

Verifying it worked

# Check what's installed vs the Brewfile:
brew bundle check --file=~/dotfiles/Brewfile
# > The Brewfile's dependencies are satisfied.

# Or list any drift:
brew bundle list --file=~/dotfiles/Brewfile

Run this monthly to catch drift — you might have brew-installed something ad-hoc and forgotten to add it to the Brewfile, or removed something but left it in the file.

The bits Brewfile doesn’t handle

Some apps live outside both Homebrew and the App Store. For those, write a small bash bootstrap that runs after brew bundle:

  • Setapp / Adobe Creative Cloud / Microsoft 365. Subscription apps that need a vendor-specific installer with login. The bootstrap can open https://www.setapp.com/download to start the process; you finish it interactively.
  • Custom-licensed apps. Things like Sublime Merge, Sketch, Affinity Designer with a license file. The bootstrap can install via brew cask, then copy your license file from ~/dotfiles/private/licenses/ into the right Application Support directory.
  • Browser extensions. Chrome syncs them via your Google account. Firefox via Sync. Safari… has no sync, you re-install by hand.
  • App preferences. Brewfile installs apps; it doesn’t restore their settings. For settings, use Mackup (which symlinks app Plist files into your dotfiles repo) or just accept that some apps need manual re-config.

A few catches I learned the hard way

  • Sign in to the Mac App Store first. If you’re not signed in, mas install silently fails. Open the App Store app, sign in with your Apple ID, then run brew bundle.
  • Some casks need passwords mid-install. Docker, Rectangle, KeyboardCleanTool. The brew bundle pauses for the sudo prompt, but you might miss it; check periodically.
  • Don’t put work-secrets in the Brewfile. If your Brewfile is in a public dotfiles repo, the package list is fine, but don’t have lines like cask "internal-company-tool" that signal what your employer is. Keep work-only entries in a separate Brewfile.work that’s gitignored.
  • Apple Silicon vs Intel paths. Brew installs to /opt/homebrew/ on M-series Macs and /usr/local/ on Intel. The brew shellenv snippet handles this automatically. If you have hardcoded paths in your scripts, update them.

End-state: a fresh Mac is a checkout-and-run. Go-back-to-an-old-config in 20 minutes. The next time your Mac dies or you switch employers, the “set up the new one” tax is a coffee break instead of a lost weekend.

Photo: Clean MacBook desk setup with keyboard, mouse and AirPods by Jean Daniel on Pexels.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.