Homebrew is the missing package manager for macOS (or Linux). It installs the UNIX tools Apple didn't include with macOS, and software not packaged for your Linux distribution — all without needing sudo. You drive it entirely through one command: brew.
This guide covers everything you do as a Homebrew user: installing it, finding and installing software, keeping it up to date, managing GUI apps (casks) and background services, capturing your setup in a Brewfile, and fixing the problems you're most likely to hit. Architecture, the full environment-variable reference, internals, and contributor commands live in the companion Admin Guide.
Table of Contents
- Quick Start
- What Homebrew Is (and the words it uses)
- Installation
- Finding Software
- Installing Software
- Keeping Things Up to Date
- Removing Software & Reclaiming Disk Space
- Inspecting What's Installed
- GUI Apps with Homebrew Cask
- Background Services
- Reproducible Setups with a Brewfile
- Taps: Third-Party Repositories
- Shell Integration
- Advanced Usage
- Configuration You'll Actually Use
- Troubleshooting
- FAQ
- Command Reference
1. Quick Start
Install Homebrew, then install your first package:
# 1. Install Homebrew (macOS or Linux)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 2. Install a package
brew install wget
# 3. Use it
wget --version
The everyday loop, once you're set up:
brew search node # find it
brew install node # install it
brew update # refresh package definitions + Homebrew itself
brew outdated # see what has newer versions
brew upgrade # upgrade everything
brew uninstall node # remove it
Tip
If you only remember one maintenance command, remember
brew update && brew upgrade. The first refreshes Homebrew's knowledge of available versions; the second installs them.
Note
Homebrew runs as your normal user. It deliberately refuses to run under
sudo— see Why Homebrew avoidssudoin the FAQ. The one exception is system-wide services (see Background Services).
2. What Homebrew Is (and the words it uses)
Homebrew installs packages into its own self-contained directory (the prefix) and then symlinks them into place so your shell can find them. Nothing is scattered across system directories, so everything Homebrew installs can be cleanly removed.
You'll meet this vocabulary constantly. Learn these eight terms and the rest of the docs read easily:
| Term | Meaning |
|---|---|
| formula | A package definition that builds from upstream source (e.g. git, wget, python). |
| cask | A package definition that installs pre-compiled binaries — typically a macOS GUI app (e.g. firefox, visual-studio-code). |
| bottle | A pre-built binary version of a formula, poured into place instead of compiling from source. Most installs use bottles, so they're fast. |
| prefix | Where Homebrew lives, e.g. /opt/homebrew (Apple Silicon), /usr/local (Intel Mac), /home/linuxbrew/.linuxbrew (Linux). |
| Cellar | The directory holding every installed formula version, e.g. /opt/homebrew/Cellar. |
| keg | One installed version of one formula, e.g. /opt/homebrew/Cellar/wget/1.25.0. |
| tap | A Git repository of formulae, casks and/or commands. This is how third parties extend Homebrew. |
| keg-only | A formula that is installed but not symlinked into the prefix (to avoid clashing with system tools). |
A few more you'll see in command output: a rack is the Cellar/<name> directory containing one or more kegs; the opt prefix (opt/<name>) is a stable symlink to the active keg; the Caskroom is the cask equivalent of the Cellar; an external command is a brew subcommand defined outside the core project (see Taps).
Important
Formula vs. cask is the single most useful distinction. A formula is usually a command-line tool, built from source or poured from a bottle into the Cellar. A cask is usually a GUI application, installed as a ready-made binary into your
/Applicationsfolder and tracked in the Caskroom. Many commands accept--formulaor--caskto disambiguate when a name exists as both.
3. Installation
Requirements
| Platform | Requirements |
|---|---|
| macOS | A 64-bit Intel or Apple Silicon CPU; the latest version of macOS is best supported. The Xcode Command Line Tools are required (the installer offers to install them). |
| Linux | A 64-bit x86_64 or ARM CPU, glibc 2.13+, plus gcc, make, and a few build basics. Homebrew installs into your home area and needs no root. |
Install with the official script
The recommended installer works on both macOS and Linux:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
==> This script will install:
/opt/homebrew/bin/brew
...
==> Installation successful!
Warning
Install Homebrew in its default location. Bottles (the fast pre-built binaries) only work in the default prefix; install anywhere else and most formulae must be slowly compiled from source, which is unsupported. The default prefixes are
/opt/homebrew(Apple Silicon),/usr/local(Intel Mac), and/home/linuxbrew/.linuxbrew(Linux).
Put brew on your PATH
On Linux, and on some macOS setups, the installer prints "Next Steps" telling you to add Homebrew to your shell. Do exactly what it says. The mechanism is brew shellenv, which prints the export lines to wire up PATH, MANPATH and INFOPATH:
zsh (macOS default)
echo 'eval "$(/opt/homebrew/bin/brew shellenv zsh)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv zsh)"
bash (Linux default)
echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv bash)"' >> ~/.bashrc
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv bash)"
fish
echo 'eval "$(/opt/homebrew/bin/brew shellenv fish)"' >> ~/.config/fish/config.fish
eval "$(/opt/homebrew/bin/brew shellenv fish)"
brew shellenv accepts bash, csh, fish, pwsh, sh, tcsh or zsh. If you omit the shell it tries to detect it, but naming it explicitly is more reliable.
Verify the install
brew --version
brew doctor
Your system is ready to brew.
Tip
brew doctoris your first stop whenever anything misbehaves. Its warnings are diagnostic hints for maintainers — if everything you use works, you can safely ignore them.
Uninstalling Homebrew
Homebrew is removed with a separate official script:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"
4. Finding Software
Search by name
brew search wget
A bare substring matches formula names and cask tokens. Flank the term with slashes to use a regular expression, and the search is extended online to homebrew/core and homebrew/cask:
brew search /^node@/ # regex: every versioned node formula
brew search --cask figma # casks only
brew search --formula jq # formulae only
Search by description
brew search --desc "json processor"
brew desc --search "image resize" # search names AND descriptions
brew desc wget # one-line description of a single package
Look at a specific package
brew info (alias abv) is how you decide whether to install something: it shows the version, what it depends on, its homepage, caveats, and whether it's already installed.
brew info node
==> node: stable 24.1.0 (bottled), HEAD
Platform built on Node.js
https://nodejs.org/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/n/node.rb
==> Dependencies
Required: brotli ✘, c-ares ✘, icu4c ✘, libuv ✘, openssl@3 ✘
Useful brew info options:
| Option | Effect |
|---|---|
--installed |
Inventory of everything you have installed. Add --json=v2 for machine-readable output. |
--json |
JSON representation (use --json=v2 for formulae and casks). |
--analytics |
Install/usage analytics for a package (see also --days 30|90|365). |
--github |
Open the package's GitHub source page in a browser. |
--sizes |
Show on-disk sizes of installed formulae and casks. |
Other discovery commands:
brew formulae # list every installable formula
brew casks # list every installable cask
brew home node # open the package's homepage in a browser
brew source node # open the package's source repository in a browser
5. Installing Software
The basics
brew install wget # a formula (command-line tool)
brew install --cask firefox # a cask (GUI app)
brew install git node wget # several at once
If a name exists as both a formula and a cask, Homebrew installs the formula and warns you. Force the choice with --formula or --cask.
Note
By default
brew install <formula>will also upgrade that formula if it's already installed but outdated, and will runbrew cleanupafterwards. You can change both behaviours with environment variables — see Configuration.
What happens during an install
- Homebrew refreshes its package data (an "auto-update", at most once every 24 hours by default).
- It resolves and installs the package's dependencies.
- It pours a bottle (pre-built binary) if one exists for your OS — fast. Otherwise it compiles from source.
- It symlinks the result into the prefix so it's on your
PATH.
Preview before committing
brew install --dry-run node # show what would happen, change nothing
brew install --ask node # print the plan, then prompt for confirmation
Tip
--ask(or settingHOMEBREW_ASK=1) is great for cautious installs: it prints the full dependency plan and only prompts when the plan pulls in more than what you named.
Common install options
| Option | What it does |
|---|---|
-s, --build-from-source |
Compile from source even when a bottle exists. |
--HEAD |
Install the latest unreleased ("main"/"trunk") version, if the formula defines one. |
-f, --force |
Install without checking for existing keg-only or non-migrated versions; for casks, overwrite existing files. |
-v, --verbose |
Print verification and post-install steps. |
-d, --debug |
On build failure, drop into an interactive debugging shell in the build directory. |
-n, --dry-run |
Show what would be installed without installing. |
--only-dependencies |
Install just the dependencies, not the package itself. |
--ignore-dependencies |
(Unsupported dev option) skip installing dependencies. |
--display-times |
Print how long each package took. |
--keep-tmp |
Keep the temporary build files. |
Cask-specific install options include --adopt (adopt an already-present identical app instead of reinstalling), --skip-cask-deps, --require-sha, and --[no-]binaries. The --*dir options (e.g. --appdir, --fontdir) control where cask artifacts land — see GUI Apps.
Installing a specific version
Many tools publish versioned formulae:
brew install node@20 # a specific major version
brew install python@3.12
Run brew search /node@/ to see what versioned formulae exist for a given tool.
6. Keeping Things Up to Date
This is the workflow you'll run most often. There are three distinct steps and it helps to keep them straight:
brew update # 1. refresh package definitions + Homebrew itself (no packages change)
brew outdated # 2. list installed packages that have a newer version
brew upgrade # 3. actually upgrade them
brew update
Fetches the newest formula/cask data and Homebrew itself from GitHub and runs any necessary migrations. It changes Homebrew's knowledge, not your installed packages.
brew update-if-needed is a fast, no-op-friendly variant for scripts: it only does work if an update is actually due.
brew outdated
brew outdated # everything with an update available
brew outdated --formula # formulae only
brew outdated --cask # casks only
brew outdated --greedy # also include auto-updating casks normally skipped
brew upgrade
brew upgrade # upgrade all outdated, unpinned packages
brew upgrade node # upgrade just one
brew upgrade --cask # only outdated casks
brew upgrade --dry-run # preview
brew upgrade --ask # print the plan, then prompt (includes download sizes)
Important
Upgrading one package can upgrade many others. Homebrew only tests one combination of versions — the latest — so when you upgrade something, everything it depends on (and everything that depends on it) is brought up to date too. This is by design and keeps your system in a tested, supported state.
Holding a package back
Pin a package to stop brew upgrade from touching it:
brew pin node # freeze node at its current version
brew upgrade # node is now skipped
brew unpin node # allow upgrades again
Warning
Pinning is a sharp tool. Other packages that need a newer version of a pinned formula may fail to install or run, because Homebrew won't build them against an outdated dependency. Prefer pinning only briefly. Pinned casks with
auto_updates truemay still update themselves through the app's own updater.
To stop Homebrew from even learning about new versions until you choose to:
export HOMEBREW_NO_AUTO_UPDATE=1
7. Removing Software & Reclaiming Disk Space
Uninstall a package
brew uninstall wget # aliases: brew remove, brew rm
brew uninstall --force node # remove ALL installed versions
brew uninstall --cask firefox # remove a GUI app
brew uninstall --zap firefox # cask: also remove its leftover files (use with care)
Caution
--zapremoves all files associated with a cask, which may include files shared with other applications.--forcedeletes every installed version and ignores errors. Both are destructive — read what they'll remove before running them.
Remove things you no longer need
brew autoremove uninstalls formulae that were only ever installed as dependencies of something you've since removed:
brew autoremove --dry-run # see what would be removed
brew autoremove # remove unused dependencies
Clean the cache and old versions
brew cleanup # remove stale downloads + old versions of everything
brew cleanup --dry-run # preview
brew cleanup node # only for node
brew cleanup --prune=all # remove ALL cached downloads
brew cleanup -s # scrub the cache, even latest-version downloads
By default brew cleanup removes downloads older than 120 days; adjust with HOMEBREW_CLEANUP_MAX_AGE_DAYS. Homebrew also runs cleanup automatically after installs and every 30 days — disable that with HOMEBREW_NO_INSTALL_CLEANUP=1.
To see where downloads live:
brew --cache # usually ~/Library/Caches/Homebrew on macOS
8. Inspecting What's Installed
List packages
brew list # everything installed (aliases: brew ls)
brew list --formula # formulae only
brew list --cask # casks only
brew list --versions # with version numbers
brew list --versions node # versions of one package
brew list node # the files inside node's keg
Filter by how things were installed:
| Option | Lists… |
|---|---|
--installed-on-request |
Packages you asked for explicitly. |
--installed-as-dependency |
Packages pulled in to satisfy others. |
--poured-from-bottle |
Packages installed from a pre-built bottle. |
--built-from-source |
Packages compiled locally. |
--pinned |
Pinned packages only. |
--multiple |
Only formulae with multiple versions installed. |
Understand dependencies
brew deps node # everything node depends on
brew deps --tree node # as an indented tree
brew deps --installed # dependencies of all installed formulae
brew uses --installed node # installed packages that depend ON node
brew leaves # installed formulae nothing else depends on
brew missing # check for missing dependencies
Tip
brew leavesplusbrew usesis the safe way to decide what you can remove.leavesshows the packages no other package needs;uses <formula>shows who would break if you removed<formula>.
Locate things
brew --prefix # Homebrew's install root
brew --prefix node # where node is installed
brew --cellar # the Cellar path
brew --caskroom # the Caskroom path
brew --repository # Homebrew's own Git checkout
brew config # full system + Homebrew config (attach this to bug reports)
brew --version # version numbers of brew + core taps
9. GUI Apps with Homebrew Cask
Casks install pre-built applications — usually macOS .app bundles — rather than building from source. Everything you learned about install, upgrade, uninstall and list works on casks; just add --cask where a name is ambiguous.
brew install --cask visual-studio-code
brew install --cask google-chrome firefox
brew upgrade --cask
brew uninstall --cask google-chrome
brew list --cask
Where cask artifacts go
By default macOS apps install into /Applications. Each artifact type has its own target directory, all of which you can override:
| Option | Default target |
|---|---|
--appdir |
/Applications |
--fontdir |
~/Library/Fonts |
--colorpickerdir |
~/Library/ColorPickers |
--prefpanedir |
~/Library/PreferencePanes |
--qlplugindir |
~/Library/QuickLook |
--screen-saverdir |
~/Library/Screen Savers |
--servicedir |
~/Library/Services |
--dictionarydir |
~/Library/Dictionaries |
--appimagedir |
~/Applications (Linux AppImages) |
(There are more, for input methods, audio/VST plugins, internet plugins, Spotlight importers and keyboard layouts.) Set them once and for all with HOMEBREW_CASK_OPTS:
export HOMEBREW_CASK_OPTS="--appdir=~/Applications --fontdir=/Library/Fonts"
--language picks a preferred language for casks that ship localized downloads, e.g. brew install --cask --language=de some-app.
Note
Some apps update themselves (via Sparkle or a built-in updater). Those casks are marked
auto_updates trueand are skipped bybrew upgradeto avoid version conflicts — see the FAQ. Force them withbrew upgrade --greedyor by naming the cask explicitly.
10. Background Services
brew services manages long-running background programs (databases, web servers, etc.) using macOS's launchctl or Linux's systemctl.
brew services list # show all managed services and their state
brew services start postgresql@16 # start now AND at login
brew services stop postgresql@16 # stop now and stop auto-starting
brew services restart postgresql@16
brew services run postgresql@16 # run now WITHOUT registering to auto-start
brew services info postgresql@16 # details about one service
brew services cleanup # remove unused service files
Operate on everything at once with --all:
brew services stop --all
User services vs. system (boot) services
By default services run as you, starting at login, from ~/Library/LaunchAgents (macOS) or ~/.config/systemd/user (Linux).
Prefix with sudo to run a service system-wide, starting at boot, from /Library/LaunchDaemons (macOS) or /usr/lib/systemd/system (Linux):
sudo brew services start postgresql@16
Caution
Running services with
sudois the one place Homebrew intentionally uses elevated privileges. Only do this for services that genuinely must start at boot or run as a different user. When yousudo brew services startas root, Homebrew may takerootownership of some of the formula's paths and will warn you — those then requiresudo rmto remove during upgrade/uninstall.
Handy flags: --file=<path> to start from a custom service file, --keep (with stop) to keep a service registered while stopping it, --no-wait/--max-wait=<secs> to control how long stop waits, and --json for machine-readable list/info output.
11. Reproducible Setups with a Brewfile
brew bundle records and restores your entire Homebrew setup from a single Brewfile — formulae, casks, taps, Mac App Store apps, and even VS Code extensions and several other package ecosystems. It's the right way to move to a new machine or keep a fleet consistent.
Capture your current setup
brew bundle dump # write a Brewfile in the current directory
brew bundle dump --global # write to ~/.Brewfile
brew bundle dump --force # overwrite an existing Brewfile
brew bundle dump --describe # add a comment describing each entry
A Brewfile looks like:
tap "homebrew/cask-fonts"
brew "wget"
brew "node"
cask "firefox"
mas "Xcode", id: 497799835
vscode "ms-python.python"
Restore it
brew bundle install # install everything in ./Brewfile
brew bundle --file=~/.Brewfile # use a specific file
brew bundle upgrade # install + upgrade outdated entries
Keep it tidy and check it
brew bundle list # list dependencies in the Brewfile
brew bundle check # verify everything in the Brewfile is installed
brew bundle cleanup # show what's installed but NOT in the Brewfile
brew bundle cleanup --force # actually uninstall those extras
brew bundle add wget # add an entry
brew bundle remove wget # remove matching entries
Tip
brew bundle exec,brew bundle shandbrew bundle envrun commands (or a shell) in an isolated environment containing only your Brewfile's dependencies. This is great for builds that must not accidentally pick up other installed software.
The Brewfile can be filtered to specific ecosystems on most subcommands with --formula, --cask, --tap, --mas, --vscode, --go, --cargo, --uv, --flatpak (Linux), --winget (WSL), --krew and --npm.
12. Taps: Third-Party Repositories
A tap is a Git repository of extra formulae, casks, and/or commands. Tapping one makes its packages installable as if they were built in. This is Homebrew's extension mechanism.
brew tap # list installed taps
brew tap user/repo # tap a GitHub repo (github.com/user/homebrew-repo)
brew tap user/repo https://... # tap from any Git URL (SSH, GitLab, etc.)
brew install user/repo/formula # install from a tap
brew untap user/repo # remove a tap
brew tap-info --installed # details about installed taps
The one-argument form is a GitHub shortcut: brew tap user/repo clones https://github.com/user/homebrew-repo. The two-argument form accepts any URL and protocol Git understands.
Note
homebrew/core(formulae) andhomebrew/cask(casks) are the official taps. By default Homebrew reads them from a fast JSON API rather than cloning them, sobrew tapmay not list them. To work with a local copy (needed to edit formulae yourself) setHOMEBREW_NO_INSTALL_FROM_API=1and runbrew tap --force homebrew/core.
Warning
Tapping a third-party repository means trusting its maintainers — its formulae run code on your machine. Homebrew is gaining a tap-trust system (
brew trust, controlled byHOMEBREW_REQUIRE_TAP_TRUST); see the Admin Guide's Security section. Only tap repositories you trust.
13. Shell Integration
Tab completion
Homebrew ships completions for Bash, Zsh and Fish. They're enabled automatically when Homebrew is on your PATH via brew shellenv. To control whether Homebrew links completions provided by taps:
brew completions state # show current state
brew completions link # enable tap completions
brew completions unlink # disable them
For Zsh, make sure Homebrew's completions directory is on your FPATH before compinit runs — brew shellenv handles this.
"Command not found" suggestions
When you run a command you don't have, Homebrew can suggest the formula that provides it. Set up the hook:
brew command-not-found-init # prints the hook; add its output to your shell rc
You can also query it directly:
brew which-formula wget # which formula provides `wget`
brew which-formula --explain wget # plus how to install it
Running tools without a permanent install
brew exec --formulae=jq,yq -- ./script.sh # add jq + yq to PATH, run a script
brew exec cowsay "moo" # find/install a tool and run it
14. Advanced Usage
Link and unlink
Linking creates the symlinks from a keg into the prefix; it happens automatically on install but you can do it by hand:
brew unlink node # remove node's symlinks (temporarily disable it)
brew link node # restore them
brew link --overwrite node # overwrite conflicting files while linking
brew link --dry-run node # preview
This is the standard trick for switching between versioned formulae, e.g. brew unlink node && brew link node@20.
Keg-only formulae
Some formulae (often ones that would shadow macOS-provided tools) are installed keg-only: present in the Cellar but not symlinked onto your PATH. brew info <formula> explains why and prints the PATH/PKG_CONFIG_PATH exports you need to use it. You can force it onto your PATH with brew link --force <formula>, but that may shadow system software.
Build from source / bleeding edge
brew install --build-from-source wget # compile rather than pour a bottle
brew install --HEAD some-formula # install the latest unreleased code
brew reinstall --build-from-source wget # rebuild from source
Fetch without installing
brew fetch node # download the bottle/source (and print checksums)
brew fetch --deps node # also fetch dependencies
brew fetch --HEAD node # fetch the HEAD version
History and logs
brew log node # git log for a formula
brew log -p node # with patches
brew gist-logs node # upload a failed build's logs to a Gist for a bug report
15. Configuration You'll Actually Use
Homebrew is configured through HOMEBREW_* environment variables. Set them in your shell profile (~/.zshrc, ~/.bash_profile, etc.). Variables must have a value — use export HOMEBREW_NO_AUTO_UPDATE=1, not a bare export.
These are the ones users reach for most often. The complete ~110-variable reference is in the Admin Guide.
| Variable | Effect |
|---|---|
HOMEBREW_NO_AUTO_UPDATE |
Don't auto-run brew update before installs/upgrades. |
HOMEBREW_AUTO_UPDATE_SECS |
Minimum seconds between auto-updates (default 86400 = 24h). |
HOMEBREW_NO_INSTALL_CLEANUP |
Don't auto-cleanup after installs or every 30 days. |
HOMEBREW_NO_CLEANUP_FORMULAE |
Comma-separated formulae to exclude from cleanup/autoremove. |
HOMEBREW_CLEANUP_MAX_AGE_DAYS |
Age threshold for cached-download cleanup (default 120). |
HOMEBREW_NO_ANALYTICS |
Disable anonymous usage analytics. |
HOMEBREW_NO_EMOJI |
Don't print the 🍺 on a successful build. |
HOMEBREW_NO_COLOR |
Disable coloured output. |
HOMEBREW_CASK_OPTS |
Default options for all cask commands, e.g. --appdir=~/Applications. |
HOMEBREW_EDITOR |
Editor for brew edit (falls back to $EDITOR/$VISUAL). |
HOMEBREW_CACHE |
Override the download-cache directory. |
HOMEBREW_NO_INSTALL_UPGRADE |
brew install <x> won't upgrade <x> if it's already installed but outdated. |
HOMEBREW_ASK |
Default to --ask (preview + confirm) on install/upgrade/reinstall. |
HOMEBREW_DOWNLOAD_CONCURRENCY |
Parallel download connections (auto = 2× CPU cores; 1 = serial). |
HOMEBREW_MAKE_JOBS |
Parallel build jobs (default = CPU cores). |
Behind a proxy, Homebrew honours the standard http_proxy, https_proxy, all_proxy, ftp_proxy and no_proxy variables for its curl/git/svn downloads.
export HTTPS_PROXY=http://proxy.example.com:8080
Note
brew analyticscontrols usage analytics interactively:brew analytics offturns them off (equivalent toHOMEBREW_NO_ANALYTICS=1),brew analytics stateshows the current setting. Read more at https://docs.brew.sh/Analytics.
16. Troubleshooting
Important
Before anything else, run
brew updateandbrew doctor. Most problems are already fixed upstream or flagged by the doctor. When you file a bug, include the output ofbrew configandbrew doctor.
Error: brew complains about absence of "Command Line Tools"
Cause: On macOS, the Xcode Command Line Tools aren't installed.
Solution: Run xcode-select --install in the terminal and follow the prompts.
Prevention: Reinstall them after every major macOS upgrade (see below).
Error: build failures after upgrading macOS
Symptoms after a macOS upgrade look like dyld: Library not loaded: /opt/homebrew/opt/icu4c/lib/libicui18n.76.dylib or configure: error: Cannot find libz.
Cause: A macOS upgrade invalidates the old Command Line Tools and some built binaries. Solution:
xcode-select --install
brew upgrade
Error: brew update complains about untracked working tree files
Cause: A long-since-fixed bug left stray files in Homebrew's Git checkout. Solution:
cd "$(brew --repository)"
git reset --hard FETCH_HEAD
# if brew doctor still complains:
cd "$(brew --repository)/Library"
git clean -fd
Error: Could not link <formula> ... Target ... already exists
Warning: Could not link <formula>. Unlinking...
Error: The `brew link` step did not complete successfully
Cause: A file Homebrew wants to symlink already exists in the prefix (often left by a non-Homebrew install). Solution: Inspect the listed conflicting files. If you're sure they're safe to replace:
brew link --overwrite --dry-run <formula> # list what would be deleted
brew link --overwrite <formula> # do it
Error: cask download fails with a cURL error
Cause: Most often a stray ~/.curlrc, an outdated cask URL, or a network/vendor problem.
Solution: Check for and remove a ~/.curlrc (ls -A ~ | grep .curlrc) and retry. If the vendor's own download link (brew home <cask>) also fails, the problem is upstream, not Homebrew. If the link works but the cask doesn't, the cask is outdated — consider submitting a fix.
Error: cask "permission denied" writing to /Applications
Cause: Your account lacks write access to /Applications, or the Caskroom isn't owned by you.
Solution: Install to a writable directory with --appdir=~/Applications, or fix Caskroom ownership:
sudo chown -R "$(whoami)" "$(brew --caskroom)"
Cask apps lose their Dock/Launchpad position or permissions after upgrade
Cause: Without "App Management" or "Full Disk Access" permission, Homebrew falls back to uninstall-then-reinstall, which makes macOS forget the app's metadata. Solution: Grant your terminal app App Management or Full Disk Access in System Settings → Privacy & Security. Homebrew then does in-place upgrades that preserve metadata.
Two Homebrew installations (after Migration Assistant)
Cause: Migration Assistant copied an Intel Mac's /usr/local Homebrew onto an Apple Silicon Mac, which should use /opt/homebrew.
Solution: Verify your terminal runs in arm64 mode (arch prints arm64), reinstall Homebrew under /opt/homebrew, restore your packages with brew bundle, then uninstall the old /usr/local install. The full procedure is in Homebrew's Common Issues docs.
My GUI apps can't find Homebrew tools
Cause: macOS GUI apps don't inherit your shell's PATH.
Solution:
sudo launchctl config user path "$(brew --prefix)/bin:${PATH}"
# then reboot
Nothing here matches
brew doctor # diagnose
brew config # gather system info for a report
brew gist-logs <formula> # share a failed build's logs
If a totally broken install can't be repaired, the cleanest reset is to brew bundle dump, uninstall Homebrew, reinstall it, and brew bundle install.
17. FAQ
Q: How do I update everything?
Run brew update (refresh definitions), then brew outdated (see what's old), then brew upgrade (upgrade it). Upgrade one package with brew upgrade <formula>.
Q: How do I stop a formula from being upgraded?
brew pin <formula>. Allow it again with brew unpin <formula>. To stop Homebrew from even learning about new versions, export HOMEBREW_NO_AUTO_UPDATE=1.
Q: How do I keep old versions when upgrading?
By default Homebrew removes old versions on upgrade and during periodic cleanup. Disable that with export HOMEBREW_NO_INSTALL_CLEANUP=1 (or per-package with HOMEBREW_NO_CLEANUP_FORMULAE=foo,bar).
Q: Where does Homebrew download things?
brew --cache (usually ~/Library/Caches/Homebrew on macOS).
Q: Why does installing one thing upgrade a bunch of others? Homebrew only tests the latest combination of all package versions, so a dependency upgrade can cascade. This keeps your system in a supported state.
Q: Why does Homebrew refuse to run under sudo?
Build scripts run arbitrary code; running them as root would let a malicious or buggy build modify anything on your system. Homebrew installs into a user-owned prefix specifically so sudo is unnecessary. (System-wide services are the deliberate exception, and even then only the service runs elevated.)
Q: What does "keg-only" mean?
The formula is installed into the Cellar but not symlinked into the prefix, usually to avoid shadowing a macOS-provided tool. brew info <formula> explains why and how to put it on your PATH.
Q: Why aren't some cask apps upgraded by brew upgrade?
Apps that update themselves are marked auto_updates true and skipped to avoid version conflicts. Upgrade them explicitly with brew upgrade <cask> or brew upgrade --greedy, or set HOMEBREW_UPGRADE_AUTO_UPDATES_CASKS=1.
Q: Can I edit formulae myself?
Yes. Set HOMEBREW_NO_INSTALL_FROM_API=1, run brew tap --force homebrew/core to get a local copy, then brew edit <formula>. brew update will even merge your edits with upstream. Undo all local changes with brew update-reset.
Q: Why can't I open a Mac app from an "unidentified developer"? That's Apple's Gatekeeper, not Homebrew. Right-click the app, choose Open, and confirm — only for apps you trust. Leave system-wide protection on.
Q: Why isn't a particular brew command documented in man brew?
It's probably an external command from a tap; run brew <command> --help.
Q: How do I completely uninstall Homebrew?
Run the official uninstall script: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)".
18. Command Reference
Get help for any command with brew help <command> or brew <command> --help. man brew has the complete manual.
Global options
These work across most commands and must appear after the command name (e.g. brew install -v node):
| Option | Meaning |
|---|---|
-d, --debug |
Display debugging information (and, on build failure, open a debug shell). |
-q, --quiet |
Make output more quiet. |
-v, --verbose |
Make output more verbose. |
-h, --help |
Show help for the command. |
Installing & removing
| Command | Purpose |
|---|---|
install |
Install a formula or cask. |
reinstall |
Uninstall and reinstall with the same options. |
uninstall (remove, rm) |
Remove a formula or cask. |
autoremove |
Remove no-longer-needed dependencies. |
pin / unpin |
Prevent / allow upgrades of a package. |
link (ln) / unlink |
Add / remove a formula's symlinks in the prefix. |
fetch |
Download a package (and dependencies) without installing. |
postinstall |
Re-run a formula's post-install steps. |
Updating
| Command | Purpose |
|---|---|
update (up) |
Refresh Homebrew and all package definitions. |
update-if-needed |
Update only if due (script-friendly). |
outdated |
List packages with newer versions available. |
upgrade |
Upgrade outdated, unpinned packages. |
update-reset |
Hard-reset Homebrew's Git repos to upstream (destroys local changes). |
migrate |
Migrate renamed packages to their new names. |
Discovering & inspecting
| Command | Purpose |
|---|---|
search (-S) |
Substring/regex search of names and tokens (extends online). |
info (abv) |
Show details about a package or your install. |
desc |
Show / search one-line descriptions. |
home (homepage) / source |
Open a package's homepage / source repo in a browser. |
list (ls) |
List installed packages (or a keg's files). |
deps / uses |
Show dependencies / dependents of a formula. |
leaves |
List formulae nothing depends on. |
missing |
Check for missing dependencies. |
options |
Show a formula's install options. |
formulae / casks |
List all installable formulae / casks. |
log |
Show a package's git log. |
config (--config) |
Show Homebrew + system configuration. |
doctor (dr) |
Diagnose potential problems. |
--prefix / --cellar / --caskroom / --cache / --repository / --version |
Show key paths and versions. |
Casks, services, bundles & taps
| Command | Purpose |
|---|---|
bundle |
Manage a Brewfile (dump, install, upgrade, check, cleanup, add, remove, list, exec, sh, env). |
services |
Manage background services (list, start, stop, restart, run, kill, info, cleanup). |
tap / untap |
Add / remove a third-party repository. |
tap-info |
Show details about taps. |
trust / untrust |
Trust / untrust a non-official tap, formula, cask or command. |
Shell & environment
| Command | Purpose |
|---|---|
shellenv |
Print export lines to add Homebrew to your shell. |
completions |
Control linking of tap shell completions. |
command-not-found-init |
Print the "command not found" hook. |
which-formula |
Find which formula provides a command. |
exec (x) |
Run a command in a Homebrew-populated environment. |
analytics |
View / toggle anonymous usage analytics. |
developer |
Toggle Homebrew's developer mode. |
commands / command |
List commands / show a command's file path. |
help |
Show usage for a command. |
Note
Homebrew also has ~60 developer commands (
audit,create,edit,bump-formula-pr,style,test,livecheck, and more) for people who write and maintain formulae. Those are documented in the Admin Guide, which also carries the completeHOMEBREW_*environment-variable reference, Homebrew's architecture, and its security model.