fzf - a command-line fuzzy finder
GitHub Repo
MIT
July 31, 2026 at 08:22 PM
0 views

fzf - a command-line fuzzy finder

@junegunnProject Author

Fzf: A Masterful Command-Line Fuzzy Finder for Every Terminal

If you spend long hours in the shell, you know the pain of hunting through mountains of files, history, and data. Enter fzf, a general-purpose command-line fuzzy finder and interactive terminal toolkit that turns your shell into a programmable playground. Portable, fast, and incredibly extensible, fzf isn’t just a tool—it’s the building block for transforming scripts into responsive, interactive terminal applications.

fzf - a command-line fuzzy finder

A quick glance at the project: portable as a single binary, lightning-fast at filtering millions of items, and designed to be programmable with an event-driven architecture. It ships with batteries-included integrations for Bash, Zsh, Fish, Nushell, Vim, and Neovim, making it a versatile companion across shells and editors. Whether you’re selecting files, paging through command history, previewing data, or stitching together complex menus, fzf provides the flexible primitives you need to craft rich terminal experiences.


Highlights: Why developers and sysadmins reach for fzf

  • Portable and easy to install: distributed as a single binary for quick setup.
  • Fast and scalable: optimized to process millions of items with near-instant responses.
  • Programmable and extensible: event-driven, designed for building custom interfaces and workflows.
  • Batteries-included: ready-made integrations across major shells and editors, plus a long roadmap of advanced features.

To show a little love for fzf, there’s also merch—shirts, mugs, and stickers—for fans who want to wear or display their fandom.

fzf merch

The spirit of fzf is simple: give you a powerful, flexible interface to filter and select from any list, while keeping the door open to integrating into larger automation or configuration workflows.


Getting started: Installation and setup

There are multiple paths to install fzf, depending on your platform and preference. The goal is to get you a working binary quickly, then unlock the full shell integration later for a smoother, more autonomous experience.

  • Homebrew (macOS and Linux): install fzf with brew install fzf, then set up the shell integration to enable key bindings and fuzzy completion.
  • Important: after installation, be sure to configure the shell integration as described below.
  • Mise: a simple installer that can pull in fzf with a single command.
  • Linux packages: a broad set of package managers across distributions (APK, APT, DNF, Pacman, Nix, etc.). The same note about shell integration applies.
  • Windows packages: chocolatey, Scoop, Winget, and MSYS2 provide fzf on Windows.
  • Using git: clone the repository and run the install script to wire up PATH and shell integration.
  • Binary releases: official binaries are available from the releases page for quick download and use.

After you’ve installed, you’ll want to enable the shell integration so you get convenient key bindings and fuzzy completion. The integration scripts provide the glue that binds the fzf engine to your shell.

  • Bash: eval "$(fzf --bash)"
  • Zsh: source <(fzf --zsh)
  • Fish: fzf --fish | source
  • Nushell: a small script-inside approach for autoloaded integration

If you’re curious about keeping default options or customizing behavior, you can point to a defaults file or export a few environment variables to steer fzf’s behavior globally.

  • Typical environment controls: FZFDEFAULTCOMMAND, FZFDEFAULTOPTS, and FZFDEFAULTOPTS_FILE
  • These enable you to define what list to present, how it’s displayed, and where to store default option sets.

[Note: the official layout provides a comprehensive “Using git” and “Binary releases” section to guide you through each install pathway.]


Setting up shell integration: binding power to your shell

Once the binary is in place, you’ll typically want to wire up the shell integration. This makes fzf pop up as a delightful interactive finder whenever you need it, with:

  • CTRL-T: paste the selected files and directories onto the command line
  • CTRL-R: paste the selected commands from history
  • ALT-C: change directory to the selected directory

The integration provides a consistent experience across Bash, Zsh, Fish, and Nushell, letting you customize or disable specific bindings if you prefer a leaner setup.

You can also tailor the behavior by adjusting FZFCTRLTCOMMAND, FZFALTCCOMMAND, and their related options, or by injecting your own commands for each binding. The integration is designed to be friendly for users who want to disable particular bindings or swap in their own logic.

A quick peek at how the presets shape the UI is helpful. The default look and feel can be changed with the --style option, offering presets such as default, full, or minimal. Each style crafts a different balance of borders, headers, and preview behavior to fit your workflow.


Vim and Neovim: a powerful pairing

For Vim and Neovim users, fzf itself ships a Vim plugin that connects the finder to editing. The basic setup (with vim-plug, for example) fetches both the core library and the Vim integration:

  • junegunn/fzf (the core)
  • junegunn/fzf.vim (the Vim plugin)

The core library ensures you have the latest binary via fzf#install(), and the Vim plugin extends the interface to drive buffers, files, and commands from within the editor. If you’re a Neovim fan, you may also explore lua-based forks like fzf-lua for smoother integration with Neovim’s modern ecosystem.


Usage: how fzf becomes your workflow companion

At its core, fzf launches an interactive finder, reads the candidate list from standard input, and writes the chosen item to standard output. A simple example:

  • Pipe a list of files: find * -type f | fzf > selected

If you don’t pipe from STDIN, fzf can still traverse the filesystem to assemble candidates for you.

  • Example: vim $(fzf)

To tailor fzf to your needs, you can override the default candidate source by:

  • Setting FZFDEFAULTCOMMAND to a command that generates the desired list
  • Or adjusting --walker, --walker-root, and --walker-skip through FZFDEFAULTOPTS

A powerful trick is to turn fzf into a different process entirely via become() bindings, essentially transforming the current fzf run into another command’s lifecycle.

  • Example: fzf --bind 'enter:become(vim {})'
  • This approach can be much more robust than wrapping commands around fzf, especially for multi-select workflows.

Keybindings overview (via shell integration) include navigation with CTRL-K/CTRL-J or CTRL-P/CTRL-N, selection with Enter, and exit with CTRL-C, ESC, or CTRL-G. Multi-select mode (-m) introduces TAB and Shift-TAB for marking items.


Display modes: how the finder presents results

fzf offers several display modes to suit different screen sizes and preferences.

  • Default fullscreen mode: the usual immersive finder experience.
  • --height mode: start the finder a certain height below the cursor (e.g., fzf --height 40%). It can be useful to leave more of the terminal visible and combine with reverse layout and borders for a tailored look.
  • Negative height: you can specify a negative height to reserve space by subtracting lines from the bottom of the screen (e.g., fzf --height -3).
  • --popup mode: run fzf in a popup window (requires tmux 3.3+ or Zellij 0.44+). This creates a floating, centered, or edge-aligned panel that can coexist with other workspace panes. If your environment doesn’t support native popups, you can still rely on the classic mode, or use the fzf-tmux wrapper in some setups.

Pro tip: you can set defaults via FZFDEFAULTOPTS to apply a consistent look and feel across all invocations, e.g., combining height, layout, border, and a preview window.

Visual references show how these presets look in practice:

  • default, full, and minimal style presets
  • a full preset example with borders and labels

Images illustrating these styles help you visualize the exact border, padding, and label behavior you’ll get with each preset.

  • fzf style default: https://raw.githubusercontent.com/junegunn/i/master/fzf-style-default.png
  • fzf style full: https://raw.githubusercontent.com/junegunn/i/master/fzf-style-full.png
  • fzf style minimal: https://raw.githubusercontent.com/junegunn/i/master/fzf-style-minimal.png
  • an example using the full preset: https://raw.githubusercontent.com/junegunn/i/master/fzf-4-borders.png

For a practical demo, a screencast showcases the breadth of fzf features and how fluidly you can navigate and select items.


Search syntax and matching

fzf’s search is designed to be forgiving yet expressive. By default, it uses extended-search mode, letting you type multiple terms separated by spaces to refine results. You can see a few patterns below:

  • sbtrkt (fuzzy match)
  • 'wild' (exact match)
  • 'wild' (exact-boundary match)
  • ^music (prefix exact)
  • .mp3$ (suffix exact)
  • !fire (inverse-exact)
  • !^music (inverse-prefix exact)
  • !.mp3$ (inverse-suffix exact)

If you prefer exact matching, you can invoke -e or --exact. The query syntax supports OR logic with a vertical bar (|) for combining terms.

This powerful syntax makes fzf suitable for hunting within filenames, history, and beyond—it's not limited to a single domain.


Environment and customization: tailoring fzf to your world

  • FZFDEFAULTCOMMAND: default command that supplies candidates. Useful when your input is tty and you want a consistent source of items.
  • FZFDEFAULTOPTS: default fzf options (layout, borders, preview, etc.). It’s common to export a preset, e.g. a reverse layout with inline info.
  • FZFDEFAULTOPTS_FILE: a path to a file containing default options if you want to manage them outside your shell startup scripts.

Shell integration and defaults are designed so you can focus on your workflow rather than repeatedly typing the same flags. The docs provide a wide array of examples for path completion, directory completion, and more advanced customization hooks.


Customizing the look: style, color, and the preview

One of fzf’s defining strengths is its visual customization. The --style option enables three primary presets—default, full, and minimal—letting you harmonize the finder with your terminal theme and workflow. You can pair a style with a rich preview:

  • A preview command, such as fzf-preview.sh, can show content in a split window.
  • You can craft complex header and input labels to describe what you’re selecting.

A representative example using the full style with a border and a labeled interface shows how you can create an onboarding experience for a project, or a focused “demo” session for teaching teammates how to use fzf.

Images of the style presets and an example bordered layout help convey the visual diversity you can achieve.

Additionally, a screencast demonstrates the power of combining the default options with a preview script to create two-pane experiences that feel native to the terminal.


Demos and hands-on: learning by watching

If you’re a learner who benefits from a walk-through, this screencast is a valuable resource for exploring fzf features and commands. It highlights the flow from installation to complex usage, including navigation, previews, and how to bind actions to keys. The linked video provides a visual tour of fzf in action.

For a quick visual cue, you can also explore a screenshot gallery that showcases how fzf looks across different presets and how the preview pane behaves as you move through candidates.

  • You can click through a YouTube screencast to watch a guided tour: https://www.youtube.com/watch?v=qgG5Jhi%5FEls

Illustrative images help bridge the gap between theory and practice, including a capture of the full interface with borders and labels.


Examples, tips, and a few advanced tricks

  • The wiki pages and ADVANCED.md are excellent sources for advanced examples and workflows. They showcase complex pipelines, ripgrep integration, and how to weave fzf into larger automation.
  • A few practical tips:
  • Respect .gitignore by combining fd with fzf to avoid listing ignored files.
  • Use fd or ripgrep to generate candidates, then pipe into fzf for fast, accurate filtering.
  • Fuzzy completion for shells (Bash, Zsh, Fish) is a major strength. You can customize fuzzy completion for commands, paths, and hosts, with per-command overrides via fzfcomplete_COMMAND hooks.

Fish shell users benefit from a slightly different interaction model: TAB and Shift-TAB work with Fish’ native completion. FZF’s Fish integration can be customized to anchor the lookup with the current command.

The fish-specific notes also cover how to set prefixes and how to apply additional options to the completions.

A dedicated section covers Nushell, with its external completer mechanism and the ability to push custom completers through the FZFCOMPLETION* environment variables.


Files and directories, PIDs, and hosts: practical fuzzy completion use cases

  • Files and directories: fuzzy completion for files and directories can be triggered with a dedicated trigger sequence (default: **). You can complete paths, browse parent directories, and filter results in-situ.
  • Process IDs: fuzzy completion supports killing processes by selecting from a list of PIDs.
  • Hostnames: for ssh, fzf can provide hostnames sourced from /etc/hosts and ~/.ssh/config, enabling quick remote connections.

As you design completion logic, you might customize:

  • Custom fuzzy completion for a specific command
  • How completion candidates are post-processed

Code examples in the docs illustrate how to wire up custom commands to fzf options, including multi-select, previews, and post-processing steps.


Fuzzy completion across shells: Bash, Zsh, Fish, Nushell

  • Bash and Zsh: the completion system uses fzfcomplete hooks to expose completions for a set of core commands. It’s possible to expand support to other commands by writing your own helper fzfsetup_completion.
  • Fish: completion behaves slightly differently, focusing on the native Fish completion system with Shift-TAB integration and separate handling for wildcards.
  • Nushell: relies on external completers; a robust example shows how to define completers as closures in your Nushell config, returning candidates or a structured object with candidate lists and options.

These details reflect fzf’s philosophy: provide a strong, consistent default experience while enabling deep customization for power users.


The Vim plugin: a seamless editing workflow

If you’re editing with Vim or Neovim, the fzf Vim plugin enables a tight integration where you can navigate and filter within your editor’s workflow. Installing the core and the Vim integration, then using the provided functions, makes file switching, command execution, and search a fluid part of your editing session. For Neovim enthusiasts, Lua-based alternatives like fzf-lua are also worth exploring for an even more native feel.


Advanced topics: performance, reload, and turning fzf into a subprocess

  • Performance: fzf is fast by design, but there are some caveats:
  • --ansi parsing and --nth can slow initial scans
  • Plain delimiter usage is typically faster than regular expressions
  • With-nth adds overhead because of tokenization
  • Executing external programs and turning into a different process:
  • You can bind enter to become(vim {}) or become(emacs {}) to hand control to another program while preserving fzf’s state
  • Reloading candidates:
  • You can bind a key to reload a different candidate source (e.g., ps, find, ripgrep) to reflect dynamic changes
  • Interactive ripgrep integration re-launches ripgrep with the current query, demonstrating how fzf can act as the selector for live-search workflows

The docs provide stepped examples showing how to wire reload actions to CTRL-R (for processes) or CTRL-D/CTRL-F to switch between sources, illustrating how fzf can be more dynamic than a static prompt.


The preview window: seeing results, not just lists

When you enable --preview, fzf launches a background command using the currently focused line as an argument and displays its output in a split pane. This is where fzf becomes a powerful tool for inspecting the selected item without leaving the finder.

  • Preview commands can leverage color and ANSI codes to provide a richer experience.
  • Common patterns include using bat or highlight to show syntax-highlighted content, or file-type specific previews to provide at-a-glance context.

An example demo demonstrates a preview window that shows the selected file’s contents with BAT:

  • fzf --preview 'bat --color=always {}'
  • And a carefully configured --preview-window setting can position, size, and border the preview pane.

It’s important to note the caveat: because fzf is a general-purpose filter, injecting heavy previews into every invocation can slow down start-up. The tip is to avoid universal previews in default OPTS and enable them selectively.


Previewing an image

fzf’s preview engine can render images in supported terminals using protocols like Kitty graphics, iTerm2 inline images, or Sixel. If your terminal supports graphical previews, you can display images in the preview pane, which can be especially helpful for reviewing media or design files directly from the finder.

Example usage:

  • fzf --preview 'fzf-preview.sh {}'

This capability adds a surprisingly rich dimension to shell workflows, letting you filter your catalog of images, diagrams, or assets while instantly inspecting their visuals.


Tips and extras: making the most of fzf

  • Respecting .gitignore: pair fzf with fd or ripgrep to respect ignore rules. You can steer default lists with FZFDEFAULTCOMMAND to use fd with hidden files if needed.
  • Fish shell quirks: CTRL-T in Fish uses the last token as the root for recursive search. If you customize the FZFCTRLT_COMMAND, the unexpanded $dir variable can be a powerful feature to leverage.
  • Theme Playground and related projects: try the FZF Theme Playground to experiment with themes and styles, helping you tailor fzf to your color schemes and terminal aesthetics.

Branding and community resources include a Theme Playground and related projects to extend fzf’s ecosystem beyond the core repository.

  • FZF Theme Playground: https://vitormv.github.io/fzf-themes/
  • Related projects: a wiki directory of community resources

License, goods, and community

  • License: The MIT License (MIT)
  • Goods: Official fzf merch with shirts, mugs, and stickers
  • Sponsors: Acknowledge and support sponsors who help sustain ongoing development

The project’s spirit is community-driven, with sponsorships helping to fund ongoing maintenance and enhancements.


A closing note

fzf remains a remarkably versatile tool for everyday terminal life. Its design philosophy—fast, portable, programmable, and batteries-included—makes it a go-to for developers, sysadmins, and power users who want to turn the shell into a dynamic, interactive workspace. From simple file selection to sophisticated completion pipelines, fzf provides a robust foundation on which to build custom, efficient, and delightful workflows.

If you haven’t explored fzf in a while, you owe it to yourself to try the latest features: natural shell integrations, rich preview options, image previews in the terminal, and the expansive ecosystem of shell completions, Vim integrations, and advanced usage examples. The combination of images, presets, and community resources illustrates just how far fzf has evolved—from a compact fuzzy finder to a complete terminal toolkit that reshapes how you interact with data in the shell.

Enjoying this project?

Discover more amazing open-source projects on TechLogHub. We curate the best developer tools and projects.

Project
fzf-a-command-line-fuzzy-finder
Created
July 31
Last Updated
July 31, 2026 at 08:22 PM

Maintain fzf - a command-line fuzzy finder? Add the badge to your README

Show that the project is featured on TechLogHub and send readers to this write-up.

Featured on TechLogHub
[![Featured on TechLogHub](https://techloghub.com/badge-neutral.svg)](https://techloghub.com/open-source/fzf-a-command-line-fuzzy-finder?utm_source=techloghub_badge&utm_medium=referral&utm_campaign=readme)

Find more projects like this

One email a week: new and trending developer tools, fresh comparisons, and what shipped. Unsubscribe in one click.