Homebrew and asdf

Image of Author
March 10, 2022 (last updated September 21, 2022)

Homebrew, aka brew, is the "missing package manager for macOS". asdf is a version manager that lets you "manage multiple runtime versions with a single CLI tool".

Which manager do I use?

If you need to manage multiple versions of a tool, use the version manager asdf. For everything else, there's mastercard brew.

Unnecessary shims are not ideal

asdf works by prepending your path with a shims folder ~/.asdf/shims/ which contains lightweight scripts that determine (at runtime) which version of an executable to point to.

which node
# -> ~/.asdf/shims/node
asdf which node
# -> ~/.asdf/installs/nodejs/[version]/bin/node

This shims strategy makes version management easy. But, if you don't want to manage multiple versions of a tool, and simply want the most up-to-date version of a tool at any given time, use brew. Brew will symlink a tool to a common path location /usr/local/bin/, and when you upgrade a brew package/tool, it will remove the old version, and re-symlink the new version, ensuring you always get direct access to the tool (through a symlink, so maybe not theoretically direct, but definitely more direct than asdf).

which rg
# -> /usr/local/bin/rg
ls -l
# -> ... /usr/local/bin/rg -> ../Cellar/ripgrep/[version]/bin/rg

Shims impact performance

There's a script sitting in front of the call to your executable. Every time you call your executable, you wait for the script to find it. A developer prioritizing performance might find this untenable. The workaround is using direnv and asdf together. This allows you to point to the version directly. It's a great solution, but no shims to begin with might be even better (aka, use brew).

Edge Cases


Direnv is, in principle, as system tool. So, in principle, you should use brew to manage it. But, as we just saw, you might want to manage it with asdf to reap the performance benefits of using it in conjunction with asdf.

Postgresql and other database tools

This might only apply to web devs, but a lot of times languages and frameworks will go out of their way to be database-tooling agnostic. Even when I write sql by hand I go out of my way to be database-tooling agnostic. The upside is you almost don't care about the version of your database. But, painful is the day/week/month you discover a production bug resultant from mismatching database versions in your different environments. You also might want to explore the edges of your database tooling for feature work. For these reason, I think versioning your database is worth it. But, I can understand the desire not to. I personally use postgres on many of my projects, and go to the hassle of using asdf to manage it (I say hassle because, in my opinion, its easier with brew).