How to Install and Use Homebrew on a Mac
Install it, finish the PATH step everyone skips, and learn the eight commands that cover everything.
beginner10 min read
dev-setuphomebrewmacosdeveloper-toolsbeginners
Installing developer tools on a Mac without a package manager means the same loop over and over: search the tool's name, land on a download page, guess whether you need the Apple Silicon or Intel build, drag something out of a disk image, and then have no record of what you installed or any way to update it. Three months later you have four versions of Node, no idea which one your shell is using, and a Downloads folder full of installers. Homebrew replaces the entire loop with one command to install, one to update everything, and a plain-text file that can rebuild the machine from scratch.
iWhat you need
A Mac running macOS 14 or newer, your admin password, an internet connection, and 30 minutes — most of which is the installer downloading Apple's Command Line Tools if you do not already have them. Open Terminal from Applications → Utilities, or press Cmd+Space and type "terminal".
A package manager is a program that installs other programs, and keeps a record of what it installed. That record is the whole point. Because Homebrew knows exactly what is on your machine and where it came from, it can tell you what is out of date, upgrade all of it in one pass, remove a tool cleanly along with the libraries only that tool needed, and reproduce the same set of software on a different Mac.
Homebrew calls a command-line package a formula and a graphical Mac app a cask. It handles both, which means Git, Python, PostgreSQL, VS Code, and Chrome are all installable the same way from the same terminal.
The official one-liner is published on brew.sh. Copy it from there or from below — never from a random blog post, since the whole command is "download a script and run it" and the URL is the only thing protecting you.
macOS
$/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
The script prints exactly what it intends to create and waits for you to press Return. Then it asks for two things. It asks for your password, because it needs
sudo once to create its install directory and set ownership to your user — after that, everyday brew install commands never need sudo again. And if the Xcode Command Line Tools are missing, it installs them, which is a couple of gigabytes and the slowest part of the process. Let it finish.When the script ends it prints a section headed Next steps with two or three commands in it. This is not optional decoration. On Apple Silicon Macs, Homebrew installs to
/opt/homebrew, and that directory is not on the default PATH — so until you run those commands, typing brew gives you "command not found". On older Intel Macs it installs to /usr/local, which is already on PATH, so there is nothing to do. That difference is the reason the instructions look different on different machines and why half the tutorials online seem wrong.bash
echo >> ~/.zprofile
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"The Apple Silicon PATH step — run these exactly as the installer printed them
The first two lines append a line to your zsh profile so every future terminal knows about Homebrew. The third runs the same thing in your current session so you do not have to reopen the window.
brew shellenv prints the environment variables Homebrew needs, and eval applies them — that indirection is why the line keeps working when Homebrew changes its internals.!Copy the paths from your own installer output
If you are on an Intel Mac, the installer may print
/usr/local/bin/brew shellenv instead, and if you use bash rather than zsh the target file is ~/.bash_profile. Use what your terminal printed, not what a guide assumed.macOS
$brew --version
macOS
$brew doctor
The first should print a version like
Homebrew 4.6.2. The second is Homebrew's self-check and prints Your system is ready to brew. on a clean machine. Run brew doctor now, while nothing is wrong, so you know what a healthy baseline looks like. It is chatty by design and often reports warnings that are genuinely harmless — unlinked kegs, config scripts outside Homebrew — so treat its output as a list of things to understand rather than a list of things to panic about.Homebrew has a long command list and a short list you use daily. Start with these and add more when you need them.
The everyday commands
- 1brew search git — find out what a package is called before installing it.
- 2brew info git — show the version, dependencies, install size, and any caveats before committing.
- 3brew install git — install it. No sudo, ever.
- 4brew list — show everything you have installed. Add --cask to see just the apps.
- 5brew outdated — list installed packages that have newer versions available.
- 6brew uninstall git — remove it. Follow with brew autoremove to drop dependencies nothing else needs.
- 7brew cleanup — delete old downloaded versions and free up disk. Easily several gigabytes on an older machine.
- 8brew deps --tree git — show what a package pulled in, which is how you find out why something you never installed is on your machine.
These two get confused constantly, and the distinction is simple once stated plainly.
brew update updates Homebrew's catalog — it fetches the newest package definitions so Homebrew knows what versions exist. It does not touch a single installed program. brew upgrade installs newer versions of the software you already have. So the real-world sequence is both, in order.macOS
$brew update && brew upgrade
Running
upgrade without update first often reports that everything is current, because Homebrew is comparing against a stale catalog. Run the pair every couple of weeks, then brew cleanup afterwards.Sometimes a project needs a package to stay exactly where it is, and a blanket
brew upgrade would move it. Pinning excludes a formula from upgrades until you change your mind.macOS
$brew pin node
Check what is pinned with
brew list --pinned and release it with brew unpin node. Leave yourself a note about why — a pin you cannot explain six months later is worse than no pin, because you will not dare remove it.A cask wraps a normal Mac application. Homebrew downloads the disk image, mounts it, copies the app into
/Applications, and unmounts it, which is the same thing you were doing by hand. The upside is that these apps then join the same brew outdated and brew upgrade flow as everything else.macOS
$brew install --cask visual-studio-code
The same works for
google-chrome, iterm2, rectangle, docker-desktop, and most of what you would otherwise download. Some apps update themselves internally, in which case Homebrew's version can drift behind — that is expected, and brew upgrade --cask resyncs it.Databases and message brokers are not commands you run once, they are processes that need to be running while you work.
brew services wraps macOS launchd so you can start them without writing a plist by hand.bash
brew install postgresql@17
brew services start postgresql@17 # starts now, and again at login
brew services list # name, status, and user for every service
brew services stop postgresql@17 # stop it and remove it from login
brew services restart postgresql@17 # after a config changeRunning PostgreSQL as a background service
✓Read the caveats
Versioned formulae like
postgresql@17 are often not linked onto your PATH, so psql may be "command not found" right after install. brew info postgresql@17 prints the exact PATH line to add. Homebrew tells you this at install time in the Caveats section — it is the part of the output worth actually reading.This is the payoff for using a package manager at all.
brew bundle dump writes every tap, formula, and cask you have installed into a plain text file called a Brewfile. Commit it to a dotfiles repository and a new Mac becomes a single command instead of a weekend.macOS
$brew bundle dump --file=~/Brewfile --describe
ruby
tap "homebrew/services"
# Version control and shell tooling
brew "git"
brew "gh"
brew "ripgrep"
brew "jq"
# Languages
brew "python"
brew "node"
# Local database, run via brew services
brew "postgresql@17"
# Applications
cask "visual-studio-code"
cask "google-chrome"
cask "iterm2"~/Brewfile — a small but real starting point
On the new machine, install Homebrew, drop the Brewfile in your home directory, and run
brew bundle install --file=~/Brewfile. It walks the list and installs anything missing. brew bundle check tells you whether the machine already matches the file, and re-running dump with --force overwrites an existing Brewfile after you have installed something new.Symptom, cause, fix
- 1zsh: command not found: brew. You skipped the Next steps PATH block on an Apple Silicon Mac. Run the two echo lines plus the eval line, then open a new terminal.
- 2brew works in one window but not a new one. You ran the eval line but never appended it to ~/.zprofile, so the change died with that session. Append it.
- 3No available formula with the name. Your catalog is stale or the thing is a cask. Run brew update, then retry, then try brew search for the real name.
- 4A cask fails saying there is already an App at that path. You installed that app manually before. Move the existing copy to the Trash, or reinstall the cask with the --adopt flag to take over the one already there.
- 5brew update fails with a git error about a shallow or broken repository. Run brew update-reset, which re-clones Homebrew's repositories.
- 6Commands are unexpectedly slow and which brew shows /usr/local/bin/brew on an Apple Silicon Mac. You are running the Intel build under Rosetta. Uninstall it and reinstall natively so it lands in /opt/homebrew.
- 7A build fails with an error about the Command Line Tools. They are outdated or partially installed. Run sudo xcode-select --install, or reinstall them from Apple's developer downloads.
- 8Your disk is filling up. Old package versions accumulate in the Homebrew cache. Run brew cleanup, then brew autoremove.
Now that installs are one command, use it. How to Install Python on a Mac starts from
brew install python and covers the virtual environment discipline that keeps projects apart, and How to Install Node.js does the same on the JavaScript side. How to Use the Command Line is worth reading alongside this one, since Homebrew assumes you are comfortable with paths, profiles, and PATH itself. Then How to Set Up VS Code gets you an editor that talks to all of it. For the ordered version of this whole journey, the Becoming a Software Engineer roadmap puts the environment, the language, and the fundamentals in the order they build on each other.