Installing software is tedious work, especially when you need to set up everything from scratch after getting a new computer.
For each and every application you have to visit its website, where you then have to navigate to the download section.
There, you have to find the correct download link for your specific operating system, only to wait for the download to eventually finish before you can finally unzip it and move the app to the
This tedious procedure cries out for automation.
Wouldn’t it be much easier if you only needed to tell your computer what application you want to install and your computer would then go ahead and take care of everything else?
If your computer could figure out everything by itself so that the requested application automatically appears in your applications folder without you doing anything?
Exactly this is the purpose of so-called package managers.
On Linux there are many different package managers—maybe you’ve heard of
apt-get—but on macOS we are going to use Homebrew.
Update 02. February 2019: Homebrew 2.0.0 was released which now supports Linux and Windows 10 too. The original article was written with macOS in mind, so please adjust everything described to your specific operating system if necessary.
Installing the Xcode Command Line Tools
You need to make sure that you have the Xcode Command Line Tools installed before you can start using Homebrew to install software. Installing them is easy. I’ll show you two different ways to get them. The Command Line Tools are necessary because Homebrew needs some tools that don’t come with macOS out-of-the-box (e.g., the compiler collection GCC).
The More Common Way
The easiest way to get the Xcode Command Line Tools is to install Xcode from the Mac App Store. Xcode contains the Command Line Tools. After you’ve installed Xcode from the Mac App Store, you first need to agree to its End User License Agreement (EULA). Just open Xcode and the EULA will pop up. Simply click on “Accept” and close Xcode again.
Alternatively, you could also accept the EULA by running this terminal command:
sudo xcodebuild -license accept
Now, Xcode brings the Command Line Tools with it, but it doesn’t install them. You have to do that yourself. After you’ve accepted Xcode’s EULA, you can install the Xcode Command Line Tools like so:
A pop-up will then ask whether you want to install the Xcode Command Line Tools. Confirm the dialog by clicking on “Install”.
I encourage you to follow the above-mentioned approach and install Xcode from the Mac App Store. However, there are scenarios where you don’t need or want a full-blown installation of Xcode. Maybe you don’t intend to ever develop iOS apps, so why occupy gigabytes of disc space with Xcode when all you’re interested in is a small subset, the Command Line Tools. Another scenario would simply be that you cannot install Xcode from the Mac App Store, maybe because you’re not on the latest macOS. Personally, I’m still on macOS Mojave because I find Catalina way too buggy. As of March 2020, I can’t download Xcode from the Mac App Store anymore because the only version of Xcode available, Xcode 11.4, requires macOS Catalina. Because I’m on macOS Mojave I need Xcode 11.3, but I can’t get it from the Mac App Store.
If for any reason you can’t or don’t want to install Xcode from the Mac App Store, go to the Apple Developer site and sign up for a free Developer Account if you don’t have one already. Again, this is free and has nothing to do with the paid Developer Account. You only have to pay Apple if you want to, for example, submit iOS apps to the App Store. After you log in with your Apple ID, you can go to the Downloads Section and download Xcode from there or, alternatively, just the Command Line Tools.
Now that the Xcode Command Line Tools are installed, you can continue to install Homebrew with this command:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
That’s it! Now you’ve got Homebrew on your system 😎 To ensure that everything went well, you could enter
brew doctor into the terminal.
Update: A while ago, the command to install Homebrew was
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)". That is, we used
ruby instead of
bash to execute the downloaded script. Nothing wrong with that change of commands. But in the following section, I use that old command as an entry point to introduce the
PATH variable. You’ll have to forgive me that I didn’t want to rewrite the following section because of this. Thanks for understanding.
Adjusting the PATH Variable
In the last step, we used Ruby—which is pre-installed on every Mac by default—to load Homebrew from its GitHub repository and install it.
The problem with this pre-installed version of Ruby is that it is not the newest version and very outdated, like most other tools pre-installed by Apple. We really should update it. What comes to mind is that now we could use Homebrew to update Ruby. That’s the reason we’ve installed Homebrew in the first place, right?
This leads us to the next problem. These system-provided versions of Ruby, Python, even Bash, and virtually every other pre-installed tool can be neither updated nor modified nor deleted by the user. That’s because they are protected by the operating system, which is perfectly fine because this ensures that we don’t accidentally break our machine. In case we one day get the (wrong) notion that we could get rid of any of these programs since they’re outdated anyway, macOS would stop us from trying to uninstall them. Our own Python or Ruby environment we can mess up all we want, but because the pre-installed distributions are controlled by Apple, macOS can always be sure that there’s at least one functioning environment. It may be outdated, but at least it’s working. That’s also the reason why we can’t install additional packages into these system environments and, by doing so, potentially mess them up.
What we’re going to do instead is to install a second copy of Ruby, which co-exists next to the system’s version. With this version we can do what we want and it also is much easier to maintain. However, now that we have two versions of Ruby installed, this poses the question which of these two versions should be executed when we call
ruby? The system’s version because it has been there from the start? Or the new one because it is more recent? How does the system know which one should be executed?
The answer is the so-called
PATH variable. This variable contains a list of locations where software is installed. The order of this list determines where the operating systems looks first. If we want to use the more recent and maintainable versions we’ve installed ourselves, then we need to change the order so that the folder for user-installed applications comes before the folder for pre-installed software. If the system can’t find the specified application there, it looks in the next folder… and if it didn’t find the program there either, it looks in the next folder, and so on. To change this list to the right order, you need to enter this command into the terminal:
echo 'export PATH="/usr/local/bin:$PATH"' >> ~/.bash_profile
This will specifically tell macOS to look for a program in the directory
/usr/local/bin (the place where Homebrew installs its stuff) before it looks anywhere else. Basically, the
PATH variable is a list of folders that are separated by a colon (
:). So we simply prepended the already existing content of that variable with
/usr/local/bin. Imagine the
PATH variable as a hierarchy. When you want to use a program, macOS looks through these locations from left to right and uses whatever version of that program it finds first.
Only in case macOS couldn’t find the program in the first folder it would continue to look in the following directories further down the waterfall as a fallback.
To test if the
PATH variable is set correctly, run these two commands:
source ~/.bash_profile echo $PATH
This first reloads the file in which the
PATH variable is set (the hidden file
.bash_profile located at
~ which is an abbreviation for your home folder, in my case
We need to do that for the changes to take effect.
Alternatively, you could also close and re-open your terminal window.
Then, we output the current value of the variable.
It should look something like this:
It doesn’t matter if your output looks slightly different or if a folder appears multiple times or if
/usr/local/bin appears both before and after
/usr/bin. The only important thing is that there is no
/usr/bin (the place where all the pre-installed software lives) coming before
/usr/local/bin, since in that case macOS would stop looking for the version we’ve installed ourselves as soon as it found the pre-installed version.
Installing Your Applications
Now that everything is set up correctly, we can finally begin to actually install programs. To install an application via Homebrew, we first need to know it’s “identifier”. We can either google it or search for it using
brew search followed by the program, for example,
brew search ruby. In most cases the identifier is the application name,
ruby in this case. There are exceptions, however, usually when there are multiple versions of the same program available for compatibility reasons (for example,
brew install python vs
brew install python@2).
The syntax is pretty straight forward. You may either install applications individually …
brew install ruby brew install bash brew install git
… or all together in one rush:
brew install ruby bash git
In case this doesn’t work on your machine, the
PATH variable probably hasn’t been adjusted correctly during the last step. I describe the use of
~/.bash_profile, but in case you’ve tinkered around with these kind of files before, your machine might be set up to use
~/.profile instead or even
~/.zshrc if you’ve switched your shell from
zsh. If you’re not sure or don’t know what all this means, please follow my instructions in this post about these so-called dotfiles.
Note: if you’re working with Python regularly,
brew install python is not the preferred way to install Python. There is a far more practical solution. Definitely check out my other post on how to set up your Python environment for scientific computing if you want to read more.
Homebrew Cask: For Applications With a Graphical User Interface
Homebrew is particularly useful for developer and command line tools, but you can also use Homebrew to install apps with a graphical user interface, e.g., Google Chrome or Spotify.
To install apps with a GUI—Homebrew calls them casks—you’ll need a slightly different syntax:
brew install --cask.
Here are a few examples which apps you might want to install using Homebrew Cask:
brew install --cask google-chrome brew install --cask 1password brew install --cask spotify brew install --cask vlc brew install --cask visual-studio-code brew install --cask microsoft-excel brew install --cask skype brew install --cask evernote brew install --cask java brew install --cask intellij-idea-ce
If you want to know which other useful apps I have installed on my Mac, you can read about my personal setup here.
Updating Applications and Maintaining the Cellar
Generally, before installing a new app or doing an update, it’s always a good idea to update Homebrew’s internal list of available programs, so that it knows the newest version available for each app (and to update Homebrew itself). This command only updates the internal list of Homebrew (aka the formulae), not your apps. To update your actual apps installed via Homebrew, you need an additional command (Homebrew calls this “upgrade”). You can combine both commands to
brew update && brew upgrade. In more recent versions of Homebrew, the
brew update part will be performed automatically and is not needed anymore. It’s sufficient to type:
This command downloads the available updates for all of your apps (if there are any).
What I don’t like about the command
brew upgrade is that it upgrades all my apps. There are some cases where I deliberately want to stay on an older version of a cask (i. e., an app with a graphical user interface), because the developers switched to a subscription business model or the new features are simply not worth the upgrade price. With
brew upgrade you would upgrade all installed apps, including those apps you don’t want to update. What you can do instead is to first upgrade only the command line tools but none of the casks using this command:
brew upgrade --formula -q
To upgrade your casks, you can either update them via their own update mechanism if they have one or you can check which casks are outdated using the command
brew outdated and then upgrade them individually using this command:
brew upgrade --cask <identifier>
You only need the
brew upgrade --cask command for apps that don’t update themselves. For instance, Google Chrome and Spotify update themselves. You don’t have to
brew upgrade --cask them.
Keep in mind that upgrading an app, be it a command line program or an app with a graphical interface, does not delete the currently installed version.
Having upgraded an application a couple of times thus results in an accumulation of multiple different versions of that application, which can easily take up several hundreds of megabytes worth of disk space, so a best practice is to perform a cleanup after each time you upgrade your apps.
Before that, let me tell you just one last thing about how Homebrew works. In case you’re wondering where your applications get installed to: GUI apps installed via Homebrew are moved to the
/Applications folder just like you did it all the time. And your command line tools live deep in the system in the
/usr/local/bin directory. That’s at least the place where other programs are looking for them.
It’s a historic UNIX convention one should follow if one doesn’t want to break things.
Remember why we needed to change the
PATH variable? Exactly for this reason! Because Homebrew installs its stuff into
/usr/local/bin—according to the convention—and we want to first look there before we use the system-provided versions which live in
/usr/bin. That’s why
/usr/local/bin has to be the leftmost entry in the colon-separated list that the
PATH variable is.
However, Homebrew doesn’t place your programs directly into the
/usr/local/bin folder. Instead, it uses a smart trick called symlinking. Homebrew maintains it’s own subdirectory which is called the Cellar. All the software you install via Homebrew gets installed into that directory first. And then Homebrew creates a link in the
/usr/local/bin folder, pointing to the newest versions in the Cellar. This symlink creates some sort of virtual copy.
But why is Homebrew doing this you ask? Why isn’t it installing the programs directly into
/usr/local/bin? Imagine downlading an update for one of your programs. And after a while another one. And another one. Eventually the
/usr/local/bin directory will be pretty crammed with multiple outdated versions of the same app. With the symlink method, you’ll only ever have one version in this important directory, and it’s always the newest one. And when you download an update, Homebrew only need’s to change the link to point to the newer version.
But this doesn’t really solve the problem! It’s just a different folder now!? Yes, that’s true. But Homebrew isn’t the only one installing software in the
/usr/local/bin directory. You yourself could write and copy files into that folder (which I don’t recommend). By keeping all its stuff in its own folder, Homebrew keeps out of the way and avoids conflicts and overriding. And for cleaning up the Cellar and deleting all the outdated versions there’s the
brew cleanup command.
Instead of the regular command
brew cleanup, I prefer this command:
brew cleanup -s
The reason is that
brew cleanup removes the no longer needed installers of old versions only if they are older than a certain time, just in case you’d like to re-install the old version, so that you wouldn’t have to download the installer again. I don’t like this default behavior. When I perform a cleanup after upgrading an app, I do not want to keep the installer for a version I no longer need just in case.
In the improbable case I need to fall back to an older version, especially after I deliberately removed the old installers, I can simply download the installer again.
When I perform a cleanup, I want everything except the most recent version gone.
brew cleanup -s doesn’t delete the installers for the version that are currently installed.
*.pkg installers are quite large, I want them gone too.
brew cleanup -s deletes the installers up to the second-most recent ones immediately instead of keeping them around for a couple of weeks,
rm -rf $(brew --cache) even deletes the most-recent installer for the version that is currently installed.
This command freed up multiple gigabytes worth of storage space on my disk.
Another very handy command for freeing up some disk space is this one:
Some applications ABC are only installed because they were needed for application D to work.
When you no longer need application D and uninstall it, the applications ABC remain installed even though you have no need for them whatsoever with application D gone.
brew autoremove removes such unnecessary orphaned applications ABC.
I hope you find this guide helpful. In case anything is still unclear or not working, ask your question in the comment section down below and I will see whether I can help you out. You can also contact me on Twitter. I’d love to hear from you 😊 Be well.