mrkeyoor.com_
Sat 08 Aug 21:01 UTC
Dev Toolsevaluationupdated 08 Aug 2026

fff

FFF is a Rust file-search engine for editors, AI agents, and other programs that search the same codebase repeatedly. It keeps file metadata and some content indexed in a long-running process, then provides typo-tolerant path search, content search, Git status, and usage-based ranking through Neovim, MCP, Rust, C, Node, Bun, and Python interfaces.

Verdict

FFF is a smart choice when search is a hot loop inside an editor or coding agent, because a persistent index, typed results, and frecency can improve more than raw query time. It is not a universal ripgrep replacement, and the project itself effectively says so. Adopt it for speed after adding scope-correctness tests and memory measurements for your repositories, especially if an agent will act on its results.

Setup4/5Prebuilt installs are short; indexing choices still need care
Docs5/5Detailed setup, APIs, memory costs, queries, and diagnostics
Community4/5Active releases and detailed issue and pull-request traffic
Maturity3/5Broad usable bindings, with current search correctness defects

Who it’s for

  • AI-agent developers who need repeated repository searches without starting a new command for every query.
  • Neovim users who want one native picker for fuzzy filenames, live content search, Git status, and frecency ranking.
  • Rust, Node, Bun, Python, or C developers who need typed search results inside a long-running tool.
  • Claude Code, Codex, OpenCode, Cursor, or Cline users willing to install an MCP search server and guide the agent to use it.

Who it’s NOT for

  • Shell users running one occasional search: the README explicitly says ripgrep is still the right tool for a single grep, while FFF pays startup and memory costs for later calls.
  • Memory-constrained environments: the project estimates about 360 bytes per content-indexed file and says a Chromium-sized tree can consume a few hundred megabytes.
  • Agent workflows where a path restriction must never leak: open reports show both MCP multi-pattern search and a Node AI-mode regex path silently returning matches outside requested scopes.
  • MCP users who add workspace roots after startup: an open issue says roots/list_changed is received but additional roots are not indexed.
  • Neovim users who cannot tolerate native-extension crashes: an open report documents a SIGSEGV after LMDB reader slots are exhausted across several long-running sessions.

Setup reality

Installation is genuinely short when a prebuilt artifact matches your system: the MCP server has a shell installer and Homebrew formula, the Neovim plugin downloads a native module or builds it with Cargo, and the Node and Python bindings install from their normal registries. The hidden work starts after installation. You must choose an index root, wait for the first scan, budget memory, decide whether filesystem watching and content indexing belong in your process, destroy SDK instances correctly, and verify ignore and constraint behavior against your own repository. C consumers also own library-path setup and Rust-specific result deallocation rules.

A search engine for the second query, not the first

FFF makes a focused argument: command-line search tools are excellent when a person runs one query, but repeated process startup and filesystem walking become wasteful inside an editor or AI agent. FFF scans once, keeps an index warm, watches for changes, and answers later searches from the same process. That gives it room to retain Git status, file metadata, content, query history, and frecency, meaning how recently and frequently a file was used.

This distinction matters more than the project's speed charts. A terminal user who searches, reads the answer, and exits gains little from a resident service. An agent that performs dozens of related searches can avoid rebuilding the same view of a repository. The README is admirably direct about the boundary: ripgrep remains the right tool for one grep, while FFF is designed for long-running repeated-search workloads.

FFF is not merely a Neovim picker anymore. The same Rust core appears as a native crate, a stable C interface, Node and Bun packages, Python bindings, a Pi agent extension, and an MCP server. That shared engine is the product. It lets an editor and an agent receive similar ranked, structured results without scraping terminal output.

Search results carry useful context

Path search is typo tolerant and ranks files using both matching and frecency. Content search supports literal, regular-expression, and fuzzy modes, with smart case and an automatic fuzzy fallback when an exact query finds nothing. Multi-pattern search can look for several identifiers in one pass. Results can include line and column positions, context, definition-like classification, file metadata, and Git state.

For an agent, structured pagination is particularly valuable. A tool can request the next page rather than dumping an unbounded grep result into model context. Definition-first hints can surface declarations before incidental uses, while annotations for modified, staged, and untracked files point the model toward current work. The MCP server exposes ffgrep, fffind, and multi-pattern search to Claude Code, Codex, OpenCode, Cursor, Cline, and other compatible clients.

Neovim gets the most complete human interface. The picker supports file, directory, and mixed searches, previews, live grep, multi-select, quickfix output, Git highlighting, custom layouts, and query constraints such as extensions or excluded directories. It also provides health checks and session logs, which matter because a native module and background index are harder to diagnose than a Lua-only filter.

Installation is easy until integration begins

The MCP binary has a one-line installer for Unix-like systems, a PowerShell route for Windows, and a Homebrew formula. The scripts are in the repository for inspection. Codex users are told to register an absolute binary path because desktop sessions may not inherit the interactive shell path. The Neovim plugin downloads a prebuilt library and falls back to a Cargo build. Node and Python users install normal packages.

Using the SDK correctly takes more thought. A caller creates a finder for a base path, waits for its initial scan, queries it repeatedly, and destroys it when finished. Switching roots can block while a new index is installed. Filesystem watching, content indexing, memory-mapped caching, frecency databases, and scan timeouts are application decisions, not invisible implementation details. C users must call the library's matching free functions rather than the standard allocator.

MCP currently has a notable root limitation. An open report says the server does not act on roots/list_changed, so a directory added later through Claude Code's /add-dir remains unindexed. The command accepts one startup path, which leaves multi-root sessions without a clean workaround. If your workspaces are dynamic, test that workflow before making FFF the agent's preferred search tool.

The speed is purchased with memory

FFF's warm queries avoid repeated filesystem traversal and process startup. The project reports sub-10 millisecond queries on a 500,000-file Chromium checkout after indexing, compared with seconds for fresh ripgrep processes. Those are project measurements, so hardware, filesystem cache, ignore rules, and query shape can change the result. The architectural advantage for repeated calls is still credible even if your numbers differ.

The trade is resident memory. The README estimates about 360 bytes for each content-indexed file, around 36 MB for 100,000 eligible files. It reports roughly 26 MB resident for a 14,000-file repository and says a Chromium-sized tree can require a few hundred megabytes. Binaries and oversized files are excluded, and a memory-mapped option can reduce anonymous memory pressure, but the index never becomes free. Containers and many concurrent workspaces need explicit budgets.

The background watcher is another part of the price. It keeps results current without rescanning on every query, yet watcher behavior varies by platform and repository shape. Recent release work reduced rescans in very large home directories and fixed empty-directory and ignore compatibility cases. An open, detailed report also argues that high-volume changes inside ignored build directories can trigger unnecessary full rescans or stale indexes. Performance testing should include your real build process, not only an idle checkout.

Correct scope matters more than a fast answer

Two current bugs deserve special attention for agent use. One report reproduces MCP multi-pattern search ignoring a standalone positive directory or exact-file constraint. Another reproduces Node AI-mode regular-expression search returning a match outside an exact-file constraint. Both produce successful-looking results rather than an explicit error. An agent can therefore read irrelevant code, waste context, or make a decision based on a scope it believes was enforced.

These are not reasons to dismiss the whole engine, but they change responsible adoption. Build small fixtures that assert include paths, excluded paths, exact files, regex alternation, ignore behavior, and multiple patterns. Keep ripgrep available as a fallback for sensitive checks. Search correctness is part of safety when downstream tools can edit files or execute commands.

Neovim users have a different operational risk. An open report traces a native crash to exhausted LMDB reader slots after several long-running sessions. Another reports a crash when Neovim starts from a directory deleted by a different shell. Native speed comes with native failure modes, so the documented health command, logs, and crash-debug instructions are useful rather than decorative.

An active project worth adopting deliberately

FFF was pushed and released on August 7, 2026. Version 0.10.3 shipped packages across its supported languages and included fixes for ignore handling, auxiliary finder reuse, giant home-directory scans, packaging, and security advisories in a dependency. New issues and pull requests were active on August 8. The repository's open count combines both, so 68 is an active work queue, not a count of confirmed bugs.

The documentation is excellent for a project this young. It explains where FFF wins, where ripgrep wins, how memory scales, how each binding manages lifecycle, and how the query language behaves. Use FFF when repeated search latency and enriched results are important enough to justify a resident index. Keep simpler tools for one-off work, and validate scoped queries before trusting them inside an autonomous agent.

Alternatives

ProjectWhat it isPick it when
ripgrepA fast, mature command-line content searcher that respects ignore files.pick this instead when searches are independent shell commands and you prefer negligible idle memory to a warm in-process index.
fzfA general-purpose command-line fuzzy finder that filters streamed input.pick this instead when you want a portable interactive filter for many data sources, not a repository-aware SDK.
TelescopeA widely used Neovim picker framework with a large extension ecosystem.pick this instead when picker variety and Lua customization matter more than sharing one native search core with agents and other applications.

What people are saying

  1. [github-trending] dmtrKovalenko/fff

Sources

  1. FFF README
  2. FFF version 0.10.3 release
  3. AI-mode path constraint issue 756
  4. MCP multi-pattern scope issue 738
  5. MCP dynamic roots issue 675
  6. Neovim LMDB crash issue 664