fff: Frecency-Ranked File Search for AI Agents and Code Editors
The fastest and the most accurate file search SDK for AI agents, Neovim, Rust, C, Python, Bun and NodeJS
At a glance
- What is it?
- fff is a Rust file search library and toolkit that provides typo-resistant path and content search, frecency-ranked file access, a background watcher, and an in-memory content index. It is designed for AI agents, Neovim, and language runtimes that perform repeated searches on the same repository.
- Who is it for?
- fff is worth adopting for AI agents and code editors that search the same repository repeatedly and where the built-in grep or find tools generate too many irrelevant results or consume too many context tokens.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 14 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What fff Is and the Problem It Addresses
AI agents and code editors that search a repository on every step face a specific performance problem: tools like ripgrep and fzf are fast as standalone CLI commands, but each invocation starts fresh with no memory of which files were recently opened or which directories are relevant. Over a session of hundreds of searches, the agent accumulates no ranking signal, so the tenth search for a file is as slow and uncertain as the first.
fff solves this with a persistent frecency index. Frecency combines frequency (how often a file has been accessed) with recency (how recently) to produce a ranked list. The index is warm-started from git touch history on first use, so files that have been committed recently already rank higher before the agent has made a single search. The README describes this as the core design: a file search toolkit for long-running processes that search more than once, and faster than CLI tools in that context.
The project started as a Neovim plugin (fff.nvim) and expanded to cover AI agent use cases when the author noticed that agent harnesses needed the same capabilities.
Installing the MCP Server and Wiring It to Claude Code
The MCP server is the primary integration path for AI agents. On Linux or macOS:
curl -L https://dmtrkovalenko.dev/install-fff-mcp.sh | bashOn Windows with PowerShell:
irm https://raw.githubusercontent.com/dmtrKovalenko/fff/main/install-mcp.ps1 | iexThe scripts print wiring instructions for the target client. On macOS or Linux with Homebrew:
brew install dmtrKovalenko/fff/fff-mcp
brew upgrade fff-mcpThe Homebrew formula in `Formula/fff-mcp.rb` is auto-bumped on every stable release via the `bump-homebrew-formula` workflow.
For Codex, register the binary using its absolute path:
codex mcp add fff -- "$(brew --prefix)/bin/fff-mcp"This writes an entry to `~/.codex/config.toml`. For Claude Code, the README recommends adding this line to your project's CLAUDE.md:
For any file search or grep in the current git-indexed directory, use fff tools.Once connected, the agent has access to `ffgrep`, `fffind`, and `fff-multi-grep` tools.
How the Search Tools Work: ffgrep, fffind, and Smart Fallbacks
The MCP server exposes three tools. `fffind` searches by path and filename, matching the full repository-relative path rather than just the filename. It is frecency-aware: files opened recently by the agent or editor rank higher. The README describes a weak-match detector that flags scattered fuzzy results before they fill the agent's context window.
`ffgrep` performs content search. It accepts `path`, `exclude`, `caseSensitive`, `context`, and cursor pagination parameters. It auto-detects whether the query is a regex and falls back to fuzzy matching on zero exact matches. The README notes that wildcard-only patterns such as `.*` are rejected up front.
The README describes four specific behaviours that change what the agent sees compared to a plain grep invocation. First, frecency memory means files you have opened rank higher on subsequent searches. Second, lines that look like code definitions are classified on the Rust side before returning results, so function and class definitions appear before other matches. Third, smart-case with auto-fuzzy fallback means `IsOffTheRecord` will match snake_case variants. Fourth, git-aware annotations mark modified, untracked, and staged files so the agent can prioritise what is currently being changed.
fff.nvim: The Original Neovim Plugin
fff.nvim is the project that preceded the agent-focused work. It is a Neovim plugin written in Lua that wraps the `fff-nvim` Rust crate. The plugin provides file picking and content search inside Neovim with the same frecency ranking and background watcher that the MCP server uses.
The `lua/` and `plugin/` directories at the repository root contain the Lua-side code. The `crates/fff-nvim/` directory contains the Rust crate that the Lua code calls via a compiled native extension.
The README mentions a demo on the Linux kernel repo (100,000 files, 8GB) to illustrate that the background watcher and in-memory index keep search latency low even on large codebases. The Neovim path does not require installing the MCP server.
Language Bindings: Node.js, Bun, Python, C, and Rust
The Cargo workspace in `Cargo.toml` lists seven crates: `fff-c`, `fff-core`, `fff-mcp`, `fff-nvim`, `fff-python`, `fff-query-parser`, and `fff-grep`. The `fff-c` crate exposes a C API for embedding fff in programs that use the C ABI. `fff-python` provides the Python binding. `fff-grep` handles the content search implementation shared across integrations.
The `packages/` directory contains the Node.js and Bun packages. The `package.json` at the repository root marks them as private workspace members. The `packages/shared/fff-api.ts` file holds the shared TypeScript API definitions that are copied into both the Node.js and Bun packages via a `make sync-js-api` step.
The Pi agent extension in `packages/pi-fff/` operates in three modes switchable at runtime with `/fff-mode`: `tools-and-ui` (the default), which injects tools and replaces the `@`-mention autocomplete; `tools-only`; and `override`, which replaces Pi's built-in `grep`, `find`, and `multi_grep` entirely.
Limitations and Comparison with ripgrep
ripgrep is the standard content search tool in repositories and is the primary alternative for both agent and editor use cases. ripgrep is a standalone CLI that starts fresh on each invocation with no frecency state. It supports a broader set of regex features and is designed for correctness and completeness. For a one-off search in a CI script or a fresh shell session, ripgrep is simpler and requires no setup.
fff's value is specific to long-running processes with repeated searches. The background watcher and frecency database require a persistent process. The MCP server mode keeps the process alive across agent steps. In a short-lived process, the warm-up cost is not amortised.
The frecency database defaults to `~/.pi/agent/fff/` for the Pi extension, and the Pi extension's env vars `FFF_FRECENCY_DB` and `FFF_HISTORY_DB` let you point it at an existing fff.nvim database if one is present. That database sharing means a developer who uses fff.nvim in Neovim and the Pi extension in a terminal will share the same frecency signal across both tools, so the ranking improves faster.
The Cargo.toml workspace uses `lto = "fat"` and `codegen-units = 1` in the release profile for maximum optimisation, and `lto = "thin"` in the CI profile to avoid cross-compilation issues on the build servers. The `mimalloc` allocator is listed in workspace dependencies, replacing the system allocator.
The current release series uses nightly versioning. The latest nightly release listed is 0.11.1-nightly.89c1927, from 2026-09-27. The last push to the repository was on 2026-09-15. There are no stable 1.x releases. The Homebrew formula is auto-bumped on every stable release via the `bump-homebrew-formula` CI workflow, so Homebrew users get updates automatically when stable releases land.
Editorial conclusion
fff is worth adopting for AI agents and code editors that search the same repository repeatedly and where the built-in grep or find tools generate too many irrelevant results or consume too many context tokens. The MCP server path is the lowest-friction entry point: install via Homebrew or the one-liner installer, add the recommended instruction to CLAUDE.md, and the agent picks up the frecency index automatically. fff is not useful as a one-shot CLI replacement for ripgrep in scripts that run against a repository once, because the frecency model requires a warm-up from git history to produce ranked results. The background watcher, frecency database, and git-status annotations are only valuable in a long-running process.
Frequently asked questions
What is fff search?
fff is a file search library and toolkit for AI agents and code editors, built in Rust. It provides frecency-ranked file access, typo-resistant path search, content search with smart-case fallback, and a background watcher. It ships as an MCP server, a Neovim plugin, and language bindings for Python, Node.js, Bun, and C.
How does frecency ranking work in fff?
fff combines frequency and recency into a frecency score for each file. On first use, it warm-starts the index from git commit history so files changed recently in the repository already rank higher. As the agent or editor opens more files, those files rise in the ranking for subsequent searches.
Can fff be used without Neovim or an AI agent?
Yes. fff exposes a C API, Python bindings, and Node.js and Bun packages that can be called directly from code. The MCP server is one surface; the underlying `fff-core` Rust crate and its language wrappers can be embedded in any application that needs frecency-ranked file search.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dmtrkovalenko-fff)