How to Set Up File Fuzzy Finding with fzf-lua in Neovim: A Complete Guide

The jdhao/nvim-config repository provides a production-ready fzf-lua integration that lazy-loads on the VeryLazy event, configures a centered floating window with Git icons, and binds intuitive <leader> keymaps for files, live grep, buffers, and help tags.

This guide walks through the exact implementation used in jdhao/nvim-config to enable blazing-fast file fuzzy finding. The setup leverages ibhagwan/fzf-lua, a Lua-based wrapper around the native fzf binary, and organizes the configuration across modular Lua files for optimal startup performance and maintainability.

Plugin Declaration and Lazy Loading

The first step registers fzf-lua as a managed plugin while ensuring it does not impact Neovim's startup time. In lua/plugin_specs.lua at lines 122–127, the plugin is declared with the VeryLazy event trigger:

{
  "ibhagwan/fzf-lua",
  event = "VeryLazy",
  config = function()
    require("config.fzf-lua")
  end,
}

This declaration instructs the plugin manager to download ibhagwan/fzf-lua from GitHub and defer its initialization until the VeryLazy event fires—after the UI has fully loaded. The config callback points to the dedicated configuration module at lua/config/fzf-lua.lua, keeping the plugin specification clean and the setup logic isolated.

Configuring the fzf-lua Interface

The core configuration resides in lua/config/fzf-lua.lua (lines 1–41), where the setup() function merges custom options with the plugin defaults. The jdhao/nvim-config implementation prioritizes a minimal, centered interface:

  • Window layout: A floating window positioned at row = 0.5 and height = 0.7, creating a centered dialog occupying 70% of the screen height
  • Preview: Disabled by default (previewers = { builtin = { enable = false } }) to maintain snappy performance
  • Icons: Mini file icons and Git integration enabled for visual scanning
  • Respect .gitignore: The file picker automatically excludes entries listed in .gitignore, with the option to override via .rgignore for fine-grained control

The configuration calls require("fzf-lua").setup({...}) with these parameters, establishing the baseline behavior for all subsequent picker invocations.

Essential Keymaps for Fuzzy Finding

After initialization, the configuration registers a suite of normal-mode mappings under the <leader> prefix. These mappings trigger specific FzfLua commands without requiring manual typing:

  • <leader>ff: Search files in the current project (respects .gitignore)
  • <leader>fg: Live grep across the codebase using ripgrep
  • <leader>fh: Search Neovim help tags
  • <leader>fb: List and switch between open buffers
  • <leader>fr: Access recently opened files

Each mapping uses vim.keymap.set with the noremap and silent flags to ensure clean execution. The <leader> key defaults to backslash (\) unless redefined elsewhere in the configuration (commonly mapped to space in lua/mappings.lua).

Prerequisites and External Dependencies

While the Lua configuration handles the UI and keybindings, the actual fuzzy-finding logic depends on external binaries that must be installed separately:

  1. fzf: The core fuzzy finder binary

    # macOS
    
    brew install fzf
    
    # Ubuntu/Debian
    
    sudo apt install fzf
  2. ripgrep (optional but recommended): Powers the live_grep functionality for fast, recursive regex search

    brew install ripgrep
    # or
    
    sudo apt install ripgrep

The plugin detects these binaries at runtime. If ripgrep is missing, the live_grep feature will fail gracefully or fall back to alternative search methods depending on your fzf-lua version.

Usage Examples and Lua API

Beyond the keymaps, you can invoke fzf-lua programmatically via the command line or Lua scripts. The following examples demonstrate both interfaces:

Command-line usage:

" Find files (respecting .gitignore)
:FzfLua files

" Search text across the project
:FzfLua live_grep

" Browse help documentation
:FzfLua helptags

" Switch between open buffers
:FzfLua buffers

Lua API for custom scripts:

local fzf = require('fzf-lua')

-- Open file picker with current configuration
fzf.files()

-- Live grep with specific options
fzf.live_grep()

-- Search old files (recently opened)
fzf.oldfiles()

The Lua API accepts optional tables to override the defaults set during initialization, allowing contextual behavior for specialized workflows.

Summary

  • The jdhao/nvim-config setup splits fzf-lua configuration between lua/plugin_specs.lua (plugin registration) and lua/config/fzf-lua.lua (behavior and keymaps)
  • Lazy loading on the VeryLazy event ensures zero startup time impact
  • The interface uses a centered floating window at 70% height with Git icons enabled and previews disabled for speed
  • Keymaps follow the <leader>f convention: ff for files, fg for grep, fh for help, fb for buffers, fr for recent files
  • You must install the fzf binary and optionally ripgrep system-wide for full functionality

Frequently Asked Questions

Do I need to install fzf separately from the Neovim plugin?

Yes. The ibhagwan/fzf-lua plugin is a Lua interface that communicates with the native fzf binary. You must install fzf via your system package manager (e.g., brew install fzf or sudo apt install fzf) before the fuzzy finder will function. The plugin does not bundle the binary.

How do I change the window size or enable file previews?

Modify the setup() call in lua/config/fzf-lua.lua. To adjust the window dimensions, change the row, col, width, or height values in the winopts table. To enable previews, remove or set to true the enable = false flag inside the previewers.builtin configuration.

Can I use fzf-lua without ripgrep?

Yes, but with limited functionality. The files picker works independently of ripgrep, relying instead on the fzf binary and find or fd (if installed). However, the live_grep feature (<leader>fg) specifically requires ripgrep (rg) to perform real-time text searching across the codebase.

What is the VeryLazy event and why is it used?

VeryLazy is a lifecycle event provided by modern Neovim plugin managers (like lazy.nvim) that fires after the UI and all initial buffers have loaded. By specifying event = "VeryLazy" in lua/plugin_specs.lua, the configuration ensures fzf-lua loads only when first needed—typically when you press a mapped key—keeping your Neovim startup time minimal and responsive.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →