This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady.
What I Built
My Downloads folder had files named doc_001.pdf, scan_004.pdf, IMG_8291.jpg, and notes_final_v3.txt. Finding anything meant opening files one by one, figuring out what they contained, renaming them, and dragging them somewhere sensible.
I kept putting it off because sorting files is one of those chores that never feels urgent enough to do.
SlothSort does that chore for you.
Point it at a folder, and SlothSort scans supported files, extracts available text, and asks an open-weight AI model running on your own machine to suggest meaningful filenames and categories. It then presents the complete plan for your review.
Nothing moves until you approve it. Existing files are never intentionally overwritten or deleted, and successful moves can be undone when the original location remains available and the integrity checks pass.
Here are some real suggestions from Gemma 3 4B on my synthetic demo folder:
| Before | After |
|---|---|
doc_001.pdf |
Invoices/Greenfield_Power_Electricity_Bill_October_2026.pdf |
hw3.docx |
Assignments/CS101_Assignment_3_Sorting_Algorithms.docx |
notes_final_v3.txt |
Notes/Project_Kestrel_Weekly_Meeting_Notes.txt |
Downloads/download (3).pdf |
Receipts/Pinecone_Books_Order_Receipt_PB88213.pdf |
These are proposed destinations, not hardcoded mappings. The application generates suggestions from the available file evidence, and you can review or edit them before anything changes.
SlothSort is for anyone with a messy folder full of bills, receipts, coursework, screenshots, and meeting notes. It's also exactly the kind of folder you might not want to upload to a cloud AI.
Demo
- 🌐 Project page: https://slothsort-two.vercel.app
SlothSort deliberately has no hosted version. It organizes files on the computer where it runs, using a model running on that same computer. A hosted copy would operate on the server's filesystem instead, or require uploading files to the server.
Keeping the application local is part of the product, not an afterthought.
Code
GitHub repository: SHWETANK-SAURABH/slothsort
Clone the repository and run it locally:
git clone https://github.com/SHWETANK-SAURABH/slothsort.git
cd slothsort
pip install -r requirements.txt
ollama pull gemma3:4b
SLOTHSORT_MODEL=gemma3:4b streamlit run app.py
You'll need Python, Ollama, and enough memory to run the selected model. The initial installation and model download require internet access. Once the model is available locally, the core workflow can run without internet access.
How I Built It
Open-source AI at the core
SlothSort is built around local inference rather than a proprietary cloud LLM API.
- Model: Google's open-weight Gemma 3 4B, running locally through Ollama. The model is configurable, and the sidebar lets users select models available in their Ollama installation.
-
Inference: Ollama's local HTTP API at
localhost:11434. I use Python's standard-libraryurllib, so there's no additional SDK or API key. -
Structured output: I pass a JSON Schema to Ollama's
formatoption. The model returns a category, suggested filename, explanation, and confidence score. Pydantic validates the response. Malformed responses receive a bounded retry; if that fails, the file falls back to clearly labelled rule-based suggestions and is flagged for review. - Everything else: Streamlit for the UI, PyMuPDF for PDF text extraction, Pydantic for validation, Pillow for image handling, SQLite for the action journal, and pytest for automated tests.
The interesting part: don't trust the model
A small local model can read text like "ELECTRICITY BILL — Amount due: $84.20" and suggest the category Invoices.
But a language model should never be trusted to decide which filesystem operations are safe.
SlothSort separates AI reasoning from file execution:
flowchart TD
S[Scan files — read only] --> M[Gemma 3 4B via Ollama]
M -->|Structured JSON| V[Deterministic validator]
V --> R[User reviews and edits]
R -->|Explicit approval| E[Safe file executor]
E --> J[(SQLite action journal)]
J --> U[Undo supported moves]
Here's how that separation works:
- The model only proposes. It returns structured text; it cannot execute commands or modify files directly.
- Every suggestion is validated. The category must be allowed, the original file extension is preserved, and unsafe names, absolute paths, path traversal, and reserved Windows filenames are rejected.
- Destinations are constrained. The resolved destination must remain inside the folder the user selected.
- File contents are untrusted input. Extracted text is clearly delimited, and the system prompt instructs the model to treat it as data rather than instructions.
-
Prompt injection is part of the demo. My synthetic dataset includes a file that tries to instruct the model to move itself into
system32. The model ignored it during my demo run, and the independent path validator is designed to reject an unsafe destination regardless of what the model suggests. - Approval is mandatory. The executor accepts only an approved plan with a fingerprint. If the plan changes after approval, execution is rejected.
- Files are checked again before moving. SlothSort rechecks file identity using size, modification time, and SHA-256, and verifies that the destination does not already exist.
- Moves are journaled. The SQLite action journal records operations so supported moves can be undone, including after an application restart. Undo also refuses to overwrite existing files.
The key design principle is simple: AI decides what might be useful; deterministic code decides what is allowed.
The bug that taught me something
On my first real run, Gemma named a grocery receipt Maple_Market_Receipt_September_2021.txt.
The receipt said 2026.
It also reported a confidence score of 0.95, just as it did for nearly everything else. That taught me that a model's self-reported confidence isn't a reliable way to decide whether a suggestion is trustworthy.
So I added a grounding check.
Any number in a proposed filename — a year, invoice ID, or amount — must appear in the extracted file text or metadata. For files without readable text, such as images and scans, suggested names are restricted to generic terms and words grounded in the original filename.
If a suggestion fails, SlothSort flags it for review with a message such as:
Check name: "2021" not found in the file.
It's a deliberately simple check, not a complete hallucination detector. But unlike trusting a confidence score, it catches a specific, reproducible class of errors.
Measured, not promised
I created a 29-file synthetic demo dataset containing invoices, receipts, assignments, notes, screenshots, photos, two pairs of exact duplicates, two unsupported files, and a prompt-injection example.
I manually labelled 27 files and ran the evaluation script twice.
| Metric | Run 1 | Run 2 |
|---|---|---|
| Gemma 3 4B category accuracy | 25/27 (92.6%) | 24/27 (88.9%) |
| Filename-only baseline accuracy | 17/27 (63.0%) | 17/27 (63.0%) |
| Malformed model responses | 0 of 7 calls | 0 of 7 calls |
| Average planning time | ≈3.0 s/file | ≈2.2 s/file |
| Approved moves completed / undone | 27/27 / 27/27 | 27/27 / 27/27 |
| Unsafe-operation probes blocked | 12/12 | 12/12 |
Twenty-seven labelled files are a sanity check, not a serious benchmark. Results varied between runs even at temperature zero, and the small sample means these numbers shouldn't be generalized to arbitrary folders.
The project also has 62 automated tests, with Ollama mocked so the test suite doesn't require a running model. These include a full UI click-through using Streamlit's AppTest.
The numbers above describe my recorded evaluation runs; the tests and evaluation scripts are available in the repository so others can inspect and reproduce them.
How the work got done
I built SlothSort in a week with the help of an AI coding agent.
I wrote the specification, including the technology stack, safety rules, priorities, and the requirement not to claim functionality before testing it. The agent wrote most of the code, ran tests, and helped with the real-model evaluation along the way.
I made the architectural decisions and checked the results. The commit history documents the progression from the core engine and tests to the UI and documentation.
Why Does Open Innovation Matter?
For SlothSort, open-weight AI is what makes the local-first approach practical.
A file organizer needs to read your files: utility bills with account numbers, receipts, coursework with your name on it, and possibly a lease agreement.
With a cloud LLM API, the excerpts needed for classification would be sent to someone else's server. You'd need an API key, an internet connection, and confidence in the provider's data-handling policies.
With Gemma running locally through Ollama, file content can stay on your computer. SlothSort's model requests go to the local Ollama endpoint rather than a remote LLM service.
That changes the privacy story from a promise about a provider's policies to an architectural choice that users can inspect.
Open weights also provide practical advantages:
- No model-provider lock-in. The model can be changed without redesigning the entire application. The evaluation script can be run again to compare supported models.
- No per-file API bill. Once the model has been downloaded, inference uses the user's own hardware rather than charging for each API request.
- User control. Developers can inspect the application, modify the prompts, change the model, and test the results themselves.
- Offline capability. After setup and model download, the core workflow can operate without internet access.
Local inference isn't free in an absolute sense: it consumes hardware resources and electricity, and larger models may require substantial memory. But it removes the need to send document contents to a proprietary inference service.
A 4B open-weight model isn't necessarily as capable as the largest closed models. For a narrow task like file organization, though, pairing a local model with deterministic validation and explicit human approval makes the trade-off worthwhile.
The Lazy Payoff
On my demo folder, planning 27 files took approximately a minute of model time. My job was to watch the progress bar and then review a single table rather than opening 27 files individually.
I haven't timed myself organizing the same folder manually, so I won't claim a specific number of minutes saved.
The bigger payoff is that I no longer have to put the task off until I have the patience to do it. SlothSort handles the repetitive work, while I retain control over the final changes.
That's the point of Slow and Steady: let the machine handle the boring part, and spend your attention where it matters.
Prize Categories
- Best Use of Gemma: SlothSort uses Google's open-weight Gemma 3 4B locally through Ollama. The reported model-evaluation results above come from Gemma.
Built with local AI, deterministic safety checks, and a healthy respect for the art of doing less repetitive work.
Top comments (0)