# What is fff.nvim Main Entry Point? Complete Plugin Architecture Guide

> Discover the fff.nvim main entry point plugin fff lua. Understand its plugin architecture and how to access core functions like find_files and live_grep.

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

---

**The fff.nvim main entry point is [`plugin/fff.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/plugin/fff.lua), which Neovim automatically executes on startup to register commands and defer initialization, while the public API resides in [`lua/fff.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff.lua) (re-exporting `fff.main`) where users access functions like `find_files()` and `live_grep()`.**

Understanding the entry point architecture of dmtrKovalenko/fff.nvim is essential for configuring and debugging this fast fuzzy finder. The plugin employs a two-stage initialization system that separates Neovim's startup sequence from the heavy lifting performed by its Rust-powered indexing backend.

## The Two-Stage Entry Point Architecture

fff.nvim splits its initialization across conventional Neovim runtime paths to optimize startup performance. This design ensures that expensive operations—such as building the fuzzy search index—run only when absolutely necessary.

### Stage 1: The Plugin Entry Point ([`plugin/fff.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/plugin/fff.lua))

Neovim automatically sources all files in `plugin/` directories during startup, making [`plugin/fff.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/plugin/fff.lua) the true fff.nvim main entry point. According to the source code, this file performs three critical tasks:

- Registers public user commands including `:FFFFind` and `:FFFScan`
- Defers heavy indexing work until after the UI is ready
- Triggers `require('fff.core').ensure_initialized()` the first time a picker is invoked

This lazy initialization strategy prevents Neovim's startup time from being affected by the Rust backend compilation or file system scanning.

### Stage 2: The Public API Module ([`lua/fff.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff.lua))

When users call `require('fff')` in their configuration, they access [`lua/fff.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff.lua). This file acts as a thin proxy that immediately re-exports the implementation:

```lua
-- lua/fff.lua
return require('fff.main')

```

The actual API implementation lives in [`lua/fff/main.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/main.lua), which contains the core functionality for `setup()`, `find_files()`, and `live_grep()`.

## How fff.nvim Initializes on Startup

The complete startup flow demonstrates the separation of concerns between the entry point and the core engine:

```

Neovim startup → loads plugin/fff.lua → sets up lazy init & commands
                → when a command or require('fff') is used,
                  lua/fff.lua → lua/fff/main.lua (core functionality)

```

By deferring `require('fff.core').ensure_initialized()` until the first picker invocation, the plugin maintains minimal impact on editor launch times while keeping the fuzzy finder immediately accessible via command mappings.

## Practical Usage Examples

### Installing with lazy.nvim

Even when using a plugin manager, the fff.nvim main entry point handles its own lazy loading internally:

```lua
-- Lazy-load with lazy.nvim (the plugin still self-initializes)
{
  'dmtrKovalenko/fff.nvim',
  lazy = false,   -- the plugin handles its own lazy loading
  opts = {        -- optional configuration passed to `require('fff').setup`
    lazy_sync = true,
    debug = { enabled = true, show_scores = true },
  },
}

```

### Accessing the Public API

After the entry point has run, access the main functions through the public module:

```lua
-- Directly require the public module
local fff = require('fff')   -- this loads lua/fff.lua → lua/fff/main.lua

-- Open the file picker
fff.find_files()

-- Perform a live grep
fff.live_grep({ query = 'TODO' })

```

### Triggering Initialization Manually

In rare cases where you need the core ready before UI interaction:

```lua
-- If you need the core to be ready before any picker interaction
require('fff.core').ensure_initialized()

```

## Core Files in the Entry Point Chain

Understanding these source files clarifies the data flow from Neovim startup to fuzzy search execution:

- **[`plugin/fff.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/plugin/fff.lua)** – The Neovim plugin entry point that registers commands and defers indexing
- **[`lua/fff.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff.lua)** – Public module that users import with `require('fff')`, forwarding to `fff.main`
- **[`lua/fff/main.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/main.lua)** – Core API implementation containing `setup()`, `find_files()`, and `live_grep()`
- **[`lua/fff/core.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/core.lua)** – Initialization logic that ensures the Rust backend is ready
- **[`crates/fff-core/src/lib.rs`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/crates/fff-core/src/lib.rs)** – Rust backend performing the fast fuzzy search and indexing

## Summary

- **fff.nvim main entry point** is [`plugin/fff.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/plugin/fff.lua), automatically sourced by Neovim on startup
- The plugin defers heavy initialization until first use via `require('fff.core').ensure_initialized()`
- Public API access flows through [`lua/fff.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff.lua) → [`lua/fff/main.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/main.lua) when calling `require('fff')`
- Commands like `:FFFFind` are registered immediately, but the Rust backend initializes lazily
- Users configure the plugin through `require('fff').setup()` in their initialization files

## Frequently Asked Questions

### What file does Neovim load first when starting fff.nvim?

Neovim automatically loads [`plugin/fff.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/plugin/fff.lua) first because it resides in the `plugin/` directory, which the runtime scans during startup. This file registers the user commands and sets up the lazy initialization hooks before any user configuration runs.

### Why does fff.nvim use a two-stage entry point?

The two-stage architecture separates command registration (which must happen immediately) from resource-intensive indexing operations. By placing the heavy Rust backend initialization in `fff.core` and deferring it until first use, the plugin prevents Neovim's startup time from increasing while keeping the fuzzy finder instantly accessible via `:FFFFind` or `:FFFScan`.

### How do I access the main fff.nvim functions in my configuration?

Import the public module with `local fff = require('fff')`, which returns the API defined in [`lua/fff/main.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/main.lua). This gives you access to `fff.find_files()`, `fff.live_grep()`, and `fff.setup()` for configuration. You do not need to manually require the entry point file; simply requiring `'fff'` loads the full API after the initial plugin setup has occurred.

### When is the Rust backend actually initialized?

The Rust backend initializes only when `require('fff.core').ensure_initialized()` is called, which happens automatically the first time you invoke a picker through `:FFFFind`, `:FFFScan`, or the Lua API functions. This lazy loading ensures that the computational cost of indexing your file system occurs after Neovim's UI is fully rendered and responsive.