TerminalVibes / The Toolshed
Part 10

The Toolshed: Getting, Unpacking, Finding

"First, install X." — every setup guide ever written

This part is about owning your machine: fetching new tools, unpacking what arrives, knowing where things actually live, and finding out what's eating your disk. Four everyday chores that every guide assumes you already know — and that your agent will hand you commands for without explaining.

Important
The thread running through this part: none of it is magic, it's all just files in places. Installing puts a file where your shell looks. An archive is one file holding many. A symlink is a file that points at another. Disk pressure is files being bigger than you thought.

10.1 Package Managers — Getting New Tools

When a command doesn't exist, your shell says command not found — which, as Environment Variables taught you, means "nothing on your $PATH has that name." A package manager is a program whose entire job is installing other programs. You name a tool; it finds the right build for your system, puts it somewhere your PATH already looks, and remembers enough to update or remove it later.

Installed = placed where $PATH can see it
One idea, several spellings
brew install cowsay            # macOS (Homebrew)
sudo apt install cowsay        # Debian/Ubuntu Linux
npm i -g serve                 # i = install, -g = global
brew install jq                # jq isn't preinstalled either — same one line

which cowsay                   # where did it land?
/usr/local/bin/cowsay          # ...somewhere on $PATH. That's all "installed" means.

That last pair of lines is the whole concept. Before the install, which cowsay finds nothing and the command fails. After it, there's a file at /usr/local/bin/cowsay, that directory is listed in your $PATH, and so typing cowsay works. Installing a command-line tool is mostly just putting a file somewhere the shell already looks.

Two spellings of one idea, and Windows has a third in winget, which pulls from its own catalogue the same way. apt needs sudo because it writes into folders that belong to the machine rather than to you; Homebrew owns its own directory, so it doesn't.

One thing no setup guide mentions: Homebrew isn't on a stock Mac. brew is itself third-party software, installed once by following the instructions at brew.sh — and until you do, the first line of that block answers command not found, which is a confusing way to be told you're missing the thing that installs things.

npm i -g serve is the odd one out. i is install; -g is global, meaning put it where PATH can see it rather than inside this project's node_modules folder, where which serve would never look. And npm installs JavaScript tools and nothing else, so if what you want isn't JavaScript, npm can't help you. It also runs things: npm run <name> executes a script the project defined for itself in its package.json file, which is all npm test && npm run deploy in Exit Codes & Chaining was ever doing.

Caution
Read what an install pulls in — especially from an agent. Three things deserve a second look: sudo npm install (a global npm install should rarely need root, and needing it usually means something is misconfigured); curl | bash installers (curl — Ask the Network decoded exactly why — download, read, then run); and any package whose name is one typo away from a popular one. That last one has a name — typosquatting — and a fix: copy the install command from the project's own documentation rather than from a search result.
Vibe it

"I'm on macOS and this guide says apt install — what's the equivalent for me?"

"Before I run this install command, tell me what it downloads and where it puts things"

Try It: Install a Tool

Watch cowsay fail, install it, and watch the same command start working — then use which to see exactly where the file landed.
Install a Tool

Loading playground...

10.2 Archives — tar & zip

tar -xzf release.tar.gz is probably the most-copied command in computing, and almost nobody can explain the letters. They're not magic — they're four separate instructions jammed together:

Many files, one crate — peek before you unpack
Decoding the flag soup
tar -xzf release.tar.gz
     │││
     ││└── f: "the next word is the archive's filename"
     │└─── z: it's gzip-compressed (that's the .gz)
     └──── x: extract

tar -tzf release.tar.gz     # t: LIST what's inside — don't unpack yet
tar -czf backup.tar.gz notes/   # c: create an archive from notes/

Swap one letter and you change the verb: x extracts, c creates, t lists. The z and f stay put, unless something other than gzip did the squeezing: -xjf for a .tar.bz2, -xJf for a .tar.xz — same idea, different squeezer. Once you can read the letters, the command stops being an incantation you paste and becomes a sentence you understand — which is the entire thesis of this course applied to one very ugly command.

tar and zip split the job differently. tar only bundles — it glues many files into one and stops there, which is why compression is a separate z and why you end up with two extensions in .tar.gz. A .zip does both jobs in one format, which is what a browser download or a Windows machine usually hands you; .tar.gz is the Unix default. Opening one is unzip archive.zip, and unzip -l lists what's inside without extracting anything — l for list, the zip spelling of tar -tzf.

Tip
Peek before you unpack. An archive decides where its own contents land, and a badly-built one scatters files all over your current folder instead of tidying them into one directory. tar -tzf archive.tar.gz lists everything without extracting anything — it costs a second and it's the same "look before you leap" habit as echo-the-glob in Wildcards.
Vibe it

"Explain this command letter by letter before I run it: tar -xjf archive.tar.bz2"

"Make me a compressed backup of my notes folder with today's date in the filename"

Try It: Peek, Then Unpack

A release archive just landed. List what's inside with tar -tzf before extracting it — then unpack it for real.
Peek, Then Unpack

Loading playground...

10.3 Links & Where Things Live

You've been seeing these for nine parts without being told what they are. Run ls -l in the right folder and some entries have an arrow:

A signpost, not a copy
The arrow ls has been showing you
ls -l /usr/local/bin
lrwxr-xr-x  node -> /opt/homebrew/Cellar/node/22.3.0/bin/node
                └── a symbolic link: a signpost pointing somewhere else

ln -s releases/v2.1 current    # plant your own signpost
ls -l
current -> releases/v2.1

Those lines are trimmed — a real ls -l puts owner, group, size and date between the permissions and the name — but the character doing the work is the first one. That l is the type character from Reading ls -l's legend, the one entry that legend pointed forward to here.

A symlink — symbolic link, which is what the -s stands for — is a tiny file whose entire content is "look over there instead." It is not a copy: there's still one real thing, and the link is a pointer to it. That's why deleting the link leaves the original alone — and why deleting the original leaves a broken link, an arrow pointing at nothing, which is the source of a whole genre of confusing errors.

A link's target can be absolute or relative, and the two behave differently. /opt/homebrew/Cellar/… above is absolute: it means the same thing from anywhere. releases/v2.1 is relative, worked out from the link's own folder rather than from yours — so moving the link somewhere else breaks it while the file it pointed at sits untouched.

This is how a surprising amount of your machine is wired. Homebrew installs the real files deep in its own folders and drops symlinks into /usr/local/bin; node_modules/.bin is full of them. A version managernvm for Node, pyenv for Python — lets one machine hold several versions of the same language, and switches between them by re-pointing a single link. When a tool insists it's installed but the command "isn't found" — or points at the wrong version — a symlink is usually the culprit, and ls -l plus which is how you catch it.

Tip
This one is a real-machine lesson — the sandbox has no symlinks to practise on. Next time you're in a terminal, run ls -l /usr/local/bin (or ls -l node_modules/.bin in any JavaScript project) and read the arrows. It's a good five-minute tour of how your tools are actually assembled.
Vibe it

"Why does which node show one path but node --version report a different version than I expect?"

"Explain what ln -s does and when I would want a symlink instead of a copy"

10.4 Disk Detective

"Your disk is almost full" arrives at the worst possible moment, and the panic response — deleting things that look big — is how people lose work. Two commands turn the guess into a measurement.

Measure before you delete
Where did it all go?
du -sh *              # how big is each thing HERE?
204M    dist
3.1M    docs
1.9G    node_modules
12M     src

df -h                 # how full is the whole disk?
Filesystem  Size  Used Avail Capacity
/dev/disk1  494G  405G   89G     82%

du is "disk usage" — -s gives one summary line per item instead of every nested folder, and -h is the same human-readable flag you aliased onto ls in Your Shell Config. It's what turns the raw byte counts from Looking Inside Files into K, M and G, each rung roughly a thousand of the one below — so 1.9G dwarfs 12M by far more than the digits suggest. df is "disk free", the whole-disk view; a real one also prints where each disk is mounted, plus a few extra columns on macOS you can ignore.

The everyday move is du -sh *: one number per folder, sorted out by eye, and the hog is immediately obvious. It's usually node_modules, a build cache, or old container images — things that regenerate, which is exactly why they're safe to delete. One catch: * never matches a name that starts with a dot, so a .cache folder stays invisible until you name it yourself: du -sh .cache.

Tip
Measure, then delete — in that order. It's the same discipline as ls before rm in Deleting (Carefully): make the invisible visible before the irreversible step. Deleting the wrong 200 MB is annoying; deleting the wrong 200 MB because you never checked is avoidable.
Vibe it

"My disk is nearly full — walk me through finding what is using the space, biggest first"

"Is it safe to delete node_modules and .cache? What regenerates and what does not?"

Try It: Find the Space Hog

The disk is filling up. Size every folder with du -sh * first, then remove the one that's actually large — measurement before deletion.
Find the Space Hog

Loading playground...

That's the toolshed stocked. You can install what you're missing, open what arrives, follow the arrows to where things really live, and find what's eating your disk — the last of the everyday chores that used to require someone else's help.

Challenge: Hand It Over, Not the Bloat

Loading challenge...