Sloth Sorter 以本地 LLM 整理下載資料夾,並支援撤銷操作
Sloth Sorter 🦥 — a local LLM tidies my Downloads folder, and every move can be undone
Hardik 開發並公開 Sloth Sorter,這款透過 Ollama 在本機執行 LLM 的離線優先工具,可分類檔案、為含糊文件改名及封存舊檔,並支援預覽和撤銷操作。
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
My Downloads folder is where files go to be forgotten. Some examples:
invoice_final_v2.pdf-
scan0003.pdf, which turns out to be a bank statement -
document(7).pdf, which is actually lecture slides - three copies of
setup.exe - a dozen
Screenshot 2026-…pngfiles
Sorting it by hand is exactly the kind of chore I keep putting off, so I built something that does it for me while I do nothing. Sloths would approve.
Sloth Sorter is a small, offline-first file tidier with a friendly web UI. You point it at the folders you never clean, like Downloads and Desktop. It then:
- sorts files into category folders: Finance, Study, Personal & ID, Screenshots, Installers and so on
-
renames vague documents to something human, so
scan0003.pdfbecomesSupermarket Bank Statement Sep 2026.pdf -
archives files you haven't touched in months into
_Archive/<year>/ - runs on a schedule, either applying changes automatically or preparing a plan for you to approve
The thing I cared about most was trust. A tool that moves my files around has to be boringly safe:
-
It never deletes and never overwrites anything. Name clashes become
report (1).pdf. - Every run starts as a plan. You see a preview table, can untick rows or change a category or name, and only then press Sort everything.
- Every move is written to a journal before it happens, and every run has an Undo button. Undo restores the original names and locations and cleans up the empty folders it created.
- It skips anything risky: hidden files, shortcuts, half-finished downloads (
.crdownload,.part), files modified in the last 10 minutes, and system folders likeC:\Windowsor AppData.
Demo
The UI is a little flat-2D "desktop" with rolling hills and drifting clouds:
- Windows you can drag, minimise and bring to the front.
- A taskbar with a Start menu, a live clock and the active model's name.
- A dusk theme.
- A sloth hanging from a branch, which sleeps when idle, says "sorting... slowly" while it works, and looks pleased when it's done.
Everything is drawn in inline SVG and CSS. The page loads nothing from the internet: no CDN, no web fonts.
Code
Sloth Sorter 🦥
Sloths move about one metre a minute, and they still get where they're going. Sloth Sorter works at the same steady pace on your Downloads, Desktop and other cluttered folders It sorts files into tidy category folders, gives vague documents sensible names, and archives things you haven't touched in ages. It runs entirely on your own computer. A local language model served by Ollama helps only where simple rules can't decide.
It never deletes anything and never overwrites anything, and every run can be undone.
60-second quickstart
pip install -e . # from this folder (Python 3.10+) ollama list # optional: check Ollama is running and has at least one model sloth-sorter # or: python -m slothsorter
Your browser opens http://127.0.0.1:8484. Then:
- In My Folders, add a folder such as
C:\Users\you\Downloads. Type the path or use Browse…. - Press Preview plan. Nothing…
Try it on your own machine:
git clone https://github.com/hardikgaikwad/Sloth-Sorter.git
cd Sloth-Sorter
pip install -e .
python scripts/make_demo_clutter.py # optional: a safe folder full of fake clutter
python -m slothsorter # opens http://127.0.0.1:8484
How I Built It
Stack: Python with FastAPI and uvicorn, SQLite, pypdf, python-docx and Pillow. The frontend is one static HTML/CSS/vanilla-JS page with no build step. The open-weight models are served locally by Ollama. I tested with Llama 3.2 (3B) and Qwen 2.5 (7B) on a laptop with a 4 GB GPU.
The key design decision is that rules go first and the LLM only gets the hard cases.
-
Rules, with no model call.
- Extensions decide installers, archives, video, audio, code, spreadsheets and slides.
- Filename patterns catch screenshots ("Screenshot", "Screen Shot", "Snip").
- A screen-sized PNG with no camera data is probably a screenshot.
- A JPEG with camera EXIF data is a photo.
In my test folder, this handled 18 of 29 files instantly.
-
The LLM handles documents and unknown files. For a PDF, DOCX, TXT, MD or CSV, I extract about 1,500 characters of text and send the filename plus that excerpt to Ollama's
/api/chat. The request usestemperature: 0and a JSON schema informat, so the model must pick a category from a fixed list and propose a short name:
"format": {
"type": "object",
"properties": {
"category": {"type": "string", "enum": list(CATEGORIES)},
"suggested_name": {"type": "string"},
"confidence": {"type": "string", "enum": ["low", "medium", "high"]},
"reason": {"type": "string"},
},
"required": ["category", "suggested_name", "confidence", "reason"],
}
-
Code checks everything the model says.
-
The model never produces paths. A path-like answer such as
C:\Windows\…or../../falls back to the original name. -
Names are sanitised. Illegal Windows characters and reserved names like
CONare removed, names are capped at 80 characters, and the original extension is always kept. - Unknown categories are rejected.
- Low-confidence answers keep the original name and are flagged "needs review" in the plan.
-
The model never produces paths. A path-like answer such as
Results are cached by content hash, model and prompt version, so re-running a plan is instant.
Two things I learned along the way:
-
Small models love CamelCase. Both models first returned names like
AcmeHostingInvoice4471. One concrete example in the system prompt fixed it: "2–8 plain words separated by spaces, e.g. 'Acme Hosting Invoice Sep 2026'". Now I getAcme Hosting Invoice Sep 2026.pdf. -
localhostcost me 4 seconds on Windows. When Ollama was off,localhosttried::1first and Windows retried the refused connection before falling back. Ollama listens on127.0.0.1, so I connect there directly. If Ollama dies in the middle of a run, Sloth Sorter stops calling it and sorts the remaining files by type, instead of waiting on each one.
If Ollama isn't running at all, nothing breaks. The app switches to rules-only mode and shows a banner explaining ollama serve and ollama pull <model>. It never pulls a model itself. It reads your installed models from /api/tags, auto-picks a small chat model, and lets you switch from a dropdown at any time.
The scheduler is a background thread inside the server: no cron, no Celery.
- Runs never overlap.
- Catch-up: if the laptop was off when a run was due, it does one catch-up pass after start-up, not one for every missed slot.
-
Safe test interface: the whole web API listens on
127.0.0.1only, with Host/Origin checks and a per-session token, so other websites in your browser can't call it.
There are 96 pytest tests. They cover:
- the folder safety rules and the filename sanitiser
- name collisions
- the LLM path, using a mocked Ollama that returns bad JSON, unknown categories and path-like names
- apply, journal and undo, with byte-for-byte restore checks
- the scheduler, using a fake clock
- the API's CSRF protections
Why Does Open Innovation Matter?
Because the files in my Downloads folder are the most private data I have. That test folder alone held a bank statement, a passport detail, a CV and invoices. A file tidier only works if it can read your files, and I'm not willing to upload my bank statements to a cloud API just to get them sorted.
Open-weight models running locally through Ollama make this possible:
-
Nothing leaves the machine. The only network traffic is to
127.0.0.1:11434. - It costs nothing to run. It can sort thousands of files on a schedule, every day, forever, with no API bill and no rate limit.
- It keeps working offline, on a train, or after some company changes its pricing.
- You choose the model. Use whatever you already have installed, and swap it from a dropdown. A 3B model is enough for "is this an invoice or lecture notes?"
The Lazy Payoff
I tested on a folder of 33 realistic clutter files: invoices, a bank statement, lecture notes, a CV, installers, screenshots and photos. These are measured numbers from the end-to-end runs, not guesses.
| Llama 3.2 3B | Qwen 2.5 7B | Rules only (Ollama off) | |
|---|---|---|---|
| Files sent to the LLM | 11 of 29 | 11 of 29 | 0 |
| Correct category | 26 / 29 | 27 / 29 | 22 / 29 |
| Time to build the plan | 11.9 s | 65.3 s | 0.3 s |
| Per LLM file | ~1.1 s | ~5.9 s | n/a |
| Undo restored everything byte-for-byte | ✅ | ✅ | ✅ |
Doing this by hand means opening each mystery PDF, deciding where it goes, renaming it and dragging it. At roughly 20 seconds per file, the 28 files it moved represent about 9 minutes of chores, replaced by about 12 seconds of the sloth thinking and one click from me. The app keeps a running "estimated time saved" counter (files moved × seconds per file, adjustable in Settings and clearly labelled as an estimate). Set a daily schedule on Downloads and that counter keeps growing while you do nothing at all, which is the whole point. 🦥
The misses were reasonable judgement calls rather than disasters:
- A CSV of rent and grocery transactions went to Spreadsheets instead of Finance.
- A README about printer drivers was labelled Installers. The model flagged it as low confidence, so it kept its name and was marked for review.
And thanks to Undo, a wrong guess costs one click.
來源:DEV Community · dev.to