macOS daemon that watches Spotlight and excludes junk dirs (node_modules, target, caches, .git) from indexing. Public mirror: github.com/ZachHandley/spotlightd-be-gone
  • Rust 96.2%
  • Shell 2.6%
  • Makefile 1.2%
Find a file
Zach Handley 9ebbc9dc8f Redesign: user-level, no root, no Spotlight watcher
Pivot from a root LaunchDaemon that watched Spotlight via fs_usage to a
user-level tool that remembers swept roots and re-sweeps on demand or schedule.

- Remove libproc/fs_usage CPU watching, nix, plist, tracing deps
- sweep [paths]: targeted recursive sweep; remembers roots
- resweep: re-walk every remembered root (catches new junk dirs)
- RootRegistry (sbg-core): JSON registry, nested-root normalisation
- gitignore: register marker in enclosing repo's .git/info/exclude
  (worktree/submodule .git-file indirection handled), never touches
  tracked .gitignore -> markers never appear in git status
- resilient sweep: per-dir errors counted, never abort (SIP caches)
- install: user LaunchAgent runs resweep on StartInterval (no sudo)
- state under ~/.local/state, config under ~/.config

19 tests green, clippy -D warnings clean, fmt clean.
2026-06-26 14:36:33 -07:00
crates Redesign: user-level, no root, no Spotlight watcher 2026-06-26 14:36:33 -07:00
packaging/launchd Redesign: user-level, no root, no Spotlight watcher 2026-06-26 14:36:33 -07:00
.gitignore spotlightd-be-gone: watch Spotlight and exclude junk dirs from indexing 2026-06-26 14:08:06 -07:00
Cargo.lock Redesign: user-level, no root, no Spotlight watcher 2026-06-26 14:36:33 -07:00
Cargo.toml spotlightd-be-gone: watch Spotlight and exclude junk dirs from indexing 2026-06-26 14:08:06 -07:00
CLAUDE.md Redesign: user-level, no root, no Spotlight watcher 2026-06-26 14:36:33 -07:00
config.example.toml Redesign: user-level, no root, no Spotlight watcher 2026-06-26 14:36:33 -07:00
install.sh Redesign: user-level, no root, no Spotlight watcher 2026-06-26 14:36:33 -07:00
LICENSE-APACHE spotlightd-be-gone: watch Spotlight and exclude junk dirs from indexing 2026-06-26 14:08:06 -07:00
LICENSE-MIT spotlightd-be-gone: watch Spotlight and exclude junk dirs from indexing 2026-06-26 14:08:06 -07:00
Makefile Redesign: user-level, no root, no Spotlight watcher 2026-06-26 14:36:33 -07:00
README.md Redesign: user-level, no root, no Spotlight watcher 2026-06-26 14:36:33 -07:00
rust-toolchain.toml spotlightd-be-gone: watch Spotlight and exclude junk dirs from indexing 2026-06-26 14:08:06 -07:00

spotlightd-be-gone

A small macOS tool that stops Spotlight from wasting CPU and disk I/O indexing directories that have no business being searchable — node_modules, Rust target/, dist/build, __pycache__, .git, caches, and friends.

macOS Spotlight has no native pattern/glob exclusion. The only mechanism it honours is a .metadata_never_index marker file dropped inside each directory you want skipped. Maintaining those by hand across hundreds of churning build dirs is hopeless. This tool does it for you — and remembers where it swept so it can re-sweep later as new junk dirs appear.

It runs entirely as your user — no root, no sudo.

Why this exists: on a 128 GB machine that was bogging down under load, the culprit wasn't RAM — it was Spotlight re-indexing ~900 build/dependency directories (and tens of thousands of churning files) over and over.

What it does

  • Targeted sweepsweep <dir> walks a directory recursively, classifies every subdirectory, and drops a .metadata_never_index marker into each junk one. The walk prunes: it never descends into node_modules/target, so it's fast.
  • Remembers roots — every path you sweep is recorded, so…
  • Resweepresweep re-walks every remembered root to catch junk dirs created since last time. Install the LaunchAgent and this runs on a schedule.
  • Git-aware — when a marker lands inside a git repo, the marker filename is added to that repo's .git/info/exclude, so it never shows up in git status. Your tracked .gitignore is never modified.
  • Ledger — every exclusion is recorded as JSONL so you can list and reverse them.

Classification

Class Examples
dependency node_modules, .venv, vendor, Pods, site-packages
build target, dist, build, __pycache__, DerivedData, .next
cache .cache, anything under a Caches/ directory
tmp tmp/temp, /var/folders
vcs .git internals
configured matched one of your junk_globs but no structural category
protected matched a protect_globnever excluded

protect_globs always win, so e.g. a node_modules under ~/Documents is left untouched. The markers only affect Spotlight — never git, builds, or your tools.

Install

git clone https://github.com/ZachHandley/spotlightd-be-gone
cd spotlightd-be-gone
cargo build --release

# one-shot, no install needed:
./target/release/spotlightd-be-gone sweep ~/code

# or install the scheduled resweep LaunchAgent (still no sudo):
./install.sh

Usage

spotlightd-be-gone sweep ~/code          # exclude junk under ~/code, remember it
spotlightd-be-gone sweep --dry-run .     # preview, write nothing
spotlightd-be-gone resweep               # re-sweep every remembered root
spotlightd-be-gone status                # index state, remembered roots, counts
spotlightd-be-gone list                  # every directory excluded so far
spotlightd-be-gone unmark <dir>          # reverse one exclusion
spotlightd-be-gone forget <root>         # stop re-sweeping a root
spotlightd-be-gone install               # user LaunchAgent for scheduled resweep
spotlightd-be-gone uninstall             # remove the LaunchAgent

State lives under ~/.local/state/spotlightd-be-gone/ (ledger + remembered roots); config at ~/.config/spotlightd-be-gone/config.toml (see config.example.toml). Set auto_apply = false to make every command preview-only.

Undoing everything

Markers are plain files. To remove every one this tool created:

spotlightd-be-gone list | awk '{print $1}' | xargs -I{} spotlightd-be-gone unmark {}

or just delete .metadata_never_index files yourself — nothing else depends on them. The .git/info/exclude entries are harmless to leave, or remove the .metadata_never_index line by hand.

License

MIT OR Apache-2.0.