Fully offline, privacy-first document sorting daemon. Watches an inbox folder for scanner-dropped documents (PDF, TIFF, images), runs OCR, extracts metadata via a local LLM, and files them with deterministic names.
- Offline & private — all processing stays on your machine (Ollama for LLM, ocrmypdf for OCR)
- German + English OCR via
ocrmypdfwith sidecar text extraction - LLM metadata extraction via local Ollama (document type, date, sender, subject, etc.)
- Deterministic filenames built from extracted metadata with collision handling
- SHA256 deduplication — duplicates are detected and moved aside
- Crash-safe pipeline — SQLite-backed state machine with recovery on restart
- Web dashboard — local web UI at
localhost:8484with pipeline status, document list, and one-click retry/re-OCR/re-extract - CLI management — status, retry, re-OCR, re-extract, and garbage collection commands
- ocrmypdf with Tesseract language packs (
deu,eng) - Ollama running locally with a model pulled (default:
llama3.2) - Rust toolchain (for building)
cargo build --releasedocsort daemonThis watches docsort/inbox/ for new files and processes them through the pipeline:
inbox/ → stability check → normalize to PDF → OCR → text cleanup → LLM extract → deterministic rename → output/
docsort --base-dir ./my-docs daemon # custom base directory
docsort --ollama-url http://host:11434 daemon
docsort --llm-model llama3.2 daemon
docsort --ocr-languages deu+eng daemonThe daemon starts a web dashboard at http://localhost:8484 with:
- Pipeline overview — card widgets showing total, processed, failed, and in-progress counts
- Document list — filterable by stage (queued, processed, failed, etc.)
- Document detail — all extracted metadata (sender, type, date, title, etc.) with action buttons
- One-click actions — retry, re-OCR, and re-extract directly from the UI
- Auto-refreshes every 5 seconds
docsort status # show pipeline counts and recent errors
docsort retry --id 42 # retry a failed document
docsort retry --all # retry all failed documents
docsort reocr --id 42 # re-run OCR on a document
docsort reextract --id 42 # re-run LLM extraction (keeps OCR text)
docsort gc --max-age-days 7 # clean up old tmp/ directoriesdocsort/
inbox/ # drop scanned files here
processing/ # in-flight documents
tmp/ # per-document work artifacts
output/ # final OCR'd PDFs with deterministic names
_duplicates/ # SHA256 duplicates
failed/ # failed documents with diagnostic bundles
db/
docsort.sqlite
MIT