2026-10-14 · shell · ai engineering

Two commands every engineer (and every AI coding agent) leans on: grep and curl

They're decades old. They're also the first thing a code model reaches for when it's working in your repo.

~/cheatsheet — bash

The shell commands worth knowing cold

Small, composable tools. Each does one job, reads text in, writes text out, and chains with a pipe.

grepfind text in files
grep -rn "TODO" src/
grep -ril "api_key" .
grep -E "error|warn" app.log
grep -c "GET /" access.log
grep -v "^#" config.ini
-r recurse · -n line numbers · -i ignore case · -l filenames only · -c count · -v invert · -E regex
curltalk to any URL
curl -s https://api.example.com/v1
curl -I https://example.com
curl -o file.zip -L https://host/a.zip
curl -X POST -H "Content-Type: application/json" \
  -d '{"q":"hi"}' https://api.example.com
-s silent · -I headers only · -L follow redirects · -o save to file · -X method · -H header · -d body
Everyday toolkit
find . -name "*.log"locate files by name, size, or age
sed -i 's/old/new/g' f.txtfind and replace in place
awk '{print $1}' filepull columns out of text
tail -f app.logwatch a log live
sort | uniq -c | sort -rncount the most common lines
jq '.items[].id' data.jsonquery JSON from the shell
xargs -I{} cmd {}run a command per input line
wc -l filecount lines, words, bytes
diff -u a.txt b.txtsee what changed
ps aux | grep nodefind a running process
lsof -i :3000who is holding a port
du -sh * | sort -hwhat is eating disk space
tar -czf out.tgz dir/bundle and compress a folder
chmod +x script.shmake a file executable
cmd 2>&1 | tee run.logcapture output and still see it
One pipeline to remember curl -s URL | jq '.[]' | grep -i "error" | sort | uniq -c | sort -rn | head Fetch → parse → filter → count → rank. Five tiny tools, one line, no script file.
The cheat sheet. Everything below expands on it.

Why these two

grep answers "where is this?" Hand it a string or a regex and it tears through a codebase in milliseconds. When an AI agent needs to find every call site before refactoring a function, it isn't reading files one by one — it's running grep -rn.

curl answers "what does this endpoint actually return?" Headers, status codes, a JSON body you can pipe straight into jq. When an agent is debugging an integration, curl is how it checks reality instead of guessing from the docs.

Why they fit code models so well

The lesson isn't "learn old tools." It's that the Unix philosophy — small programs, plain text, clear contracts — turned out to be the ideal interface for machines that think in language.


The full reference

Beyond the graphic: the flags and patterns that actually get used.

grep

commandwhat it does
grep -rn "pattern" dir/recursive search with file:line prefixes — the default move
grep -ril "pattern" .case-insensitive, print only matching filenames
grep -E "a|b" fileextended regex (alternation, +, ?, {n})
grep -F "literal.string" filefixed string, no regex — safer and faster for literals
grep -w "word" filewhole-word match only
grep -c "pattern" filecount matching lines
grep -v "pattern" fileinvert: lines that do not match
grep -A3 -B1 "pattern" fileshow 3 lines after, 1 before (-C for both)
grep -o "[0-9]\+" fileprint only the matching part, one per line
grep --include="*.py" -rn "def " .restrict recursion to certain file types
grep -rn "x" . --exclude-dir=node_modulesskip a directory
rg "pattern"ripgrep: same idea, respects .gitignore, much faster on big trees

curl

commandwhat it does
curl -s URLsilent: no progress meter, just the body
curl -sS URLsilent but still show errors
curl -I URLHEAD request — headers only
curl -i URLinclude response headers with the body
curl -L URLfollow redirects
curl -o out.bin URLsave to a named file (-O keeps the remote name)
curl -X POST -d '{"a":1}' -H "Content-Type: application/json" URLJSON POST
curl -H "Authorization: Bearer $TOKEN" URLauth header
curl -u user:pass URLbasic auth
curl -F "file=@report.pdf" URLmultipart file upload
curl -w "%{http_code}\n" -o /dev/null -s URLprint only the status code
curl --retry 3 --max-time 10 URLretries and a hard timeout
curl -v URLverbose: TLS handshake, request and response headers

Finding and reading files

commandwhat it does
find . -name "*.log"find by name (-iname for case-insensitive)
find . -type f -mtime -1files modified in the last day
find . -size +100Mfiles larger than 100 MB
find . -name "*.tmp" -deletefind and delete (run without -delete first)
ls -lahlong listing, hidden files, human sizes
head -n 20 file / tail -n 20 filefirst / last 20 lines
tail -f app.logfollow a growing file
less +F app.logfollow, but with search and scrollback
wc -l fileline count (-w words, -c bytes)
cat a b > cconcatenate

Transforming text

commandwhat it does
sed 's/old/new/g' filereplace on every line (prints to stdout)
sed -i 's/old/new/g' filereplace in place (macOS: sed -i '' …)
sed -n '10,20p' fileprint lines 10–20
awk '{print $1}' filefirst whitespace-separated column
awk -F, '{print $3}' file.csvthird comma-separated column
awk '$3 > 100' filerows where column 3 exceeds 100
cut -d: -f1 /etc/passwdfield 1 using : as delimiter
tr 'a-z' 'A-Z'character translation
sort | uniq -c | sort -rnfrequency count, most common first
sort -t, -k2 -n file.csvnumeric sort on column 2
jq '.items[] | {id, name}' data.jsonreshape JSON
jq -r '.[].email' data.jsonraw strings, no quotes
xargs -n1 cmdrun cmd once per input token
… | tee out.logwrite to file and still print

Processes, ports, disk

commandwhat it does
ps aux | grep nodefind a process
pgrep -f "python app.py"PIDs matching a full command line
kill -9 PIDforce kill (try plain kill first)
lsof -i :3000what's listening on port 3000
ss -tulpnall listening sockets with owning process
top / htoplive CPU and memory
df -hdisk free per filesystem
du -sh * | sort -hsize of each item here, sorted
nohup cmd &keep running after you log out
cmd 2>&1 | tee run.logcapture stdout and stderr together

Archives, permissions, misc

commandwhat it does
tar -czf out.tgz dir/create a gzipped tarball
tar -xzf in.tgzextract one
zip -r out.zip dir/ · unzip in.zipzip equivalents
chmod +x script.shmake executable
chown user:group filechange owner
ln -s target linksymbolic link
which cmd / type cmdwhere a command resolves to
history | grep sshfind that command you ran last week
!!re-run the last command (sudo !! is the classic)
ctrl-rreverse search your history