The Modern CLI Toolbox: 8 Tools That Replace grep, find, cat, and cd

July 19, 2026 · 6 min read

The core Unix tools were designed in the 1970s for teletypes and kilobytes of RAM. They still work — but a generation of rewrites (mostly in Rust, a few in Go) has quietly fixed their worst UX problems: cryptic flags, no awareness of .gitignore, and output that assumes you enjoy parsing monochrome walls of text.

Here are the 8 replacements I actually use daily, with the exact commands that made me switch.

1. ripgrep (rg) — replaces grep

ripgrep searches recursively by default, respects your .gitignore, skips binary files, and is genuinely 5–50x faster than GNU grep on real codebases. The flags you'll actually use:

rg "handleWebhook"          # search everywhere, respects .gitignore
rg -i "error"               # case insensitive
rg -S "UserID"              # smart case: insensitive unless you type a capital
rg -l "TODO"                # just list files with matches
rg -C 3 "panic"             # 3 lines of context around each hit
rg --files -g "*.py"        # list all Python files it would search

The killer detail: rg "foo" in a repo already excludes node_modules, target/, and whatever else you've gitignored. With grep you've been typing --exclude-dir chains for years. That alone is worth the switch.

2. fd — replaces find

Nobody should have to remember find . -name "*.log" -mtime +30 -exec rm {} \;. fd's syntax is what find's should have been:

fd report              # find files/dirs matching "report" (regex, recursive)
fd -e log              # by extension
fd -t d node_modules   # directories only
fd -x rm               # run rm on every match
fd changed -d 3        # match "changed", max depth 3

Like ripgrep, it respects .gitignore and is dramatically faster on large trees. One gotcha: on Debian/Ubuntu the package is fd-find and the binary is fdfind — alias it in your shell rc: alias fd=fdfind.

3. bat — replaces cat

bat adds syntax highlighting, line numbers, and a Git gutter (showing modified lines) to file viewing:

bat src/main.go        # highlighted, numbered, paged
bat --plain deploy.sh  # plain output, safe for piping
bat -r 40:60 app.py    # show only lines 40-60

It pages through less automatically when output is long, and passes through cleanly when piped — so aliasing alias cat=bat is safe for interactive use (keep real cat in scripts).

4. eza — replaces ls

exa was the popular modern ls, but the project went unmaintained and its repo was archived. eza is the actively maintained community fork — install that one, not exa.

eza -l --git --icons        # long view with git status per file
eza --tree -L 2             # tree view, 2 levels deep
eza -l --sort=modified      # sort by modification time

The --git column showing staged/modified status next to each filename is the feature that makes plain ls -la feel broken afterward.

5. zoxide — replaces cd

zoxide learns which directories you visit and lets you jump with fragments instead of paths. After a day of use:

z auto        # jumps to /tmp/auto-blog (your most "frecent" match)
z blog docs   # matches paths containing both
zi            # interactive picker (uses fzf)

Setup is one line in your .zshrc or .bashrc:

eval "$(zoxide init zsh)"

"Frecent" = frequency + recency. The directory you edited ten minutes ago outranks one you visited heavily last month. It sounds like a gimmick until you realize you've stopped typing full paths entirely.

6. fzf — fuzzy-finds everything

fzf isn't a replacement for one tool — it's an interactive filter you wire into your whole shell. The three bindings that change your life (installed via the package's install script):

And the composition pattern is endless:

vim $(fzf)                       # pick a file, open it
git checkout $(git branch | fzf) # pick a branch, check it out
kill $(ps aux | fzf | awk '{print $2}')

Unlike most of this list, fzf is written in Go (by Junegunn Choi) — proof the ecosystem isn't a monoculture.

7. jq — JSON without tears

Every API, CI system, and cloud CLI speaks JSON. jq is how you answer questions without writing a Python script:

curl -s api.example.com/users | jq '.users[].email'
kubectl get pods -o json | jq '.items[] | select(.status.phase=="Failed") | .metadata.name'
jq -r '.dependencies | keys[]' package.json   # raw output, no quotes

Learning curve tip: master just three things — .key, .[], and select(). That covers 90% of daily use. The -r (raw) flag matters more than people expect; without it you're sed-ing quotes off strings forever.

8. delta — replaces git's default diff pager

delta renders git diff and git show with syntax highlighting, line numbers, and optional side-by-side view. Configure once in ~/.gitconfig:

[core]
    pager = delta
[interactive]
    diffFilter = delta --color-only
[delta]
    line-numbers = true
    side-by-side = true

Every diff you read from then on — including inside git add -p — is highlighted and numbered. Code review in the terminal stops being eye strain.

Install everything in one line

# macOS
brew install ripgrep fd bat eza zoxide fzf jq git-delta

# Debian/Ubuntu (note the renamed binaries)
sudo apt install ripgrep fd-find bat jq fzf
# eza, zoxide and delta: use cargo install, or their .deb releases

Bottom Line

Don't install all eight at once — you'll remember none of them. Start with ripgrep and fzf's Ctrl-R; they'll pay rent within an hour. Add zoxide next week. By the time you wire in delta, the 1970s toolchain will feel like a museum exhibit.

The pattern behind all of these isn't speed — it's defaults. They assume you're in a Git repo, on a color terminal, in 2026. The classics assume a teletype. Pick accordingly.