I'll admit something a little embarrassing. For years, every time I forgot the exact flags for tar, or couldn't remember whether it was -C or -c to change directory, my reflex was to alt-tab to a browser and search for it. Same with Kubernetes — I'd go hunting through the docs website every time I needed to remember what fields go into a Pod spec.
At some point it clicked that this was ridiculous. The machine right in front of me already knows all of this. It ships with the answers built in. I just wasn't asking it.
So this post is about the handful of tools that killed my habit of Googling command syntax: tldr, apropos, and info for everyday Linux commands, and kubectl explain for writing Kubernetes manifests without guessing. None of these are new or fancy. They're just underused, and once they're part of your muscle memory you stop breaking your flow to go look things up.
The problem with man
Everyone knows man. You type man tar and you get... the entire manual. Every flag, every edge case, every historical note, all in one dense scroll. It's thorough, and that's exactly the problem. When I've forgotten how to create a gzipped archive, I don't want a 600-line reference. I want the one line that does the thing.
man is a reference manual. Most of the time what you actually need is an example or a reminder. That's where the other tools come in.
tldr — examples, not essays
tldr is the one I reach for most. The name is literally "too long; didn't read," and that's the whole philosophy. Instead of the full manual, it gives you a short list of the most common real-world uses of a command, with copy-pasteable examples.
Here's tldr tar on my machine:
tar
Archiving utility. Often combined with a compression method, such as gzip or bzip2.
- [c]reate an archive and write it to a [f]ile:
tar cf path/to/target.tar path/to/file1 path/to/file2 ...
- [c]reate a g[z]ipped archive and write it to a [f]ile:
tar czf path/to/target.tar.gz path/to/file1 path/to/file2 ...
- E[x]tract a (compressed) archive [f]ile into the current directory [v]erbosely:
tar xvf path/to/source.tar.ext
- E[x]tract a (compressed) archive [f]ile into the target directory:
tar xf path/to/source.tar.ext -C path/to/directory
- Lis[t] the contents of a tar [f]ile [v]erbosely:
tar tvf path/to/source.tar
Look at how readable that is. See the little brackets — [c]reate, g[z]ipped, [f]ile? That's a genuinely clever touch. The letters in brackets map directly to the flags, so czf suddenly makes sense: create, g*zipped, **f*ile. You stop memorizing flags and start understanding them.
That tar example alone covers maybe 95% of what anyone ever does with tar. No scrolling, no essay, just the thing you came for.
Getting it
It's not always installed by default, but it's one package away:
# Debian / Ubuntu
sudo apt install tldr
# macOS
brew install tldr
# Via npm (the original client)
npm install -g tldr
First run might fetch the pages, and you can refresh the local cache whenever you want:
tldr --update
Use it for literally anything you half-remember — tldr ssh, tldr find, tldr git rebase, tldr ffmpeg. The ffmpeg one in particular has saved me more times than I can count, because nobody on earth remembers ffmpeg syntax.
apropos — when you don't even know the command's name
tldr is great when you know which command you want. But sometimes you don't. You know what you want to do, you just can't remember what it's called.
That's apropos. It searches the names and descriptions of all the man pages on your system for a keyword and shows you everything that matches. It's basically "search the manual by topic."
First, a gotcha that got me
The very first time I tried this, I got nothing but errors:
$ apropos compress
compress: nothing appropriate.
If that happens to you, don't panic — apropos isn't broken and the commands aren't missing. It relies on a prebuilt search index, and on a fresh or minimal install (this bites people on WSL and slim container images especially) that index just doesn't exist yet. Build it once:
sudo mandb
You'll see it churn through your man pages:
Processing manual pages under /usr/local/man...
7612 manual pages were added.
Now apropos has something to search, and it works.
Now it actually does something
With the index built, apropos compress returns a wall of genuinely useful results. Here's a trimmed slice of what came back on my machine:
bunzip2 (1) - a block-sorting file compressor, v1.0.8
bzip2 (1) - a block-sorting file compressor, v1.0.8
gunzip (1) - compress or expand files
gzip (1) - compress or expand files
lz4 (1) - lz4, unlz4, lz4cat - Compress or decompress .lz4 files
lzma (1) - Compress or decompress .xz and .lzma files
pigz (1) - compress or expand files
unzip (1) - list, test and extract compressed files in a ZIP archive
xz (1) - Compress or decompress .xz and .lzma files
zcat (1) - compress or expand files
You went in knowing only the word "compress" and came out with every compression tool on the box. From there, tldr gzip or man xz gets you the actual usage.
The real output is actually much longer than that — apropos matches the keyword anywhere in the description, so you also get things like zgrep, zless, library functions, and perl modules. Which brings us to the useful trick for cutting the noise.
Narrowing it down
Man pages are split into numbered sections, and section 1 is user commands. So if you only care about actual commands you can run, scope the search to section 1:
apropos -s 1 copy
cp (1) - copy files and directories
cpio (1) - copy files to and from archives
dd (1) - convert and copy a file
docker-cp (1) - Copy files/folders between a container and the local filesystem
install (1) - copy files and set attributes
objcopy (1) - copy and translate object files
That's much cleaner than the unfiltered version, which also drags in library calls and config file formats you don't care about when you're just trying to copy a file.
Think of the pairing like this: apropos finds the name of the command, tldr tells you how to use it. Together they cover the full "I forgot" spectrum.
info — the deep dive when you actually need it
Sometimes you do need the full story — not an example, not a one-liner, but the real, complete documentation with all the context. That's where info comes in.
info reads GNU Info documents, which are often far more detailed and better structured than the equivalent man page. For GNU tools especially (coreutils, gcc, make, tar, grep), the info manual is the authoritative, book-length version with chapters, sections, and cross-links you can navigate like a hyperlinked document.
info coreutils
info tar
info grep
A few navigation basics, because info trips people up the first time:
- Arrow keys scroll.
-
ngoes to the next node (section),pto the previous one. -
ugoes up a level. -
Enteron a highlighted link follows it. -
qquits.
Honestly I don't live in info the way I live in tldr. But when I genuinely need to understand why a tool behaves a certain way, or I'm chasing some obscure option, the info manual is usually where the real explanation lives.
So the mental model for the three is:
-
tldr— "just remind me how to do the common thing." -
apropos— "I forgot what the command is even called." -
info— "I need to actually understand this properly."
Now the Kubernetes version of the same problem: kubectl explain
Here's where this gets really useful, because the exact same frustration shows up when writing Kubernetes manifests. You're staring at a blank YAML file trying to remember: is it containers or container? Does image go under the pod spec or inside the container? What fields does a probe even take?
Most people's instinct is to go to the Kubernetes docs website. But kubectl has the entire API schema baked in, and kubectl explain is the self-documentation tool that mirrors exactly what tldr/man do for shell commands — except here it's generating the structure of your manifest for you.
The best part: it reads the schema straight from your cluster, so it matches your Kubernetes version. No guessing whether a field exists in your version or not.
Start at the top
kubectl explain pod
KIND: Pod
VERSION: v1
DESCRIPTION:
Pod is a collection of containers that can run on a host.
FIELDS:
apiVersion <string>
kind <string>
metadata <ObjectMeta>
spec <PodSpec>
status <PodStatus>
Right away this tells you the four top-level keys of any Pod manifest: apiVersion, kind, metadata, and spec. That's your skeleton:
apiVersion: v1
kind: Pod
metadata:
spec:
Drill down with dot notation
Now, what goes inside spec? Just ask:
kubectl explain pod.spec
KIND: Pod
VERSION: v1
FIELD: spec <PodSpec>
DESCRIPTION:
Specification of the desired behavior of the pod.
FIELDS:
activeDeadlineSeconds <integer>
affinity <Affinity>
automountServiceAccountToken <boolean>
containers <[]Container> -required-
List of containers belonging to the pod. There must be at least one
container in a Pod.
dnsPolicy <string>
enum: ClusterFirst, ClusterFirstWithHostNet, Default, None
...
This output is doing a lot of work for you. Look at the details:
-
containers <[]Container> -required-— the[]means it's a list, and-required-means you can't skip it. So you knowcontainersis a YAML list and it's mandatory. -
dnsPolicy <string>even shows you the validenumvalues, so you don't have to guess what strings are allowed. - Each field shows its type, which tells you how to shape the YAML — a
<string>is a plain value, an<Affinity>is a nested object, a<[]Container>is a list of objects.
Keep going until you hit plain values
containers is a []Container, so let's see what a container looks like:
kubectl explain pod.spec.containers
KIND: Pod
VERSION: v1
FIELD: containers <[]Container>
DESCRIPTION:
A single application container that you want to run within a pod.
FIELDS:
args <[]string>
command <[]string>
env <[]EnvVar>
image <string>
imagePullPolicy <string>
name <string> -required-
ports <[]ContainerPort>
resources <ResourceRequirements>
volumeMounts <[]VolumeMount>
...
Now you can see that a container needs a name (required), takes an image, and that ports, env, and volumeMounts are all lists of their own object types. If you want to know what goes in a port, you just keep drilling:
kubectl explain pod.spec.containers.ports
You follow the types down the tree until everything bottoms out in <string>, <integer>, or <boolean> — plain scalar values you can actually type. That's your signal that you've reached the leaves and the manifest is complete.
Putting it together into a real manifest
Walking the schema with kubectl explain — pod → pod.spec → pod.spec.containers → pod.spec.containers.ports — gives you everything you need to assemble this by hand, confidently, without the docs website:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers: # []Container, required
- name: nginx # string, required
image: nginx:1.27 # string
ports: # []ContainerPort
- containerPort: 80 # integer
Every single field in that file maps back to something kubectl explain told us: containers is a required list, each item needs a name, image is a string, ports is a list, and containerPort is an integer. Nothing memorized, nothing guessed.
A couple of handy variations
Dump the entire nested tree in one shot instead of drilling level by level:
kubectl explain pod --recursive
That's a firehose, but it's great when you want to see the full shape of a resource at a glance.
And this works for every resource type, not just pods:
kubectl explain deployment.spec.template.spec.containers
kubectl explain service.spec
kubectl explain ingress.spec.rules
kubectl explain configmap
The deployment.spec.template.spec path is the one I use constantly, because that's where the pod template lives inside a Deployment and it's easy to lose track of how deep it is.
Why this matters more than it looks
None of these tools are impressive on their own. But together they change a habit, and the habit is what matters.
When you Google command syntax, three things happen: you break your focus by leaving the terminal, you risk landing on a Stack Overflow answer from eight years ago that's subtly wrong for your version, and you never actually learn the tool — you just copy and move on. When you ask your own machine instead, the answer is version-accurate (especially with kubectl explain, which reads your real cluster schema), it's instant, and you stay in flow.
The bracket notation in tldr and the type annotations in kubectl explain also quietly teach you why the syntax is the way it is, so over time you need them less. That's the real win. The goal isn't to depend on these forever — it's to stop context-switching to a browser for things your terminal can answer in half a second.
Quick reference
# Forgot how to use a command you know the name of
tldr <command>
# Forgot the command's name, know what it does
apropos <keyword>
sudo mandb # run once if apropos finds nothing
# Need the full, detailed GNU manual
info <command>
# Building a Kubernetes manifest, forgot the fields
kubectl explain <resource>
kubectl explain <resource>.spec
kubectl explain <resource>.spec.<field>
kubectl explain <resource> --recursive
Wrapping up
I stopped Googling tar flags and Pod spec fields the day I realized the answers were already sitting on my machine, offline, version-correct, one command away. tldr for quick examples, apropos to find a command you've forgotten the name of, info for the deep dive, and kubectl explain to build manifests field by field straight from the API schema.
Next time you catch yourself reaching for the browser to look up syntax, try asking your terminal first. It knows. It's been waiting the whole time.
If you've got a self-documentation trick I didn't mention here, drop it in the comments — I'm always happy to retire another browser tab.
Top comments (0)