The terminal, and why it is not optional

The handful of commands that cover ninety per cent of a backend engineer's day, and why the GUI cannot replace them.

6 min read🧭 Programming Foundations

The terminal is a text conversation with your machine. You type an instruction, it answers. That is all it is, and the reason it will not go away is that text is the only interface that can be written down — scripted, logged, put in a pipeline, pasted into a ticket by somebody trying to help you.

A backend engineer lives here. Not because the GUI is bad, but because the servers your code runs on have no GUI at all.

The shape of a command

plaintext
javac -d out Hello.java
─────  ── ─── ──────────
  │     │   │      │
  │     │   │      └── argument: what to act on
  │     │   └───────── the flag's value
  │     └───────────── flag: changes how it behaves
  └─────────────────── the program to run

Everything follows that shape. Once you see it, an unfamiliar command stops being noise: you can tell which part is the program and which parts are instructions to it, even when you know nothing about the tool.

Two conventions worth knowing immediately: a single dash usually introduces a one-letter flag (-d), two dashes a word (--release), and almost every program answers --help.

The commands that cover most days

CommandWhat it doesThe one thing to remember
pwdprint working directory"where am I" — the answer to most confusion
lslist filesls -la shows hidden files and details
cdchange directorycd .. goes up; cd alone goes home
catprint a filefine for small files, terrible for large ones
lesspage through a fileq quits. Everybody forgets this once
grepfind lines matching a patterngrep -r "text" . searches a whole tree
tailthe end of a filetail -f app.log follows it live — the one you will use most
mkdirmake a directory-p makes parents too
cp / mv / rmcopy, move, removerm does not ask, and there is no bin

That last row deserves its own warning.

Piping: the idea that makes it powerful

Any program's output can become the next program's input, with |:

bash
grep ERROR app.log | tail -20

Find the lines with ERROR, then show me the last twenty of those. Neither program knows about the other. grep does one thing, tail does one thing, and the pipe composes them.

This is the whole philosophy, and it is why the tools are so small: you are not meant to find one program that does what you want. You are meant to join three.

bash
grep ERROR app.log | grep -v Timeout | wc -l

Count the error lines that are not timeouts. Three tools, one question answered, and you could keep going.

Watch it narrow

The argument for pipes is easier to believe with numbers on it. A log file with two hundred lines in it:

plaintext
$ wc -l app.log
200
 
$ grep ERROR app.log | wc -l
90
 
$ grep ERROR app.log | grep -v Timeout | wc -l
35

200 → 90 → 35. Each stage hands its output to the next as plain text, and nothing in the middle is written to disk or held anywhere you could look at. Then swap the counter for the thing you actually wanted:

plaintext
$ grep ERROR app.log | grep -v Timeout | tail -3
2026-09-12T10:15:00Z ERROR NullPointerException in OrderMapper
2026-09-12T10:17:00Z ERROR NullPointerException in OrderMapper
2026-09-12T10:18:00Z ERROR NullPointerException in OrderMapper

Two hundred lines to the three that matter, with no program written and nothing installed. Notice what happened at the second stage in particular: grep -v Timeout threw away fifty-five error lines as noise you already know about, which is the move that turns an unreadable log into a readable one.

Where you will actually use it

Not for writing code — you have an IDE for that. For everything around it:

  • Reading a log on a server that has nothing else
  • tail -f while you reproduce a bug
  • Running the build, the tests, the container
  • Git
  • Finding which of 4,000 files mentions a class name
  • Being inside a container, where there is nothing but a shell

Try it yourself

Ten minutes that pay for themselves

In a terminal, without looking anything up beyond --help:

  1. Find out where you are, then list everything including hidden files.
  2. Make a directory, move into it, create a file with some text in it, and print it.
  3. Search your whole home directory for files whose name contains "java" — and notice how long it takes and how much it prints.
  4. Run ls --help (or man ls) and find the flag that sorts by modification time.
The commands
bash
pwd
ls -la
 
mkdir scratch && cd scratch
echo "hello" > note.txt
cat note.txt
 
find ~ -iname "*java*"
 
ls --help | grep -i "sort"    # -t sorts by time

Step 3 is the instructive one: it prints more than you expected, and it is slow. That is what teaches you to narrow a search before running it — a habit that matters far more on a server with a million files than on your laptop.

Misconceptions

  • "The terminal is for experts." It is for anybody who wants to repeat what they did. A click cannot be pasted into a runbook.
  • "I'll learn it when I need it." You need it the first time production is broken, which is the worst moment to be learning tail.
  • "Memorising commands is the skill." The skill is knowing a tool exists and that --help will tell you the rest. Nobody remembers tar's flags.
Progress is saved on this device and to your account when signed in.