# How to Configure fff.nvim Features: A Complete Guide to Customization

> Master fff.nvim customization. Learn to configure its features, layout, preview, keymaps, and search algorithms with this comprehensive guide.

- Repository: [Dmitriy Kovalenko/fff.nvim](https://github.com/dmtrKovalenko/fff.nvim)
- Tags: how-to-guide
- Published: 2026-04-04

---

**Configure fff.nvim by setting a Lua table in `vim.g.fff` before startup or calling `require('fff.conf').setup()`, which merges your options with sensible defaults defined in [`lua/fff/conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/conf.lua) to control layout, preview behavior, keymaps, and search algorithms.**

`fff.nvim` is a high-performance file picker backed by a Rust core that provides fuzzy finding, live grep, and file previewing. All customization flows through a single global configuration table that the plugin validates and merges via the `get()` function in [`lua/fff/conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/conf.lua) (lines 89–103), allowing you to override only the settings you need while maintaining safe defaults for everything else.

## Configuration Fundamentals

The plugin reads runtime options from the global variable `vim.g.fff`. When the plugin initializes, `require('fff.conf').get()` merges your table with a comprehensive set of defaults, handling deprecated keys automatically.

Set your configuration before requiring the plugin:

```lua
-- init.lua
vim.g.fff = {
  layout = { height = 0.9, width = 0.9 },
  preview = { enabled = true },
}
require('fff').setup()

```

Alternatively, call the setup function directly at any time:

```lua
require('fff.conf').setup({
  layout = { preview_position = 'left' }
})

```

## Layout and Window Settings

Control the picker dimensions, preview placement, and responsive behavior using the `layout` table defined in [`lua/fff/conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/conf.lua) (lines 99–115).

Key options include:

- **`height`** and **`width`**: Fractions of screen size (0–1) defaulting to `0.8`.
- **`preview_position`**: Place the preview on `"right"`, `"left"`, `"top"`, or `"bottom"`.
- **`flex`**: Enable responsive layouts that switch preview position based on terminal width.
- **`path_shorten_strategy`**: Truncate long paths using `"middle_number"`, `"middle"`, or `"end"`.

```lua
vim.g.fff = {
  layout = {
    height = 0.85,
    width = 0.75,
    preview_position = 'left',
    preview_size = 0.4,
    flex = { size = 130, wrap = 'top' },
    show_scrollbar = false,
  },
}

```

## Preview Pane Configuration

Fine-tune the file preview buffer through the `preview` table (lines 116–131 in [`conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/conf.lua)).

**Critical settings:**

- **`enabled`**: Toggle the preview pane entirely (`true` by default).
- **`max_size`**: Skip files larger than 10 MiB to prevent hanging.
- **`binary_file_threshold`**: Bytes scanned to detect binary files (set `0` to disable).
- **`line_numbers`** and **`wrap_lines`**: Control display formatting.
- **`filetypes`**: Override settings per filetype (e.g., force wrap for markdown).

```lua
vim.g.fff = {
  preview = {
    line_numbers = true,
    wrap_lines = false,
    filetypes = {
      markdown = { wrap_lines = true },
      svg = { wrap_lines = true },
    },
    max_size = 5 * 1024 * 1024, -- 5 MiB
  },
}

```

## Customizing Keymaps

All interactive commands are configurable via the `keymaps` table (lines 132–152 in [`conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/conf.lua)). Values can be single strings or lists of alternative keys.

Default actions include:
- **`close`**: `<Esc>`
- **`select`**: `<CR>`
- **`select_split`** / **`select_vsplit`**: `<C-s>` / `<C-v>`
- **`move_up`** / **`move_down`**: `{ '<Up>', '<C-p>' }` / `{ '<Down>', '<C-n>' }`
- **`preview_scroll_up`** / **`preview_scroll_down`**: `<C-u>` / `<C-d>`
- **`send_to_quickfix`**: `<C-q>`

```lua
vim.g.fff = {
  keymaps = {
    close = '<C-c>',
    select = '<CR>',
    move_up = '<C-k>',
    move_down = '<C-j>',
    send_to_quickfix = '<C-q>',
  },
}

```

## Frecency and History Settings

Configure smart file ranking and query history persistence in the `frecency` and `history` tables (lines 159–171 in [`conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/conf.lua)).

- **`frecency.enabled`**: Track file open frequencies to boost recently used files.
- **`frecency.db_path`**: SQLite database location (defaults to `stdpath('cache')..'/fff_nvim'`).
- **`history.enabled`**: Store past queries for quick recall.
- **`history.combo_boost_score_multiplier`**: Score multiplier for consecutive selections (default `100`).

Disable frecency to use pure fuzzy matching:

```lua
vim.g.fff = {
  frecency = { enabled = false },
  history = {
    min_combo_count = 3,
    combo_boost_score_multiplier = 50,
  },
}

```

## Live Grep Configuration

Control the behavior of the integrated grep search through the `grep` table (lines 292–298 in [`conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/conf.lua)).

**Performance and matching options:**

- **`modes`**: Ordered list of search modes available for cycling (`{ 'plain', 'regex', 'fuzzy' }`).
- **`smart_case`**: Case-insensitive unless pattern contains uppercase (default `true`).
- **`time_budget_ms`**: Maximum milliseconds spent per search (default `150`, set `0` for unlimited).
- **`max_matches_per_file`**: Limit matches per file to prevent UI overload.

```lua
vim.g.fff = {
  grep = {
    modes = { 'regex', 'fuzzy', 'plain' },
    smart_case = true,
    time_budget_ms = 0, -- disable time limit
    max_matches_per_file = 50,
  },
}

```

## Appearance and Git Integration

Override highlight groups and Git status indicators via the `hl` table (lines 155–190 in [`conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/conf.lua)). Git status can display as signs or colored filenames.

Common highlight groups include:
- **`git_sign_staged`**
- **`git_sign_unstaged`**
- **`git_sign_untracked`**

```lua
vim.g.fff = {
  hl = {
    git_sign_staged = 'DiffAdd',
    git_sign_unstaged = 'DiffChange',
  },
}

```

## Debugging and Logging

Activate runtime diagnostics through the `debug` and `logging` tables (lines 190–205 in [`conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/conf.lua)).

- **`debug.show_scores`**: Display match scores in the UI for algorithm tuning.
- **`logging.log_level`**: Set to `'debug'`, `'info'`, `'warn'`, or `'error'`.

Toggle debug mode programmatically:

```lua
require('fff.conf').toggle_debug() -- Toggles debug.enabled and debug.show_scores

```

## Summary

- **Configuration entry point**: Set `vim.g.fff` before startup or call `require('fff.conf').setup()`.
- **Layout control**: Adjust `layout.height`, `layout.width`, and `layout.preview_position` for window sizing.
- **Preview behavior**: Configure `preview.max_size`, `preview.line_numbers`, and per-filetype overrides.
- **Keybindings**: Remap any action via the `keymaps` table using single keys or lists.
- **Search tuning**: Modify `frecency.enabled`, `grep.modes`, and `grep.time_budget_ms` to optimize performance.
- **Source authority**: All defaults and merge logic reside in [`lua/fff/conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/conf.lua).

## Frequently Asked Questions

### Where does fff.nvim store its configuration?

`fff.nvim` reads configuration from the global Lua table `vim.g.fff`. This table is merged with internal defaults in [`lua/fff/conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/conf.lua) (lines 89–103) when the plugin initializes. You can also call `require('fff.conf').setup(your_table)` at runtime to apply settings dynamically.

### How do I disable the file preview entirely?

Set `preview.enabled = false` in your configuration. You can also disable specific preview features like binary detection by setting `preview.binary_file_threshold = 0`, or limit resource usage by lowering `preview.max_size` to prevent large files from being loaded into memory.

### Can I change the search modes available in live grep?

Yes. The `grep.modes` array controls which modes are available and their cycling order. The default is `{ 'plain', 'regex', 'fuzzy' }`, but you can reorder or remove modes. For example, setting `grep.modes = { 'regex', 'fuzzy' }` removes plain text search and prioritizes regex matching.

### How do I customize the appearance of Git status indicators?

Git status is controlled through the `hl` configuration table. Override highlight group names like `git_sign_staged`, `git_sign_unstaged`, and `git_sign_untracked` to link them to your colorscheme's highlight groups. These definitions are processed in [`lua/fff/conf.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/conf.lua) (lines 155–190) and applied by the picker UI.