Let’s say you install a tool. Maybe it’s Node, or maybe it’s a CLI for a project you just cloned. The installer runs successfully.
Then you open your terminal and type:
node
And your shell responds:
zsh: command not found: node

A completely normal reaction to seeing “command not found.”
At some point, most of us have Googled a fix, copy-and-pasted something like export PATH=..., and moved on without really understanding what we changed.
For years, that was me. 🫣 Eventually, enough mysterious version conflicts and broken environments forced me to learn what the PATH environment variable actually does. As it turns out, it’s not magic—and once you understand it, a whole category of terminal confusion disappears.
What the PATH Environment Variable Is
The PATH environment variable is simply a list of directories your shell searches to find commands. When you type a command like:
git status
Your shell looks through each directory listed in PATH and checks:
Is there an executable file named git in here?
The first match it finds, it runs! You can see your current PATH with:
echo $PATH
You’ll get something like:
/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:/Users/jenn/.local/bin
These directories are searched in order, from left to right. That order matters. If two different versions of a tool exist in different directories, whichever appears first in PATH wins.
You can see which version you’re using with:
which git
If it returns:
/usr/bin/git
That’s the exact executable your shell is running.
A Quick Demo: Make Your Own CLI Tool
To make this concrete, let’s create a tiny command-line tool.
First, make a directory:
mkdir -p ~/my-tools
Create a simple script:
touch ~/my-tools/hello
chmod +x ~/my-tools/hello
Edit hello so it contains:
#!/bin/bash
echo "Hello from my custom CLI!"
Now try running:
hello
You’ll likely see:
command not found: hello
Why? Because ~/my-tools isn’t in your PATH. Your shell has no idea it should look there.
To fix that, open your shell configuration file (~/.zshrc or ~/.bashrc) and add:
export PATH="$HOME/my-tools:$PATH"
This line adds your directory to the front of PATH while preserving everything that was already there.
Reload your shell:
source ~/.zshrc
Now try:
hello
And you should see:
Hello from my custom CLI!
That’s PATH in action! 🎉
Tip: Notice we didn’t replace PATH entirely. A common mistake looks like:
export PATH="/my/custom/path"
This overwrites your entire PATH and can break core tools like git or even ls. Always extend PATH using :$PATH so you keep what’s already configured.
Common PATH Problems (and How to Debug Them)
Once you understand PATH, debugging becomes much calmer and more systematic.
1. “Command not found” after installing something.
First, check whether the executable exists:
which node
If nothing returns, find where it was installed and confirm that the directory appears in your PATH:
echo $PATH
If the directory isn’t listed, that’s your issue.
2. The wrong version is running.
which python
python --version
If the path and version don’t match what you expect, you probably have multiple installations. PATH order decides which one wins.
Version managers like nvm, pyenv, and asdf work largely by manipulating PATH under the hood.
3. It works in VS Code but not in your terminal.
Different environments may load different configuration files. If PATH is defined in one file but not another, you’ll see inconsistent behavior.
When in doubt, print echo $PATH in both environments and compare.
What PATH Isn’t
- PATH doesn’t install tools.
- It doesn’t fix broken installations.
- It doesn’t manage versions.
It simply tells your shell where to look when you type a command.
Why Understanding PATH Changes Things
Before I understood PATH, my terminal felt unpredictable. After understanding it, debugging became a checklist:
- Does the executable exist?
- Is its directory in PATH?
- Is PATH ordered correctly?
That shift—from copy-and-pasting fixes to understanding the system—made my development environment feel intentional instead of fragile.
If you use the terminal daily, it’s worth understanding the invisible mechanism behind every command you run. Once you do, “command not found” stops being a mystery and starts being a clue.
And that’s a much better place to be 😌