* fix(pi-fff): resolve startup config before tool registration * refactor(pi-fff): resolve queued tool names lazily
7.9 KiB
@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/rgprocess 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 search —
finduses 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 regexpath— directory/file constraint (e.g.src/,*.ts)ignoreCase— force case-insensitiveliteral— treat as literal string (default: true)context— context lines around matcheslimit— 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 constraintlimit— 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 lineslimit— 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): registersfffind,ffgrep,fff-multi-grepas additional tools + FFF-backed@autocompletetools-only: additional tools only; keep pi's default@autocompleteoverride: replaces pi's built-infind,grepand addsmulti_grep+ FFF-backed@autocomplete
Startup mode precedence:
--fff-mode <mode>CLI flagPI_FFF_MODE=<mode>environment variablemodein the global config file- 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_DBenv). Optional; see Data for the default.--fff-history-db <path>— path to query history database (also:FFF_HISTORY_DBenv). Optional; see Data for the default.--fff-enable-root-scan— allow indexing when launched from/(also:FFF_ENABLE_ROOT_SCAN=1env). 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_SCANenv). Enabled by default. Disable with--fff-enable-home-scan=falseorFFF_ENABLE_HOME_SCAN=0if your$HOMEcontains huge trees (toolchains, kernel sources, build outputs) that make the background index run for a long time. When launched from$HOMEwith 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:
- CLI flag —
--fff-frecency-db/--fff-history-db - Env var —
FFF_FRECENCY_DB/FFF_HISTORY_DB - Global config —
frecencyDbPath/historyDbPath - 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_HOMEdefaults to~/.cacheandXDG_DATA_HOMEto~/.local/share; on Windows both fall back under%LOCALAPPDATA%\nvim-data. Only directories count — a plain file at those paths is ignored.
- frecency:
- 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/