📌 项目地址:dmtrKovalenko/fff | ⭐ 7,127 颗星 | 🔧 Rust | 📜 未标注
问题:ripgrep快,但AI用起来越来越慢
单次文件搜索,ripgrep和fzf确实快,毫秒级返回。问题不在单次,在重复。
想象一个场景:你让Claude Code在代码库里“找到所有调用某函数的地方”,它先用grep搜一次,跳转到调用处,为了确认逻辑,又要搜另一个文件。一次对话中可能触发十几次查找。每次都是新进程、重新读磁盘。累积的I/O开销让AI反应逐渐变慢,尤其是几万文件的大项目。
fff的做法是:起一个后台进程常驻内存,建好文件内容索引,后续搜索直接查内存。命中次数和访问时间决定排序(frecency)。项目最早是Neovim插件,后来发现编辑器、AI代理都需要同样的能力,就拆成独立库和MCP服务。现在被opencode、nushell等项目采用。
两种集成方式
MCP服务器:给任何AI代理装上fff
支持Claude Code、Codex、OpenCode、Cursor、Cline等任意MCP客户端。安装后工具名为ffgrep、fffind、fff-multi-grep,AI会自动调用。
安装
Linux / macOS:
curl -L https://dmtrkovalenko.dev/install-fff-mcp.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/dmtrKovalenko/fff.nvim/main/install-mcp.ps1 | iex
两个安装脚本都在源码中,可公开审阅:install-mcp.sh、install-mcp.ps1。安装后脚本会打印具体的客户端配置步骤。
Mac用户还可以用Homebrew:
brew install dmtrKovalenko/fff/fff-mcp
brew upgrade fff-mcp
Formula存放在Formula/fff-mcp.rb,每次稳定版本发布自动更新(参见.github/workflows/release.yaml中的bump-homebrew-formula)。
建议在项目的CLAUDE.md中加入:
For any file search or grep in the current git-indexed directory, use fff tools.
这是唯一需要的提示。AI连接MCP服务器后,会自动使用fff代替内置查找工具。
实现代码在crates/fff-mcp/。我试了下效果:在一个7万文件的monorepo里,第一次搜索时还算正常,第二次开始几乎秒回。AI连续查十几个文件的调用关系,不再有卡顿感。
Pi编辑器扩展
如果你用Pi编辑器(一个终端AI编辑器),安装很简单:
pi install npm:@ff-labs/pi-fff
三种运行模式,运行时通过/fff-mode切换:
| 模式 | 功能 |
|---|---|
tools-and-ui(默认) |
注入ffgrep、fffind工具 + 替换@自动补全为fff |
tools-only |
只注入工具,保留编辑器原生自动补全 |
override |
替换编辑器内建的grep/find/multi_grep为fff实现 |
环境变量控制:PI_FFF_MODE、FFF_FRECENCY_DB、FFF_HISTORY_DB。启动参数也有对应flag。我把模式设为override后,编辑器内部所有文件查找都走了fff,再用@补全时反应更跟手了。
四个对AI搜索有用的设计
1. frecency记忆:越用越准
frecency是频率(frequency)和最近(recency)的组合。你或AI常打开、刚打开的文件,搜索结果排在前面。
注意不是纯粹的热数据。启动时自动从git touch历史做warm-up,即使你刚重启机器,索引还在。本地数据存储路径通过FFF_FRECENCY_DB和FFF_HISTORY_DB指定。我用了一个月,发现常用的配置文件、入口文件总是排在结果最前面,AI不再犯“搜出20个匹配结果却找不到目标”的错误。
2. 定义优先:省token,不误判
代码里有大量非定义行(注释、赋值、调用)。Rust端在索引时就把函数、类、接口定义行标记出来(比如以def、fn、func、class开头),搜索结果里这些行排前面。
这意味着AI可以直接拿到定义位置,不需要在prompt里写正则做额外筛选。我观察发现,在一些上万行的长文件里,AI经常要反复翻找关键函数。用fff后,搜索结果直接显示它在第几行的定义位置,节省了2-3次额外调用。
3. 智能大小写+自动模糊回退
搜索IsOffTheRecord能命中is_off_the_record这类snake_case变体。如果精确查询返回0条,自动切到模糊搜索,返回最接近的匹配项。
这对AI特别实用。我试过让Claude Code找一个叫processBatchUpload的函数,但它打字成ProcessBatchUpload,还是命中了。另一次搜一个记不全名字的函数,只记得大概拼写handl_msg,模糊回退直接找到了handle_message。AI记不住精确命名时,这个特性降低了回退成本。
4. Git状态标注:直接显示文件是否已改动
搜索结果里直接标注modified、staged、untracked。AI能一眼看出你当前在改哪个文件,避免引用旧版本。
我观察到AI很少主动调用git status检查文件状态。自动标注让AI直接使用最新内容,减少“引用了旧版本然后报错”的来回。
谁适合用
如果你只是偶尔在终端敲一次rg或fzf,单次搜索的ripgrep已经足够,fff没有优势。
但如果你在用AI代理写代码,一次对话里要确认十几个文件的定义或用法,fff的持久化索引和frecency排序能明显减少等待。它在AI频繁调用搜索的场景下,把搜索从“每次独立调用”变成“持续积累的上下文”。
一句实话:目前fff主要面向AI代理和编辑器集成,还不是一个可以直接在终端当作rg替代品的命令行工具。它有命令行接口(ffgrep、fffind),但更推荐通过MCP或Pi插件使用。另外,Neovim插件部分已被移除,文档里只保留了MCP和Pi扩展的说明。Neovim用户暂时不能直接装这个插件。
===
标签:AI搜索工具,文件索引,MCP服务器,代码编辑器增强