{"slug": "i-built-slothd-a-local-first-offline-capable-ai-daemon-that-patiently-organizes", "title": "I Built slothd: A Local-First, Offline-Capable AI Daemon That Patiently Organizes Your Messy Workspace", "summary": "A developer built slothd, an open-source (MIT) local-first AI file organizer that runs entirely offline, using local Ollama models (Gemma 3 for document understanding, nomic-embed-text for embeddings) with a SQLite vector fallback to classify and sort messy workspaces. The daemon waits for keyboard idle time, performs a two-stage metadata-triage-then-AI-plan funnel, requires explicit approval via a dry-run preview, and supports semantic search plus one-click rollback that restores files to their exact original paths. Cloud services such as Tiger Data pgvector, SerpApi and ElevenLabs are strictly opt-in via CLI flags, each with an offline fallback.", "body_md": "*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady](https://dev.to/challenges/hacktoberfest-week3-2026-10-19)*\n\n💡 **Quick Navigation:** What I Built · Live Demo · Code · Architecture & Funnel · Open Innovation · Lazy Payoff · Prize Categories (8 Tracks) · Discussion\n\n**📖 Table of Contents** (Click to expand)\n\nLast 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.\n\nWorkspaces, 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*.\n\nI built **slothd**, a local-first, offline-capable AI file organizer designed around the philosophy of **\"Slow and Steady\"**:\n\n`nomic-embed-text`) with a local SQLite vector fallback, enabling queries like `slothd undo` restores every file to its exact original path.\n🔒 **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.\n\nEvery 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.\n\nThe complete interactive loop demonstrates the full lifecycle:\n\n```\nMessy Workspace \n  ➜ Fast Metadata Triage (TabPFN / Local Heuristic) \n  ➜ Local AI Plan (Gemma 3) \n  ➜ Dry-Run Preview \n  ➜ Explicit Approval \n  ➜ Semantic Search (Tiger Data) \n  ➜ SQLite Manifest Inspection \n  ➜ 1-Click Rollback\n```\n\n`yuv420p` + `faststart` for instant playback across all browsers)\nYou 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.\n\nAnyone can clone and run the scan immediately:\n\n```\ngit clone https://github.com/JaniDhruv/slothd.git\ncd slothd\nuv run slothd scan test_workspace/messy_inbox\n```\n\nIn under a second, you will observe the verified metrics:\n\nThe project is 100% open-source under the MIT License:\n\n👉 **GitHub Repository:** [github.com/JaniDhruv/slothd](https://github.com/JaniDhruv/slothd)\n\n`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/`\nA 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:\n\n```\n┌────────────────────────────────────────────────────────┐\n│               Messy Target Directory                   │\n└───────────────────────────┬────────────────────────────┘\n                            │\n              1. Deduplicate & Extract Features\n                            │\n                            ▼\n┌────────────────────────────────────────────────────────┐\n│     STAGE 1: Prior Labs TabPFN Metadata Triage         │\n│  (7 tabular signals: log size, depth, ext, time, etc.) │\n└─────────────┬────────────────────────────┬─────────────┘\n              │                            │\n   Leftover installers, archives,          │ Needs deeper\n   screenshots, duplicate clutter          │ semantic classification\n              ▼                            ▼\n   Flagged for cleanup          ┌────────────────────────┐\n                                │ STAGE 2: Gemma 3 Local │\n                                │   (Ollama Vision/Text) │\n                                └──────────┬─────────────┘\n                                           │\n                                           ▼\n                                ┌────────────────────────┐\n                                │ SQLite Reversible Log  │\n                                │  + Tiger Data pgvector │\n                                └────────────────────────┘\n```\n\nBefore running AI models, `slothd` extracts 7 tabular signals from the filesystem:\n\nWhen 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**.\n\n*(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).*\n\nOnly files requiring semantic classification (unlabeled PDFs, scanned receipts, documents) are forwarded to local **Gemma 3** via **Ollama**.\n\n`format` parameter. The model output is validated token-by-token at the grammar level:\n`category`, `subcategory`, `description`, `date`, `vendor`, `proposed_name`, `confidence`, and `tags`.\nThe organization pipeline enforces strict safety invariants:\n\n`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`.\nSentry was not added as a decorative vanity badge; it was an active part of the developer feedback loop during development.\n\nThe 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`.\n\n```\n[Transaction] slothd.organize_cycle (total: 1,248 ms)\n├─ [Span] scanner.scan_directory .................... 12 ms [10 files discovered]\n├─ [Span] ai.tabular_triage (TabPFN) ................ 1 ms [2 anomalies flagged]\n├─ [Span] ai.gemma_classify_batch (Ollama) .......... 1,180 ms [Prompt: 412 tok, Resp: 86 tok]\n├─ [Span] organizer.preview_manifest ................ 3 ms [Manifest prepared]\n├─ [Span] db.wal_log_commit ......................... 4 ms [SQLite WAL sync]\n└─ [Span] search.index_pgvector (Tiger Data) ........ 48 ms [768-dim embeddings stored]\nIssue ID: 7805015409\nRelease: slothd@0.1.0 (production)\nTitle: ConnectionError: Connection refused to 127.0.0.1:11434\nCulprit: slothd.engine.classifier in classify_batch\nTrace ID: 71ac0b2ff1dc4c4788ff6a5b7098e354\nSpan ID: a1ea6839c23ccbb5 (op: ai.classify_batch, desc: \"Gemma 3 batch classify (4 files)\")\nBreadcrumb: [warning] slothd.engine.classifier: Ollama server is offline or unreachable. Fast-falling back to local classification.\nHandled: Yes (Circuit-breaker tripped gracefully without crashing the daemon)\n```\n\n| Observed Failure in Sentry | Root Cause Revealed | Resolution & Test | \n|---|---|---|\n| `ConnectionError` on`127.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`](https://github.com/JaniDhruv/slothd/commit/3a327ea) ). | \n| `ValidationError: confidence > 1.0` | Gemma 3 occasionally returned confidence as a percentage ( `90` or`100` ) instead of float`0.0–1.0` | Added automatic percentage normalization validator in Pydantic schema with bounds coverage ( [`a914b53`](https://github.com/JaniDhruv/slothd/commit/a914b53) ). | \n| `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`](https://github.com/JaniDhruv/slothd/commit/df19f29) ). | \n\nPersonal files contain our most vulnerable data:\n\nUploading this stream of daily life to closed, centralized cloud APIs creates an unacceptable privacy tradeoff.\n\n**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:\n\n`--enrich-online`) and are never enabled by default.\nPrivacy is not a checkbox added after the architecture is done; with open-source AI, privacy **is** the architecture.\n\nThe lazy payoff is not about moving files a few milliseconds faster. It is about **removing the cognitive dread of manual digital housekeeping**.\n\nInstead of spending Sunday afternoon opening dozens of PDFs one by one, deciphering cryptic filenames, and deciding where each document belongs:\n\n`slothd daemon` run in the background.\n\n```\n10 files scanned\n2 clutter anomalies identified\n1 duplicate set found\n973 B reclaimable disk space\n1 ms metadata triage (local deterministic 7-signal engine / TabPFN schema)\n0 cloud API calls required\n100% offline isolation\n```\n\nWhile `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:\n\n| Track | How `slothd` Uses It | Source Module | \n|---|---|---|\n| **Google Gemma** | Local `gemma3:4b` vision + text via Ollama with strict Pydantic JSON outputs | [`classifier.py`](https://github.com/JaniDhruv/slothd/blob/main/slothd/engine/classifier.py) | \n| **Prior Labs TabPFN** | 1ms 7-feature tabular triage flagging stale archives & size outliers before LLM wakeup | [`tabular_predictor.py`](https://github.com/JaniDhruv/slothd/blob/main/slothd/engine/tabular_predictor.py) | \n| **Tiger Data** | 768-dim `pgvector` semantic search (`<=>` ) + hybrid keyword re-ranking | [`tiger_data.py`](https://github.com/JaniDhruv/slothd/blob/main/slothd/integrations/tiger_data.py) | \n| **Sentry Tracing** | Distributed spans ( `slothd.scan` ,`predict` ,`classify` ,`search` ) tracking latency & tokens | [`sentry_tracing.py`](https://github.com/JaniDhruv/slothd/blob/main/slothd/integrations/sentry_tracing.py) | \n| **SerpApi** | Opt-in `--enrich-online` live web grounding for cryptic filenames & unknown vendors | [`serpapi_client.py`](https://github.com/JaniDhruv/slothd/blob/main/slothd/integrations/serpapi_client.py) | \n| **ElevenLabs** | `slothd briefing` Sloan-the-Sloth voice summary via`eleven_multilingual_v2` | [`elevenlabs.py`](https://github.com/JaniDhruv/slothd/blob/main/slothd/integrations/elevenlabs.py) | \n| **GitHub Copilot** | Cross-OS CI matrix (Ubuntu/Windows, Py 3.11/3.12) + `.github/copilot-instructions.md` | [`ci.yml`](https://github.com/JaniDhruv/slothd/blob/main/.github/workflows/ci.yml) | \n| **Entire** | Full agent session provenance & Git checkpoints via `.entire/settings.json` | [`.entire/`](https://github.com/JaniDhruv/slothd/tree/main/.entire) | \n\n`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`\nEvery test runs in total offline isolation (no live external services required):\n\n```\nuv run pytest -v\n# 118 passed in 40.87s\n\nuv run ruff check .\n# All checks passed!\n```\n\nWe 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`. \n\n`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.** \n\nBy 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.\n\nI'd love to hear your thoughts and feedback:\n\nIf `slothd` brought a little bit of calm to your daily workflow, consider dropping a ⭐ on the [GitHub repository](https://github.com/JaniDhruv/slothd), leaving a comment below, and sharing your experience! Happy Hacktoberfest! 🍂🦥", "url": "https://wpnews.pro/news/i-built-slothd-a-local-first-offline-capable-ai-daemon-that-patiently-organizes", "canonical_source": "https://dev.to/dj29/i-built-slothd-a-local-first-offline-capable-ai-daemon-that-patiently-organizes-your-messy-53e7", "published_at": "2026-10-21 21:51:28+00:00", "updated_at": "2026-10-21 22:11:08.799335+00:00", "lang": "en", "topics": ["ai-tools", "ai-agents", "large-language-models", "ai-products"], "entities": ["slothd", "Ollama", "Gemma 3", "nomic-embed-text", "Tiger Data", "SerpApi", "ElevenLabs", "TabPFN"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/i-built-slothd-a-local-first-offline-capable-ai-daemon-that-patiently-organizes", "markdown": "https://wpnews.pro/news/i-built-slothd-a-local-first-offline-capable-ai-daemon-that-patiently-organizes.md", "text": "https://wpnews.pro/news/i-built-slothd-a-local-first-offline-capable-ai-daemon-that-patiently-organizes.txt", "jsonld": "https://wpnews.pro/news/i-built-slothd-a-local-first-offline-capable-ai-daemon-that-patiently-organizes.jsonld"}}