DEV Community

Sudharsan B
Sudharsan B

Posted on

I Let a Sloth Tidy My Downloads Folder (Local Gemma, No Cloud)

Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady Submission 🦥

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

What I Built

sloth-tidy is a small Python CLI that sorts, renames and archives a cluttered folder, like the Downloads folder I keep promising myself I'll clean up.

It reads each file's name, size and the first 300 characters of text files. A local open-weight model then picks a category (Documents, Images, Receipts, ...) and proposes a clean kebab-case name. Nothing moves until you pass --apply, and --undo puts everything back.

Anyone with a folder they dread opening gets to be a little lazier: point it at the folder, read the plan, press go.

Demo

Dry-run on a sample folder (extension-rules mode, --no-llm):

IMG_0042.png  ->  Tidied/Images/IMG_0042.png
backup.zip  ->  Tidied/Archives/backup.zip
installer.dmg  ->  Tidied/Installers/installer.dmg
invoice-oct.pdf  ->  Tidied/Documents/invoice-oct.pdf
notes.txt  ->  Tidied/Documents/notes.txt

5 file(s) planned (dry-run; add --apply).
Enter fullscreen mode Exit fullscreen mode

Code

sloth-tidy

Sorts, renames and archives a messy folder using a local open-weight model (Gemma via Ollama). No cloud, no API key, stdlib-only Python.

ollama pull gemma3:4b
python3 sloth_tidy.py ~/Downloads            # dry-run: prints the plan
python3 sloth_tidy.py ~/Downloads --apply    # moves files, writes an undo log
python3 sloth_tidy.py ~/Downloads --undo     # puts everything back
Enter fullscreen mode Exit fullscreen mode

Safety: dry-run by default, never overwrites, skips hidden files and anything modified in the last 10 minutes, falls back to extension rules if the model is unreachable (--no-llm forces this). Only the first 300 characters of text files are sent to the model, and only to localhost.

Tests: python3 -m pytest

ollama pull gemma3:4b
python3 sloth_tidy.py ~/Downloads            # dry-run: prints the plan
python3 sloth_tidy.py ~/Downloads --apply    # moves files, writes an undo log
python3 sloth_tidy.py ~/Downloads --undo     # puts everything back
Enter fullscreen mode Exit fullscreen mode

How I Built It

  • Model: Gemma (default gemma3:4b), served locally by Ollama. The --model flag swaps in any other Ollama model.
  • Integration: plain POST /api/chat to localhost:11434 with format: "json". No SDK and no third-party dependencies, so the whole tool is one Python file using only the standard library.
  • Batching: files go to the model 20 at a time, each with an id, so replies map back to files reliably.
  • Don't trust the model: every reply is validated. Unknown categories fall back to extension rules, suggested names are re-slugified, and name collisions get -2, -3 suffixes so nothing is overwritten.
  • Fails soft: if the server is down or returns bad JSON, that batch falls back to extension rules.
  • Safety rails: dry-run by default, hidden files and files modified in the last 10 minutes are skipped, and every applied run writes an undo log.

Unit tests cover the fallback rules, apply/undo, model renames, collisions, invalid categories, recent-file skipping and model failure. They use a stubbed model, so they run without Ollama.

Honest note: I verified the model path against a stubbed response, not a live Gemma run, so I'm not claiming any naming-quality or speed numbers.

Why Does Open Innovation Matter?

  • Privacy: a Downloads folder is full of invoices, tax PDFs and screenshots. With a local model, file names and text previews only go to localhost. A closed API would mean uploading that listing to a server I don't control.
  • Offline and free: it works without a connection and costs nothing per run, so it's fine to run on a schedule.
  • Swappable: the model is one flag. A bigger model for better names, or a smaller one for speed, needs no code change.
  • Small is enough: JSON-mode output plus validation means a small local model can do this job. Filing a PDF doesn't need a frontier model.

Top comments (0)