📌 项目地址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客户端。安装后工具名为ffgrepfffindfff-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.shinstall-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_MODEFFF_FRECENCY_DBFFF_HISTORY_DB。启动参数也有对应flag。我把模式设为override后,编辑器内部所有文件查找都走了fff,再用@补全时反应更跟手了。

四个对AI搜索有用的设计

1. frecency记忆:越用越准

frecency是频率(frequency)和最近(recency)的组合。你或AI常打开、刚打开的文件,搜索结果排在前面。

注意不是纯粹的热数据。启动时自动从git touch历史做warm-up,即使你刚重启机器,索引还在。本地数据存储路径通过FFF_FRECENCY_DBFFF_HISTORY_DB指定。我用了一个月,发现常用的配置文件、入口文件总是排在结果最前面,AI不再犯“搜出20个匹配结果却找不到目标”的错误。

2. 定义优先:省token,不误判

代码里有大量非定义行(注释、赋值、调用)。Rust端在索引时就把函数、类、接口定义行标记出来(比如以deffnfuncclass开头),搜索结果里这些行排前面。

这意味着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状态标注:直接显示文件是否已改动

搜索结果里直接标注modifiedstageduntracked。AI能一眼看出你当前在改哪个文件,避免引用旧版本。

我观察到AI很少主动调用git status检查文件状态。自动标注让AI直接使用最新内容,减少“引用了旧版本然后报错”的来回。

谁适合用

如果你只是偶尔在终端敲一次rgfzf,单次搜索的ripgrep已经足够,fff没有优势。

但如果你在用AI代理写代码,一次对话里要确认十几个文件的定义或用法,fff的持久化索引和frecency排序能明显减少等待。它在AI频繁调用搜索的场景下,把搜索从“每次独立调用”变成“持续积累的上下文”。

一句实话:目前fff主要面向AI代理和编辑器集成,还不是一个可以直接在终端当作rg替代品的命令行工具。它有命令行接口(ffgrep、fffind),但更推荐通过MCP或Pi插件使用。另外,Neovim插件部分已被移除,文档里只保留了MCP和Pi扩展的说明。Neovim用户暂时不能直接装这个插件。

===
标签:AI搜索工具,文件索引,MCP服务器,代码编辑器增强

这篇文章对你有帮助吗?

发表回复