On an Apple Silicon Mac, Homebrew installs to /opt/homebrew/bin, and that folder is not on your PATH by default. Add this line to the end of ~/.zprofile, then open a new Terminal window:
eval "$(/opt/homebrew/bin/brew shellenv)"
On an Intel Mac, Homebrew uses /usr/local/bin instead, which macOS already includes in PATH. That’s why most people who hit this error are on an M1, M2, M3 or M4 Mac. The same idea fixes npm, node and other tools installed with Homebrew. python, pip and code have different causes, covered below.
Why zsh can’t find brew
zsh looks for commands only in the folders listed in PATH. The default list comes from /etc/paths. On my test Mac (MacBook Air M3, macOS Tahoe 26.6.2) it contains:
/usr/local/bin
/System/Cryptexes/App/usr/bin
/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin is there. /opt/homebrew/bin is not. To show the problem, I started a clean zsh with only the system PATH and no personal config:
zsh:1: command not found: brew
zsh:1: command not found: npm
zsh:1: command not found: python
zsh:1: command not found: pip
In a normal Terminal window, the message reads zsh: command not found: brew. Brew was installed the whole time:
ls /opt/homebrew/bin/brew
uname -m
uname -m printed arm64, and /usr/local/bin/brew did not exist. If you get x86_64, you’re on Intel (or in a Rosetta terminal), and brew should be at /usr/local/bin/brew.
The fix: brew shellenv in ~/.zprofile
The Homebrew installer prints this step under “Next steps” at the end, and it’s easy to miss. Here’s what brew shellenv outputs on this Mac:
/opt/homebrew/bin/brew shellenv
export HOMEBREW_PREFIX="/opt/homebrew";
export HOMEBREW_CELLAR="/opt/homebrew/Cellar";
export HOMEBREW_REPOSITORY="/opt/homebrew";
fpath[1,0]="/opt/homebrew/share/zsh/site-functions";
export FPATH;
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin${PATH+:$PATH}";
[ -z "${MANPATH-}" ] || { export MANPATH="${MANPATH%"${MANPATH##*[!:]}"}"; export MANPATH=":${MANPATH#"${MANPATH%%[!:]*}"}"; };
export INFOPATH="/opt/homebrew/share/info:${INFOPATH:-}";
It puts /opt/homebrew/bin and /opt/homebrew/sbin at the front of PATH and sets up zsh completions. Wrapping it in eval "$(...)" runs those lines in your shell.
To add it permanently:
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
Use the full path /opt/homebrew/bin/brew here, not brew. The whole point is that brew can’t be found yet.
I didn’t edit my real ~/.zprofile for this test. I put that one line in a .zprofile inside a scratch folder and pointed zsh at it with ZDOTDIR. After that, a login shell found everything:
/opt/homebrew/bin/brew
/opt/homebrew/bin/npm
Gotcha: .zprofile only runs in login shells
The same scratch config gave different results depending on how zsh started:
| How zsh started | command -v brew |
|---|---|
Login shell (zsh -l) | /opt/homebrew/bin/brew |
Non-login shell (zsh -c) | not found |
Terminal.app opens login shells, so ~/.zprofile works there. But some tools start non-login shells, such as scripts, cron jobs and some editor terminals. If brew works in Terminal but not inside a tool, that’s the reason. You can put the line in ~/.zshrc too. For more on which file does what, see how to set an environment variable permanently on Mac.
Editing the file doesn’t change windows that are already open. Open a new tab, or run source ~/.zprofile.
Gotcha: running it twice doesn’t duplicate PATH
Many people end up with the line in both .zprofile and .zshrc. I tested this by running the eval twice in one shell. PATH was identical after the second run:
PATH=/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
The reason: when /opt/homebrew/bin is already on PATH, brew shellenv simply leaves out the export PATH line. I counted it in both cases. It was there once with a plain PATH and zero times with Homebrew already on PATH (Homebrew 7.0.11). Older Homebrew versions may behave differently.
“command not found: python” (use python3)
macOS has no python command at all, only python3:
command -v python
command -v python3
which -a python3
python3 --version
/usr/bin/python3
/usr/bin/python3
Python 3.9.6
The first command printed nothing, because python doesn’t exist. /usr/bin/python3 is a small Apple shim. The Python it runs comes from Xcode Command Line Tools:
/Library/Developer/CommandLineTools/usr/bin/python3
That’s sys.executable on this Mac, and xcode-select -p pointed to /Library/Developer/CommandLineTools. Without the Command Line Tools installed, macOS offers to install them the first time you run python3. That case wasn’t tested here.
Your options:
- Type
python3instead ofpython. This is the simplest fix. - Add
alias python=python3to~/.zshrc. I tested this with a scratch.zshrc, andpython --versionthen printedPython 3.9.6. - Install a newer Python (
brew install python, pyenv or uv) if you need something newer than 3.9. Note thatwhich -a python3lists every match in PATH order. The first line wins.
“command not found: pip” (use pip3 or python3 -m pip)
Same story. There’s pip3 but no pip:
command -v pip
command -v pip3
python3 -m pip --version
/usr/bin/pip3
pip 21.2.4 from /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/site-packages/pip (python 3.9)
Prefer python3 -m pip install .... It always uses the pip that belongs to the python3 you’re running. With several Pythons installed, plain pip3 can point to a different one.
“command not found: npm” or node
If you installed Node with Homebrew, npm and node sit next to brew, in /opt/homebrew/bin. On this Mac, command -v npm printed /opt/homebrew/bin/npm. The brew shellenv fix above fixes them too. If you used the installer from nodejs.org, it puts them in /usr/local/bin, which is already on PATH. If you used nvm, its setup lines in ~/.zshrc are missing or broken.
“command not found: code” (VS Code)
VS Code doesn’t add the code command for you. Open VS Code, press Cmd+Shift+P, and run Shell Command: Install ‘code’ command in PATH. It creates a link at /usr/local/bin/code. I didn’t run this, because VS Code isn’t installed on the test Mac.
That led to a real surprise, though. code already worked:
command -v code
ls -l /usr/local/bin/code
/usr/local/bin/code
lrwxr-xr-x 1 root wheel 56 Apr 5 2025 /usr/local/bin/code -> /Applications/Cursor.app/Contents/Resources/app/bin/code
The code command pointed to Cursor, not VS Code. Editors built on VS Code can install their own code command at the same path. Whichever editor installed last owns it. If code . opens the wrong app, run ls -l "$(command -v code)" to see where it points, then run the Shell Command again from the editor you want.
Common questions
How do I check where any command comes from?
Use command -v name for the first match, or which -a name for all matches in PATH order. No output means zsh can’t find it.
Do I need to reinstall Homebrew?
No. If /opt/homebrew/bin/brew exists, only PATH is missing. Reinstalling won’t change that.
Why did this start after I migrated from an Intel Mac?
Migration Assistant copies your old ~/.zprofile, which may refer to /usr/local. On Apple Silicon, update it to the /opt/homebrew line above.
Is it safe to edit ~/.zprofile?
Yes, it’s a plain text file in your home folder. Files starting with a dot are hidden in Finder. See how to show hidden files on Mac to view them.