fff.nvim Custom Configuration: Complete Guide to Setup Options

Yes, fff.nvim supports extensive custom configurations through vim.g.fff or require('fff').setup(), allowing you to customize UI layout, keymaps, preview behavior, git integration, and search algorithms.

fff.nvim is a fast fuzzy finder plugin for Neovim built around a flexible configuration system. The plugin reads user preferences from a global variable or setup function and merges them with comprehensive defaults defined in lua/fff/conf.lua. Whether you need to adjust the window layout, disable previews, or configure grep modes, every aspect of the plugin can be tailored to your workflow.

Configuration Architecture

Understanding how fff.nvim processes configuration helps you decide between setup methods and troubleshoot issues.

Configuration Sources

The plugin supports two primary methods for supplying custom settings. When the plugin first needs its configuration, fff.conf checks vim.g.fff at line 89 in lua/fff/conf.lua:

local config = vim.g.fff or {}

If you call require('fff').setup({ ... }), the function stores your table directly in vim.g.fff at line 45 of the same file. This design ensures compatibility with any plugin manager, as the configuration persists in a global variable accessible throughout the session.

Default Values and Merging

A complete set of defaults resides in default_config (lines 92-135 of lua/fff/conf.lua). This table defines base paths, prompt strings, layout dimensions, keymaps, highlight groups, frecency settings, git integration, debug flags, and logging options.

When conf:get() executes, it merges user settings with defaults using:

vim.tbl_deep_extend('force', default_config, migrated_user_config)

This deep merge at lines 39-40 ensures your overrides take precedence while preserving unspecified defaults.

Deprecation Handling

The plugin automatically migrates old option names to new schemas. The handle_deprecated_config() function (lines 58-73 of lua/fff/conf.lua) processes legacy keys like width (migrated to layout.width) and emits warnings via vim.notify when it detects deprecated usage.

Lazy Initialization

Configuration loading is deferred until the UIEnter event, as implemented in plugin/fff.lua (lines 7-12). During initialization, require('fff.core').ensure_initialized() accesses the merged configuration. You can disable this lazy loading by setting lazy_sync = false in your configuration.

How to Configure fff.nvim

You can supply configuration before or after the plugin loads, depending on your preference and plugin manager setup.

Using setup()

The most common approach calls the setup function in your Neovim configuration:

require('fff').setup({
  base_path = vim.fn.expand('~/projects'),
  prompt = '🔎 ',
  layout = {
    height = 0.9,
    width = 0.7,
    preview_position = 'bottom',
    preview_size = 0.4,
    show_scrollbar = false,
  },
  keymaps = {
    close = 'q',
    select = '<CR>',
    toggle_debug = '<F5>',
    cycle_grep_modes = '<C-Tab>',
  },
  git = { status_text_color = true },
  debug = { enabled = true, show_scores = true },
})

Using vim.g.fff

For users who prefer global variables or need configuration available before the plugin loads:

vim.g.fff = {
  lazy_sync = false,
  max_results = 200,
  grep = {
    modes = { 'plain', 'regex' },
    smart_case = false,
  },
}

Because conf.lua reads vim.g.fff on first demand, this table is respected even if you never explicitly call setup().

Runtime Configuration Changes

The configuration object remains mutable after load. Access the active configuration table and modify specific values:

local cfg = require('fff.conf').get()
cfg.layout.preview_position = 'left'
cfg.keymaps.toggle_select = '<Space>'

Debug scores can also be toggled on the fly using the :FFFDebug command, which manipulates require('fff.conf').get().debug.show_scores.

Configuration Examples

Customizing UI Layout

Control the finder window dimensions and preview placement:

require('fff').setup({
  layout = {
    height = 0.8,
    width = 0.6,
    preview_position = 'right',
    preview_size = 0.5,
  },
})

Disabling Preview

To save screen real estate, completely disable the preview pane:

require('fff').setup({
  preview = { enabled = false },
})

The UI will render only the file list without the preview panel.

Grep Mode Configuration

Customize how the grep functionality behaves across different search modes:

vim.g.fff = {
  grep = {
    modes = { 'plain', 'regex', 'fuzzy' },
    smart_case = true,
    max_results = 100,
  },
}

Key Source Files

Reference these files when diving deeper into fff.nvim custom configuration:

  • lua/fff/conf.lua – Core configuration handling including defaults, merging logic, deprecation migration, and the public setup()/get() API
  • plugin/fff.lua – Lazy-loading bootstrap that determines when configuration is first consulted
  • lua/fff/main.lua – Public module interface that forwards calls to core logic
  • lua/fff/picker_ui.lua – UI layout implementation that respects the layout and preview configuration tables
  • lua/fff/file_picker/icons.lua – Icon handling that detects providers based on configuration settings

Summary

  • fff.nvim custom configuration is handled through vim.g.fff or require('fff').setup(), with both methods storing values in a global variable that merges with defaults
  • The configuration system in lua/fff/conf.lua uses vim.tbl_deep_extend to combine user settings with comprehensive defaults covering UI, keymaps, git, and search behavior
  • Deprecated options are automatically migrated via handle_deprecated_config() with user notifications
  • Configuration supports runtime modification by accessing require('fff.conf').get()
  • Lazy initialization defers configuration loading until UIEnter unless lazy_sync is disabled

Frequently Asked Questions

How do I configure fff.nvim without calling setup()?

Set the vim.g.fff global variable before the plugin initializes. Because lua/fff/conf.lua reads this variable at line 89 when first accessed, your settings will apply even without an explicit setup() call. This approach works with any plugin manager and ensures configuration is available during the lazy-loading phase.

Can I change configuration options after fff.nvim has loaded?

Yes. The configuration table returned by require('fff.conf').get() remains mutable after initialization. You can modify values like layout.preview_position or keymaps.toggle_select at runtime, and they will affect subsequent picker windows. Debug settings specifically can be toggled using the :FFFDebug command.

Where are the default configuration values defined?

Default values are defined in the default_config table at lines 92-135 of lua/fff/conf.lua. This comprehensive table includes settings for base paths, prompts, window dimensions, keymaps, highlight groups, frecency databases, git integration, and logging options. These defaults are merged with your custom configuration using vim.tbl_deep_extend.

How does fff.nvim handle deprecated configuration options?

The plugin includes a handle_deprecated_config() function at lines 58-73 of lua/fff/conf.lua that automatically migrates old option names to new schemas. For example, the deprecated width option is migrated to layout.width. When the function detects deprecated keys, it emits a warning via vim.notify to alert you to update your configuration while still applying the correct values.

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 →