CLI tool
junegunn/fzf avatar
junegunn/fzf

fzf: The fuzzy finder that turns shell scripts into interactive terminal tools

fzf is an interactive command-line fuzzy finder that filters files, command history, processes, and other text streams.

82,995 stars2,877 forksGoMIT

At a glance

What is it?
fzf is a single-binary fuzzy finder for filtering files, history, and arbitrary text streams. It scales to millions of items and ships with shell and editor integrations, but its event-driven architecture is where the real power lies.
Who is it for?
Adopt fzf if you spend time in a terminal and want fast, scriptable fuzzy selection for files, history, or custom data streams. The single binary and MIT license make it low-risk to integrate.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What fzf actually solves

fzf solves a specific pain: choosing one item from a long list in a terminal without typing the full name. It reads text from stdin, displays it in an interactive list, and lets you filter with fuzzy matching. The README describes it as a general-purpose command-line fuzzy finder and an interactive terminal toolkit. That second phrase matters. fzf is not just a file picker. It is a building block for turning shell scripts into rich terminal applications. The target user is anyone who lives in a shell: developers, sysadmins, data analysts. The classic use cases are selecting files, browsing command history, and picking processes, but the design allows much more. The core value is speed and programmability. The README claims it is optimized to process millions of items in milliseconds. That is a bold claim, but the Go implementation and the single-binary distribution make it plausible. If you have ever waited for a recursive grep to finish before you could even start typing, fzf changes that workflow.

The mechanism: stdin in, selection out

fzf operates as a filter. You pipe text into it, it presents an interactive list, and when you select an item, it prints that item to stdout. The simplest invocation is something like `ls | fzf`. But the real power comes from the event-driven architecture. The README mentions this explicitly: fzf is programmable and event-driven. That means you can reload the candidate list on the fly, execute external programs, and change the entire process. For example, the README describes reloading the list of processes by pressing CTRL-R, switching between sources with CTRL-D or CTRL-F, and integrating interactive ripgrep. The data flow is not static. You can have fzf run a command, take its output as the new list, and keep the current query. This makes it a dynamic interface, not just a static picker. The preview window is another key mechanism. You can define a command that shows details for the currently highlighted item. The README gives examples like previewing an image. That turns fzf into a lightweight file manager or data browser.

Getting it running: installation and shell integration

Installation is straightforward because fzf is distributed as a single binary. The README lists package managers for every major platform. On macOS or Linux, `brew install fzf` works. On Debian or Ubuntu, `sudo apt install fzf`. On Windows, you have Chocolatey, Scoop, Winget, and MSYS2. There is also a git-based install and binary releases. The important step after installation is shell integration. The README has a section titled Setting up shell integration, and it warns that key bindings and fuzzy completion require this step. For Bash, Zsh, Fish, and Nushell, you need to source the integration script. The exact command is not in the README excerpt, but the warning is clear: without it, you get the bare finder but not the CTRL-T file search or CTRL-R history search. For Vim and Neovim, there is a plugin. The README mentions it as part of the batteries-included philosophy. So the first run is not just `fzf`; you need to configure your shell to get the full experience.

Search syntax and customization

The search syntax is one of fzf's strengths. It supports fuzzy matching by default, but you can use exact matches, prefix matches, and suffix matches. The README has a section on search syntax, though the specific tokens are not in the excerpt. What is clear is that you can customize the look and behavior extensively. There are options for display modes: `--height` mode and `--popup` mode. The `--height` mode keeps fzf within a certain number of lines, so it does not take over the whole terminal. The `--popup` mode makes it appear as a popup, which is useful in editors. Environment variables are also part of the configuration. The README lists them under Environment variables. This means you can set defaults in your shell profile rather than passing flags every time. The customization goes deep. The README mentions a Theme Playground and tips for respecting `.gitignore`. The latter is important: you can make fzf respect your project's ignore rules, which is a common need when searching files.

A real limitation: it is interactive by design

fzf is not a replacement for non-interactive filtering. If you need to filter a stream in a script without human input, fzf is the wrong tool. It waits for a selection. You can use it with `--select-1` or `--exit-0` to make it behave more like a filter, but the README does not emphasize that as a primary use. Another limitation is the preview window. It depends on external commands and your terminal emulator. Image previews, for example, require a compatible terminal and additional setup. The README has a section on previewing an image, which implies it is not a plug-and-play feature. Also, the event-driven architecture has a learning curve. The README's advanced topics cover reloading and executing external programs, but that is not beginner material. You need to understand shell scripting and how fzf's events work. Finally, the project moves fast. The release history shows v0.74.3, v0.74.2, and v0.74.1 within a few weeks. That means options and behaviors can change. If you rely on a specific flag, you need to watch the changelog.

Alternatives: peco and skim take different paths

fzf is not the only fuzzy finder. Two notable alternatives are peco and skim. peco is written in Go and follows a simpler model. It reads stdin, filters, and prints the selection. It does not have the same event-driven architecture or the extensive preview window. peco is more of a straightforward filter. If you only need basic fuzzy selection, peco is easier to understand and customize. skim is written in Rust and aims for high performance, similar to fzf's claim. But skim has a different feature set. For example, skim supports a more advanced preview system and has a different set of options. The key difference in approach is that fzf emphasizes programmability and shell integration. The README highlights this with the event-driven architecture and the integrations for Bash, Zsh, Fish, Nushell, Vim, and Neovim. peco and skim do not have that same level of built-in shell integration. If you want a drop-in tool that works with your editor and shell out of the box, fzf is ahead. If you want a minimal filter that you can script yourself, peco might be enough.

Maintenance and license

fzf is actively maintained. The last push was August 2026, and releases come out regularly. The project is not archived. The license is MIT, which is permissive. You can use it in commercial projects, modify it, and redistribute it, as long as you include the copyright notice. This is a low barrier for adoption. The README also mentions sponsorship and merchandise, which suggests a sustainable project. The single-binary distribution means upgrading is simple: replace the binary. The README has a section on upgrading fzf. For shell integration, you need to keep the scripts in sync with the binary. If you install via a package manager, that is handled for you. If you install from git, you need to pull and re-run the install script. The release cadence is fast, which is good for bug fixes but can be a maintenance burden if you pin a specific version. You should check the release notes before upgrading, especially for breaking changes in options or key bindings.

Editorial conclusion

Adopt fzf if you spend time in a terminal and want fast, scriptable fuzzy selection for files, history, or custom data streams. The single binary and MIT license make it low-risk to integrate. Skip it if you need a GUI or if your workflow demands deterministic, non-interactive filtering; for that, use grep or ripgrep directly. Before adopting, verify that the shell integration scripts for your shell (Bash, Zsh, Fish, Nushell) match your environment, and test the preview window with your terminal emulator, since image previews require extra setup. Also check the latest release notes for any breaking changes in options or key bindings, as the project evolves quickly with frequent releases.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Community notes

Community notes