Posted on · 2 min to read · 369 words

If you are switching from Linux to a Mac you might be confused that there is no default package manager on macOS. The de facto default is homebrew, at least that is what I and most people I know are using (there still exists some alternatives like macports to name one). You can use brew more or less like any package manager on Linux like apt or pacman. It supports installing programs via brew install jj and removing them again with brew uninstall jj.

But I stumbled upon the interesting concept of managing all external packages in a single file called Brewfile, by reading the excellent post from Matthias. Please head over to his blog, because he documented the approach perfectly. To me this sounds like a perfect way to have most external programs and dependencies stored at a single place and to actually know which external dependencies I got on my system.

All the commands to manage your single file with all external programs and dependencies in it are available via brew bundle.

I see the following advantages:

  1. I can install and update all my programs with a single command.
  2. I can try out programs without adding them permanently to my system. Even if I forget to remove them, the next update/install will remove them again.
  3. I can easily distribute my favorite apps via my dotfiles between machines.

My setup is mostly matching what Matthias wrote on his blog post. I have a single command called buu, which is my legacy command to call brew update && brew upgrade, which now calls brew bundle. This is my fish alias for it:

alias buu="brew update &&\
    brew bundle install --cleanup --file=~/.config/Brewfile &&\
    brew upgrade"

The --cleanup flag will remove all other packages that were installed via brew, which are not in the Brewfile.

An example for a very simple Brewfile:

brew "jq"

# basic unix tools
brew "fish"
brew "stow"

# devtools
cask "visual-studio-code"
brew "neovim"
cask "ghostty"
cask "eurkey"
brew "fzf"
brew "go"
brew "jj"

# macos tools
cask "stats"
cask "alt-tab"

# apps
cask "obsidian"
cask "firefox"
cask "thunderbird"
brew "syncthing"

As you can see it is still possible to install both, casks and normal non GUI tools with the Brewfile. Furthermore, it is also possible to use taps by just declaring the tap in the Brewfile.

So far this setup is very convenient to use, and I like the more declarative approach to manage the software on my Macs.