dotfilesshell

The PATH Environment Variable, Dotfiles and Shell Configuration Files

I once spent two hours debugging why 'node' wouldn't run after installing it. Turns out my PATH was broken. Here's what I wish I'd known about shell configuration.

·5 min read

I installed Node.js via Homebrew once and spent two hours trying to figure out why node wouldn't run in my terminal. The command just returned command not found even though I'd successfully installed it. Homebrew confirmed it was there. I could see the binary in /usr/local/bin/node.

Turns out my PATH was misconfigured and my shell couldn't find it.

That's when I finally learned how PATH, dotfiles, and shell configuration actually work. Here's what I wish someone had explained to me from the start.

What is a Shell?

Your shell is the program that interprets the commands you type in a terminal. When you type git status or npm install, your shell finds and executes those programs.

Most people use one of these:

  • Bash - Default on Linux and older macOS versions
  • Zsh - Default on modern macOS (since Catalina)
  • Fish - More beginner-friendly with better autocomplete

Check which shell you're using:

echo $SHELL

When I switched from Bash to Zsh, half my commands stopped working because I hadn't migrated my configuration. Learned that lesson fast.

What is PATH and Why It Broke My Setup

PATH is a list of directories your shell searches to find commands. When you type node, your shell checks each directory in PATH until it finds a node executable.

Check your current PATH:

echo $PATH

You'll see something like:

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

Those are directories separated by colons. The shell searches left to right, top to bottom. First match wins.

This is why order matters. If you have Node.js installed in two places, the shell uses whichever one it finds first in PATH.

My Node.js problem? /usr/local/bin wasn't in my PATH at all. The shell couldn't find the binary even though it existed on my system. Once I added /usr/local/bin to PATH, node worked immediately.

How to Modify PATH with export

To add a directory to PATH, use the export command:

export PATH="$HOME/bin:$PATH"

This prepends ~/bin to your existing PATH. Now your shell checks ~/bin before all other directories.

Breaking it down:

  • export makes the variable available to child processes (any programs you run from this shell)
  • $HOME/bin is the new directory you're adding
  • :$PATH appends your existing PATH after it

The order matters. Put the directory first if you want it to take priority.

I once had two versions of Python installed - one from Homebrew, one from the system. The wrong one kept running because the system Python's directory was listed first in PATH. Fixed it by prepending the Homebrew directory.

Shell Scripting Languages

Each shell has its own scripting language:

  • Bash - The most common, works on Linux and macOS
  • Zsh - Similar to Bash with extra features (better autocomplete, themes)
  • Fish - Different syntax, more beginner-friendly

Your .bashrc or .zshrc files are written in these languages. They're scripts that run every time you open a new terminal.

Most commands work across all shells (echo, export, cd). But there are subtle differences in things like arrays and functions. I learned this when a Bash script broke in Zsh because I used a Bash-specific array syntax.

Dotfiles - Where Configuration Lives

Dotfiles are hidden config files in your home directory. They control your shell behavior, aliases, and environment variables.

Common dotfiles:

  • .bashrc - Runs every time you open a new Bash terminal
  • .zshrc - Same but for Zsh
  • .profile or .bash_profile - Runs once when you log in

See your dotfiles:

ls -la ~/ | grep "^\."

Here's what my .zshrc looks like:

# Add pnpm to PATH
export PNPM_HOME="$HOME/Library/pnpm"
export PATH="$PNPM_HOME:$PATH"

# Git aliases
alias gs="git status"
alias gp="git push"
alias gc="git commit"

# Custom prompt
export PS1="%n@%m %~ %> "

Breaking down the prompt:

  • %n - Username
  • %m - Computer name
  • %~ - Current directory (abbreviated)
  • %> - A > character

Every time I open a terminal, Zsh runs this file. PATH gets modified, aliases load, prompt gets customized. It's automatic.

Real-World Debugging Example

I installed pnpm recently and it wouldn't run. Checked the PATH:

echo $PATH

Pnpm wasn't there. Checked my .zshrc - the pnpm PATH export was missing. Added this:

export PATH="$HOME/Library/pnpm:$PATH"

Reloaded the shell:

source ~/.zshrc

Boom. pnpm command worked.

This is the cycle with PATH issues:

  1. Install a tool
  2. Command not found
  3. Check PATH
  4. Add the directory to PATH in your dotfile
  5. Reload shell
  6. Fixed

Common Mistakes I've Made

Mistake 1: Editing the wrong dotfile

Bash uses .bashrc. Zsh uses .zshrc. I edited .bashrc while using Zsh. Nothing worked. Check which shell you're using first (echo $SHELL).

Mistake 2: Not reloading the shell

Changed .zshrc but didn't reload. The old config was still active. Either restart your terminal or run source ~/.zshrc.

Mistake 3: Overwriting PATH instead of prepending

Wrote export PATH="/new/path" instead of export PATH="/new/path:$PATH". Wiped out my entire PATH. Nothing worked. Always append :$PATH to preserve existing directories.

Keep It Simple

Don't overcomplicate your dotfiles. Mine is 50 lines total - PATH modifications, a few aliases, that's it.

I've seen .zshrc files with 500+ lines, custom themes, 20 plugins. Cool, but harder to debug when something breaks.

Start minimal. Add things as you need them. Your future self will thank you when you're troubleshooting why a command suddenly stopped working.