You've been having conversations with your computer for months.
You just didn't know the grammar yet.
~34 minutes · 12 sections · interactive · progress saved
Verb. Object. Modifiers. That's it. You already parse these instinctively.
Click each part to understand it:
# Every command follows this shape: command --options arguments # Real examples you've seen: ls -la ~/Desktop # list · long format · this folder git commit -m "fix bug" # git · commit · message · "fix bug" brew install bat # brew · install · the program "bat"
-l is a single-letter flag. --long is the full-word version.
They usually do the same thing. -la is two flags smashed together: -l + -a.
This is the confusion that started it all. Three tools, three jobs, one truth table.
"Find me every line that contains this text"
grep "function" app.js # lines with "function" in app.js grep -r "TODO" ./src # search recursively in src/ grep -i "error" *.log # case-insensitive in all .log files
Claude equivalent: Grep tool (uses ripgrep, faster)
"Find me files whose names match this pattern"
ls *.js # all .js files here ls **/*.test.ts # all .test.ts files, any depth src/{components,hooks}/*.tsx # .tsx in either folder
Claude equivalent: Glob tool (file pattern matching)
"Find me files that match these conditions (size, date, type, name...)"
find . -name "*.pdf" # all PDFs below here find . -size +100M # files bigger than 100MB find . -mtime -7 # modified in last 7 days
Your upgrade: fd (simpler syntax, faster, respects .gitignore)
Because sometimes you need the whole book. Sometimes just the last page.
| Command | What it does | When to use |
|---|---|---|
cat |
Dumps entire file to screen | Short files, piping content |
head |
First N lines (default 10) | Peek at structure, CSV headers |
tail |
Last N lines | Log files, recent entries |
less |
Scrollable viewer (q to quit) | Big files, browsing |
wc |
Count lines/words/bytes | How big is this thing? |
cat config.json # show it all head -20 data.csv # first 20 lines tail -f server.log # follow (live stream new lines) wc -l *.py # count lines in all Python files
bat replaces cat with syntax highlighting, line numbers, and git integration.
Same thing, prettier. You already have it installed.
cat -n with superpowers — can read images, PDFs, notebooks too.
One symbol that turns simple commands into a production line. The | connects the output of one command to the input of the next.
# > writes output to a file (overwrites) echo "hello" > greeting.txt # >> appends to a file echo "world" >> greeting.txt # < feeds a file as input sort < names.txt # 2> redirects errors only find / -name "*.conf" 2> /dev/null # hide permission errors
grep finds, sort sorts, wc counts, head trims.
Together they're a data pipeline. This is why Unix won.
Your computer is a tree. Every file has an address. Two kinds of address exist.
# Absolute path — starts from root (/), works everywhere /Users/manossom/Documents/Manos/Υποθέσεις/ # Relative path — starts from where you ARE right now ./Υποθέσεις/ΣΩΜΑΡΑΚΗΣ_ΝΙΚΟΛΑΟΣ/ # ./ = current dir ../Desktop/ # ../ = go up one level
| Symbol | Means | Example |
|---|---|---|
~ |
Your home directory | ~/Desktop → /Users/manossom/Desktop |
. |
Current directory | ./script.sh → run script here |
.. |
Parent directory | cd .. → go up one level |
/ |
Root of everything | /usr/local/bin → where Homebrew lives |
- |
Previous directory | cd - → toggle back |
z Υποθέσεις jumps to the most-used directory matching that name.cd habits. Frecency-based (frequency + recency).
Every file has a lock with three slots. Click each character to decode it.
# Three groups, three permissions each: # [user/owner] [group] [others] # r=read w=write x=execute -=no chmod 755 script.sh # rwxr-xr-x (you: all, others: read+execute) chmod 644 readme.md # rw-r--r-- (you: read+write, others: read) chmod +x script.sh # add execute permission
permission denied. Fix: chmod +x script.sh.
The numeric system (755, 644) is worth knowing, not memorizing.
The shell is the program that reads your commands. zsh is your dialect. It has settings, shortcuts, and a startup sequence.
# When you open a terminal, zsh reads these files in order: ~/.zshenv # always runs first (environment variables) ~/.zprofile # login shells only ~/.zshrc # interactive shells (THIS IS YOUR MAIN CONFIG) ~/.zlogin # after .zshrc, rarely used
Named values that programs can read. Like global settings.
# See a variable echo $HOME # → /Users/manossom echo $PATH # → where your shell looks for programs # Set one (current session only) export MY_VAR="hello" # Set permanently (add to ~/.zshrc) export EDITOR="code" # default editor for git, etc.
# In ~/.zshrc: alias ll="eza -la --icons" # pretty ls alias gs="git status" # less typing alias brewup="brew update && brew upgrade" # See all your aliases alias # lists everything
$PATH is a list of directories separated by :.
When you type bat, your shell checks each directory in PATH until it finds a program called bat.
That's why brew install works — Homebrew puts programs in a PATH directory.
which bat → shows you exactly where it found the program.
Every command spawns a process. Processes have IDs, can be paused, resumed, or killed.
# See what's running ps aux # all processes, detailed ps aux | grep claude # find a specific one # Run in background python3 server.py & # & = run in background jobs # list background jobs fg %1 # bring job 1 to foreground # Ctrl+Z = pause current process # bg = resume it in background # Stop a process kill 12345 # ask process 12345 to stop (SIGTERM) kill -9 12345 # force-kill (SIGKILL) — last resort pkill -f claude-monitor # kill by name pattern
q to quit, k to kill a process, f to filter.
pkill -f claude-monitor if things get tight.
btop shows you who's eating RAM.
Not the theory. Not the graph model. Just: what you actually do and why.
The flow of every git change:
# Check state git status # what's changed? git diff # show the actual changes git log --oneline -10 # last 10 commits, compact # Save work git add . # stage everything git commit -m "msg" # snapshot git push # upload # Branches git branch # list branches git checkout -b new-feat # create + switch to new branch git switch main # switch to main (modern way) # Undo git stash # hide changes temporarily git stash pop # bring them back git restore file.js # discard changes to one file
git reset --hard = delete uncommitted work. No undo.git push --force = overwrite remote history. Can destroy others' work.You already have these installed. Here's what each one replaces and why it's better.
# Instead of ls eza -la --icons --git # everything, beautifully eza --tree -L2 # tree view, 2 levels deep # Instead of find fd "\.pdf$" # all PDFs (regex, not glob) fd "config" -e json # files named *config*.json # Fuzzy everything fzf # fuzzy-find files cat file | fzf # fuzzy-find within file content Ctrl+R # atuin: fuzzy search history # Smart cd z Υποθ # jumps to Υποθέσεις (learned) z dev # jumps to Development
Read the command. Pick what it does. No man pages needed — you know this now.
Click a command on the left, then its description on the right.
One file. Zero dependencies. Dark mode. Progress saved.
Made with Claude Code for a lawyer who called himself semiliterate.
He wasn't.