6 Alternative CLI Tools I Immediately Install on Every Linux Machine — And Why You Should Too
Six modern CLI replacements for grep, find, cat, cd, and git diff that will transform your Linux terminal workflow.
Six modern CLI replacements for grep, find, cat, cd, and git diff that will transform your Linux terminal workflow.
If you spend any time in a Linux terminal — and if you run a homelab, you definitely do — you already know the feeling. You SSH into a fresh server, start poking around log files, and immediately hit the limits of the tools you have been using for years. Grep is slow. Find has an esoteric syntax you have to look up every single time. Cat dumps raw text in your face with zero syntax highlighting. And cd? It works, but it does not remember anything.
I have been running Linux servers in my homelab for over a decade, and somewhere around year eight I realized something: the tools I was using daily were designed in the 1970s. Not that there is anything wrong with that — classic Unix tools are battle-tested. But there are now modern replacements that do the same jobs faster, with better defaults, prettier output, and features that actually matter for day-to-day homelab work.
Here are the six CLI tools I install on every single Linux machine, whether it is a Raspberry Pi running Pi-hole, a Proxmox node, or a Docker swarm manager. I have been running all six in production for years, and I am not going back.
Let us start with the easiest win. bat is cat with syntax highlighting, line numbers, and git integration. If you have ever tried to read a YAML configuration file or a JSON log entry using plain cat, you already know the pain. bat colorizes the output based on the file type automatically, so your .yaml files are color-coded, your Python scripts are highlighted, and your Markdown files render with visible structure.
# Debian/Ubuntu
sudo apt install bat
# On Debian and Ubuntu, the binary is named `batcat` due to a naming conflict.
# Add this alias to your .bashrc or .zshrc:
alias bat='batcat'
# Fedora
sudo dnf install bat
# Arch Linux
sudo pacman -S bat
# macOS (Homebrew)
brew install batWhy this matters for your homelab: Every single time you tail a log file, view a Docker Compose file, or inspect an Nginx config, bat makes it readable at a glance. Combined with tail -f or journalctl, you get live log monitoring with syntax highlighting. That alone has saved me countless minutes of squinting at unformatted text.
bat also pipes gracefully. When you pipe its output to another command, it detects that stdout is not a terminal and falls back to plain cat behavior automatically. No flags needed.
If you want to use bat as a pager, set:
export BAT_PAGER='less -R'ripgrep (command: rg) is the search tool I use more than any other. It recursively searches your current directory for a regex pattern and returns results faster than anything else I have tested. It respects .gitignore files by default, so you are not wading through node_modules or .venv directories unless you explicitly ask for it.
# Debian/Ubuntu
sudo apt install ripgrep
# Fedora
sudo dnf install ripgrep
# Arch Linux
sudo pacman -S ripgrep
# macOS
brew install ripgrepHomelab use case: Searching through gigabytes of log files across multiple services. I run a media server stack (Plex, Sonarr, Radarr, etc.), and when something breaks, I need to find the error fast. With rg, I can search all logs recursively in under a second:
rg "ERROR" /var/log/ --type-add 'logs:*.log' -t logsripgrep also supports PCRE2 (Perl-compatible regex) when you pass the -P flag, which opens up lookaheads and backreferences. For most daily searches, the default regex engine is already plenty fast.
One thing I genuinely love: rg handles binary files gracefully. It skips them by default and tells you it did. No more terminal lockups because you accidentally grepped a .iso file.
I will be honest: I could never remember find syntax. Is it -name or -iname? Do you need curly braces? What about -exec? Every time I needed find, I pulled up a man page or a browser tab. Then I found fd.
fd is a fast, user-friendly alternative to find. It uses sensible defaults: colorized output, regex-based pattern matching, and automatic .gitignore awareness. The syntax is intuitive:
# Find all files named "config.yml"
fd config.yml
# Find all Python files
fd '\.py$'
# Find files modified in the last 24 hours
fd --changed-within 24h
# Find files over 100MB
fd --size +100M# Debian/Ubuntu
sudo apt install fd-find
# On Debian/Ubuntu, the binary is named `fdfind`.
# Add this alias:
alias fd='fdfind'
# Fedora
sudo dnf install fd-find
# Arch
sudo pacman -S fd
# macOS
brew install fdHomelab use case: Finding large files eating up your ZFS pool, locating stray Docker volumes, or hunting down config files scattered across /opt. I use fd daily to find recently modified configs:
fd --changed-within 1h --extension ymlThat command alone has become muscle memory. No more find / -name "*.yml" -mmin -60 and hoping the syntax is right.
fzf is a general-purpose fuzzy finder. You pipe text into it, start typing, and it interactively filters down the list in real time. It is one of those tools that seems simple until you realize how many workflows it unlocks.
# Debian/Ubuntu
sudo apt install fzf
# Fedora
sudo dnf install fzf
# Arch
sudo pacman -S fzf
# macOS
brew install fzf
# Or from Git (always the latest)
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/installThe killer combination: You can pipe fd into fzf for interactive file searching:
fd --type f | fzfPress Enter, and the selected file path is printed to stdout. You can wrap that in a function to open the file in your editor:
# In your .bashrc or .zshrc
function fe() {
local file
file=$(fd --type f | fzf)
if [[ -n "$file" ]]; then
$EDITOR "$file"
fi
}Homelab use case: I have hundreds of Docker Compose files across multiple directories. With fzf bound to Ctrl+T (it sets this up automatically during install), I can type cd ** and press Tab to fuzzy-search my directory history. It is fast enough that I stopped bookmarking paths entirely.
fzf also integrates with your shell history. Press Ctrl+R in your terminal, and instead of the default bash reverse search, you get an interactive fuzzy search of your entire command history. Type part of a long Docker command you ran three days ago and find it instantly.
zoxide is a smarter cd. It learns which directories you visit most frequently and lets you jump there with a partial name. You type z proj and it takes you to /home/you/projects/homelab-infra or wherever you spend the most time.
# Debian/Ubuntu (may require adding a PPA or using cargo)
cargo install zoxide
# Fedora
sudo dnf install zoxide
# Arch
sudo pacman -S zoxide
# macOS
brew install zoxide
# With the install script (recommended for latest version)
curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bashAfter installation, add this to your shell config:
eval "$(zoxide init bash)" # or zsh, fish, etc.How it works: zoxide maintains a database of directories you visit, weighted by frequency and recency. When you type z <pattern>, it finds the best match. You can also use zi to launch an interactive fzf-powered picker.
Homelab use case: If you SSH into multiple servers, each with its own directory structure, zoxide adapts independently on each machine. On my main NAS running TrueNAS Scale, I jump between /mnt/tank/apps, /mnt/tank/media, and /root/docker constantly. With zoxide, I type z tank, z media, or z docker and I am there. No aliases, no bookmarks, no thought required.
One minor caveat: zoxide needs a bit of time to build up its database. For the first day or two, the suggestions are hit or miss. After a week of normal use, it becomes eerily accurate.
delta is a syntax-highlighting pager for git diff, git log, git show, and git blame output. If you have ever stared at a wall of green and red diff output and struggled to spot the actual changed line, you know why this matters.
# Debian/Ubuntu
sudo apt install git-delta
# Fedora
sudo dnf install git-delta
# Arch
sudo pacman -S git-delta
# macOS
brew install git-deltagit config --global core.pager "delta"
git config --global interactive.diffFilter "delta --color-only"
# Optional: side-by-side view
git config --global delta.side-by-side true
# Optional: line numbers
git config --global delta.line-numbers trueDelta highlights the exact characters that changed within a line using word-level diff, not just line-level. The output is colorized, with a dark or light theme depending on your terminal. It also shows line numbers and a file-by-file navigation header.
Homelab use case: I manage my entire homelab configuration — Docker Compose files, Ansible playbooks, Nginx site configs — in a private Git repository. When I review changes before pushing, delta makes it obvious what I actually changed versus what got reformatted. That distinction matters when you are debugging why a container stopped working after a config update.
Here is the combo I actually use every day. Pipe fd into fzf with bat as a preview window:
fd --type f | fzf --preview 'bat --style=numbers --color=always {}'This gives you an interactive file browser with syntax-highlighted previews. You can scroll through files without ever opening an editor. For anyone managing a homelab with dozens of config files scattered across directories, this workflow is transformative.
If you want to search file contents instead of file names, swap in ripgrep:
rg --line-number --color=always --smart-case '' | fzf --delimiter=: --preview 'bat --style=numbers --color=always --highlight-line {2} {1}'This lets you fuzzy-search the text inside all your config files. Type a keyword, see matches in real time with context, and jump to the exact line. I use this weekly to find configuration options I set months ago and forgot.
Every single one of these tools works inside a Docker container too. If you build custom Docker images for your homelab services, adding bat and ripgrep to your image can make debugging inside the container much easier. Just add them to your Dockerfile:
RUN apt-get update && apt-get install -y \
bat \
ripgrep \
fzf \
&& rm -rf /var/lib/apt/lists/*I do not recommend bloating production images, but for development and debugging images, these tools are invaluable.
I have been running these six tools across every Linux machine in my homelab for years — from a Pi-hole on a Raspberry Pi Zero 2 W to a Ryzen-powered Proxmox host. None of them are resource hogs. All of them are available in the default repos of every major distro. And once you start using them, going back to the originals feels genuinely painful.
If you install only one tool from this list, make it ripgrep. It is the one I reach for most often, and the speed difference versus grep is shocking the first time you try it on a large directory. But honestly, install all six. You will wonder why you waited so long.
One honest observation: zoxide takes a few days to become useful, and fzf initially feels like overkill if you have a small directory tree. Stick with both. After a week, removing them from your workflow will feel like losing a limb.
These tools are stable, actively maintained, and widely adopted by the Linux community. They are not experimental toys. They are the modern standard. Install them, use them, and reclaim the hours you used to spend wrestling with 1970s syntax.
Now go alias batcat to bat and get back to work.