目录

FFF.nvim:让 AI 和 Neovim 拥有极速文件搜索与记忆能力

学习目标

读完本文你能:

  1. 解释 FFF.nvim 的双重定位(AI Agent MCP 服务器 + Neovim 插件)如何共享同一套文件搜索基础设施
  2. 配置 FFF.nvim 作为 MCP 服务器连接到 Claude Code / Codex,验证 Token 节省效果
  3. 调优 Frecency 排序算法,理解频率(Frequency)和时效(Recency)如何共同决定文件优先级
  4. 使用 约束条件搜索、多选与 Quickfix 集成等高级功能提升搜索效率
  5. 对比 FFF.nvim 与 Telescope.nvim / fzf.vim 的核心差异,判断是否需要迁移

项目速览

FFF.nvim(Freakin Fast Fuzzy file finder)— 为 AI Agent 和 Neovim 提供极速文件搜索与记忆能力

GitHubdmtrKovalenko/fff
Stars9,323+
Forks359+
许可证MIT
语言Rust(核心二进制)+ Lua(Neovim 插件)
创建时间2025-07-31
Neovim 版本要求≥ 0.10.0

目录


项目概述

是什么

FFF.nvim(Freakin Fast Fuzzy file finder)是一个极速文件搜索工具,同时为 AI Agent 和 Neovim 提供内置记忆的文件搜索能力。

它的核心理念:**Just for file search,

核心定位

FFF.nvim 有两个主要使用场景:

使用场景说明
AI Agent (MCP)作为 MCP 服务器,为 Claude Code、Codex 等 AI Agent 提供文件搜索能力,大幅减少 Token 消耗
Neovim 用户作为 Neovim 插件,提供极速、抗拼写错误、带有记忆的文件搜索体验

技术栈

组件技术
Neovim 插件Lua
核心二进制Rust
搜索算法Smith-Waterman 评分
存储SQLite(frecency/history)

核心特性详解

AI Agent MCP 集成

FFF.nvim 可以作为 MCP 服务器连接到 AI Agent,带来以下优势:

优势说明
减少 Token内置记忆让 AI 更精准地找到代码,减少往返次数
更快搜索Rust 实现的高速搜索,比内置工具快
减少无用文件读取智能排序让 AI 优先看到最相关的内容

安装命令

curl -L https://dmtrkovalenko.dev/install-fff-mcp.sh | bash

安装脚本会输出连接说明,指导你如何配置到 Claude Code、Codex、OpenCode 等 AI Agent。

在 CLAUDE.md 中添加

# CLAUDE.md

For any file search or grep in the current git indexed directory use fff tools

Neovim 文件搜索

对于 Neovim 用户,FFF.nvim 提供:

功能说明
极速模糊搜索基于 Rust,支持百万级文件
抗拼写错误Smith-Waterman 算法容忍 typos
Frecency 排序结合频率和时效的智能排序
Git 状态集成显示文件修改状态

快捷键映射

快捷键功能
ff查找文件
fg实时 Grep 搜索
fz模糊 Grep 搜索
fc搜索当前光标单词

Frecency 排序算法

Frecency 是一种结合**频率(Frequency)和时效(Recency)**的排序算法:

因素权重说明
Frecency最近打开且频繁打开的文件优先
Git 状态未跟踪、已修改的文件会提升排名
文件大小小文件略微优先
定义匹配与搜索词匹配的函数/类名优先

三种搜索模式

FFF.nvim 支持三种搜索模式,可通过 <S-Tab> 切换:

模式说明适用场景
Plain纯文本匹配,特殊字符无含义搜索代码中的正则元字符
Regex正则表达式需要精确模式匹配
FuzzySmith-Waterman 模糊匹配容忍拼写错误,如 mtxlk 可匹配 mutex_lock

跨模式建议

FFF.nvim 的智能之处在于跨模式建议

场景自动行为
文件搜索无结果自动显示 Grep 搜索建议
Grep 搜索无结果自动显示文件名建议

这避免了用户在两种模式之间手动切换。


AI Agent MCP 集成详解

为什么 AI Agent 需要 FFF

传统 AI Agent 的文件搜索存在以下问题:

问题影响
Token 浪费需要多次往返才能找到正确文件
上下文膨胀读取大量无关文件浪费 Token
搜索不精准不了解项目结构,优先显示无关文件

FFF 通过内置记忆解决这些问题:

# 安装后,AI 会自动学习
# 下次搜索 "auth" 时,会优先显示:
# - 最近频繁打开的 auth.py
# - 包含 "auth" 的重要文件
# - 忽略 test/auth_fixture.py(低频)

连接到的 AI Agent

AI Agent支持状态配置方式
Claude Code✅ 完全支持安装脚本自动配置
Codex✅ 完全支持安装脚本自动配置
OpenCode✅ 完全支持安装脚本自动配置
其他 MCP 客户端✅ 通用 MCP手动配置

使用示例

安装完成后,只需在对话中告诉 AI:

请使用 fff 工具搜索 "auth" 相关的文件

AI 会自动调用 FFF MCP 服务,返回精准的搜索结果。

Token 节省效果

根据项目测试,FFF 相比内置工具可以节省:

场景Token 节省
单次文件搜索~30%
多轮搜索任务~50%
大型代码库(100k+ 文件)~70%

Neovim 安装与配置

前置要求

  • Neovim ≥ 0.10.0
  • Git(用于版本控制集成)
  • Rustup(用于从源码编译,非必须)

使用 lazy.nvim 安装

{
  'dmtrKovalenko/fff.nvim',
  build = function()
    -- 下载预编译二进制,或使用现有 rustup 工具链编译
    require("fff.download").download_or_build_binary()
  end,
  -- 如果使用 NixOS:
  -- build = "nix run .#release",
  opts = {
    -- (可选) 调试配置
    debug = {
      enabled = true,
      show_scores = true,  -- 显示评分,帮助优化
    },
  },
  -- 无需 lazy-load,FFF 会自动延迟加载
  lazy = false,
  keys = {
    { "ff", function() require('fff').find_files() end, desc = 'FF: Find files' },
    { "fg", function() require('fff').live_grep() end, desc = 'FF: Live grep' },
    { "fz", function() require('fff').live_grep({ grep = { modes = { 'fuzzy', 'plain' } } }) end, desc = 'FF: Fuzzy grep' },
    { "fc", function() require('fff').live_grep({ query = vim.fn.expand("<cword>") }) end, desc = 'FF: Search current word' },
  }
}

使用 vim.pack 安装

-- 添加到 init.lua
vim.pack.add({
  'https://github.com/dmtrKovalenko/fff.nvim'
})

-- 配置自动构建
vim.api.nvim_create_autocmd('PackChanged', {
  callback = function(event)
    if event.data.updated then
      require('fff.download').download_or_build_binary()
    end
  end,
})

-- 基础配置
vim.g.fff = {
  lazy_sync = true,  -- 仅在打开 picker 时同步文件
  debug = {
    enabled = true,
    show_scores = true,
  },
}

-- 快捷键
vim.keymap.set('n', 'ff', function() require('fff').find_files() end, { desc = 'FF: Find files' })

完整配置示例

require('fff').setup({
  -- 基础配置
  base_path = vim.fn.getcwd(),
  prompt = '🪿 ',
  title = 'FFFiles',
  max_results = 100,
  max_threads = 4,
  lazy_sync = true,

  -- 布局配置
  layout = {
    height = 0.8,
    width = 0.8,
    prompt_position = 'bottom',
    preview_position = 'right',
    preview_size = 0.5,
    flex = {
      size = 130,
      wrap = 'top',
    },
    show_scrollbar = true,
    path_shorten_strategy = 'middle_number',
  },

  -- 预览窗口配置
  preview = {
    enabled = true,
    max_size = 10 * 1024 * 1024,  -- 10MB
    chunk_size = 8192,
    line_numbers = false,
    cursorlineopt = 'both',
    wrap_lines = false,
    filetypes = {
      svg = { wrap_lines = true },
      markdown = { wrap_lines = true },
      text = { wrap_lines = true },
    },
  },

  -- Frecency 配置(文件打开频率+时效)
  frecency = {
    enabled = true,
    db_path = vim.fn.stdpath('cache') .. '/fff_nvim',
  },

  -- 搜索历史配置
  history = {
    enabled = true,
    db_path = vim.fn.stdpath('data') .. '/fff_queries',
    min_combo_count = 3,
    combo_boost_score_multiplier = 100,
  },

  -- Git 集成
  git = {
    status_text_color = false,
  },

  -- Grep 配置
  grep = {
    max_file_size = 10 * 1024 * 1024,
    max_matches_per_file = 100,
    smart_case = true,
    time_budget_ms = 150,
    modes = { 'plain', 'regex', 'fuzzy' },
  },

  -- 调试配置
  debug = {
    enabled = false,
    show_scores = false,
  },
})

高级功能详解

约束条件搜索

FFF 支持通过约束条件精细化搜索结果:

约束示例说明
Git 状态git:modified只显示已修改文件
目录限制test/显示任意嵌套的 test/ 目录
排除!something排除匹配项
Glob./**/*.{rs,lua}任意有效 glob 表达式

组合使用示例

git:modified src/**/*.rs !src/**/mod.rs user controller

这会查找:所有已修改的 Rust 文件,排除 mod.rs,优先显示包含 user 和 controller 的结果。

多选与 Quickfix 集成

快捷键功能
<Tab>切换当前文件选中状态
<C-q>发送选中文件到 Quickfix 并关闭

当选中文件时,sign column 会显示 标记。

Git 状态高亮

FFF 支持两种 Git 状态可视化方式:

Sign Column 指示器(默认启用)

状态高亮组
已暂存FFFGitSignStaged
已修改FFFGitSignModified
已删除FFFGitSignDeleted
已重命名FFFGitSignRenamed
未跟踪FFFGitSignUntracked
已忽略FFFGitSignIgnored

文件名文字高亮(需开启)

require('fff').setup({
  git = {
    status_text_color = true,  -- 启用文件名颜色
  },
  hl = {
    git_staged = 'FFFGitStaged',      -- 已暂存
    git_modified = 'FFFGitModified',   -- 已修改
    git_deleted = 'FFFGitDeleted',     -- 已删除
    git_untracked = 'FFFGitUntracked', -- 未跟踪
  },
})

.ignore 文件支持

FFF 自动读取 .gitignore 规则。此外,你还可以创建 .ignore 文件来额外过滤:

# .ignore

# 排除所有 markdown 文件
*.md

# 排除特定子目录
docs/archive/**/*.md

调试模式

启用调试

方式操作
快捷键在 picker 中按 F2
命令:FFFDebug [on|off|toggle]
默认启用debug.show_scores = true

查看日志

:FFFOpenLog

或手动打开:~/.local/state/nvim/log/fff.log


API 与命令

Lua API

-- 查找文件
require('fff').find_files()

-- 触发重新扫描
require('fff').scan_files()

-- 刷新 Git 状态
require('fff').refresh_git_status()

-- 在指定目录查找
require('fff').find_files_in_dir("/path/to/dir")

-- 更改索引基准目录
require('fff').change_indexing_directory("/new/path")

-- 带初始查询的 Grep
require('fff').live_grep({ query = "search term" })

Neovim 命令

命令说明
:FFFScan手动触发重新扫描
:FFFRefreshGit刷新 Git 状态
:FFFClearCache [all|frecency|files]清除缓存
:FFFHealth检查健康状态和依赖
:FFFDebug [on|off|toggle]切换调试模式
:FFFOpenLog在新标签页打开日志

健康检查

运行 :FFFHealth 会检查:

  • ✅ 文件 picker 初始化状态
  • ✅ 可选依赖(git、图片预览工具)
  • ✅ 数据库连接

常见问题与故障排查

1. 安装后 Neovim 找不到 FFF 命令?

症状:按 ff 无反应,或报错 module 'fff' not found

排查步骤

  1. 检查构建是否成功:

    :messages

    查看是否有下载或编译错误。

  2. 手动触发构建:

    :lua require('fff.download').download_or_build_binary()
  3. 检查二进制是否存在:

    ls ~/.local/share/nvim/fff/

解决:如果网络不好,可以手动下载预编译二进制放到 ~/.local/share/nvim/fff/

2. MCP 服务器连接后,AI 仍然不用 FFF 工具?

原因:CLAUDE.md 或系统提示里没有明确要求使用 FFF。

解决:在项目的 CLAUDE.md 里加入:

For any file search or grep in the current git indexed directory use fff tools

或者在对话里明确说:

请使用 fff 工具搜索文件,不要用内置的 search 工具

3. Frecency 排序不准确,常用文件排后面?

排查步骤

  1. 检查数据库是否存在:

    ls ~/.cache/nvim/fff_nvim/
  2. 清除旧数据重新学习:

    :FFFClearCache frecency
  3. 正常使用几天,让 Frecency 积累足够数据。

注意:Frecency 需要学习期,新安装的前几天排序可能不准。

4. 大型代码库(100k+ 文件)搜索卡顿?

优化方案

  1. 增大线程数:

    require('fff').setup({
      max_threads = 8,  -- 默认 4
    })
  2. 启用 lazy_sync

    lazy_sync = true,  -- 仅在打开 picker 时同步文件
  3. 设置 time_budget_ms

    grep = {
      time_budget_ms = 150,  -- 超时截断
    }

5. Git 状态不更新?

原因:Git 状态缓存过期,或者仓库状态变化未触发刷新。

解决

:FFFRefreshGit  " 手动刷新

或者在配置里设置自动刷新间隔(如果支持)。


与同类工具对比

对比 Telescope.nvim

维度FFF.nvimTelescope.nvim
性能Rust 二进制,极速Lua 实现,稍慢
AI 集成原生 MCP 支持需额外配置
Frecency内置,开箱即用需插件额外配置
模糊算法Smith-Watermanfzf 算法
配置复杂度简洁较复杂

对比 fzf.vim

维度FFF.nvimfzf.vim
Neovim 原生✅ 专用插件❌ 依赖外部 fzf
Git 集成✅ Sign + 文字颜色仅 Sign
多选支持✅ Quickfix 集成基础
AI Agent 支持✅ MCP 服务器❌ 无

自测题

  1. FFF.nvim 的双重定位是什么?为什么这两个场景可以共享同一套文件搜索基础设施?

    答案双重定位是 AI Agent MCP 服务器 + Neovim 插件。它们共享同一套 Rust 核心二进制和 SQLite 数据库(Frecency/History),无论是 AI 还是人类触发搜索,都走相同的索引和排序逻辑,互相促进学习效果。
  2. Frecency 排序算法如何结合频率和时效?新文件但打开次数少,为什么也能排前面?

    答案Frecency = Frequency(频率) + Recency(时效)。新文件如果最近打开过(Recency 高),即使 Frequency 低也会排前面。算法会给「最近打开」额外的时效权重,确保新文件有机会出现在顶部。
  3. Smith-Waterman 模糊匹配算法相比普通 fuzzy 匹配有什么优势?为什么能容忍拼写错误?

    答案Smith-Waterman 是生物信息学里的局部序列比对算法,可以找出「最相似的子序列」而不是要求全局匹配。这意味着即使用户输错几个字符(如 `mtxlk` 匹配 `mutex_lock`),算法仍能找到最优对齐,容忍 insertions/deletions/substitutions。
  4. 如何将 FFF.nvim 配置为 Claude Code 的 MCP 服务器?如何验证 Token 节省效果?

    答案运行安装脚本 `curl -L https://dmtrkovalenko.dev/install-fff-mcp.sh | bash`,按输出说明配置 Claude Code。验证效果:对比使用 FFF 前后,AI 搜索文件需要的往返次数和最终上下文大小,应该能看到 ~30-50% 的 Token 节省。
  5. 约束条件搜索支持哪些语法?如何组合多个约束条件?

    答案支持:Git 状态(`git:modified`)、目录限制(`test/`)、排除(`!something`)、Glob(`./**/*.{rs,lua}`)。组合示例:`git:modified src/**/*.rs !src/**/mod.rs user controller`——查找已修改的 Rust 文件,排除 mod.rs,优先显示包含 user 和 controller 的结果。

进阶路径

阶段 1:安装并跑起来(1 天)

  • 安装 FFF.nvim(lazy.nvim 或 vim.pack)
  • 配置基础快捷键(ff, fg, fz, fc
  • 打开 Neovim,按 ff 搜索文件,观察 Frecency 排序效果

目标:确认 FFF 在你的系统上正常工作,感受 Rust 二进制的极速体验。

阶段 2:配置 MCP 集成,让 AI 用上 FFF(2-3 天)

  • 运行 MCP 安装脚本,配置 Claude Code / Codex
  • 在 CLAUDE.md 里加入 FFF 使用说明
  • 让 AI 搜索文件,观察 Token 消耗变化

目标:理解 AI Agent 如何通过 MCP 调用 FFF,验证 Token 节省效果(应该能看到 ~30-50% 下降)。

阶段 3:调优 Frecency 和高级功能(1 周)

  • 调整 max_threadstime_budget_mslazy_sync 等参数
  • 使用约束条件搜索、多选与 Quickfix 集成
  • 开启 Git 状态文字高亮,自定义颜色

目标:把 FFF 调成你的个人偏好,提升日常搜索效率。

阶段 4:深度定制或贡献(2 周+)

  • 读 Rust 源码,理解 Smith-Waterman 实现和 Frecency 算法
  • 写自定义 picker 或集成到其他工具(Vim/Emacs)
  • 提交 PR 修复 bug 或添加新 feature(如支持更多 VCS)

目标:从用户变成 contributor,影响项目方向。


总结

FFF.nvim 是一个专注于文件搜索的极致工具,它的关键价值在于:

为什么选择 FFF:

优势说明
双重用途同时服务 AI Agent 和人类开发者
极致性能Rust 二进制驱动,百万级文件秒搜
智能排序Frecency 算法让常用文件永远优先
AI 友好MCP 集成大幅减少 Token 消耗
抗错误Smith-Waterman 容忍拼写错误

适用场景:

  • 使用 Claude Code / Codex 等 AI Agent 进行开发
  • 在大型代码库中使用 Neovim
  • 需要精准文件搜索的开发者
  • 希望减少 AI Token 消耗的团队

不适用的场景:

  • 不使用 Neovim 的用户(可单独使用 MCP)
  • 小型项目(普通模糊搜索足够)

随着 AI 编程工具的普及,FFF.nvim 代表了一个重要方向:让 AI 和人类共享同一个高效的文件搜索基础设施


附录:相关资源

  • GitHub 仓库:https://github.com/dmtrKovalenko/fff
  • 官网:https://fff.dmtrkovalenko.dev/
  • MCP 安装脚本:https://dmtrkovalenko.dev/install-fff-mcp.sh
  • 作者:dmtrKovalenko