Articles

How to Use fzf: Fuzzy-Finding in Your Terminal

fzf is a command-line fuzzy finder that filters any list interactively. Here's how to use it for file search, shell history, and git workflows.

The Lycoris Team The Lycoris Team · · 5 min read
A laptop showing code in a terminal

fzf is a general-purpose command-line fuzzy finder: pipe any list of lines into it — files, shell history, running processes, git branches, anything — and it opens an interactive filter where you type a few characters and it narrows the list in real time, ranking matches by how well they fit rather than requiring an exact substring. It’s not tied to any one use case; its power comes from being a small, composable Unix tool that other commands and shell integrations pipe into.

Installing it and running it for the first time

fzf is packaged for every major platform — available through Homebrew, most Linux package managers, and as a standalone binary from its GitHub repository. After installing, the fastest way to see what it does is to pipe something into it directly:

find . -type f | fzf

This lists every file under the current directory and opens fzf’s interactive prompt. Start typing and the list filters live; the characters you type don’t need to be contiguous or in order relative to the filename — fzf matches main.py against typing mp because both characters appear in that order somewhere in the string, which is what “fuzzy” means here as opposed to a literal substring search. Arrow keys (or Ctrl-J/Ctrl-K) move the selection, and Enter prints the selected line to standard output, which is the key to how fzf composes with other commands: it reads a list on stdin and writes one selection to stdout, so it slots into a pipeline like any other filter.

Practical pattern: opening a file in your editor

Because fzf’s selection goes to stdout, wrapping it in command substitution turns it into a file picker for anything that takes a filename argument:

vim "$(find . -type f | fzf)"

This is the core pattern behind most fzf workflows — generate a list, pipe it through fzf, feed the result to another command.

Searching shell history

fzf’s shell integration (installed via a setup script bundled with fzf, or through your package manager) binds Ctrl-R to a fuzzy search over your shell history, replacing the default reverse-incremental search most shells ship with. Instead of cycling through matches one at a time with repeated Ctrl-R presses, you get the full interactive filtered list at once and can type a few relevant characters from anywhere in a command you remember running, without needing to recall its exact prefix.

The same shell integration typically binds Ctrl-T to fuzzy-find files to insert at the cursor, and Alt-C to fuzzy-find a directory and cd into it — both operating on the current directory tree the same way the manual find | fzf pipeline above does, just wired up as keybindings instead of typed commands.

Git workflows

fzf’s real productivity gain for many developers shows up in git, where several commands produce a list — branches, commits, stashes, tags — that fzf can filter interactively instead of you scrolling raw output. A common pattern for checking out a branch fuzzily:

git checkout "$(git branch --all | grep -v HEAD | sed 's/^[* ]*//' | fzf)"

The same idea extends to interactively selecting a commit to view or cherry-pick, or a stash entry to pop, by piping the relevant git log --oneline or git stash list output through fzf instead of memorizing hashes or stash indices. This pairs naturally with other git navigation habits — the same instinct that makes git bisect useful for narrowing down a bug’s origin, or a git worktree useful for working on two branches at once, is the instinct fzf serves for browsing through git’s often long, unstructured list output.

Preview windows

A frequently used flag, --preview, runs a shell command against the currently highlighted line and shows its output in a side pane, updating live as you move the selection:

find . -type f | fzf --preview 'bat --color=always {}'

Here {} is replaced with the currently highlighted line, and bat — or plain cat, head, or a git diff command — renders a preview of whatever that file or commit actually contains, so you can confirm you’re selecting the right thing before committing to it with Enter.

Editor and multiplexer integration

Beyond the shell, fzf has plugins for most popular editors (fuzzy file and buffer switching inside Vim or Neovim being the most common use, an alternative to the file-tree browsing habits covered when comparing Vim and Emacs) and for terminal multiplexers like tmux, where it’s commonly used to fuzzy-switch between sessions and windows the same way it fuzzy-switches between files.

Killing processes and other one-off uses

fzf’s composability means it’s just as useful for tasks that have nothing to do with files or git. Piping ps aux through fzf and feeding the selected line’s process ID to kill turns hunting through process listings for the right PID into a filtered, interactive pick:

kill -9 "$(ps aux | fzf | awk '{print $2}')"

The pattern is always the same three steps — produce a list on stdout, filter it interactively with fzf, extract and act on the selected line — which is why fzf tends to accumulate more uses over time in a given developer’s shell config rather than staying confined to whichever task it was first installed for. Once the pattern is familiar, it’s easy to wire up for anything that starts as an unwieldy list: docker containers to stop, npm scripts to run, environment variables to inspect.

The takeaway

fzf’s value comes from being a small, composable filter rather than a feature-specific tool: pipe any list into it, get an interactively narrowed result out, and wire that into whatever command actually needs the selection — an editor, cd, git checkout, a kill signal for a process. The shell history and git integrations are usually where new users feel the biggest speedup, but the same core pattern extends to any list-producing command already sitting in your terminal workflow.

Chisato Chisato · · 5 min read

The State of AI Coding Assistants in 2026

AI coding tools have moved from autocomplete to autonomous agents. Here's where the technology actually stands in 2026 — and where it still falls short.

#AI #Developer Tools #Productivity