Skip to content

Modern CLI Workflows - Primer

Why This Matters

The default Linux tools -- find, grep, cat -- were written decades ago. They work, but they are slow, their output is hard to read, and they ignore modern conventions like .gitignore. Modern replacements are faster, have better defaults, and compose together more naturally.

This is about speed. An engineer who uses fzf, ripgrep, and fd navigates a codebase in seconds where others take minutes. The philosophy is Unix: each tool does one thing well, accepts piped input, and produces clean output. Power comes from composition.

Core Concepts

1. fzf: Fuzzy Finder for Everything

fzf takes any list on stdin and provides interactive fuzzy search.

Who made it: fzf was created by Junegunn Choi in 2013, written in Go. The name stands for "fuzzy finder." It is the single most-starred command-line tool on GitHub (60K+ stars). fzf's power is that it turns any list into an interactive selection menu — files, processes, git branches, Kubernetes pods, anything.

vim $(fzf)                    # Find and open file
ps aux | fzf | awk '{print $2}' | xargs kill
git branch | fzf | xargs git checkout

Key bindings (default config): - Ctrl+R -- Search shell history - Ctrl+T -- Find file in current directory - Alt+C -- cd into subdirectory

Preview windows:

fzf --preview 'bat --color=always {}'

Faster than grep, respects .gitignore, better defaults.

rg "def authenticate"        # Search pattern
rg -i "todo"                 # Case insensitive
rg -t py "import requests"   # Filter by filetype
rg -C2 "panic"               # Context lines
rg -l "deprecated"           # Filenames only
rg -F "func()"               # Fixed string
rg -uu "secret"              # Include hidden+ignored

3. fd: Intuitive File Finding

Replaces find with simpler syntax and .gitignore awareness.

fd "config"                  # Find by name
fd -e yaml                   # By extension
fd -t d "test"               # Directories only
fd -e log -x gzip {}         # Find and execute
fd -H ".env"                 # Include hidden
fd -E node_modules "package" # Exclude directory

4. bat: cat with Syntax Highlighting

bat config.yaml              # Highlighted output
bat -p config.yaml           # Plain (no chrome)
bat -r 10:20 main.py         # Line range
bat --diff main.py           # Show git changes

5. delta: Better Diffs

Configure in ~/.gitconfig:

[core]
    pager = delta
[delta]
    navigate = true
    side-by-side = true
    line-numbers = true

After this, git diff, git log -p, and git show all use syntax-highlighted diffs automatically.

6. zoxide: Smarter Directory Navigation

Name origin: zoxide is a Rust rewrite of z (which itself was inspired by autojump). The "oxide" suffix is a Rust community convention (Rust = iron oxide). Created by Ajeet D'Souza in 2020, it is faster than the shell-script z and maintains a frecency-ranked database (frequency + recency).

Tracks your most-used directories and jumps to them by partial name.

z projects     # Jump to best match
z grok dev     # Multiple terms narrow results
zi             # Interactive selection with fzf

Learns from your cd usage automatically. Needs about a week of use before it becomes useful.

7. tldr: Practical Man Pages

Community-maintained command examples. Concise, practical, covers common use cases.

tldr tar
tldr curl
tldr iptables

8. atuin: Shell History on Steroids

Fun fact: atuin (named after the Great A'Tuin, the world-turtle from Terry Pratchett's Discworld) replaces your shell history with a SQLite database that syncs across machines. It records context (directory, exit code, duration) with each command, making it easy to answer "what command did I run in that project last week that took 5 minutes?" Consider it a modern alternative to the HISTSIZE approach below.

8. Shell History Optimization

# In .bashrc or .zshrc
export HISTSIZE=100000
export HISTFILESIZE=100000
export HISTCONTROL=ignoredups:erasedups
shopt -s histappend  # bash

With fzf, Ctrl+R becomes interactive fuzzy search through your entire history.

9. Composing Tools with Pipes

The real power is composition:

# Find YAML files, search for key, pick, edit
fd -e yaml | xargs rg -l "apiVersion" | \
  fzf --preview 'bat --color=always {}' | \
  xargs $EDITOR

# All TODOs grouped by file
rg "TODO|FIXME|HACK" --heading

# Files changed today, preview, edit
fd --changed-within 1d -e py | \
  fzf --preview 'bat --color=always {}' | \
  xargs $EDITOR

# JSON API: fetch, filter, format
curl -s https://api.example.com/items | \
  jq '.items[] | {name, status}'

10. Dotfile Management

Track tool configurations in version control:

# Bare git repo approach
git init --bare $HOME/.dotfiles
alias dot='git --git-dir=$HOME/.dotfiles \
  --work-tree=$HOME'
dot config status.showUntrackedFiles no
dot add ~/.bashrc ~/.gitconfig
dot commit -m "add shell and git config"

Alternatives: GNU Stow, chezmoi, yadm. The tool matters less than having your config versioned.

What Experienced People Know

  • Install fzf first. Highest leverage tool -- makes every other tool interactive.
  • alias cat=bat and alias ls=eza gives better defaults everywhere with zero behavior change.
  • fd and rg respect .gitignore by default. -u adds ignored files, -uu adds hidden files too.
  • Invest 30 minutes configuring delta. Every git diff for the rest of your career will be more readable.
  • jq and yq are essential for JSON/YAML work. Learn .field, .[], select(), map().
  • Most of these tools install via brew, apt, pacman, or cargo. One-liner setup.
  • Shell aliases for your most common multi-step commands compound over time. Invest in them.
  • Keep dotfiles in git. New machine setup goes from days to minutes.

Remember: The modern CLI stack mnemonic: "FRF BDZ" — Fzf (find anything), Ripgrep (search content), Fd (find files), Bat (read files), Delta (diff files), Zoxide (navigate dirs). Install these six and you have replaced the entire legacy toolkit with faster, smarter alternatives.