One of the reasons I like macOS has to do with its Unix underpinnings. From the pre-installed Terminal application, I can efficiently perform administrative tasks, edit text files with Vim, connect to other systems via SSH, and so on and so forth. I admit there are times macOS almost feels like a BSD or a Linux system to me – but with a sleek GUI on top.

Of course, I very well know that macOS is neither BSD nor Linux. And the first time anyone comes to this rather obvious realization is when they find out there is no command line tool for managing applications.

Enter Homebrew. According to the slogan on the official site, Homebrew is the missing package manager for macOS (or Linux). And what does Homebrew do? This question is prominently asked on the front page of said site, and please let me copy here most of the given answers:

  • Homebrew installs the stuff you need that Apple (or your Linux system) didn’t.
  • Homebrew installs packages to their own directory and then symlinks their files into /usr/local.
  • Homebrew won’t install files outside its prefix and you can place a Homebrew installation wherever you like.
  • Trivially create your own Homebrew packages.
  • It’s all Git and Ruby underneath, so hack away with the knowledge that you can easily revert your modifications and merge upstream updates.
  • Homebrew formulae are simple Ruby scripts.
  • Homebrew complements macOS (or your Linux system). Install your RubyGems with gem and their dependencies with brew.

You do not have to know anything about Ruby or RubyGems to manage packages with Homebrew from your macOS Terminal. Provided you are a bit familiar with tools like apt, zypper or dnf, immediately after installing Homebrew, you can start using brew to refresh the local cache of available packages, search for and install any tool/application/library/programming language you want, upgrade packages to the latest versions available, or remove packages you do not need anymore.

Homebrew Formulae

Initially, I used brew exclusively for installing formulae. In Homebrew parlance, a formula is a Ruby script that tells brew how to install a specific package and any dependencies. For example, take a look at the first lines in the formula for Ansible (ansible.rb):

class Ansible < Formula
  include Language::Python::Virtualenv

  desc "Automate deployment, configuration, and upgrading"
  homepage "https://www.ansible.com/"
  url "https://files.pythonhosted.org/packages/81/75/5bd49b1a637461676a8cab3556dff77f74f7ab246b7ef0eda38b2b250a87/ansible-3.2.0.tar.gz"
  sha256 "01774d8b4778844f29920812f0dab7a90c8643e8f826460a941565b2620e5b7d"
  license "GPL-3.0-or-later"
  head "https://github.com/ansible/ansible.git", branch: "devel"

  bottle do
    sha256 cellar: :any, arm64_big_sur: "1a61774075d49088b9d17e5e9fbc1b2ad21a6ed5b366c42f24f15182ee6dc36e"
    sha256 cellar: :any, big_sur:       "822cc4694e6e5bc9856d5bdcfd58ce7714c7793c99938e897cb6cf49675742d8"
    sha256 cellar: :any, catalina:      "da7f620e5981f943d1f2bc28ab78d430b066e6320106c50430f009c14903723b"
    sha256 cellar: :any, mojave:        "cf1cdfb70ef6bb54cd958762f68f5e1c4b979e21fd4d4b8343dce84e04531f49"
  end

  depends_on "pkg-config" => :build
  depends_on "rust" => :build
  depends_on "libyaml"
  depends_on "openssl@1.1"
  depends_on "python@3.9"

  uses_from_macos "krb5"
  uses_from_macos "libffi"
  uses_from_macos "libxslt"

[...]

Again, you do not even have to know where those Ruby scripts reside in your local installation of Homebrew. Do you want Ansible? You can have it! You first update the local set of all available formulae (and casks, introduced in a bit)…

brew update

…and then you search for Ansible:

brew search ansible

You can take a look at the description of the package if you want…

brew info ansible

…and finally you go ahead and install it:

brew install ansible

If you are extra security conscious, then before installing any formula (or cask), you can always look at the corresponding Ruby script and pay attention to download URLs and relevant hashes. By default, all available formulae reside in this directory:

/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula

Homebrew Casks and contributions

As I mentioned a bit earlier, initially, I was using Homebrew for managing applications described by formulae. At some point, I realized that, besides formulae, Homebrew understands casks also. Cask is an extension of Homebrew, which also allows brew to manage macOS native applications. So instead of visiting the home page of your favorite application, locating the downloads page, getting the application package locally, and then doing whatever is appropriate for actually installing, you can just open Terminal and type something like brew install exodus (yes, I am referring to that Exodus).

For the casks you regularly use, you may find that some of them are lagging behind the versions available on the official sites. This has kept happening to me with Exodus, so at some point, I thought to do a brew update, then edit the corresponding cask file on my local system and, finally, upgrade to the latest version of Exodus with brew upgrade exodus --cask --greedy. By the way, here is the default local path to all casks:

/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask/Casks

Take a look at the contents of exodus.rb which, at the time of this writing, reflected the latest official version of Exodus:

cask "exodus" do
  version "21.3.29"
  sha256 "fb5be5d86de3dd358a548fb411e25ea7a58f14b89d830bfab9fa6edb12fcf344"

  url "https://downloads.exodus.com/releases/exodus-macos-#{version}.dmg"
  appcast "https://www.exodus.com/releases/"
  name "Exodus"
  desc "Desktop wallet for cryptocurrency assets"
  homepage "https://www.exodus.com/"

  auto_updates true

  app "Exodus.app"

  zap trash: [
    "~/Library/Application Support/Exodus",
    "~/Library/Preferences/com.electron.exodus.helper.plist",
    "~/Library/Preferences/com.electron.exodus.plist",
    "~/Library/Saved Application State/com.electron.exodus.savedState",
  ]
end

To edit this particular cask file, so it references the latest version available, all you have to do is edit two lines: version and sha256. Just make sure the appropriate values from https://downloads.exodus.com/releases/hashes-exodus-21.3.29.txt are used (first visit https://www.exodus.com/releases, then click on View Release hashes under the big download button).

And since you got into the trouble of editing cask files locally, why not take it one step further and submit your changes upstream so other users of Homebrew can benefit from your work? The Homebrew project offers simple and detailed instructions on how to contribute, so you can start submitting to upstream in no time. Just do it regularly for the casks corresponding to applications you use and care about. That should be useful enough for the entire Homebrew community.