Free, open source, for Linux

Scour Instant file search for Linux.

Scour keeps the machine’s files and folders in an index of its own and answers searches from it: on this machine 4,842,854 entries, a one-word search in 7.9 ms. That is the difference from find, which walks the disk every time. No account, no cloud, no network request; written in Rust, licensed MIT/Apache-2.0.

Rust MIT / Apache-2.0 No account No network Linux MCP
View the source on GitHub

Measured

Measurements

None of them is a target; every one was taken from a running installation. The method and the raw figures are in the repository, in MEASUREMENTS.md.

4,842,854
files and folders indexed
a home directory, a second NTFS volume and the system
7.9 ms
a one-word search
socket, parse, search, sort, count and forty rows included
493 MB
the index on disk
memory-mapped — the kernel can reclaim it under pressure
0.8%
of one core while idle
two volumes watched live, nobody looking

Four faces

Four interfaces, one index

The three pictures below were taken at the same moment, on the same machine, from the same query: kind:code dm:7d size:>10kb. The only difference is what you are looking at. The fourth face, the one-line scour command, is what scripts use — and its form for language models, scour-mcp: eleven read-only tools, every answer bounded; scour mcp-config --for codex says what to paste where.

Window

The desktop’s own application

A native window in Rust and Slint. The CPU draws it — measured, and a GPU wins nothing on a list of text while costing 24 MB more memory. Twelve columns to pick from and drag; a name that was cut says the whole of itself on hover; the preview opens beside the list. Put it on a key, and the second press brings the same window forward.

Scour’s desktop window: a syntax-coloured query on a dark ground, a type rail, the result list and a distribution over time.

Browser

A local bridge, not a remote server

It opens a port on your own machine and serves the page from there. The same columns, the grid view, CSV export, duplicate finding and the report tab live here. The link carries a token, the token changes every run, and no port faces outward.

Scour’s browser interface: a query line on a light ground, type and scope filters on the left, the result table.

Terminal

ratatui, and the far end of an ssh session

The same index, full-screen in a terminal. Wherever a window cannot open — a remote machine, a rescue shell, a server — the search is there at the same speed. And a plain scour command answers in one line.

Scour’s terminal interface: type, location and size rails on the left, the result list in the middle, a distribution over time below.

Query language

Query language

A space is AND, | is OR, ! is NOT; quotes make a phrase, * and ? are wildcards, field:value narrows. One word on its own is enough. Field names can be written in Turkish too. An unknown field is not an error — it is searched for as text — and scour explain says how a query was read.

01
report
anything with that in its name
02
ext:pdf size:>1mb
PDFs over a megabyte
03
kind:image dm:7d
pictures changed this week
04
*.slint | *.rs
either of the two
05
!target ext:toml
TOML files with no target in the name
06
user:root perm:/222
owned by root, writable by anyone

The whole list: scour syntax — or the query language page in the docs.

How it keeps up

Watching the filesystem

The index is updated as the filesystem changes. Linux offers two ways to hear about that; Scour uses fanotify only. The reason and the cost follow.

inotify — and why not

It wants one watch per directory. This machine has 609,322 of them; the kernel hands out 524,288 per session. So this machine cannot be watched with inotify at all — not even if Scour swallowed the entire budget by itself.

And that budget is shared: your editor, your IDE, your file manager and every npm run dev draw from the same pool. When one program exhausts it the failure does not appear in that program — it appears in the next one to start, and it never says “out of watches”. Each watch holds about a kilobyte of unswappable kernel memory.

fanotify

It marks the filesystem itself rather than the directories in it. This machine has two volumes, so: two marks. The number of folders does not enter into it — a million folders is still two marks. Measured cost while idle, with both volumes watched: 0.16% of one core.

Root is needed once

Listening to a whole filesystem means, by definition, seeing things outside your own files, and the kernel puts that behind CAP_SYS_ADMIN — a reasonable place for it. But Scour does not hold that privilege. It borrows it for a moment and gives it back.

scour-watch is a separate program that depends on no part of Scour and does only this: it opens the fanotify descriptor, places the marks, resolves them, drops the privilege and execs the service. The handover was measured rather than assumed — the process that comes out reports CapEff=0, and both attempts to escalate return EPERM. It installs nothing: no setcap, no persistent mount.

The thing people reach for instead — a passwordless sudo rule — is worse here: every binary in the chain lives under the user’s home, so a passwordless rule pointing at one of them is passwordless root for anything that can write that directory.

And it is optional. Without it Scour still works — but it does not fall back to inotify; that road is deliberately gone. When a volume’s write counter moves it reconciles by walking: nothing is missed, changes take a little longer to appear. Network and FUSE mounts have no counter and need the mark.

Install

Install

The install script never asks for one. Seven binaries go to ~/.local/bin, a menu entry and an icon to ~/.local/share; on GNOME and KDE it puts the window on Super+F. Deleting those files undoes it.

Commands

tar xzf scour-0.2.0-alpha.1-linux-x86_64.tar.gz
cd scour-0.2.0-alpha.1-linux-x86_64
./install.sh

Where it runs. The binaries are built against glibc 2.39: Ubuntu 24.04 and newer, Debian 13+, Fedora 40+, and any rolling distribution. Ubuntu 22.04 and Debian 12 carry an older glibc; there it builds from source, which takes about a minute.

Tested on Ubuntu 24.04 and Fedora — not “compiles for”, but run. In clean containers, as a stranger would: the installer ran, all seven binaries reported their version, the service indexed the home directory, the command line searched, the terminal face drew, the browser face served its page, and the window opened on a virtual display.

Limits

Linux only, in practice. The Windows build was started once on one machine for an afternoon and that is all — untested; the zip is on the release page for whoever wants to try it. macOS compiles and has never been run; compiling is not running.

Version 0.2.0-alpha.1. Alpha: daily use on one machine, measured against 4.8 million entries; the index format may change. Report problems on GitHub.