Best Practices for Configuring fff.nvim: Complete Setup Guide
Configure fff.nvim by setting options in the global table vim.g.fff before calling setup(), enable lazy_sync to defer file indexing until first use, and activate frecency and history databases for intelligent result ranking.
fff.nvim is a high-performance fuzzy finder for Neovim powered by a Rust-based search engine. The plugin reads all user preferences from vim.g.fff and merges them with comprehensive defaults defined in lua/fff/conf.lua (lines 89–136) during the initialization sequence. Understanding this configuration architecture ensures minimal startup overhead and a picker tailored to your workflow.
Configuration Architecture
The plugin employs a two-phase initialization system designed for speed and flexibility.
Global Configuration Merging
All runtime options are stored in vim.g.fff and merged with internal defaults using vim.tbl_deep_extend('force', ...) inside lua/fff/conf.lua. The init() function processes this table, applies deprecated-option migrations (such as rewriting legacy top-level width keys to layout.width), and caches the final configuration in a module-local state object. This approach allows you to define preferences in your init.lua without side effects, as the plugin only reads the global variable during its initialization phase.
Lazy Initialization
In plugin/fff.lua (lines 7–12), the plugin checks vim.g.fff.lazy_sync before spawning the Rust indexer. When set to true (the default), require('fff.core').ensure_initialized() is scheduled after UIEnter, deferring file indexing until you open your first picker. This keeps Neovim's startup time fast while ensuring the search backend is ready when needed.
Essential Configuration Domains
Base Path and UI Options
Define the search context and visual identity through top-level keys. Set base_path = vim.fn.getcwd() to ensure the picker always starts in your current project. Configure prompt = '🪿 ' and title = 'FFFiles' to customize the window header, and adjust max_results = 200 if you frequently work with large repositories and need deeper result sets.
Layout and Window Management
The layout system in lua/fff/conf.lua (lines 190–215) supports responsive sizing. Use height = 0.8 and width = 0.8 to occupy 80% of the screen estate, providing a comfortable view on most terminals. Set preview_size = 0.5 and enable flex = { size = 130, wrap = 'top' } to automatically hide the preview panel when the terminal width drops below 130 columns. For file path display, path_shorten_strategy = 'middle_number' intelligently compresses long paths while preserving the project structure.
Preview Settings
Prevent UI freezes by limiting preview.max_size = 10 * 1024 * 1024 (10 MiB) for binary files. Enable line wrapping for documentation filetypes by setting preview.filetypes = { markdown = { wrap_lines = true }, text = { wrap_lines = true } }, improving readability of README files and logs without affecting code files.
Grep Configuration
Live grep performance is controlled through the grep sub-table. Set max_file_size = 10 * 1024 * 1024 and max_matches_per_file = 100 to prevent the Rust engine from choking on minified assets. A time_budget_ms = 150 ensures responsive results even on large codebases. Define modes = { 'plain', 'regex', 'fuzzy' } to cycle between literal string matching, regular expressions, and fuzzy finding during searches.
Frecency and History Databases
Enable persistent scoring to improve result relevance over time. Set frecency = { enabled = true } to store usage data in stdpath('cache')/fff_nvim, boosting frequently opened files in the ranking algorithm. Activate history = { enabled = true } to save successful queries in stdpath('data')/fff_queries, enabling the "combo-boost" feature that favors files repeatedly opened with similar queries.
Git Integration
Control visual noise with git.status_text_color = false (default) to keep filenames neutral, or enable it to colorize text based on git status. The plugin uses highlight groups such as FFFGitModified and FFFGitUntracked defined in the default configuration, which you can remap to your color scheme's groups.
Debugging Options
Keep debug.enabled = false for daily use to avoid performance overhead. Enable debug.show_scores = true temporarily when tuning scoring algorithms to visualize why certain files rank higher. Access this toggle at runtime via require('fff.conf').toggle_debug() or the :FFFDebug toggle command.
Complete Configuration Examples
Minimal Future-Proof Setup
Place this in your init.lua before the plugin loads to ensure all preferences are captured during the initialization phase in lua/fff/conf.lua:
-- ~/.config/nvim/init.lua
vim.g.fff = {
-- Search context
base_path = vim.fn.getcwd(),
prompt = '🪿 ',
title = 'FFFiles',
max_results = 200,
-- Responsive layout
layout = {
height = 0.85,
width = 0.85,
preview_position = 'right',
preview_size = 0.45,
flex = { size = 120, wrap = 'top' },
path_shorten_strategy = 'middle_number',
},
-- Preview handling
preview = {
enabled = true,
max_size = 5 * 1024 * 1024, -- 5 MiB limit
binary_file_threshold = 0, -- Treat all files as text
filetypes = {
markdown = { wrap_lines = true },
text = { wrap_lines = true },
},
},
-- Grep performance tuning
grep = {
max_file_size = 8 * 1024 * 1024,
time_budget_ms = 100,
modes = { 'plain', 'regex', 'fuzzy' },
},
-- Smart ranking databases
frecency = { enabled = true },
history = { enabled = true },
-- Git visuals
git = { status_text_color = false },
-- Diagnostics
debug = { enabled = false, show_scores = false },
}
require('fff').setup(vim.g.fff)
Per-Picker Overrides
Override specific options for individual commands without touching the global configuration:
-- Quick grep with only regex and plain modes
vim.keymap.set('n', '<leader>sg', function()
require('fff').live_grep({
query = vim.fn.expand("<cword>"),
grep = { modes = { 'regex', 'plain' } },
})
end, { desc = 'Search word with regex-fallback' })
This demonstrates that live_grep() accepts a grep sub-table, letting you tailor the search mode list for specific workflows while keeping your default configuration intact.
Custom Highlight Groups
Map git status colors to your color scheme for consistent theming:
-- Define custom highlights
vim.api.nvim_set_hl(0, 'CustomGitModified', { fg = '#ff8800' })
vim.api.nvim_set_hl(0, 'CustomGitUntracked', { fg = '#00ff88' })
vim.g.fff = {
git = { status_text_color = true },
hl = {
git_modified = 'CustomGitModified',
git_untracked = 'CustomGitUntracked',
},
}
require('fff').setup(vim.g.fff)
This configuration binds the plugin's default highlight group names (defined in doc/fff.nvim.txt lines 90–120) to your custom color definitions, ensuring the picker respects your terminal's aesthetic.
Summary
- Initialize early: Set
vim.g.fffbefore callingsetup()to ensurelua/fff/conf.luacaptures your preferences during the merge phase. - Defer indexing: Keep
lazy_sync = true(the default inplugin/fff.lua) to prevent startup delays by scheduling the Rust indexer afterUIEnter. - Enable smart ranking: Turn on
frecencyandhistorydatabases to improve result relevance based on your editing patterns. - Limit resource usage: Cap
preview.max_sizeandgrep.max_file_sizeat 5–10 MiB to prevent UI freezes on large binary files. - Use flex layouts: Configure
layout.flexto automatically adapt the preview panel width based on terminal size. - Debug sparingly: Enable
debug.show_scoresonly when tuning algorithms, and usetoggle_debug()for runtime inspection without configuration changes.
Frequently Asked Questions
How do I migrate deprecated configuration options in fff.nvim?
The configuration loader in lua/fff/conf.lua automatically migrates legacy keys using an internal migration table. For example, top-level width and height keys are automatically rewritten to layout.width and layout.height with a deprecation warning via vim.notify. To avoid these warnings, update your configuration to use the current nested structure under layout and preview sub-tables as documented in the default configuration (lines 89–136).
Why should I enable lazy_sync in fff.nvim?
Setting lazy_sync = true (the default) in vim.g.fff defers the execution of require('fff.core').ensure_initialized() until after Neovim's UIEnter event, as implemented in plugin/fff.lua (lines 7–12). This prevents the Rust file indexer from blocking your editor during startup, ensuring immediate responsiveness when opening Neovim while maintaining fast picker performance once the index is built in the background.
How do I customize git status colors in fff.nvim?
Map the plugin's highlight group names to your color scheme after calling setup(). The default groups FFFGitModified, FFFGitUntracked, and others are documented in doc/fff.nvim.txt (lines 90–120). Set git.status_text_color = true in your configuration, then use vim.api.nvim_set_hl to link these groups to your preferred colors, or override the group names entirely in the hl configuration table to point to custom highlight groups you define.
What is the recommended way to debug scoring algorithms in fff.nvim?
Enable runtime inspection by calling require('fff.conf').toggle_debug(), which flips the debug.show_scores boolean and emits a notification. This overlays relevance scores directly in the picker UI, allowing you to see why the Rust ranking algorithm prioritizes certain files. For file-based diagnostics, ensure logging.enabled = true and log_level = 'info' are set to capture detailed indexer behavior in Neovim's log files without impacting interactive performance.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →