A file detail view: extracted content, identity and
hash, user metadata. Shown against the test fixtures the
integration suite runs on.
What it is
Point it at mounted folders and it scans them, extracts metadata
and text, and exposes a timeline by year, month and day, faceted
full-text search, duplicate detection, detail views with inline
images and embedded PDFs, user tags, and an admin console for the
indexing workers. The point is to make a decade of files and
photos findable without sending them anywhere.
How it's built
Datalog plus Lucene. Structured metadata lives in
DataScript, persisted to SQLite; full text lives in Apache
Lucene with a per-field analyzer (keyword for identities,
standard for content), which fixed a real delete-and-update bug.
File identity is mount-relative, so a mount can move.
Sidecar ingestion. OCR and speech-to-text results arrive
as files next to the source: photo.jpg gets a
photo.visionocr (Apple Vision, with bounding quads),
audio.mp3 gets an audio.srt (Whisper),
and .meta.edn carries user tags. Each is transacted
atomically with its source, and the indexer never couples to an
ML runtime.
Cancellable async workers. Indexer and OCR workers are
atom-backed state machines with progress counters, per-file
failure isolation and a polled JSON status that drives the live
UI. Scanning is incremental by mtime and hash.
Duct and Integrant. About forty routes declared in
configuration with injected dependencies; a Hiccup-rendered
server side and a replicant SPA for the interactive parts.
Two deploy paths. A macOS launchd service deployed from
source (rsync, config swap, ClojureScript compile) and a Docker
image with layer-cached dependencies and volume state.
Search with mount, type and format facets.The timeline, drilled down to a day.
How it's verified
Integration tests run the real pipeline against checked-in OCR
and transcript fixtures; unit tests cover the indexer, the
search layer and the sidecar resolver. 2.1 k lines of tests for
7.4 k lines of code.
The project's contract requires a changelog entry per change,
structured logging only, confirmation on destructive UI, and a
phase plan committed before implementation.
The screenshots here were taken from a scratch clone pointed
at the test mounts, so nothing personal was indexed for them.