fff.nvim Example Usage: Complete Guide to Fast File Finding in Neovim
To use fff.nvim, install the plugin with a Rust binary build, then call require('fff').find_files() or require('fff').live_grep() with optional configuration overrides for layout, search modes, and filters.
fff.nvim is a high-performance file finder and live grep plugin for Neovim that combines a Lua-based UI with a Rust-powered search engine. This guide provides practical fff.nvim example usage patterns drawn directly from the source code, demonstrating how to configure the plugin, invoke searches, and integrate advanced features like frecency scoring and Git status tracking.
Minimal Installation with lazy.nvim
The plugin requires a Rust binary that handles filesystem indexing and search operations. When using lazy.nvim, define a build step to handle the compilation or download automatically.
{
'dmtrKovalenko/fff.nvim',
build = function()
-- Downloads a pre‑built binary or builds it from source
require('fff.download').download_or_build_binary()
end,
opts = {
debug = {
enabled = true, -- show file‑info panel
show_scores = true, -- display scoring data in the UI
},
},
keys = {
{ 'ff', function() require('fff').find_files() end, desc = 'Find files' },
{ 'fg', function() require('fff').live_grep() end, desc = 'Live grep' },
{ 'fc', function() require('fff').live_grep({ query = vim.fn.expand('<cword>') }) end,
desc = 'Grep word under cursor' },
},
}
Source: lua/fff/main.lua (entry points find_files and live_grep) and lua/fff/picker_ui.lua (window rendering).
Core API Functions
The public API exposed in lua/fff/main.lua provides three primary entry points for file and content discovery.
Finding Files
Call find_files() to open a fuzzy finder over your project directory. Pass an options table to customize the title, result limits, or layout for that specific invocation.
local fff = require('fff')
-- Open the picker with a custom title and reduced result set
fff.find_files({
title = 'My Project Files',
max_results = 50,
})
This delegates to picker_ui.open() in lua/fff/picker_ui.lua, which spawns the Rust-based FilePicker::new_with_shared_state in a background thread.
Live Grep
Use live_grep() to search file contents with bigram-accelerated indexing. Configure search modes, case sensitivity, and preview positioning per call.
-- Perform a grep limited to specific modes with bottom preview
fff.live_grep({
grep = { modes = { 'plain' } },
query = 'TODO',
layout = { preview_position = 'bottom' },
})
The search engine in crates/fff-grep/src/lib.rs handles the query parsing and content scanning, supporting plain text, regex, and fuzzy matching modes.
Configuration Examples
Configuration is managed through require('fff').setup() or the global vim.g.fff table, defined in lua/fff/conf.lua.
Layout and Preview
Control floating window geometry and preview behavior via the layout and preview sections.
require('fff').setup({
layout = {
height = 0.8,
width = 0.9,
preview_position = 'right',
preview_size = 0.5,
},
preview = {
enabled = true,
max_size = 100000, -- bytes
binary_file_threshold = 1024,
line_numbers = true,
},
})
Frecency and History
Enable frecency tracking to bias results toward recently and frequently opened files. History remembers previous queries and boosts repeated selections.
{
frecency = {
enabled = true,
db_path = vim.fn.stdpath('data') .. '/fff/frecency.db',
},
history = {
enabled = true,
db_path = vim.fn.stdpath('data') .. '/fff/history.db',
min_combo_count = 3,
combo_boost_score_multiplier = 1.5,
},
}
These features are implemented in crates/fff-core/src/frecency.rs and integrate with the FilePicker index.
Advanced Usage Patterns
Beyond basic file finding, fff.nvim example usage includes programmatic searches, manual index management, and debugging utilities.
Programmatic Search
Access the Rust search engine directly without opening the UI by calling search() with a query string and result limit. This returns a Lua table of matches for custom processing.
local fff = require('fff')
local results = fff.search('init', 20) -- returns up to 20 matches
for _, file in ipairs(results) do
print(file.relative_path, file.frecency_score)
end
Source: lua/fff/main.lua → M.search → FilePicker::fuzzy_search_files.
Manual Index Management
Force a full filesystem rescan after massive repository changes like branch switches or bulk file operations.
-- Trigger a complete rescan in the background
require('fff').scan_files()
Refresh Git status caching independently of the file scan:
require('fff').refresh_git_status()
Both functions delegate to FilePicker methods in crates/fff-core/src/file_picker.rs.
Runtime Debugging
Toggle debug mode and scoring overlays without restarting Neovim:
-- Enable score visualization in the picker
vim.api.nvim_command('FFFDebug on')
This updates the configuration defined in lua/fff/conf.lua at runtime.
Summary
- fff.nvim separates the Lua UI (
lua/fff/picker_ui.lua) from the Rust search core (crates/fff-core/) for non-blocking performance. - Install via package managers using
require('fff.download').download_or_build_binary()to handle the Rust binary compilation. - Invoke
find_files()andlive_grep()fromlua/fff/main.luawith per-call option overrides for layout and search modes. - Configure persistence via
setup()inlua/fff/conf.lua, supporting frecency scoring, history, and Git status integration. - Use
scan_files()andrefresh_git_status()to manually synchronize the index after large repository changes. - Access the search engine programmatically via
search()for custom tooling and AI agent integrations.
Frequently Asked Questions
How do I install fff.nvim if I don't have Rust installed?
The plugin includes a download mechanism that retrieves pre-built binaries for supported platforms. In your package manager configuration, ensure you call require('fff.download').download_or_build_binary() in the build step. If a pre-built binary is unavailable for your system, you will need Rust to compile from source.
Can I use fff.nvim without opening the floating window?
Yes. The search() function in lua/fff/main.lua provides direct access to the Rust fuzzy search engine. Pass a query string and maximum results count to receive a Lua table of matches containing file paths and frecency scores, enabling integration with scripts or other plugins.
What is the difference between find_files and live_grep in fff.nvim?
find_files() searches filenames using a fuzzy matching algorithm against the filesystem index built by FilePicker::fuzzy_search. live_grep() searches file contents using a bigram index built by build_bigram_index in Rust, supporting plain text, regex, and fuzzy content matching with real-time results as you type.
How do I force a rescan of my project directory?
Call require('fff').scan_files() to trigger FilePicker::scan_files in the Rust backend. This walks the filesystem using ignore::WalkBuilder, rebuilds the file index, and updates the bigram overlay. Use this after operations that modify many files at once, such as checking out a different Git branch.
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 →