fzf
A general-purpose command-line fuzzy finder for interactively filtering lines from files, history, processes, and commands.
Why consider fzf?
fzf is a general-purpose, interactive command-line fuzzy finder written in Go. It reads a list from STDIN, lets you filter it with fuzzy matching in real time, and writes the selection to STDOUT — making it composable with any Unix pipeline. It ships as a single portable binary and includes built-in shell integrations for Bash, Zsh, Fish, and Nushell, plus Vim/Neovim plugins.
Learn fzf by building
Practical setup notes, real use cases, and copy-ready examples in one focused guide.
In this guide13 sections
fzf — Command-Line Fuzzy Finder
fzf is a general-purpose command-line fuzzy finder and an interactive terminal toolkit. It reads a list of items from standard input, lets you filter them interactively with fuzzy matching, and writes the selected item to standard output. You can think of it as an interactive version of grep that slots into any Unix pipeline.
Source: github.com/junegunn/fzf
Key Highlights
The README lists four headline features:
- Portable — distributed as a single binary for easy installation
- Fast — optimized to process millions of items in milliseconds
- Programmable — event-driven architecture for building custom terminal interfaces and workflows
- Batteries-included — comes with integrations for Bash, Zsh, Fish, Nushell, Vim, and Neovim
fzf is written in Go, which gives it a single self-contained binary with no runtime dependencies.
Installation
macOS / Linux via Homebrew
brew install fzfLinux package managers
fzf is available in virtually every major Linux package manager:
| Package Manager | Distribution | Command |
|---|---|---|
| APT | Debian 9+ / Ubuntu 19.10+ | sudo apt install fzf |
| DNF | Fedora | sudo dnf install fzf |
| Pacman | Arch Linux | sudo pacman -S fzf |
| Nix | NixOS | nix-env -iA nixpkgs.fzf |
Windows
On Windows, fzf is available via Chocolatey, Scoop, and Winget:
# Chocolateychoco install fzf# Scoopscoop install fzf# Wingetwinget install fzfFrom source (git)
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf~/.fzf/installThe install script adds lines to your shell configuration file to update $PATH and set up shell integration.
Shell Integration
After installing, set up key bindings and fuzzy completion by adding one line to your shell config:
Bash (~/.bashrc):
# Set up fzf key bindings and fuzzy completioneval "$(fzf --bash)"Zsh (~/.zshrc):
# Set up fzf key bindings and fuzzy completionsource <(fzf --zsh)Fish (~/.config/fish/config.fish):
# Set up fzf key bindingsfzf --fish | sourceOnce set up, three powerful shortcuts become available in your shell:
CTRL-T— fuzzy-search files and paste the selection into the command lineCTRL-R— fuzzy-search command historyALT-C— fuzzy-search directories andcdinto the selected one
Basic Usage
fzf follows Unix philosophy: it is a filter. It reads from STDIN and writes to STDOUT.
# Open fzf over all files; write the selection to 'selected'find * -type f | fzf > selected# Open a file in vim, chosen via fzfvim $(fzf)# Open fzf in a 40% tall window below the cursorfzf --height 40%# Reverse layout with a borderfzf --height 40% --layout reverse --borderWithout a STDIN pipe, fzf automatically traverses the current directory to build the file list.
Advanced: Pipelines and Dynamic Reloading
fzf's real power shows in pipeline compositions. Here is the canonical process-killer example from the ADVANCED.md docs:
# 1. ps: Feed the list of processes to fzf# 2. fzf: Interactively select a process using fuzzy matching algorithm# 3. awk: Take the PID from the selected line# 3. kill: Kill the process with the PIDps -ef | fzf | awk '{print $2}' | xargs kill -9The --bind and reload actions let you dynamically update the candidate list without restarting fzf:
(date; ps -ef) | fzf --bind='ctrl-r:reload(date; ps -ef)' \ --header=$'Press CTRL-R to reload\n\n' --header-lines=2 \ --preview='echo {}' --preview-window=down,3,wrap \ --layout=reverse --height=80% | awk '{print $2}' | xargs kill -9You can also switch between multiple data sources with separate key bindings:
find * | fzf --prompt 'All> ' \ --header 'CTRL-D: Directories / CTRL-F: Files' \ --bind 'ctrl-d:change-prompt(Directories> )+reload(find * -type d)' \ --bind 'ctrl-f:change-prompt(Files> )+reload(find * -type f)'Preview Window
fzf supports a built-in preview window that runs an arbitrary command on the highlighted item:
# Preview file contents with batfzf --preview 'bat --color=always {}'# Preview with syntax highlighting, border and 60% heightfzf --preview 'bat --color=always {}' --preview-window '~3'Vim / Neovim Integration
For Vim users with vim-plug:
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }Plug 'junegunn/fzf.vim'junegunn/fzfprovides the core library and keeps the binary up-to-date viafzf#install().junegunn/fzf.vimis a separate project that wraps fzf into convenient Vim commands like:Files,:Buffers,:Commits, and more.
Neovim users who prefer Lua-based plugins can use the community-maintained fzf-lua plugin.
Customizing Defaults
All options can be set permanently via the $FZF_DEFAULT_OPTS environment variable:
export FZF_DEFAULT_OPTS="--height=40% --layout=reverse --info=inline --border --margin=1 --padding=1"Override the default file source with $FZF_DEFAULT_COMMAND:
# Use fd (respects .gitignore) as the default file sourceexport FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'License
fzf is released under the MIT License.
Related tools
More options with a similar category or technology profile.
diskus
Minimal, fast alternative to du -sh written in Rust using multi-threaded directory traversal.
peco
Simplistic interactive filtering tool for Unix pipelines, process lists, and file trees.
Dapr CLI
Command-line tool for managing Dapr distributed application runtime environments and sidecars.
Freeze
Generate beautiful image screenshots and SVGs of code snippets and terminal outputs.