This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
π‘ Quick Navigation: What I Built Β· Live Demo Β· Code Β· Architecture & Funnel Β· Open Innovation Β· Lazy Payoff Β· Prize Categories (8 Tracks) Β· Discussion
π Table of Contents (Click to expand)
Last week I ran du -sh ~/Downloads on my laptop and realized I was hoarding hundreds of cryptic PDFs (INV-9041-final(1).pdf), forgotten .exe installers, and unnamed screenshotsβand I refused to upload my private bank receipts or .env configs to a cloud AI just to sort them. So for International Sloth Day, I built a daemon that waits until I walk away from my keyboard and cleans the mess locally while I sleep.
Workspaces, Desktop dumps, and project inboxes are where good intentions go to hibernate. Cryptic filenames pile up (Screenshot 2026-10-18 at 2.34.12 PM.png, INV-9041-final(1).pdf, DockerDesktopInstaller.exe). Receipts, strategy documents, archives, and configuration files end up in a flat, unorganized heap because standard file extensions tell you almost nothing about what a document actually contains.
I built slothd, a local-first, offline-capable AI file organizer designed around the philosophy of "Slow and Steady":
nomic-embed-text) with a local SQLite vector fallback, enabling queries like slothd undo restores every file to its exact original path.
π Local-First & Air-Gapped by Default: The entire core workflowβidle detection, filesystem scanning, tabular metadata triage, Gemma 3 document understanding via local Ollama, SQLite WAL manifests, and 1-click rollbackβexecutes 100% locally on your machine with zero internet calls. A genuinely air-gapped deployment simply leaves external integrations disabled. Cloud partner services (Tiger Data pgvector, SerpApi vendor lookup, ElevenLabs voice) are strictly opt-in extensions via explicit CLI flags (--enrich-online), and each is engineered with a complete offline fallback (local SQLite vector search, local heuristics, terminal audio chimes). No personal file or metadata ever leaves your device by default.
Every developer, creator, and researcher who wastes 20 minutes every week digging through unorganized files, manually dragging PDFs into dated folders, or putting off digital cleanup. You let the sloth run patiently while you make coffee, return to an inspected plan, and keep complete control.
The complete interactive loop demonstrates the full lifecycle:
Messy Workspace
β Fast Metadata Triage (TabPFN / Local Heuristic)
β Local AI Plan (Gemma 3)
β Dry-Run Preview
β Explicit Approval
β Semantic Search (Tiger Data)
β SQLite Manifest Inspection
β 1-Click Rollback
yuv420p + faststart for instant playback across all browsers)
You don't need to risk your own files to evaluate slothd. The repository includes a deterministic test fixture in test_workspace/messy_inbox containing an invoice, duplicate invoice, Uber receipt, project notes, Python benchmark, configuration file, leftover Windows installer, stale zip archive, and unsorted screenshots.
Anyone can clone and run the scan immediately:
git clone https://github.com/JaniDhruv/slothd.git
cd slothd
uv run slothd scan test_workspace/messy_inbox
In under a second, you will observe the verified metrics:
The project is 100% open-source under the MIT License:
π GitHub Repository: github.com/JaniDhruv/slothd
slothd/cli.py`` slothd/ui.py``slothd/engine/tabular_predictor.py`` slothd/engine/classifier.py``slothd/engine/organizer.py`` slothd/engine/search.py``slothd/integrations/tiger_data.py`` slothd/integrations/sentry_tracing.py``slothd/web/`` docs/demo/
A file organizer that feeds every single file into a heavy vision model is noisy, slow, and expensive. Instead, slothd uses a structured two-stage funnel:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Messy Target Directory β
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
1. Deduplicate & Extract Features
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β STAGE 1: Prior Labs TabPFN Metadata Triage β
β (7 tabular signals: log size, depth, ext, time, etc.) β
βββββββββββββββ¬βββββββββββββββββββββββββββββ¬ββββββββββββββ
β β
Leftover installers, archives, β Needs deeper
screenshots, duplicate clutter β semantic classification
βΌ βΌ
Flagged for cleanup ββββββββββββββββββββββββββ
β STAGE 2: Gemma 3 Local β
β (Ollama Vision/Text) β
ββββββββββββ¬ββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββ
β SQLite Reversible Log β
β + Tiger Data pgvector β
ββββββββββββββββββββββββββ
Before running AI models, slothd extracts 7 tabular signals from the filesystem:
When TabPFN credentials or a local model checkpoint are configured, TabPFN evaluates these tabular feature distributions directly (taking ~15β25 ms). To guarantee strict zero-credential, air-gapped operation by default, slothd also bundles a calibrated deterministic heuristic engine (TabPFN-Heuristic-Local) that evaluates the exact same 7-signal feature vector in under 1 millisecond.
(Note on benchmark accuracy: The 1 ms timing reported in the deterministic test fixture reflects this local offline heuristic engine. When running against TabPFN's hosted model with credentials, inference takes ~20 ms across the batch. Both modes share the exact same Pydantic triage interface and 100% test pass rate).
Only files requiring semantic classification (unlabeled PDFs, scanned receipts, documents) are forwarded to local Gemma 3 via Ollama.
format parameter. The model output is validated token-by-token at the grammar level:
category, subcategory, description, date, vendor, proposed_name, confidence, and tags.
The organization pipeline enforces strict safety invariants:
slothd organize prints the plan without moving files. You must explicitly pass --go or click "Approve" in the dashboard.Invoices/AWS_Invoice_2026.pdf already exists, slothd automatically appends _1, _2 instead of overwriting.mtime, atime) are preserved on moved files. batch_id, old_path, new_path, and timestamp.
Sentry was not added as a decorative vanity badge; it was an active part of the developer feedback loop during development.
The integration initializes Sentry with release slothd@0.1.0 and traces critical pipeline boundaries: scanner.scan_directory, ai.classify_batch, organizer.preview, organizer.execute, organizer.undo, and search.query.
[Transaction] slothd.organize_cycle (total: 1,248 ms)
ββ [Span] scanner.scan_directory .................... 12 ms [10 files discovered]
ββ [Span] ai.tabular_triage (TabPFN) ................ 1 ms [2 anomalies flagged]
ββ [Span] ai.gemma_classify_batch (Ollama) .......... 1,180 ms [Prompt: 412 tok, Resp: 86 tok]
ββ [Span] organizer.preview_manifest ................ 3 ms [Manifest prepared]
ββ [Span] db.wal_log_commit ......................... 4 ms [SQLite WAL sync]
ββ [Span] search.index_pgvector (Tiger Data) ........ 48 ms [768-dim embeddings stored]
Issue ID: 7805015409
Release: slothd@0.1.0 (production)
Title: ConnectionError: Connection refused to 127.0.0.1:11434
Culprit: slothd.engine.classifier in classify_batch
Trace ID: 71ac0b2ff1dc4c4788ff6a5b7098e354
Span ID: a1ea6839c23ccbb5 (op: ai.classify_batch, desc: "Gemma 3 batch classify (4 files)")
Breadcrumb: [warning] slothd.engine.classifier: Ollama server is offline or unreachable. Fast-falling back to local classification.
Handled: Yes (Circuit-breaker tripped gracefully without crashing the daemon)
| Observed Failure in Sentry | Root Cause Revealed | Resolution & Test |
|---|---|---|
ConnectionError on127.0.0.1:11434 (Issue #7805015409) |
Ollama daemon was offline during CLI execution | Added 200ms pre-flight probe, local heuristic fallback, and circuit-breaker regression test ( 3a327ea ). |
ValidationError: confidence > 1.0 |
Gemma 3 occasionally returned confidence as a percentage ( 90 or100 ) instead of float0.0β1.0 |
Added automatic percentage normalization validator in Pydantic schema with bounds coverage ( a914b53 ). |
RuntimeError: generator didn't stop after throw() |
Tracing context manager was incorrectly re-entering on caught exceptions | Cleaned up tracing wrapper to propagate exceptions correctly and verified with regression tests ( df19f29 ). |
Personal files contain our most vulnerable data:
Up this stream of daily life to closed, centralized cloud APIs creates an unacceptable privacy tradeoff.
Open-weight AI (Gemma 3) and open-source tabular models (TabPFN) fundamentally change this dynamic. They make it possible to run state-of-the-art vision and tabular triage entirely inside the boundary of your own computer:
--enrich-online) and are never enabled by default.
Privacy is not a checkbox added after the architecture is done; with open-source AI, privacy is the architecture.
The lazy payoff is not about moving files a few milliseconds faster. It is about removing the cognitive dread of manual digital housekeeping.
Instead of spending Sunday afternoon opening dozens of PDFs one by one, deciphering cryptic filenames, and deciding where each document belongs:
slothd daemon run in the background.
10 files scanned
2 clutter anomalies identified
1 duplicate set found
973 B reclaimable disk space
1 ms metadata triage (local deterministic 7-signal engine / TabPFN schema)
0 cloud API calls required
100% offline isolation
While slothd operates completely offline out of the box, it was engineered with a modular architecture that cleanly interfaces with specialized ecosystem tools. Rather than a superficial checklist of sponsor imports, each partner integration represents an optional, verified subsystem that enhances capability without compromising our local-first core:
| Track | How slothd Uses It |
Source Module |
|---|---|---|
| Google Gemma | Local gemma3:4b vision + text via Ollama with strict Pydantic JSON outputs |
classifier.py |
| Prior Labs TabPFN | 1ms 7-feature tabular triage flagging stale archives & size outliers before LLM wakeup | tabular_predictor.py |
| Tiger Data | 768-dim pgvector semantic search (<=> ) + hybrid keyword re-ranking |
tiger_data.py |
| Sentry Tracing | Distributed spans ( slothd.scan ,predict ,classify ,search ) tracking latency & tokens |
sentry_tracing.py |
| SerpApi | Opt-in --enrich-online live web grounding for cryptic filenames & unknown vendors |
serpapi_client.py |
| ElevenLabs | slothd briefing Sloan-the-Sloth voice summary viaeleven_multilingual_v2 |
elevenlabs.py |
| GitHub Copilot | Cross-OS CI matrix (Ubuntu/Windows, Py 3.11/3.12) + .github/copilot-instructions.md |
ci.yml |
| Entire | Full agent session provenance & Git checkpoints via .entire/settings.json |
.entire/ |
GetLastInputInfo, macOS IOHIDSystem, Linux xprintidle) that sleeps during work and activates only after 5+ minutes of continuous inactivity. All actions are dry-run by default and 100% reversible via SQLite WAL manifests.gemma3:4b running in Ollama. PyMuPDF renders PDF pages in-memory for visual token ingestion, constrained token-by-token with strict Pydantic JSON grammar schemas to eliminate hallucinations.tests/test_tabular_predictor.py`` pgvector IVFFlat cosine distance indexing (<=>), backed by an automatic local SQLite vector fallback. Issue #7805015409, trace_id: 71ac0b2ff1dc4c4788ff6a5b7098e354) that resolved three real development regressions ( 3a327ea``a914b53`` df19f29``slothd/integrations/serpapi_client.py`` slothd/integrations/elevenlabs.py``eleven_multilingual_v2 (slothd briefing), featuring local offline chime fallbacks when no API key is configured..github/copilot-instructions.md``.github/prompts/``/new-sorter, /audit-privacy, /verify-demo), CLI prompt inspector ( slothd copilot), and cross-OS CI matrix (.github/workflows/ci.yml``.entire/settings.json``.agents/hooks.json
Every test runs in total offline isolation (no live external services required):
uv run pytest -v
uv run ruff check .
We spend so much time micromanaging our digital clutterβmanually dragging files into folders, hunting for lost receipts, or feeling guilty about a desktop covered in final_v2_really_final.pdf.
slothd was built on a very simple premise: your machine should quietly work for you when you're resting, not steal your attention when you're busy.
By embracing open-weights, deterministic rule fallbacks, and respectful idle scheduling, you don't have to surrender your personal documents to cloud silos or burn your laptop's battery just to keep a clean workspace. Take a breath, close your laptop lid, and let the sloth do the heavy lifting while you take a break.
I'd love to hear your thoughts and feedback:
If slothd brought a little bit of calm to your daily workflow, consider dropping a β on the GitHub repository, leaving a comment below, and sharing your experience! Happy Hacktoberfest! ππ¦₯