๐Ÿš Phase 0 ยท Module 1

Navigating the Shell

โฑ ~6 hours ๐Ÿ“… Week 1 ๐ŸŽฏ Read this, then /learn T1

By the end of this module you will:

Shell zsh Filesystem Paths Navigation File ops man pages Redirection

What the shell actually is

When you open Terminal.app on your Mac, you're looking at a text box that talks to a program called a shell. The shell is not the terminal window โ€” it's what runs inside it. The terminal is the window; the shell is the interpreter reading what you type and deciding what to run.

macOS ships with zsh (the Z shell) as the default. Zsh is a Unix shell โ€” a direct descendant of the same family as bash and sh. The commands you learn here work on your Mac and on remote Linux servers, because they're all speaking the same underlying language: POSIX Unix. This is the foundational vocabulary of every developer tool you'll ever use.

Compare this to Finder. Finder and the shell are looking at exactly the same files on the same disk โ€” different interfaces to the same filesystem. Finder is point-and-click; the shell is type-and-run. As a developer you'll use both, but everything that involves automation, scripts, remote servers, package managers, and developer tools happens through the shell. Finder can't reach those places.

macOS Terminal vs Linux terminal

The reference book for this module (The Linux Command Line) is written for GNU/Linux. macOS uses BSD userland tools โ€” same commands, slightly different flags in a few places. This lesson flags the differences as they come up. The portable forms taught here work on both.

Where am I? Moving around

The shell always has a current directory โ€” the folder it considers "here." Every command you run acts relative to that location unless you say otherwise. Three commands cover everything you need to navigate:

pwd โ€” print working directory

pwd tells you where you are right now. Run it whenever you're disoriented:

$ pwd
/Users/john/projects/demo

That output is an absolute path โ€” it starts from / (the root of the entire filesystem) and spells out every directory along the way. Every file on your Mac has exactly one absolute path.

ls โ€” list directory contents

ls shows what's in the current directory. On its own it gives you a quick list. Add flags to see more detail:

$ ls             # basic list
$ ls -l          # long format: permissions, owner, size, date
$ ls -a          # show hidden files (names starting with .)
$ ls -lah        # long + all + human-readable sizes โ€” these combine
$ ls -G          # coloured output on macOS (BSD ls)
macOS colour flag: -G, not --color

GNU/Linux uses ls --color. macOS ships with BSD ls, which uses ls -G. If you copy a Linux alias like alias ls='ls --color', it will break on your Mac. The macOS equivalent is alias ls='ls -G'. This is the most common "works on Linux, not on Mac" trip-up for shell newcomers.

cd โ€” change directory

cd moves you to another directory. You'll use a handful of shorthand forms constantly:

$ cd /Users/john/projects    # absolute path โ€” works from anywhere
$ cd projects                # relative โ€” works only if projects/ is inside the current dir
$ cd ..                      # go up one level to the parent directory
$ cd ~                       # go to your home directory (/Users/john on macOS)
$ cd -                       # go back to wherever you just were (toggle)
$ cd                         # no argument โ€” same as cd ~

The tilde (~) is a shell shorthand for your home directory. You'll see it everywhere โ€” ~/.zshrc means /Users/john/.zshrc. It's not a real directory name; the shell expands it before running the command.

Looking at files

Before reaching for a text editor, the shell gives you several commands for reading files directly from the terminal โ€” essential on remote servers where you have no GUI at all.

cat โ€” print the whole file

$ cat notes.txt

cat dumps the entire file to the terminal in one go. Good for short files. For anything longer than a screenful, use less โ€” cat on a large file just scrolls past everything you wanted to read.

less โ€” page through a file

$ less server.log

less opens the file in a scrollable viewer. Controls: arrow keys (or j/k) to scroll, q to quit, /word to search (then n for next match, N for previous). Unlike cat, less doesn't load the whole file into memory first โ€” it handles gigabyte log files without complaint.

head and tail โ€” read the beginning or end

$ head config.yaml        # first 10 lines (default)
$ head -n 20 config.yaml  # first 20 lines
$ tail -n 50 app.log      # last 50 lines
$ tail -f app.log         # follow: keep printing new lines as they arrive

tail -f is one of the most practical debugging tools you'll use โ€” run it in a terminal while your app is running to watch log lines appear in real time.

file โ€” identify what something actually is

$ file mystery_binary
mystery_binary: Mach-O 64-bit executable arm64

$ file photo.jpg
photo.jpg: JPEG image data, JFIF standard 1.01

file inspects the actual bytes of a file (not just its name) and reports what it is. Useful when you find a file with no extension, or an extension that doesn't match the contents.

Absolute vs relative paths

This is the single concept that unlocks everything else in the shell. Once you have this, mysterious "No such file or directory" errors stop being mysterious.

Absolute path: starts with /. Always means the same thing, regardless of where you currently are.

Relative path: starts with a directory name, . (current dir), or .. (parent dir). Means something relative to your current directory.

# Assume you are in /Users/john/

$ cat Documents/notes.txt             # relative: looks inside ./Documents/
$ cat /Users/john/Documents/notes.txt # absolute: same file, always works

$ ls ../shared/                       # relative: go up one level, then into shared/
$ ./script.sh                         # relative: run script.sh right here
./script.sh vs script.sh

If you try to run a script by typing just script.sh, the shell won't find it โ€” even if it's sitting right in front of you. The shell doesn't look in the current directory by default (that's a security feature). You need to be explicit: ./script.sh means "run script.sh from this directory." This surprises everyone the first time.

The most common beginner error: getting "No such file or directory" and staring at it in confusion. Fix: run pwd first. You're probably not where you think you are.

Making and moving things

Five commands cover almost all file management you'll ever do from the shell:

mkdir โ€” make a directory

$ mkdir projects                    # create a single directory
$ mkdir -p projects/demo/src        # create the whole tree at once

Always use -p. Without it, mkdir fails if any parent directory in the path doesn't exist yet. With -p, it creates whatever is missing, and doesn't error if the directory already exists. It's strictly better in every case.

cp โ€” copy

$ cp notes.txt notes_backup.txt     # copy a file
$ cp -r src/ src_backup/            # copy a directory (-r = recursive)

For directories you must pass -r. Without it, cp refuses to copy a directory and gives you an error.

mv โ€” move and rename

$ mv old_name.txt new_name.txt      # rename a file
$ mv report.txt ~/Documents/        # move to another directory
$ mv src/ ~/projects/myapp/         # move a whole directory

In the shell, rename and move are the same operation. There's no separate rename command โ€” mv does both.

rm โ€” remove

$ rm file.txt                       # delete a file
$ rm -r old_project/                # delete a directory and everything inside it
rm is permanent โ€” no Trash, no undo

Deleting a file via Finder sends it to the Trash where you can recover it. rm does not. Files deleted with rm are gone immediately. There is no undo, no confirmation prompt by default, no recovery. Be certain of what you're deleting before you press Enter. Never run rm -rf on a path you can't name exactly โ€” an unset variable or a typo can widen the target catastrophically. You'll see concrete examples in the flaw drill below.

rmdir โ€” remove an empty directory

$ rmdir empty_folder/

rmdir only works on empty directories โ€” it refuses if anything is inside. That's a safety feature. To delete a directory and its contents, use rm -r. Consider rmdir the "are you really sure this is empty?" check before the more powerful command.

Getting unstuck โ€” reading the manual

You will regularly encounter a command you've never seen or can't remember. The shell has authoritative built-in help for everything:

man โ€” the manual

$ man ls          # opens the manual for ls (press q to quit)
$ man cp
$ man zshbuiltins # built-in zsh commands like cd, echo, type

Man pages are the authoritative reference for every command. They're terse and assume context โ€” but once you know how to read them, they're faster than any search result. Use /word to search within a man page (same controls as less), n/N to jump between matches, q to quit.

Reading strategy: skip the dense SYNOPSIS block at the top. Go to DESCRIPTION first for a plain-English explanation, then EXAMPLES if they exist. Return to the flag listing as a lookup reference, not as reading material.

--help

$ git --help
$ python3 --help
$ wrangler --help

Most modern tools respond to --help with a concise usage summary. Faster than man for a quick flag reminder; less complete for deep questions.

type and which โ€” what is this command?

$ type python3
python3 is /usr/local/bin/python3

$ which python3
/usr/local/bin/python3

$ type cd
cd is a shell builtin

type is more complete than which โ€” it tells you whether a command is a shell builtin (like cd), an alias, a shell function, or an external binary on disk. which only finds external binaries. When you're debugging "why is this running the wrong Python?" โ€” type python3 is your first move.

macOS note: on macOS, open is a Finder bridge. open . opens the current directory in Finder. open file.pdf opens it in Preview. It's the one command that crosses back from the shell to the GUI world.

A first taste of power โ€” redirection and pipes

The real leverage of the shell is combining commands. Here's a brief preview; T2 covers this in depth.

Output redirection: > and >>

$ echo "hello world" > greeting.txt    # write to a file (creates or overwrites)
$ echo "second line" >> greeting.txt   # append to the file
$ ls -l > file_list.txt                # save command output to a file
> truncates first, writes second

When you run cmd > file.txt, the shell opens file.txt and empties it to zero bytes before running the command. If the command then fails or produces no output, the file is empty. This is one of the most common accidental data-loss patterns in shell work. Use >> when you're not certain you want to overwrite โ€” it appends instead.

Pipes: |

$ ls -l | less              # page through ls output
$ cat app.log | tail -n 20  # last 20 lines of a log

The pipe character | takes the output of the command on the left and feeds it as input to the command on the right โ€” no temp file needed. This is how you build powerful one-liners from small, focused tools. You'll build on this heavily in T2.

Resources for this module

๐Ÿ’ป Exercise โ€” do this with Cody

Open Claude Code and say: /learn T1

Cody will give you a terminal-only challenge: from the shell (no Finder), build a ~/projects/demo directory tree, create files using touch and redirection, mv/cp/rename them into subdirectories, verify the result with ls -R, and clean up scratch copies with rm.

This week's milestone is reading the lesson โ€” the exercise is available but optional for week 1. Shell fluency pays off immediately in A3 (Git) and every module after it.

๐Ÿ”
Flaw Drill โ€” after you finish the exercise
Find the shell footguns before they find you. This is the skill.

The six commands below each contain a hidden danger โ€” something that could silently destroy data, expose secrets, or do far more damage than intended. Read each one carefully, identify exactly what could go wrong, and explain what the correct form would be. Then run /learn T1 flaw-drill and Cody will grade your findings.

# 1
rm -rf $TMPDIR/build/

# 2
file="my notes.txt"
rm $file

# 3
cp important.conf backup.conf > important.conf

# 4
mv *.txt archive

# 5
chmod 777 ~/.ssh

# 6
curl http://example.com/install.sh | sh

Write your findings for all six, then verify with /learn T1 flaw-drill in Cody.

โ† Phase 0 Next: Pipes, Search & Text โ†’