Files

@ff-labs/pi-fff

A pi extension that replaces the built-in find and grep tools with FFF — a Rust-native, SIMD-accelerated file finder with built-in memory.

What it does

Built-in tool pi-fff replacement Improvement
find (spawns fd) fffind (FFF fileSearch) Fuzzy matching, frecency ranking, git-aware, pre-indexed
grep (spawns rg) ffgrep (FFF grep) SIMD-accelerated, frecency-ordered, mmap-cached, no subprocess
(none) fff-multi-grep (FFF multiGrep) OR-logic multi-pattern search via Aho-Corasick
@ file autocomplete (fd-backed) @ file autocomplete (FFF-backed, default) Fuzzy ranking from FFF index/frecency

Key advantages over built-in tools

  • No subprocess spawning — FFF is a Rust native library called through the Node binding. No fd/rg process per call.
  • Pre-indexed — files are indexed in the background at session start. Searches are instant.
  • Frecency ranking — files you access often rank higher. Learns across sessions.
  • Query history — remembers which files were selected for which queries. Combo boost.
  • Git-aware — modified/staged/untracked files are boosted in results.
  • Smart case — case-insensitive when query is all lowercase, case-sensitive otherwise.
  • Fuzzy file searchfind uses fuzzy matching, not glob-only. Typo-tolerant.
  • Cursor pagination — grep results include a cursor for fetching the next page.

Install

Requirements:

  • pi

Install as a pi package

Via npm (recommended):

pi install npm:@ff-labs/pi-fff

Project-local install:

pi install -l npm:@ff-labs/pi-fff

Via git:

pi install git:github.com/dmtrKovalenko/fff

Pin to a release:

pi install git:github.com/dmtrKovalenko/fff@v0.3.0

Local development / manual install

git clone https://github.com/dmtrKovalenko/fff.git
cd fff/packages/pi-fff
npm install

Then add to your pi settings.json:

{
  "extensions": ["/path/to/fff/packages/pi-fff/src/index.ts"]
}

Or test directly:

pi -e /path/to/fff/packages/pi-fff/src/index.ts

This extension registers FFF-powered tools (fffind, ffgrep, fff-multi-grep) alongside pi's built-in tools.

Tools

ffgrep

Search file contents. Smart case, plain text by default, regex optional.

Parameters:

  • pattern — search text or regex
  • path — directory/file constraint (e.g. src/, *.ts)
  • ignoreCase — force case-insensitive
  • literal — treat as literal string (default: true)
  • context — context lines around matches
  • limit — max matches (default: 100)
  • cursor — pagination cursor from previous result

fffind

Fuzzy file name search. Frecency-ranked.

Parameters:

  • pattern — fuzzy query (e.g. main.ts, src/ config)
  • path — directory constraint
  • limit — max results (default: 200)

fff-multi-grep

OR-logic multi-pattern content search. SIMD-accelerated Aho-Corasick.

Parameters:

  • patterns — array of literal patterns (OR logic)
  • constraints — file constraints (e.g. *.{ts,tsx} !test/)
  • context — context lines
  • limit — max matches (default: 100)
  • cursor — pagination cursor

Commands

  • /fff-health — show FFF status (indexed files, git info, frecency/history DB status)
  • /fff-rescan — trigger a file rescan
  • /fff-mode <mode> — switch mode (tool name changes require /reload)

Modes

  • tools-and-ui (default): registers fffind, ffgrep, fff-multi-grep as additional tools + FFF-backed @ autocomplete
  • tools-only: additional tools only; keep pi's default @ autocomplete
  • override: replaces pi's built-in find, grep and adds multi_grep + FFF-backed @ autocomplete

Startup mode precedence:

  1. --fff-mode <mode> CLI flag
  2. PI_FFF_MODE=<mode> environment variable
  3. mode in the global config file
  4. default (tools-and-ui)

When a session resumes, its most recent /fff-mode selection takes precedence over the startup resolution above. Switching to or from override takes effect after /reload, when the tools are registered again.

Configuration

For persistent global configuration, create pi-fff.json in pi's agent directory (~/.pi/agent/pi-fff.json by default; PI_CODING_AGENT_DIR is respected):

{
  "$schema": "https://raw.githubusercontent.com/dmtrKovalenko/fff/main/packages/pi-fff/pi-fff.schema.json",
  "mode": "override",
  "frecencyDbPath": "/path/to/frecency",
  "historyDbPath": "/path/to/history",
  "enableFsRootScanning": false,
  "enableHomeDirScanning": true
}

All fields are optional:

Field Type Default
$schema non-empty string none
mode tools-and-ui, tools-only, or override tools-and-ui
frecencyDbPath non-empty string See Data
historyDbPath non-empty string See Data
enableFsRootScanning boolean false
enableHomeDirScanning boolean true

CLI flags take precedence over environment variables, which take precedence over this file. A missing file is ignored. Malformed JSON, unknown fields, and invalid values stop the extension from loading and report the file path and error. /fff-mode changes the current session; it does not edit this file.

The file is global only. Project-level config cannot safely control tool names because pi decides which tools an extension registers before project configuration can be trusted.

Flags

  • --fff-mode <mode> — set mode (see above)
  • --fff-frecency-db <path> — path to frecency database (also: FFF_FRECENCY_DB env). Optional; see Data for the default.
  • --fff-history-db <path> — path to query history database (also: FFF_HISTORY_DB env). Optional; see Data for the default.
  • --fff-enable-root-scan — allow indexing when launched from / (also: FFF_ENABLE_ROOT_SCAN=1 env). FFF refuses to init at the filesystem root by default.
  • --fff-enable-home-scan — index the home directory when launched from $HOME (also: FFF_ENABLE_HOME_SCAN env). Enabled by default. Disable with --fff-enable-home-scan=false or FFF_ENABLE_HOME_SCAN=0 if your $HOME contains huge trees (toolchains, kernel sources, build outputs) that make the background index run for a long time. When launched from $HOME with this enabled, pi shows a warning that the whole home tree is being indexed.

Data

FFF uses two LMDB databases:

  • frecency database - file access frequency/recency, used to rank results
  • history database - query-to-file selection history

Each path is resolved independently, in this order:

  1. CLI flag — --fff-frecency-db / --fff-history-db
  2. Env var — FFF_FRECENCY_DB / FFF_HISTORY_DB
  3. Global config — frecencyDbPath / historyDbPath
  4. An existing fff.nvim database, so pi reuses the frecency you built up in your editor:
    • frecency: $XDG_CACHE_HOME/nvim/fff_nvim
    • history: $XDG_DATA_HOME/nvim/fff_queries
    • XDG_CACHE_HOME defaults to ~/.cache and XDG_DATA_HOME to ~/.local/share; on Windows both fall back under %LOCALAPPDATA%\nvim-data. Only directories count — a plain file at those paths is ignored.
  5. pi-local directory, created on demand — $PI_CODING_AGENT_DIR/fff/{frecency,history}, defaulting to ~/.pi/agent/fff/{frecency,history}

The extension only reads these databases; it never records the agent's own searches into your Neovim history. If a database cannot be opened, the finder starts without persistence and pi shows a warning instead of failing.

No project files are uploaded anywhere by this extension. It runs locally and only uses the configured LLM through pi itself.

Security

  • No shell execution
  • No network calls in the extension code
  • No telemetry
  • No credential handling beyond whatever pi and your configured model provider already do
  • Search state is stored locally under ~/.pi/agent/fff/