Have you ever opened your Mac Terminal, typed a command like python, and wondered “how does my computer even know what to run”?
Or maybe you’ve tried changing your Python version, only to find the Terminal stubbornly still using the old one.
To understand all that, we need to peek behind the curtain and see what’s really going on when you open a shell.
1. What exactly is a “shell”?#
The Terminal is just a window — a text interface that lets you talk to your computer. But the real brain behind it is something called a shell.
A shell is a command interpreter: it takes what you type, translates it, and tells the operating system what to do.
Common shells include:
- bash – used to be the default on macOS
- zsh – the new default shell on macOS (since Catalina)
- fish, tcsh, and others
You can check which one you’re using by typing:
echo $SHELLIf you see /bin/zsh, congratulations — you’re talking to zsh.
2. What happens when you open a Terminal window?#
When you open Terminal (or the integrated terminal in VS Code), your system launches a shell program.
Here is how it looks:

Before it shows you that little blinking cursor, what is under the hood is that the shell first loads a few configuration files that tell it:
- what your environment variables are,
- where to look for programs,
- what aliases you’ve defined,
- and even how your prompt looks.
Don’t worry if you don’t know what those concepts mean! In simple terms:
- Environment variables are like little notes the system keeps to remember important settings — for example, where Python is installed, or which editor to use by default.
- Programs are just the command-line tools you run, like
python,git, orls. The shell needs to know where on your computer these tools live. - Aliases are shortcuts you create to save time — for instance, you can make
gsmeangit status. But we don’t recommend this and it is better to use the normal names. - How your prompt looks means the style of that line before your cursor (like
MacBook ~ %or(base) user@MacBook %), which you can customize to show your username, folder, or virtual environment.
Think of it as the shell’s “morning routine” — washing up, putting on clothes, and getting ready for the day.
3. What are .zprofile and .zshrc?#
Both are configuration files for zsh, but they serve different purposes.
.zprofile: the “morning setup”#
This file runs only when you log in (for example, when you open a new Terminal window or log in via SSH).
It’s used to set up environment variables and system paths (basically, things that should be configured once per session).
Typical contents:
# Add Homebrew to PATHexport PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
# Add pyenvexport PATH="$HOME/.pyenv/bin:$PATH"Why do you need to add Homebrew to PATH?#
You need to add Homebrew’s bin folder to your PATH so your shell knows where to find the programs that Homebrew installs.
If you don’t, you can install a package like python or git via Homebrew, but when you type python or git in the Terminal, the system will still use the old built-in versions — because it doesn’t know Homebrew’s versions exist (they’re “in a different folder”).
If you want to know more, the following in-depth explanation will help you to understand better:
When you type any command in the Terminal (say python), your shell doesn’t magically know what that is.
It checks every folder listed in your PATH variable, in order, until it finds a matching file named python.
On macOS:
- The system’s own tools live in places like
/usr/binand/bin. - Homebrew installs everything under
/opt/homebrew/bin(on Apple Silicon Macs) or/usr/local/bin(on Intel Macs).
But by default, the system’s PATH usually looks like:
/usr/bin:/bin:/usr/sbin:/sbinwhich does not include Homebrew’s directory.
That means if you install a newer python with Homebrew, it goes into /opt/homebrew/bin/python3,
but your shell will never look there unless you tell it to — by adding it to the PATH.
So we write in .zprofile:
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"This prepends Homebrew’s folder to the PATH, so when you type python, your shell will find the Homebrew version first, before the system one.
Why it’s not always “automatic”
Sometimes, when you install Homebrew, it does show you a message like:
==> Next steps:- Add Homebrew to your PATH in your shell profile: (echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile)That’s because Apple doesn’t let installers modify your shell config automatically for security reasons. So Homebrew politely tells you what to add, but you have to paste it yourself.
Once you add it, it’s “automatic” from then on, because every time your shell starts, .zprofile runs and updates PATH.
Quick summary
| Concept | Meaning |
|---|---|
| Homebrew installs programs to | /opt/homebrew/bin (Apple Silicon) |
| macOS system PATH originally points to | /usr/bin, /bin, etc. |
| So without editing PATH | The shell keeps using the old system tools |
| Adding Homebrew to PATH | Tells the shell: “look here first for my new programs” |
.zshrc: the “daily tools”#
This file runs every time you start an interactive shell, meaning every new Terminal tab or VS Code terminal. It’s where you put aliases, prompts, and shell behavior.
Example:
# Initialize pyenvif command -v pyenv 1>/dev/null 2>&1; then eval "$(pyenv init -)"fi
# Add some shortcutsalias ll="ls -alF"alias gs="git status"In short:
| File | When it runs | What it’s for |
|---|---|---|
.zprofile | At login | Set up environment (PATH, variables) |
.zshrc | Every new shell | Customize interaction (aliases, functions, prompts) |
4. Why does PATH matter so much?#
PATH is one of the most important environment variables in your shell.
It tells the shell where to look for programs when you type a command.
For example, when you type:
pythonyour shell doesn’t magically know where Python is.
It looks through all the folders listed in PATH, from left to right, and runs the first python file it finds.
You can see your current PATH like this:
echo $PATHIt looks like a long list separated by colons:
/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbinSo if you installed Python 3.12 in /opt/homebrew/bin, but /usr/bin (which has Python 3.9) comes first —
the shell will find and use the 3.9 version before even looking at the newer one.
That’s why PATH order matters, and why sometimes “changing Python” doesn’t seem to work: your system still finds the old one first.
5. Why do VS Code and Terminal sometimes behave differently?#
Here’s a common mystery:
you fix your PATH in .zprofile, everything works in Terminal —
but VS Code’s built-in terminal still shows the old Python version.
That’s because:
- Terminal opens a login shell → runs
.zprofile+.zshrc - VS Code opens a non-login shell → runs only
.zshrc
The fix?
Move PATH settings into .zprofile, and keep behavior settings in .zshrc.
This ensures both environments stay consistent.
6. A quick mental model#
You can think of zsh’s startup like this:
When you open Terminal: 1. Run ~/.zprofile → set up PATH and environment 2. Run ~/.zshrc → load tools, aliases, and pyenv 3. Show prompt → ready for commands!It’s like:
.zprofile= getting dressed.zshrc= picking your work tools for the day
7. A simple recommended setup#
Here’s a safe, beginner-friendly setup for macOS:
~/.zprofile
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"export PATH="$HOME/.pyenv/bin:$PATH"~/.zshrc
if command -v pyenv 1>/dev/null 2>&1; then eval "$(pyenv init -)"fi
alias ll="ls -alF"alias gs="git status"After saving, restart your Terminal (or VS Code), and everything will load cleanly.
8. Summary#
| Concept | What it means |
|---|---|
| Terminal | Just a window to talk to your system |
| Shell (zsh) | The interpreter that runs your commands |
| .zprofile | Runs once at login, sets up environment (PATH, variables) |
| .zshrc | Runs for every new shell, defines tools and aliases |
| PATH | A list of directories that tells your shell where to find programs |
| Order matters! | The first match in PATH always wins |
9. Final analogy#
Think of your shell like your morning routine:
.zprofileis brushing your teeth and putting on clothes and it is done once per day..zshrcis grabbing your favorite tools before you start each new task.PATHis your toolbox, and its order decides which hammer you grab first.
Once you understand these three, the mysterious behavior of your Terminal suddenly becomes logical and fixable.