Stop Reinstalling Tools by Hand with Homebrew Brewfile
Declare macOS and Linux developer tools in a Brewfile and install them reproducibly with brew bundle, plus verification steps and limitations.
25 Dec 2025, 22:03 UTC

The problem: setup drift on every new machine
When you get a new Mac or rebuild a Linux workstation, reinstalling developer tools by hand is easy to get wrong. You might forget a formula, install a cask with the wrong options, or end up with different versions on your laptop and desktop. Homebrew's brew bundle command reads a Brewfile—a plain text file that declares the packages, casks, and Mac App Store apps you want—so you can install the same environment repeatedly instead of remembering each command.
What goes in a Brewfile
A Brewfile is evaluated as Ruby by Homebrew. Common directives include:
tap— adds a Homebrew repository tap before installing from it.brew— installs a formula, which is command-line software.cask— installs a macOS application distributed as a cask.mas— installs a Mac App Store app by its identifier.
You can pin versions with brew "package", version: "1.2.3" and separate macOS-only casks from Linux formulae with conditionals such as if OS.mac?. Directive support varies by Homebrew release, so run brew help bundle before adopting new syntax.
Worked example: declare and install without surprises
Create a file named Brewfile in your dotfiles repository or project folder:
tap "homebrew/bundle"
brew "git"
brew "ripgrep"
brew "fd"
cask "visual-studio-code"
cask "orbstack"
# mas "1480933944" # Example: Xcode, requires signed-in Apple ID
Run this in your terminal where Homebrew is installed. Formulae do not require sudo, but casks on macOS may ask for administrator authentication or user interaction during installation.
brew bundle --file=./Brewfile --no-upgrade
The --no-upgrade flag installs anything missing but leaves already-installed packages at their current versions. This is safer for workstations than brew bundle upgrade, which can update packages unexpectedly.
Afterward, verify what changed:
brew list --formula
brew list --cask
If a mas entry is included, it will fail in headless CI or on a Mac where you are not signed into the Mac App Store. Remove or comment out Mac App Store lines for automated environments.
Capture an existing workstation safely
To see what brew bundle dump would record without changing your system, write to a temporary directory:
brew bundle dump --force --file=./tmp/Brewfile.dump
Inspect the output before moving it into your dotfiles. It may list casks or formulae you no longer want, so edit the file rather than committing it blindly.
Limitations and practical checks
- No single undo.
brew bundle installchanges system state. Review with--no-upgradefirst, and uninstall unwanted packages individually if needed. - Cask interaction. Some casks require
sudoor a GUI dialog, which breaks fully automated provisioning. - Version drift. Brewfile syntax can change between Homebrew releases. Check
brew --versionandbrew help bundleon each machine. - Mac App Store.
masneeds a signed-in Apple ID and does not work in headless CI.
Practical check: run brew bundle --file=./Brewfile --no-upgrade in a scratch directory, then compare brew list before and after. If the output matches your intent, commit the Brewfile to your dotfiles repository.
Closing
A Brewfile turns workstation setup from memory work into a declarative file you can version, review, and reuse. Start with one file, test it with --no-upgrade, and add packages as your environment evolves.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.