Homebrew: The Complete Guide to Setup, Usage & Best Practices
Homebrew is the missing package manager for macOS. Apple ships a great operating system, but it doesn't include a way to install developer tools like git, node, python, postgresql, or hundreds of other utilities from the command line. Homebrew fills that gap — and once you're used to it, you'll wonder how you ever worked without it.
This guide covers everything: installation, daily usage, managing GUI apps, automating your setup, and best practices to keep things clean and secure.
What is Homebrew?
Homebrew is a free, open-source package manager that installs software into its own directory (/opt/homebrew on Apple Silicon, /usr/local on Intel) and symlinks files into /usr/local. Crucially, it never requires sudo for package installs — which keeps it safe and your system clean.
It handles two types of software:
- Formulae — command-line tools and libraries (
git,wget,node,ffmpeg) - Casks — macOS GUI applications (
visual-studio-code,firefox,docker)
1. Installation
Prerequisites
Before installing Homebrew, make sure you have the Xcode Command Line Tools. These provide essential compilers, git, and build utilities that Homebrew depends on:
| 1 | xcode-select --install |
A dialog will appear — click Install and wait for it to finish (around 5–10 minutes).
Install Homebrew
Run the official one-liner in your terminal:
| 1 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" |
The script will tell you exactly what it's going to do before doing it. Confirm, enter your password when prompted, and let it run.
Add Homebrew to your PATH (Apple Silicon only)
On Apple Silicon Macs (M1, M2, M3, M4), Homebrew installs to /opt/homebrew, which isn't in your PATH by default. After installation, the script will show you the exact commands to run — they look like this:
| 1 | # Add to ~/.zshrc (or ~/.bash_profile if using Bash) |
| 2 | echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrc |
| 3 | eval "$(/opt/homebrew/bin/brew shellenv)" |
Close and reopen your terminal, or run source ~/.zshrc to apply the change.
Verify the installation
| 1 | brew --version |
| 2 | # Homebrew 4.x.x |
| 3 | |
| 4 | brew doctor |
| 5 | # Your system is ready to brew. |
brew doctor checks for common issues and tells you if anything needs fixing. Run it whenever something feels off.
2. Core Commands
Installing packages
| 1 | # Install a formula (CLI tool) |
| 2 | brew install git |
| 3 | brew install node |
| 4 | brew install python |
| 5 | brew install wget |
| 6 | brew install postgresql@16 |
| 7 | |
| 8 | # Install a cask (GUI app) |
| 9 | brew install --cask visual-studio-code |
| 10 | brew install --cask docker |
| 11 | brew install --cask firefox |
| 12 | brew install --cask rectangle # Window manager |
Searching for packages
| 1 | # Search for a package by name |
| 2 | brew search node |
| 3 | brew search --formula node # Only CLI tools |
| 4 | brew search --cask node # Only GUI apps |
| 5 | |
| 6 | # Get detailed info before installing |
| 7 | brew info node |
| 8 | brew info --cask visual-studio-code |
brew info is worth running before any install — it shows the version, homepage, dependencies, and any caveats you need to know about.
Updating and upgrading
| 1 | # Update Homebrew and its list of formulae |
| 2 | brew update |
| 3 | |
| 4 | # See what's outdated |
| 5 | brew outdated |
| 6 | brew outdated --cask |
| 7 | |
| 8 | # Upgrade everything |
| 9 | brew upgrade |
| 10 | brew upgrade --cask |
| 11 | |
| 12 | # Upgrade a specific package |
| 13 | brew upgrade node |
💡 Tip: Run
brew update && brew upgraderegularly — weekly is a good cadence. Staying current means security patches and new features.
Removing packages
| 1 | brew uninstall node |
| 2 | brew uninstall --cask visual-studio-code |
| 3 | |
| 4 | # Also remove all associated config files |
| 5 | brew uninstall --cask --zap visual-studio-code |
The --zap flag does a thorough removal including preferences and support files — useful when you want a completely clean slate.
Listing what's installed
| 1 | # All installed formulae |
| 2 | brew list |
| 3 | |
| 4 | # All installed casks |
| 5 | brew list --cask |
| 6 | |
| 7 | # Only top-level packages (not installed as dependencies) |
| 8 | brew leaves |
| 9 | |
| 10 | # See what depends on a package before removing it |
| 11 | brew uses --installed node |
brew leaves is really useful — it shows you the packages you installed, not the dependencies that came along for the ride.
3. Managing Background Services
Many developer tools (databases, web servers, Redis) need to run continuously in the background. brew services manages these using macOS's built-in launchd:
| 1 | # Install PostgreSQL |
| 2 | brew install postgresql@16 |
| 3 | |
| 4 | # Start and configure to auto-start on login |
| 5 | brew services start postgresql@16 |
| 6 | |
| 7 | # Stop the service |
| 8 | brew services stop postgresql@16 |
| 9 | |
| 10 | # Restart (useful after config changes) |
| 11 | brew services restart postgresql@16 |
| 12 | |
| 13 | # See all managed services and their status |
| 14 | brew services list |
Example output of brew services list:
| 1 | Name Status User File |
| 2 | mysql started jane ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist |
| 3 | postgresql@16 started jane ~/Library/LaunchAgents/homebrew.mxcl.postgresql@16.plist |
| 4 | redis none |
4. Taps — Third-Party Repositories
A tap is an additional repository of formulae beyond the core Homebrew collection. Some tools aren't in the main index and need you to add a tap first:
| 1 | # Add a tap |
| 2 | brew tap hashicorp/tap |
| 3 | |
| 4 | # Then install from it |
| 5 | brew install hashicorp/tap/terraform |
| 6 | |
| 7 | # See which taps are active |
| 8 | brew tap |
| 9 | |
| 10 | # Remove a tap you no longer need |
| 11 | brew untap hashicorp/tap |
⚠️ Security note: Taps have less oversight than the main Homebrew core. Only add taps from organisations you trust, and consider reviewing the formula source on GitHub before installing.
5. Brewfile — Automate Your Entire Setup
A Brewfile is a declarative list of everything you want Homebrew to install. Think of it as a package.json for your Mac. This is one of the most powerful Homebrew features — it lets you set up a new machine in minutes, or share your exact toolset with teammates.
Creating a Brewfile from your current setup
| 1 | brew bundle dump --file=~/Brewfile |
This generates a file from everything currently installed.
Example Brewfile
| 1 | # Taps |
| 2 | tap "homebrew/bundle" |
| 3 | tap "homebrew/cask-fonts" |
| 4 | |
| 5 | # CLI tools |
| 6 | brew "git" |
| 7 | brew "node" |
| 8 | brew "python" |
| 9 | brew "wget" |
| 10 | brew "jq" # JSON processor |
| 11 | brew "ripgrep" # Fast grep replacement |
| 12 | brew "fzf" # Fuzzy finder |
| 13 | brew "gh" # GitHub CLI |
| 14 | brew "postgresql@16" |
| 15 | brew "redis" |
| 16 | |
| 17 | # GUI apps (Casks) |
| 18 | cask "visual-studio-code" |
| 19 | cask "docker" |
| 20 | cask "firefox" |
| 21 | cask "rectangle" # Window manager |
| 22 | cask "iterm2" # Terminal |
| 23 | cask "fig" # Terminal autocomplete |
| 24 | |
| 25 | # Fonts |
| 26 | cask "font-jetbrains-mono-nerd-font" |
| 27 | |
| 28 | # Mac App Store apps |
| 29 | mas "Xcode", id: 497799835 |
Installing from a Brewfile
| 1 | # Install everything in the Brewfile |
| 2 | brew bundle install --file=~/Brewfile |
| 3 | |
| 4 | # Check if anything is missing |
| 5 | brew bundle check --file=~/Brewfile |
| 6 | |
| 7 | # Remove anything NOT in the Brewfile |
| 8 | brew bundle cleanup --force --file=~/Brewfile |
💡 Pro tip: Commit your
Brewfileto a dotfiles repository on GitHub. When you get a new Mac, clone the repo and runbrew bundle install— you're back to full speed in minutes.
6. Keeping Things Clean
Homebrew keeps old versions of packages around in case you need to roll back. Over time this eats up significant disk space.
| 1 | # Remove old versions of all installed formulae |
| 2 | brew cleanup |
| 3 | |
| 4 | # See what would be removed without actually removing it |
| 5 | brew cleanup --dry-run |
| 6 | |
| 7 | # Remove everything older than a specific number of days |
| 8 | brew cleanup --prune=30 |
| 9 | |
| 10 | # Check how much space you'd reclaim |
| 11 | brew cleanup -n |
Automating this is even better. Add it to a weekly cron or create a shell alias:
| 1 | # Add to ~/.zshrc |
| 2 | alias brewclean='brew update && brew upgrade && brew cleanup && brew doctor' |
Now brewclean does a full update, upgrade, cleanup, and health check in one command.
7. Best Practices
Never use sudo with Homebrew
Homebrew is explicitly designed to work without administrator privileges. Using sudo brew install can cause permission issues that are painful to untangle:
| 1 | # ❌ Don't do this |
| 2 | sudo brew install node |
| 3 | |
| 4 | # ✅ Always this |
| 5 | brew install node |
If you're getting permission errors without sudo, run brew doctor — it will usually tell you exactly how to fix them.
Stick to homebrew/core when possible
The main Homebrew repository has a thorough review process: download URLs are validated, checksums verified, and formulas reviewed by multiple people before merging. Third-party taps have significantly less oversight — treat them with the same caution you'd give any unvetted code.
Inspect packages before installing
For anything outside the core repository:
| 1 | # View what a formula actually does |
| 2 | brew info <package> |
| 3 | |
| 4 | # Check its dependencies |
| 5 | brew deps <package> |
| 6 | |
| 7 | # Look at the formula source |
| 8 | brew cat <package> |
Audit your installed packages periodically
| 1 | # See top-level packages (what you explicitly installed) |
| 2 | brew leaves |
| 3 | |
| 4 | # Find anything outdated |
| 5 | brew outdated |
| 6 | |
| 7 | # Full health check |
| 8 | brew doctor |
Pin packages you need to stay at a specific version
If a newer version would break your workflow, you can pin a formula to prevent it from being upgraded:
| 1 | # Pin to current version |
| 2 | brew pin node |
| 3 | |
| 4 | # See what's pinned |
| 5 | brew list --pinned |
| 6 | |
| 7 | # Unpin when you're ready to upgrade |
| 8 | brew unpin node |
Use --cask explicitly for GUI apps
While Homebrew can often figure out intent, being explicit is good practice and avoids ambiguity:
| 1 | # ✅ Explicit |
| 2 | brew install --cask visual-studio-code |
| 3 | |
| 4 | # Works, but less clear |
| 5 | brew install visual-studio-code |
Keep your Brewfile in version control
Your Brewfile is documentation. It tells anyone (including future you) exactly what tools your environment depends on. Keep it in a dotfiles repo alongside your .zshrc, .gitconfig, and editor settings.
8. Essential Packages to Get Started
Here are some widely-used packages worth knowing about: Developer Tools
git— Version control (newer than the Apple-bundled version)gh— GitHub CLI for managing PRs, issues, and repos from the terminalnode— JavaScript runtimepython— Python 3 (the system Python should be left alone)nvm— Node version manager (switch between Node versions)pyenv— Python version manager Terminal Utilitiesfzf— Fuzzy finder for files and command historyripgrep— Blazing fast search (bettergrep)jq— Query and format JSON in the terminalbat— Bettercatwith syntax highlightinghtop— Interactive process viewerwget/curl— Download files from the command linetree— Display directory structure as a tree Databases & Servicespostgresql@16— PostgreSQL databasemysql— MySQL databaseredis— In-memory data store GUI Apps (Casks)visual-studio-code— Code editordocker— Container platformiterm2— Powerful terminal replacementrectangle— Window snapping and managementraycast— Spotlight replacement with Homebrew integration
Quick Reference Cheatsheet
| 1 | # Install |
| 2 | brew install <formula> # CLI tool |
| 3 | brew install --cask <app> # GUI app |
| 4 | |
| 5 | # Search & Info |
| 6 | brew search <name> # Search packages |
| 7 | brew info <name> # Details, version, caveats |
| 8 | |
| 9 | # Update |
| 10 | brew update # Update Homebrew itself |
| 11 | brew outdated # See what's old |
| 12 | brew upgrade # Upgrade everything |
| 13 | brew upgrade <name> # Upgrade one package |
| 14 | |
| 15 | # Remove |
| 16 | brew uninstall <name> # Remove a package |
| 17 | brew cleanup # Delete old versions |
| 18 | |
| 19 | # Inspect |
| 20 | brew list # All installed formulae |
| 21 | brew list --cask # All installed casks |
| 22 | brew leaves # Top-level (non-dependency) packages |
| 23 | brew services list # Background services status |
| 24 | |
| 25 | # Health |
| 26 | brew doctor # Diagnose issues |
| 27 | brew audit <name> # Audit a formula |
| 28 | |
| 29 | # Brewfile |
| 30 | brew bundle dump # Export current setup |
| 31 | brew bundle install # Install from Brewfile |
| 32 | brew bundle cleanup # Remove anything not in Brewfile |
Summary
Homebrew is the single most important tool to install on a new Mac. It gives you access to thousands of packages, keeps them updated, manages background services, and lets you script your entire environment into a Brewfile that can reproduce your setup on any machine.
Start with the one-liner install, run brew doctor to confirm everything is healthy, and commit a Brewfile to version control as soon as you have your core tools in place. Future you — setting up a new Mac or onboarding a teammate — will thank you.