# How to Update fff.nvim: Complete Guide for Plugin Users and Maintainers

> Learn how to update fff.nvim easily for plugin users and maintainers. Covers automatic updates, manual Lua API methods, and building from source.

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

---

**Update fff.nvim automatically via your plugin manager's build hook, manually using Lua API commands like `ensure_downloaded()`, or by building from source with `build_binary()`.**

The `fff.nvim` plugin is a fuzzy finder for Neovim that relies on a companion Rust binary for high-performance file searching. Because the plugin architecture spans both Lua and Rust, the update process involves synchronizing the Lua plugin code with the correct native binary version for your platform. This guide covers the three contexts for updating: automatic updates via plugin managers, manual command-line updates, and the release workflow for project maintainers.

## Updating via Plugin Manager (Lazy.nvim)

Most users manage `fff.nvim` through a plugin manager like **lazy.nvim**, which automates the binary synchronization through a build hook. According to the source code in [`lua/fff/download.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/download.lua), the `download_or_build_binary()` function orchestrates the entire process.

When you update the plugin through your package manager, the build hook executes before the plugin becomes available:

```lua
{
  'dmtrKovalenko/fff.nvim',
  build = function()
    -- Downloads the pre‑built binary or falls back to a local cargo build
    require('fff.download').download_or_build_binary()
  end,
  opts = { debug = { enabled = true, show_scores = true } },
  lazy = false,
  keys = {
    { "ff", function() require('fff').find_files() end, desc = 'FFFind files' },
    { "fg", function() require('fff').live_grep()   end, desc = 'LiFFFe grep' },
  },
}

```

The build hook triggers the following sequence:

1. **Tag Resolution** – The plugin reads the current version from [`lua/fff/utils/version.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/utils/version.lua) to determine the correct GitHub release tag (handling both stable releases and nightly/dev builds).
2. **Download Attempt** – It calls `download_from_github` (lines 83-122 in [`download.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/download.lua)) to fetch the pre-built binary for your specific platform triple (e.g., `x86_64-unknown-linux-gnu`).
3. **Fallback Build** – If no pre-built asset exists or the download fails, the function automatically triggers `build_binary()` (lines 215-232), which runs `cargo build --release` in the repository root.

This entire process completes during the lazy-loading phase, ensuring the binary is ready before you invoke any picker commands.

## Manual Update Methods

You can force an update or build from source without waiting for a plugin manager sync by executing Lua functions directly in Neovim.

### Force a Fresh Binary Download

To bypass the cache and re-download the current release version, use `ensure_downloaded` with the force flag:

```lua
:lua require('fff.download').ensure_downloaded({force = true}, function(ok, err) 
  print(ok and 'fff.nvim binary refreshed' or 'Failed: ' .. err) 
end)

```

This corresponds to line 35 in [`lua/fff/download.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/download.lua), where `download_or_build_binary()` internally calls `ensure_downloaded({force = true})`.

### Build from Source

If you have Rust installed and want to compile the binary locally (useful for development or unsupported platforms), run:

```lua
:lua require('fff.download').build_binary(function(ok, err) 
  if ok then
    print("Successfully built fff.nvim binary")
  else
    print("Build error: " .. err)
  end
end)

```

### Verify Binary Location

To confirm which binary is currently active or debug path issues:

```lua
:lua print(require('fff.download').get_binary_path())

```

## Release Author Workflow

If you are maintaining a fork or contributing releases, use the automated release script at [`scripts/release.sh`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/scripts/release.sh) to publish new versions. This script handles version bumping, Git tagging, and CI triggering.

The release process executes three critical steps:

1. **Version Bump** – Runs `cargo set-version <new_version>` (using `cargo-edit`, which the script auto-installs if missing on lines 27-31).
2. **Git Tagging** – Creates an annotated tag in the format `v${VERSION}` and pushes it to origin.
3. **CI Trigger** – The [`.github/workflows/release.yaml`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/.github/workflows/release.yaml) workflow detects the new tag, builds Rust binaries for all supported platforms, and attaches them to the GitHub release.

After the CI completes, users can download binaries from URLs following the pattern:
`https://github.com/dmtrKovalenko/fff.nvim/releases/download/<TAG>/<TRIPLE>.<EXT>`

## Troubleshooting Update Issues

### Binary Locked on Windows

On Windows, if Neovim holds a lock on the old DLL, the atomic update may fail. The downloader writes to a `.tmp` file first, then attempts to rename it. If this fails, `vim.notify` emits a warning (lines 33-38 in [`download.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/download.lua)). **Restart Neovim** to release the lock and allow the update to complete.

### Missing Platform Binaries

If your architecture lacks a pre-built release asset, check the GitHub releases page. If your target triple is missing, run `:lua require('fff.download').build_binary()` to compile locally, provided you have `rustup` and Cargo installed.

### Debug Logging

Update operations log to `vim.fn.stdpath('log') .. '/fff.log'`. Inspect this file using the `:FFFOpenLog` command to diagnose download failures or version mismatches.

## Summary

- **Plugin manager updates** rely on the `build` hook calling `download_or_build_binary()` in [`lua/fff/download.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/download.lua), which attempts to download pre-built assets before falling back to local compilation.
- **Manual updates** use `ensure_downloaded({force = true})` to refresh binaries on demand, or `build_binary()` for source compilation.
- **Release authoring** requires running [`scripts/release.sh`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/scripts/release.sh) to bump the crate version in [`Cargo.toml`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/Cargo.toml), create Git tags, and trigger GitHub Actions.
- All binary downloads target the release tag determined by [`lua/fff/utils/version.lua`](https://github.com/dmtrKovalenko/fff.nvim/blob/main/lua/fff/utils/version.lua), supporting both stable and prerelease channels.

## Frequently Asked Questions

### How do I force fff.nvim to download a fresh binary without reinstalling the plugin?

Run `:lua require('fff.download').ensure_downloaded({force = true})` from Neovim. This bypasses the local cache and re-downloads the asset matching your current plugin version tag from GitHub releases.

### What happens if there is no pre-built binary for my operating system?

The downloader automatically falls back to building from source. Ensure you have Rust installed (via `rustup`), then the `build_binary()` function will compile the Rust component locally using `cargo build --release`.

### Can I update the binary without restarting Neovim?

Yes, by running the Lua commands manually. However, on Windows, if the previous binary is loaded into memory, you must restart Neovim to release the file lock before the new binary can take effect.

### Where does fff.nvim store its update logs?

The plugin writes detailed operation logs to the path returned by `vim.fn.stdpath('log') .. '/fff.log'`. Access this file directly or use the `:FFFOpenLog` command to review download attempts, build errors, and version resolution details.