Back to plugins
File Search
v0.0.25 nightwatch75

About

File Search

A noctalia v5 bar plugin: fuzzy search files and folders as you type, with fzf as the matching subsystem. Click the bar glyph to open a search panel; picking a result opens it with the system MIME association (xdg-open) β€” directories open in your file manager. One button widens the search to the USB disks you have plugged in, or narrows it to those alone.

Plugin

Field Value
ID nightwatch75/file-search
Entries Bar widget: file-search; panel: panel; launcher provider: launcher
Launcher Prefix /fs

Usage

Add the file-search widget from Noctalia's widget picker and click it to open the search panel. You can also open the panel directly or bind it in your compositor:

noctalia msg panel-toggle nightwatch75/file-search:panel
Action Effect
Left click Open/close the search panel
Right click Open the search folder in the file manager

Middle click is not used: every bar widget carries a built-in binding for it that opens the widget's own settings, and a bound gesture never reaches the plugin. Use the panel's βš™ button, or the command below, for the settings.

In the panel:

Key Action
Enter Open the top match
Esc Close the panel (noctalia default)

On a result row:

Action Effect
Left click Open it with the system MIME association
Right click Copy its path, or reveal it in the file manager

The πŸ—/πŸ— button in the panel header picks which of the two, and remembers it. Reveal opens the containing folder with the item selected. Both leave the panel up, so several rows can be picked off in a row. (Middle click is not an option: a panel row only ever receives left and right clicks.)

A path too long for one row is shortened in the middle rather than at the end, so the file name β€” the part the query matched β€” always stays readable: .local/share/flatpak/repo/tmp/cache/…dolphin.idx.sig.

The plugin version sits next to the panel title. The footer counts what is listed and what is indexed, and on the right how long the walk behind that index took β€” per scope, kept across restarts, and still visible while a new walk runs, which is when knowing the last one's cost is most useful.

Search syntax

The query goes to fzf as-is, so its extended-search operators work here. The panel keeps a one-line reminder of them above the status bar.

Query Matches
panel luau both terms, in any order (space is AND)
'panel.luau exact, not fuzzy β€” a single quote, not double quotes
^src at the start
.webp$ at the end
luau !src luau, excluding anything with src
.toml$ | .json$ either one (spaces around the | are required)

A lowercase query is case-insensitive; one uppercase letter anywhere makes it case-sensitive. There is no regex: fzf does not have one.

The πŸ— /πŸ—Ί button in the header switches how matches are scored, and remembers it:

Glyph Ranking
πŸ—Ί path-aware (default) β€” a match starting a file or folder name wins, so config finds .ssh/config and not the deepest …/Steam Controller Configs/
πŸ—  generic β€” fzf's own scoring, which mostly rewards the shortest path

Path-aware costs about a third more CPU per keystroke and needs fzf 0.36 or newer; on an older build the button stays on generic and says so.

Searching external disks

The πŸ—€ button in the panel header cycles what the search covers:

Glyph Scope Covers
πŸ—€ Search folder only (default) The search_folder setting, as before
πŸ—€πŸ—€ Search folder + external disks Both, in one index
⚿ External disks only Only the mounted removable volumes

An external disk is a mounted volume that came from a USB port or reports itself removable: sticks and drives (bus-powered SSDs and LUKS-encrypted ones included), SD cards, optical media. Internal drives never count, not even a second SATA/NVMe under /mnt β€” put that in search_folder instead. The plugin mounts nothing; it only sees what your desktop has already mounted.

The choice survives restarts and is shared with the /fs launcher, which offers the same switch. Each scope keeps its own index, so switching to the disks and back does not re-walk your home folder.

External disks are only ever indexed on command, because walking a multi-terabyte drive takes minutes. Switching scope, opening the panel, changing a setting or plugging a disk in never start a walk: the index stays in use and the footer says out of date. The ↻ button (or Rebuild search index in the launcher) is what rebuilds it, and a scope never indexed says so and waits. The search folder alone keeps re-indexing itself, as before β€” it takes seconds.

The panel header also carries a βš™ button that opens this plugin's page in Settings β†’ Plugins, and a ↻ button that rebuilds the index. The same settings page opens from the command line, so it can be bound in your compositor too:

noctalia msg settings-open-plugin nightwatch75/file-search

In the noctalia launcher (keyboard-first flow, native navigation):

Key Action
/fs <text> Fuzzy search files and folders
↑ / ↓ Move through the results
Enter Open the selected result (MIME/xdg-open)

With an empty /fs query the list also offers Rebuild search index and the scope switch; the index is shared with the panel. Rebuild search index walks the tree there and then, keeping the launcher open, and is offered next to the results whenever the index is out of date.

Features

  • Live results while you type: the search folder is walked once with find into a cache, then every keystroke is fuzzy-matched through fzf --filter, so typing stays responsive even on large trees
  • Configurable bar glyph, search folder (defaults to ~), excluded folder names (.git, node_modules, .cache, .venv by default, matched anywhere in the tree), hidden entries on/off, max results
  • One button to search the mounted USB/removable disks as well, or only those: one index per scope, and disks walked only when you ask
  • Enter opens the top match; every result row opens on click via the system MIME association β€” files in their default app, folders in the file manager
  • Launcher provider for a keyboard-first flow: type /fs <text> in the noctalia launcher and navigate the results with the native arrow keys + Enter (plugin panels cannot receive arrow keys in the current Luau API, so the launcher is the keyboard way to browse results)
  • Folder results are marked with a trailing / and a folder glyph
  • Right click copies a result's path, or reveals it in the file manager with the item selected (org.freedesktop.FileManager1.ShowItems β€” Thunar, Nautilus, Dolphin, Nemo, Caja and PCManFM-Qt all implement it)
  • The search-folder index rebuilds itself when the relevant settings change, and on demand via the panel's refresh button; any index covering an external disk rebuilds on demand only
  • Panel placement (attached/floating), position and open-near-click are the standard per-panel settings noctalia exposes in Settings β†’ Plugins

Settings

Setting Type Default Description
search_folder folder (empty) Root folder the search indexes. Empty = your home folder.
exclude_dirs string .git, node_modules, .cache, .venv Folder names skipped while indexing, separated by , or ;, matched anywhere in the tree.
show_hidden bool false Index files and folders whose name starts with a dot.
max_results int 50 How many matches the panel lists at most (10–200).
glyph (widget) glyph search Icon shown on the bar.

Requirements

  • noctalia v5.0.0-beta.6 or newer β€” the first tagged release that accepts plugin_api = 15 (noctalia.openSettings(), the panel's βš™ button)
  • fzf β€” the fuzzy matcher. 0.36 or newer for the path-aware ranking; older builds work, with fzf's default ranking
  • find (GNU findutils) β€” walks the roots into the index
  • xdg-open (xdg-utils) β€” opens results with the MIME association
  • mktemp, mv, wc, head, rm, date β€” GNU coreutils, standard on any Linux desktop (date times the index walk for the footer)
  • lsblk (util-linux) β€” lists the mounted USB/removable volumes; only run when the scope includes them. Missing, it falls back to /proc/mounts and the udisks2 layout (/run/media/<user>/…, /media/…)
  • gdbus (glib2) β€” reveals a result in the file manager (FileManager1.ShowItems); only run on that right click. Missing, or with no file manager implementing it, the click opens the containing folder instead

Install

Install File Search from Noctalia's plugin store (Settings β†’ Plugins), then add the widget to a bar from Settings β†’ Bar. Plugin options live in Settings β†’ Plugins.

For local development, add your working copy as a path source instead (.luau edits hot-reload):

noctalia msg plugins source add dev path /path/to/plugins
noctalia msg plugins enable nightwatch75/file-search

Notes

  • The index lives in the plugin's private data directory (noctalia.pluginDataDir(), by default ~/.local/state/noctalia/plugins/data/nightwatch75/file-search/ β€” honors NOCTALIA_STATE_HOME/XDG_STATE_HOME): list-<scope> is a plain list of paths, meta-<scope> records the scope, roots and exclusions that built it, count-<scope> its line count and the walk's duration in milliseconds, and scope, row-action and ranking the one word each header toggle cycles. A fingerprint that no longer matches β€” a settings change, a scope change, a disk plugged in or removed β€” rebuilds the search-folder index automatically and marks a disk index out of date.
  • Several disks share one index, not one each: a rebuild walks every mounted volume in a single pass. Records are relative to the root when there is only one (the common case, and what keeps the rows short) and absolute when there are several β€” and they are always read the way the index was written, so unplugging one of two disks leaves the rest of the results openable.
  • Volume metadata is pruned at every root, since a disk used on Windows or macOS otherwise contributes tens of thousands of records that are not your files: lost+found, $RECYCLE.BIN, RECYCLER, System Volume Information, .Trash-*, .Spotlight-V100, .fseventsd, .Trashes, .TemporaryItems, .DocumentRevisions-V100, Backups.backupdb, *.sparsebundle, *.backupbundle, ._*, .DS_Store, .AppleDouble, .AppleDB, .AppleDesktop, Network Trash Folder, Temporary Items, TheVolumeSettingsFolder.
  • find is bound by metadata latency, so a spinning USB drive with a million files runs for minutes β€” hence on-demand only. A walk covering disks gets 30 minutes against 3 for the search folder, and the panel stays usable throughout, scope button included: a second walk is never queued.
  • Cheap by design elsewhere too: the mount scan is cached 30 seconds and never concurrent, and the line count comes from a count-<scope> sidecar instead of re-reading a >100 MB index.
  • Detection reads the transport and removable flags of the parent disk, not of the mounted partition β€” a USB partition reports neither. NVMe and SATA drives advertising hot-plug are deliberately not treated as removable.
  • Both files are written to mktemp-created private files and renamed into place, so a rebuild never writes through a symlink planted at the cache path.
  • Names containing a newline are excluded from the index (they would break the one-record-per-line format), and every record is validated against the roots it claims to come from before being opened.
  • Excluded entries match by folder/file name (find -name), not by path; entries containing / are skipped and logged.
  • With hidden entries off, anything starting with a dot is pruned β€” both hidden folders (not descended into) and hidden files.
  • Unreadable subtrees are silently skipped (permission errors don't fail the index).

License

MIT.

Versions

VersionPlugin APIUpdated
v0.0.25 latest15Jul 30, 2026
v0.0.11 9Jul 24, 2026
v0.0.10 3Jul 17, 2026

Older versions stay installable on a Noctalia release whose plugin API is below the latest version's.