Install

# Debian / Ubuntu
sudo apt install ripgrep fd-find bat fzf

# Arch
sudo pacman -S ripgrep fd bat eza zoxide fzf

# macOS
brew install ripgrep fd bat eza zoxide fzf

# Or via mise / cargo / scoop (see /tutorials/mise-polyglot-runtime-versions.html)
cargo install ripgrep fd-find bat eza zoxide

Two Debian quirks: fd is packaged as fdfind (alias it to fd in your shell), and bat on older Debian is called batcat (same).

# Add to ~/.bashrc or ~/.zshrc
alias fd='fdfind'
alias bat='batcat'

ripgrep (rg) — the replacement for grep

What it does differently from grep:

  • Recursive by default; no -r needed.
  • Respects .gitignore, .ignore, and .rgignore; skips .git, node_modules, target, etc.
  • Uses parallel threads — on a multi-core machine, several times faster than GNU grep.
  • Detects binary files and skips them by default.
  • Colours matches; shows file path + line number with a sensible format.
# Most uses are just "rg PATTERN"
rg fastify

# Limit to certain file types
rg --type ts 'TODO'
rg --type-list      # see available types

# Search in hidden files / ignored files
rg --hidden --no-ignore 'API_KEY'

# Show matches with N lines of context
rg -C 3 'function deploy'

# Replace (preview)
rg 'oldName' --files-with-matches | xargs sed -i 's/oldName/newName/g'

# Or use the experimental --replace + --passthrough
rg 'oldName' --replace 'newName' --passthrough > preview.txt

fd — the replacement for find

What it does differently from find:

  • Pattern is a regex (or with -g a glob), no -name required.
  • Respects .gitignore.
  • Colours output; parallel I/O.
  • Smart-case: lowercase patterns are case-insensitive; mixed case is exact.
# Find by name
fd readme

# Find by extension
fd -e ts -e tsx

# Find & execute (one call per file)
fd -e py -x black {}

# Find & execute (one call with all results)
fd -e log -X rm

# Include hidden files / ignored files
fd --hidden --no-ignore

# Limit depth
fd -d 2 config.

bat — the replacement for cat

  • Syntax highlighting for ~200 languages.
  • Line numbers and git-diff annotations in the gutter.
  • Falls back to plain cat when stdout is not a terminal (so pipes keep working).
bat src/main.rs
bat -p src/main.rs           # plain output, useful in scripts
bat --diff main.rs           # only show changed lines

# Use as the man-page pager
export MANPAGER="sh -c 'col -bx | bat -l man -p'"

eza — the replacement for ls

Successor to the older exa (which is unmaintained). What it does:

  • Colours by file type, git status, permission bits.
  • Tree view (--tree) builtin — replaces the separate tree command.
  • Per-file git status when run in a repo.
eza -lah
eza --tree --git-ignore -L 3
eza -la --git --no-permissions --no-user --time-style=relative

The aliases worth setting:

alias ls='eza'
alias ll='eza -lah'
alias la='eza -la'
alias lt='eza --tree -L 2'

zoxide — the replacement for cd

zoxide tracks how often you visit directories and lets you jump to any of them by partial match:

# Add to ~/.bashrc or ~/.zshrc
eval "$(zoxide init bash)"
# or for fish:
zoxide init fish | source
# It defines a `z` command (and overrides `cd` only if you tell it to)
z proj            # jumps to ~/code/big-project (your most-frecent match)
z proj api        # narrows to ~/code/big-project/services/api

# Interactive picker
zi                # opens an fzf picker of all known dirs

After a week of normal use, z + 3 letters reliably gets you anywhere. cd still works unchanged.

fzf — the universal fuzzy picker

Not a replacement for one thing — a primitive that composes with everything else. Pipe any list of items into it, fuzzy-search, pick:

# Pick a file to edit
nvim "$(fd -t f | fzf)"

# Pick a Git branch to switch to
git checkout "$(git branch | fzf | tr -d ' *')"

# Pick a recent command to re-run (default Ctrl-R binding)
# Pick a process to kill
kill -9 "$(ps -ef | fzf | awk '{print $2}')"

The shell key-bindings (run $(brew --prefix)/opt/fzf/install on Mac, apt install fzf sets it up on Debian) add three superpowers:

  • Ctrl-R — fuzzy-search command history (replaces the default reverse-search).
  • Ctrl-T — insert filename(s) from fuzzy picker at cursor.
  • Alt-C — fuzzy-cd into a subdirectory.

The next tier worth knowing

  • delta — a diff viewer that renders git diff output with syntax highlighting and side-by-side. Configure as core.pager.
  • dust — a replacement for du with a treemap-style output.
  • duf — a replacement for df with cleaner formatting.
  • btop — a replacement for top/htop with mouse support, network/disk panels, and themes.
  • procs — a replacement for ps with column auto-sizing and TCP/UDP port mapping.
  • just — a make-style command runner without the tab-quirk syntax.
  • direnv / mise — per-directory environment variables (mise's variant covered in that tutorial).

Aliases worth keeping

# ~/.bashrc / ~/.zshrc
alias ls='eza'
alias ll='eza -lah --git'
alias la='eza -la'
alias lt='eza --tree -L 2 --git-ignore'

alias cat='bat -p'         # paged when on a terminal, plain when piped
alias grep='rg'            # keep the original under /usr/bin/grep
alias find='fd'

eval "$(zoxide init bash)"
[ -f /usr/share/fzf/key-bindings.bash ] && source /usr/share/fzf/key-bindings.bash

None of these break existing scripts that hardcode /usr/bin/grep or /usr/bin/find; the aliases only apply to interactive shells.