fff Search icon

fff Search for Vicinae

File name and file content search for Vicinae, powered by fff.
Typo-tolerant, frecency-ranked, git-aware, and fast enough to search on every keystroke.


Search File Contents with the preview panel Search Files finding a file despite typos

Why fff Search

Vicinae's built-in file search matches file names. fff Search adds:

  • Search inside files. Plain text, regex or fuzzy matching, with the surrounding lines previewed and one key to open your editor at the matching line.
  • Speed for content search. About 5 ms per search on a warm index. A ripgrep search of the same home folder takes about 180 ms, and a launcher repeats it on every keystroke.
  • Focus on your own files. .gitignore rules, hidden folders and dependency folders such as node_modules are skipped, so caches and app data do not crowd the results.
  • Git awareness. Modified, untracked and staged files are tagged in the results.
  • Ranking that learns. Recently modified files rank first, and files you open for a query rank higher the next time you type that query.
  • Typo tolerance in both commands. serch contnts finds search-file-contents.tsx, and content search has a fuzzy mode for misspelled text.

See docs/comparison.md for measurements and an honest comparison with the alternatives, including what fff Search does not do.

Features

CommandWhat it does
Search FilesFuzzy search over file and folder names. An empty query lists recently modified files. Add :42 to a query (main.rs:42) to open the editor at line 42.
Search File ContentsSearches inside text files. A dropdown switches between Plain Text, Regex and Fuzzy matching. Results are grouped by file.
Manage File IndexShows the status of every indexed folder, and rescans, restarts or stops the background index.

Both search commands have a preview panel. File search previews text with syntax highlighting, images, and folder listings. Content search shows the lines around each match, with the match marked.

Query syntax

These work in both search commands, and come from fff's query language:

QueryMeaning
invoice 2024Fuzzy match on both words, in any order.
*.ts useStateOnly .ts files.
src/ TODOOnly paths under a src/ folder.
report.md:120File search only: open the result at line 120.

Content search is smart-case: an all-lowercase query ignores case, while a query with an uppercase letter matches case exactly.

Actions

ActionShortcut
Open, or Open in Editor at Line for content matchesEnter
Open in Editor (when an editor is configured)Ctrl+E
Open With…Vicinae's Open With shortcut
Show in File BrowserCtrl+Shift+F
Open Terminal HereCtrl+Shift+T
Copy PathCtrl+Shift+C
Copy NameCtrl+Shift+N
Copy Line (content matches)Ctrl+Shift+L
Copy FileCtrl+Shift+.
Toggle PreviewCtrl+Shift+P
Rescan IndexVicinae's Refresh shortcut

Requirements

  • Vicinae 0.29 or newer.
  • Node.js 18 or newer and npm, to build the extension. At runtime fff Search uses the Node runtime bundled with Vicinae.
  • One of the platforms fff ships prebuilt binaries for:
OSArchitectures
Linux (glibc or musl)x64, arm64
macOSx64 (Intel), arm64 (Apple Silicon)
Windowsx64, arm64

Install

git clone https://github.com/selfxplanatorium/fff-search
cd fff-search
npm install
npm run build

npm install also installs the background index's native library for your machine. npm run build places the extension in Vicinae's extension folder. Restart Vicinae (vicinae server --replace, or log out and back in) if the commands do not appear.

One bundle for every platform

npm run build:universal includes the native library for all eight supported platforms in a single build of about 75 MB. Use it when the build is made on one machine and run on others, for example a shared Nix or dotfiles setup. Builds in CI (CI=true, as in the Vicinae store's pipeline) do this automatically, and FFF_SEARCH_ALL_PLATFORMS=1 forces it. Every downloaded package is checked against the hashes in assets/daemon/package-lock.json.

Configuration

Open Vicinae's settings, then Extensions → fff Search.

PreferenceDefaultNotes
Indexed Directories~Comma-separated, for example ~, /mnt/data/projects. Each folder gets its own index.
Editor CommandemptyOpens files at a line. Placeholders: {file}, {line}, {column}. When empty, files open in their default application.
Run editor command in a terminaloffFor terminal editors such as Neovim or Helix.
Show preview panelonThe starting state. Ctrl+Shift+P toggles it.
Follow symlinked directoriesoff

Editor command examples:

EditorCommandTerminal option
VS Codecode --goto {file}:{line}:{column}off
VSCodiumcodium --goto {file}:{line}:{column}off
Zedzed {file}:{line}:{column}off
Sublime Textsubl {file}:{line}:{column}off
JetBrains IDEsidea --line {line} {file}off
Katekate -l {line} -c {column} {file}off
Neovimnvim +{line} {file}on
Helixhx {file}:{line}:{column}on
micromicro +{line}:{column} {file}on

Searching from the main search bar

Vicinae does not let extensions add results to its main search bar. That bar only shows file results from Vicinae's own indexer, and only when "search_files_in_root": true is set in its config.

To use fff Search from the main bar, make it a fallback command. Fallbacks are offered when nothing else matches what you typed, and fff Search opens with your text already searched. Add its entrypoint ID to fallbacks in Vicinae's settings.json, or manage fallbacks from Vicinae's settings window:

"fallbacks": [
  "@selfxplanatorium/fff-search:search-files",
  "files:search" // Vicinae's built-in file search, the default fallback
]

A global shortcut also works well. Bind vicinae://launch/@selfxplanatorium/fff-search/search-files (or search-file-contents) in your desktop's shortcut settings.

What gets indexed

fff decides what to index:

  • Inside git repositories, .gitignore rules are respected.
  • Outside git repositories, hidden files and folders are skipped, as are common dependency and cache folders: node_modules, __pycache__, venv, .venv, target/debug, target/release, go/pkg/mod, .cargo/registry, .rustup/toolchains, .gradle/caches, .m2/repository, .npm/_cacache and .local/state.
  • Content search reads text files under 10 MB. Binary files, PDFs and office documents are listed in file search but not searched inside.

To include a hidden folder such as ~/.config, add it to Indexed Directories.

How it works

Vicinae runs each command in a short-lived worker, so an index built inside the command would be thrown away every time. fff Search instead starts a small background process on first use. It holds the fff index in memory, keeps it current with a file watcher, and answers the commands over a local socket (a named pipe on Windows).

The process exits on its own when Vicinae exits, when the extension is removed, or when you stop it from Manage File Index. It makes no network connections.

Details: docs/architecture.md.

Data and privacy

Everything stays on your machine, in Vicinae's support folder for the extension (~/.local/share/vicinae/support/fff-search on Linux):

  • db/: search history used for ranking, one database per indexed folder.
  • daemon.log: the background process's log.

Deleting the folder resets the ranking history.

Uninstall

  1. Remove the extension from Vicinae's settings, or delete its folder from Vicinae's extension directory (~/.local/share/vicinae/extensions/fff-search on Linux).
  2. Optionally delete the support folder listed above.

The background process notices that it was removed and exits within 10 seconds.

Documentation

Credits

  • fff by Dmitriy Kovalenko does all of the searching and indexing.
  • Vicinae provides the launcher and the extension API.

License

MIT