cd /news/ai-tools/i-built-slothd-a-local-first-offline… Β· home β€Ί topics β€Ί ai-tools β€Ί article
[ARTICLE Β· art-154883] src=dev.to β†— pub= topic=ai-tools verified=true sentiment=↑ positive

I Built slothd: A Local-First, Offline-Capable AI Daemon That Patiently Organizes Your Messy Workspace

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.

by read9 min views4 publishedOct 21, 2026

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! πŸ‚πŸ¦₯

── more in #ai-tools 4 stories Β· sorted by recency
── more on @slothd 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/i-built-slothd-a-loc…] indexed:0 read:9min 2026-10-21 Β· β€”