← blog blog / fzf-terminal-workflow-guide.md

fzf — The One CLI Tool I Recommend to Everyone

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.

fzf — The One CLI Tool I Recommend to Everyone

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.

Thanks for reading!

I write about frontend craft, React, TypeScript, and the web. Found this useful? Let me know.

@samuellawrentz →

$ echo "enjoyed this post?" · subscribe via rss ↗

$ git log --oneline --grep="cli"

More articles

cd ../blog →
  1. 50db2ae My lazygit Config - Branch Menus, Ticket Commits and a Dinosaur

    Oct 06, 2026 3 min read tag: gittag: lazygit

    My lazygit Config - Branch Menus, Ticket Commits and a Dinosaur
  2. dce7f89 kron - I Got Tired of Cron Not Telling Me Anything

    Oct 05, 2026 3 min read tag: rusttag: cli

    kron - I Got Tired of Cron Not Telling Me Anything
  3. b4296ef I Forked taskwarrior-tui Until It Felt Like Linear

    Oct 04, 2026 4 min read tag: taskwarriortag: terminal

    I Forked taskwarrior-tui Until It Felt Like Linear
  4. be6d36b How I Wired Claude Code Into Neovim (It's Smaller Than You Think)

    Oct 03, 2026 4 min read tag: neovimtag: claude

    How I Wired Claude Code Into Neovim (It's Smaller Than You Think)

$ giscus --load ./comments

00:00

This helps me increase the session time of my site. Thank you!

Can you stay a bit longer?