Skip to content

When You Open the Terminal, What Happens Behind the Scenes

· 6 min

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:

You can check which one you’re using by typing:

Terminal window
echo $SHELL

If 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:

terminal

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:

Don’t worry if you don’t know what those concepts mean! In simple terms:

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:

Terminal window
# Add Homebrew to PATH
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
# Add pyenv
export 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:

But by default, the system’s PATH usually looks like:

/usr/bin:/bin:/usr/sbin:/sbin

which 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:

Terminal window
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

ConceptMeaning
Homebrew installs programs to/opt/homebrew/bin (Apple Silicon)
macOS system PATH originally points to/usr/bin, /bin, etc.
So without editing PATHThe shell keeps using the old system tools
Adding Homebrew to PATHTells 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:

Terminal window
# Initialize pyenv
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
fi
# Add some shortcuts
alias ll="ls -alF"
alias gs="git status"

In short:

FileWhen it runsWhat it’s for
.zprofileAt loginSet up environment (PATH, variables)
.zshrcEvery new shellCustomize 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:

Terminal window
python

your 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:

Terminal window
echo $PATH

It looks like a long list separated by colons:

/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

So 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:

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:

Here’s a safe, beginner-friendly setup for macOS:

~/.zprofile

Terminal window
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
export PATH="$HOME/.pyenv/bin:$PATH"

~/.zshrc

Terminal window
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#

ConceptWhat it means
TerminalJust a window to talk to your system
Shell (zsh)The interpreter that runs your commands
.zprofileRuns once at login, sets up environment (PATH, variables)
.zshrcRuns for every new shell, defines tools and aliases
PATHA 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:

Once you understand these three, the mysterious behavior of your Terminal suddenly becomes logical and fixable.