DigUp Kills Its Own Indexer to Stay Small

A macOS menu-bar app that searches your files by meaning, then fires the process that did the work. The architecture is the story.

~9 min read • View on GitHub • More from ARahim3

An editorial illustration of a tidy desk viewed from a slight elevation. A small index-card tray fills with neatly stacked cards as a tiny paper figure slides the last one into place. Behind the figure, a narrow automatic door stands open with a faint trail of footprints leading through it, and a small framed gauge on the far wall rests at zero.
The whole design in one frame: work gets done, the index grows, and the worker leaves through the door so the memory goes back to the OS.
Key Takeaways

The Indexer That Dies on Purpose

DigUp is a menu-bar app. It sits in the corner of your screen, waits for a keyboard shortcut, and searches chosen folders by meaning across photos, PDFs, recordings, video, and code. The interesting part is not the search. The interesting part is what happens between searches.

The heavy work (Vision OCR, media decoding, embedding) runs in a short-lived helper process at Contents/Helpers/digup index-service. When a pass finishes, the helper exits. The operating system reclaims its memory. The app goes back to being small. The Engine source states the reasoning directly:

// Indexing runs in a helper process (Contents/Helpers/digup index-service)
// that exits when it's done: extraction is heavy (Vision OCR alone keeps
// ~100 MB of models in the process that ran it), and the app has to stay
// small while idle.

Every menu-bar utility faces the same problem. The moment you do real work, you drag a hundred megabytes of models into memory and the app stops feeling like a background utility. DigUp's answer is radical and almost funny: make the indexer disposable. Spawn it, let it work, let it die. The cost is IPC complexity, because the app and the helper now have to talk over pipes and handle each other's failures. The payoff is a utility that stays invisible.

What You Actually Search For

Once the helper model makes sense, the product behind it is easier to see. You type a description and DigUp finds the thing you half-remember:

The distinction that matters is where a result takes you. DigUp opens a video at the timestamp, a PDF at the page, a codebase at the line. This is navigation to a location, not file retrieval. That single difference is what separates it from a filename search that happens to also scan text.

⇧⌘Space opens the search panel from any app. ↩ opens a video at the moment and a PDF with your words in Preview's search, and Space shows Quick Look right there.

DigUp project, Project description in the official GitHub release · Releases · ARahim3/DigUp · GitHub
An extreme close-up of a single sheet of paper jammed sideways in a small machine. One gear tooth is visibly cracked. A mechanical paw presses a lever that shunts the jammed sheet into a narrow side drawer tagged with the number 75, while the gears on the right keep turning and a fresh sheet feeds in.
The watchdog and the poison file: a stuck helper is killed with exit code 75, the offending file is shunted aside, and a fresh helper picks up the next one.

A Reddit Project That Refused to Phone Home

DigUp comes from the GitHub account ARahim3 and traces back to a Reddit project thread. The release notes credit a small community of contributors and bug reporters by name, and a Windows port (cgoat/DigUp-Windows) follows the same design with llama.cpp and CUDA, Vulkan, or CPU backends. The concept traveled because the constraint did.

The privacy stance is not a marketing line bolted on afterward. There is no account and no telemetry. Indexing never leaves the machine. The only network traffic is a one-time model download and a daily update check that, per the release notes, sends nothing about your files. When a network blocks the download, the notes describe supplying the model files by hand.

Everything runs on your Mac.

DigUp project, Project description in the official GitHub release · Releases · ARahim3/DigUp · GitHub

Four Queues, Four Jobs, Zero Actors

The helper model forces the app to answer a concurrency question. DigUp splits work across four serial queues, each with its own quality-of-service:

The Engine class is declared @unchecked Sendable. The team chose manual confinement over Swift actors. That buys precise control over quality-of-service and avoids actor reentrancy surprises, but it moves correctness out of the compiler and into convention. The only enforcement is a comment ("Every engine object is confined to one serial queue") and per-property annotations like // indexQueue only and // watchQueue only. It is a classic trade: explicit and fast, but unchecked.

The Watchdog and the Poison File

A helper that wedges on one bad file must not be allowed to hang the whole index. So a watchdog watches. When it decides the helper is stuck, it kills the process with exit code 75. That number is EX_TEMPFAIL, and it carries meaning: the stop was deliberate and file-specific, not a crash. The engine reads it that way, tracks the event as watchdogStops, and can back off or quarantine the offending file while a fresh helper continues with the rest.

Two smaller rules keep the lifecycle honest. syncWantedAt records when a sync was requested but no helper has started yet, so a helper that exits too early gets restarted to finish the work. And pruneWanted, which drops index entries for folders you no longer chose, is guarded by a safety rule in the source: an app with no folders at all never empties the index by itself. That protects your index from a missing or unmounted drive.

Play with the helper lifecycle: watch the memory gauge fill and snap to zero, then click a stuck file to see the watchdog quarantine it and spawn a fresh helper.

Where DigUp Sits

DigUp is not the only way to search a computer. The axis that matters here is whether a tool returns a location inside a file or just a file.

ToolRetrieval modeMultimodalLocalOpens to a location
DigUpSemantic + keywordImages, audio, video, docs, codeYesPage, timestamp, line
SpotlightFilename, metadata, some textLimitedYesFile
RecollFull-textDocumentsYesFile / passage
DocFetcherFull-textDocumentsYesFile / passage
EverythingFilenameNoYesFile
RewindActivity captureScreen + audioLocalMoment in activity

A caveat worth stating plainly: the distinction from Spotlight is functional, not a published performance comparison. No independent benchmark puts these tools head to head. Treat the table as a description of design intent, not a scoreboard.

Exact words count too: invoice numbers, error codes and names, in file names, documents and the text inside screenshots.

DigUp project, Project description in the official GitHub release · Releases · ARahim3/DigUp · GitHub

What It Costs You

The design is opinionated, and the constraints are part of the deal:

None of this is hidden. Stating it plainly is the honest version of the pitch: a specialized local semantic index, not a universal replacement for the search already built into your operating system.