fzf is the CLI tool I’ve been asked about more than any other. Here’s how I actually use it — and the integrations that make it irreplaceable.
The mental model
fzf isn’t a file finder. That’s what throws people off. It’s a filter. Pipe anything into it, get an interactive fuzzy search, pipe the selected result out. That’s the whole thing.
echo "foo\nbar\nbaz" | fzf
# → interactive list, pick one, output goes to stdout
Once that clicks, everything else follows.
Install and shell integration
brew install fzf
Then one line in your ~/.zshrc:
source <(fzf --zsh)
What you get immediately:
- CTRL+R — fuzzy search your entire shell history (this alone is worth the install)
- CTRL+T — fuzzy file finder, pastes selected path into your current command
- ALT+C — fuzzy
cd, jumps to any directory
I covered the full terminal stack separately — Ghostty, Starship, Catppuccin. fzf is the piece that makes the shell itself feel interactive.
Four workflows I use daily
Interactive branch switch:
git checkout $(git branch | fzf)
Kill a process without knowing its PID:
kill $(ps aux | fzf | awk '{print $2}')
Browse git commits with a live diff preview:
git log --oneline | fzf --preview 'git show --stat {1}'
Open any TypeScript file:
open $(find . -name '*.ts' | fzf)
Same shape every time: pipe a list in, pick something, pipe it somewhere useful. Once you know the pattern, you start seeing it everywhere.
Ghostty makes previews better
fzf’s --preview flag renders noticeably better in Ghostty — the GPU-accelerated rendering means the preview pane updates instantly as you type. Pair it with bat for syntax highlighting:
fzf --preview 'bat --color=always {}'
In Neovim
fzf-lua brings everything into Neovim and supports Ghostty’s kitty graphics protocol — image previews in file search, inside your editor. It’s the integration I’ve settled on in my Neovim config.
{ "ibhagwan/fzf-lua", opts = {} }
One line via lazy.nvim. Fuzzy files, buffers, git status, LSP references — all wired up.
Why it’s composable
fzf does one thing and does it well enough that it plugs into everything else. It doesn’t care what you pipe in — branches, processes, commit hashes, grep results. If it’s text, fzf can filter it. That composability is exactly what makes it fit CLI-first workflows as the connective tissue between commands.
Five minutes to install, weeks to fully explore. Start with CTRL+R and go from there.