Understanding the Basics
Before typing commands, understand what you're actually talking to.
A terminal (or terminal emulator) is simply the window application you open to type commands. On macOS it's called Terminal.app or you might use iTerm2. On Windows it's Windows Terminal or PowerShell. On Linux it's GNOME Terminal, Konsole, etc.
Think of it like a text message app -- it's just the interface. The terminal itself doesn't understand your commands. It passes them to something called a shell.
A shell is the interpreter that actually reads and executes your commands. When you type ls, the shell figures out what that means and runs it.
Common shells include Bash (Bourne Again SHell), Zsh (Z Shell), Fish, and sh. They each have slightly different syntax and features, but they all do the same fundamental job: interpret your typed commands.
The kernel is the core of your operating system. It's the software that directly talks to your hardware -- CPU, memory, disk, network cards, etc.
When your shell runs a command like "read this file," it asks the kernel. The kernel is the middleman between software and hardware. You never interact with it directly -- the shell does that for you.
Every command you type flows through these layers:
Since macOS Catalina (2019), the default shell is Zsh. Before that, it was Bash. Linux mostly defaults to Bash.
The good news: they're ~95% the same. Almost every command, pipe, redirect, and script works identically in both. Zsh adds fancier tab-completion, themes (Oh My Zsh), and some syntax sugar. If you learn Bash, you effectively know Zsh too.
echo $SHELL. You'll see /bin/zsh or /bin/bash.
PATH is an environment variable that tells your shell where to look for programs.
Analogy: Imagine your phone's contact list. When you say "call Mom," your phone looks through your contacts to find the number. PATH works the same way -- when you type git, the shell searches through a list of directories (the PATH) to find the git program.
Each directory is separated by :. The shell checks them left to right until it finds the program.
Every program has three standard streams -- think of them as three channels for data:
stdin (standard input) -- data going INTO a program (keyboard input, or piped data).
stdout (standard output) -- normal output from a program (what you see printed).
stderr (standard error) -- error messages. Looks the same as stdout on screen, but it's a separate channel so you can handle errors differently.
These operators let you connect programs and control where data flows:
|
Pipe -- sends stdout of one command as stdin to the next. cat file.txt | grep "error"
>
Redirect stdout -- write output to a file (overwrites). echo "hello" > file.txt
>>
Append stdout -- add output to end of file. echo "world" >> file.txt
<
Redirect stdin -- use a file as input. sort < names.txt
2>
Redirect stderr -- send errors to a file. cmd 2> errors.log
&>
Redirect all -- send both stdout and stderr. cmd &> output.log
Every time you open a new terminal window, your shell starts fresh — it has no memory of what you did before. So how does it remember your preferences, custom commands, and PATH changes? That's what .zshrc is for.
What is .zshrc?
The .zshrc file (short for "zsh run commands") is a script that runs automatically every time you open a new terminal. It lives in your home directory at ~/.zshrc. Think of it as your shell's startup checklist — everything in this file gets executed before you even see the prompt.
.) at the beginning makes it a hidden file. You won't see it in Finder, but it's always there. Use ls -a ~ to see hidden files.How it connects to the Kernel and Shell
Remember the layers from earlier:
Without .zshrc, you'd have to re-type all your preferences every time you open Terminal. The shell reads this file, applies your settings, and then shows you the prompt.
What goes in .zshrc?
# PATH — tell the shell where to find programs export PATH="/opt/homebrew/bin:$PATH" # Aliases — shortcuts for commands you type often alias ll="ls -la" alias gs="git status" alias gp="git push" # Environment variables — settings for programs export EDITOR="code" export ANTHROPIC_API_KEY="sk-ant-..." # Oh My Zsh — loads plugins and themes source ~/.oh-my-zsh/oh-my-zsh.sh # NVM — Node version manager setup export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"
Common .zshrc tasks
export PATH="..."
Add directories so the shell can find new programs (Homebrew, Node, Python)
alias name="cmd"
Create shortcuts — type gs instead of git status
export VAR="val"
Set environment variables that programs read (API keys, editor prefs)
source file.sh
Run another script's commands — used by Oh My Zsh, NVM, etc.
Editing and reloading
After editing, reload without closing the terminal:
.zshrc, every new terminal will show errors. If this happens, you can always fix it by editing the file directly: nano ~/.zshrcOther config files
You might also encounter these related files:
.zprofile
Runs once at login (not every new tab). Good for one-time setup.
.zshenv
Runs for every zsh instance, even scripts. Rarely edited directly.
.bashrc
Same concept but for Bash (the older default shell). macOS switched to zsh in 2019.
Interactive Bash Guide
Walk through essential commands with examples and expected output.
-l = long format (permissions, owner, size, date). -a = show ALL files, including hidden ones (those starting with a dot). Together -la gives you the complete picture of what's in a directory.find when you know the filename pattern, and grep when you know what the file contains.Every file has permissions for three groups: owner, group, and others.
chmod 750 means owner=rwx, group=r-x, others=nothing.sed to change text, use awk to extract/format columns.bg to resume it in the background, or fg to bring it back.
MY_VAR="hello" sets a variable only for the current shell. export MY_VAR="hello" makes it available to any program launched from that shell (child processes). If you want an app you run to see the variable, you need export.Bash Cheatsheet
Quick reference cards. Click any command to copy it.
Shell shortcuts (Ctrl+) work in both. iTerm2 adds powerful app-level shortcuts (Cmd+).