All articles

10 Linux Tools That Upgraded My Terminal Workflow

I was using the same Linux tools for years and never thought to question them. Then I found these 10 alternatives — all faster, cleaner, and smarter than what they replace — and realized how much time I was leaving on the table.

Eissa Saber profile photo
Eissa SaberJune 18, 2026 · 10 min read

I was comfortable. That was the problem.

For years I used the same terminal tools that came with Linux. find, grep, cat, ls, htop. I knew them well enough to get things done, so I never looked for anything else. Comfortable is a tricky place to be. You stop noticing the small annoyances — the long flags you have to look up every time, the messy output you have to squint at, the terminal session you lose and have to rebuild from scratch. I just thought that was part of working in the terminal. Turns out it doesn't have to be. Every tool in this list is faster, easier to read, or smarter than the one it replaces. Some are all three.

1. fd vs find — same job, half the typing

find does the job, but the syntax is frustrating. To find all .js files and skip node_modules, you have to write something like find . -name "*.js" -not -path "*/node_modules/*". Every time. And if you get the flag order wrong, you get a cryptic error. fd is faster than find and the syntax makes sense. You just type what you're looking for. It respects .gitignore automatically so ignored folders stay out of your results without any extra flags. The output has colors that make it easy to tell files from folders. On a big project, fd also returns results noticeably faster than find because it runs searches in parallel. I still reach for find on remote servers where fd isn't around, but on my own machine I haven't typed find in months.

Shell
# find needs this to skip node_modules:
find . -name "*.js" -not -path "*/node_modules/*"

# fd just does it automatically:
fd -e js

# more examples:
fd config                     # find anything with "config" in the name
fd -e js src/                 # find .js files only inside src/
fd -H .env                    # include hidden files in the search
fd -e log --older-than 7d     # find log files older than 7 days
fd run -x chmod +x            # find files named run and make them executable

2. tmux vs plain terminals — sessions that survive

A regular terminal gives you one session that dies the moment you close the window. If your SSH connection drops or you accidentally close the terminal, everything running inside it is gone. tmux keeps your sessions alive in the background. You can have multiple windows and split panes inside a single session, detach from it, close the terminal completely, and come back later to find everything exactly where you left it. The difference is especially obvious when working on multiple projects at the same time — with plain terminals you're constantly rebuilding your setup, with tmux you just switch sessions.

Shell
# plain terminal: close window = lose everything
# tmux: detach = session keeps running

tmux new -s blog              # start a session called blog
tmux new -s api               # start another for your API project
tmux ls                       # see all your running sessions
tmux attach -t blog           # jump back into the blog session
Ctrl+b d                      # detach (session stays alive)
Ctrl+b %                      # split screen left and right
Ctrl+b "                      # split screen top and bottom
Ctrl+b arrow                  # move between panes
Ctrl+b c                      # create a new window inside the session

3. fzf vs Ctrl+R — fuzzy search that actually works

The built-in Ctrl+R history search is linear. You type and it looks for an exact match from the start of the command. If you can't remember the first word, you're stuck. fzf replaces that with fuzzy search — type a few letters from anywhere in the command and it shows every match instantly as you type. It's faster and it finds things the old search would miss. Beyond history, fzf plugs into everything: file pickers, git branch switching, process killing. It turns any list into an interactive searchable menu. Once you have it wired into your shell you wonder how you worked without it.

Shell
# old Ctrl+R: exact match from the start only
# fzf Ctrl+R: fuzzy match from anywhere in the command

vim $(fzf)                           # fuzzy pick a file to open
cd $(fd -t d | fzf)                  # fuzzy pick a directory to jump into
fzf --preview 'bat {}'               # browse files with a live preview
git checkout $(git branch | fzf)     # fuzzy pick a branch to switch to
kill $(ps aux | fzf | awk '{print $2}')  # pick a running process to kill
docker stop $(docker ps | fzf | awk '{print $1}')  # fuzzy stop a container

4. bat vs cat — the same file, but readable

cat dumps raw text to the screen. No colors, no line numbers, no structure. For a short file that's fine, but for a config file or a script it means you have to do all the reading work yourself. bat is a drop-in replacement for cat that adds syntax highlighting, line numbers, and git change indicators on the side. The file is readable the moment it appears on screen. It's not just cosmetic — colors give you structural information before you've read a single word. bat also uses a pager automatically for long files, and steps out of the way when you're piping output so it doesn't break your scripts.

Shell
# cat: raw text, no context
# bat: same file, syntax highlighted with line numbers

bat config.js                        # JavaScript with proper highlighting
bat src/index.ts                     # TypeScript, same thing
bat -n notes.txt                     # line numbers only, no extra decoration
bat --diff file.js                   # highlight only the lines changed in git
bat /etc/hosts                       # config files are much easier to read
fzf --preview 'bat --color=always {}' # use bat as a preview inside fzf

5. ripgrep vs grep — faster search with smarter defaults

grep -r works but it searches everything including node_modules, .git, and binary files unless you tell it not to. On a real project that means a lot of noise in the results and a noticeable wait before they appear. ripgrep is significantly faster than grep — it searches in parallel and uses smarter algorithms — and it respects .gitignore by default so you only see results from files that matter. The output format is also cleaner: file name, line number, and the matched text with the match highlighted. No extra flags needed to get readable results.

Shell
# grep: slow on large projects, searches node_modules too
grep -r "useState" . --include="*.js" --exclude-dir=node_modules

# rg: fast, skips ignored files automatically
rg "useState"

# more examples:
rg "useState" src/             # search only inside src/
rg -t js "import"              # search only JavaScript files
rg -i "todo"                   # case-insensitive
rg -l "API_KEY"                # only show file names, not every match
rg -n "useEffect" --stats      # show match count and how long it took
rg "function" -A 3             # show 3 lines of context after each match

6. eza vs ls — a directory listing you can actually use

ls -la gives you information but it's hard to scan. File sizes are in raw bytes, everything is the same color, and there's no git information. eza gives you the same information but in a format you can read at a glance. Folders and files have different colors, sizes are in KB and MB, and you can see which files have uncommitted git changes without running a separate command. There's also a tree view that works well for exploring unfamiliar projects. It sounds like a minor upgrade but ls is one of the most-typed commands in the terminal, so a better version of it adds up quickly.

Shell
# ls: hard to scan, sizes in bytes, no colors by default
ls -la

# eza: colors, readable sizes, git status
eza -la

# more examples:
eza -la --git                  # show git status next to each file
eza --tree                     # tree view of the directory
eza --tree --level=2           # tree view, 2 levels deep
eza -la --sort=size            # sort by file size
eza -la --sort=modified        # sort by when the file was last changed
eza -la --icons                # show file type icons (needs a Nerd Font)

7. btop vs htop — a monitor you can read at a glance

htop works, but the layout takes a moment to process every time you open it. The numbers are there, but there's no visual shape to them. btop shows the same CPU, memory, disk, and network information but with graphs, so you immediately see trends — memory climbing, CPU spiking during a build, network activity from a background process. It also handles everything in one place where htop often needs you to switch views. I keep btop open in a tmux pane while working so I can glance at it without switching windows.

Shell
btop                           # open btop

# keyboard shortcuts inside btop:
# F2 or o   open options and settings
# f         filter processes by name
# k         kill the selected process
# /         search through running processes
# m         toggle between memory display modes
# 1-4       switch between CPU graph styles

8. dust vs du — disk usage that makes sense immediately

du -sh * shows directory sizes but the output is unsorted and flat. You have to pipe it through sort -h just to see the biggest folders first, and even then you can't see what's inside them. dust shows disk usage as a sorted tree with the biggest items at the top. You can immediately see which folder is eating your space and drill into it to find exactly which files are responsible. What used to take me several commands and a minute of hunting now takes one.

Shell
# du: unsorted, no nesting, need extra pipe to sort
du -sh * | sort -h

# dust: sorted tree, biggest items at the top
dust

# more examples:
dust ~/projects                # check a specific folder
dust -d 1                      # only show top-level folders, no nesting
dust -d 3                      # go 3 levels deep into the tree
dust -r                        # reverse order, smallest at top
dust -X node_modules           # exclude node_modules from results
dust -n 10                     # show only the top 10 largest items

9. greenclip vs the default clipboard — history that doesn't disappear

Linux has no clipboard history by default. When you copy something new, the previous thing is gone forever. You don't notice this until you copy a URL, copy something else for a second, and then realize you need that URL back. greenclip runs quietly in the background and saves everything you copy. When you need something from earlier you open it through rofi and pick from the list. It searches as you type so even a long history is fast to navigate. It's one of those tools that becomes invisible almost immediately because it just quietly stops a frustrating thing from happening.

Shell
# default clipboard: copy something new = lose the old one
# greenclip: keeps a searchable history of everything you copy

greenclip daemon &                   # run in background, add to autostart
rofi -modi "clipboard:greenclip print" -show clipboard  # open the history
greenclip print                      # print history to terminal
greenclip clear                      # clear all saved history

10. starship vs oh-my-zsh — a fast prompt that works everywhere

A lot of people who want a better prompt install oh-my-zsh. It works, but it's heavy — it loads a lot of things you probably don't need and adds real startup time to every terminal you open. starship gives you everything you actually want from a prompt — git branch, uncommitted changes, active language version, last command duration, exit code color — and does it in a fraction of the time. The startup is nearly instant because it's written in Rust. It also works in bash, zsh, fish, and every other shell without any changes, so you don't have to switch to zsh just to get a better prompt. If you're already on zsh, you don't need oh-my-zsh. starship does more and costs less.

TOML
# oh-my-zsh: zsh only, slow to load, lots of overhead
# starship: any shell, starts instantly, shows what you actually need

# starship.toml — one config file for all shells

[git_branch]
format = "on [$symbol$branch]($style) "
symbol = " "

[git_status]
format = '([\[$all_status$ahead_behind\]]($style) )'

[cmd_duration]
min_time = 2_000
format = "took [$duration](yellow) "

[nodejs]
format = "via [⬢ $version](green) "

[python]
format = "via [🐍 $version](yellow) "

[character]
success_symbol = "[❯](green)"
error_symbol = "[❯](red)"

The old tools still work. These ones just work better.

None of the tools I switched from were broken. grep finds text. find finds files. cat shows content. They all do what they say. But faster search, readable output, and sessions that survive closing the terminal are not small things — they're things you interact with dozens of times a day. The time you save on each one doesn't feel like much by itself, but it compounds. If you want to start somewhere, pick ripgrep or bat first. They're the easiest to drop in and the improvement is obvious within the first hour.

LinuxVoid LinuxTerminalCLIDWMProductivity
Eissa Saber profile photo
Eissa Saber

Full Stack Developer with 6+ years building React, Next.js & Node.js applications. Available for full-time and contract roles.

Work with me