DEV Community

Cover image for Sloth Tidy: a folder sorter that runs on my own gemma3, offline.
JUKUN MAN WITH SME POWER
JUKUN MAN WITH SME POWER

Posted on

Sloth Tidy: a folder sorter that runs on my own gemma3, offline.

Sloth Tidy sorts and renames a messy folder for you. Point it at Downloads or Desktop and it proposes moves like Untitled1.txt -> documents/standup-notes.txt, based on what the file actually says, not just its extension.
It is lazy-friendly by design:

  • Dry run by default. Nothing moves until you click Apply.
  • Never overwrites a file (name clashes get -2, -3).
  • One-click undo puts everything back.

There is a command-line tool and a small local web page (python ui.py) with Preview, Apply and Undo buttons. I'd never organise my Downloads folder myself, so now I don't have to.

Sloth Tidy

Point it at a messy folder. It sorts and renames everything using a local open-weight model (via Ollama). Nothing leaves your machine. Python stdlib only.

ollama pull gemma3:4b          # any open-weight model works (gemma3:1b is faster)
python3 sloth.py ~/Downloads             # dry run: shows what it would do
python3 sloth.py ~/Downloads --apply     # do it
python3 sloth.py ~/Downloads --undo      # change your mind
Enter fullscreen mode Exit fullscreen mode

Prefer clicking? python ui.py opens a small local web page (preview, apply, undo). It listens on 127.0.0.1 only.

IMG_0042.JPG becomes images/img-0042.jpg. Untitled(3).txt containing meeting notes becomes documents/team-standup-notes.txt.

How it works

  • For each file, sends the filename plus the first 600 characters (text files only) to the local model and asks for JSON: {category, name}.
  • Output is validated; a bad answer or an unreachable server falls back to extension rules, so it never hangs or breaks.
  • Safe by default: dry…

Two files sorted by their content, using gemma3:1b on my own CPU:

PS> python sloth.py $HOME\mini --model gemma3:1b
(first file may be slow while gemma3:1b loads)
[1/2] note2.txt ...
[2/2] Untitled1.txt ...
note2.txt  ->  documents\groceries-list.txt
Untitled1.txt  ->  documents\standup-notes.txt
dry run: 2 files. add --apply to do it.
Enter fullscreen mode Exit fullscreen mode

Sloth Tidy

Point it at a messy folder. It sorts and renames everything using a local open-weight model (via Ollama). Nothing leaves your machine. Python stdlib only.

ollama pull gemma3:4b          # any open-weight model works (gemma3:1b is faster)
python3 sloth.py ~/Downloads             # dry run: shows what it would do
python3 sloth.py ~/Downloads --apply     # do it
python3 sloth.py ~/Downloads --undo      # change your mind
Enter fullscreen mode Exit fullscreen mode

Prefer clicking? python ui.py opens a small local web page (preview, apply, undo). It listens on 127.0.0.1 only.

IMG_0042.JPG becomes images/img-0042.jpg. Untitled(3).txt containing meeting notes becomes documents/team-standup-notes.txt.

How it works

  • For each file, sends the filename plus the first 600 characters (text files only) to the local model and asks for JSON: {category, name}.
  • Output is validated; a bad answer or an unreachable server falls back to extension rules, so it never hangs or breaks.
  • Safe by default: dry…
  • Model: Google's open-weight gemma3 (1B and 4B), served locally by Ollama. I already had it installed, so setup took no time and no new downloads.
  • Tool: plain Python, standard library only, no dependencies. For each file it sends the filename and the first 600 characters of text files to the local model and asks for JSON ({category, name}).
  • Guardrails: the model's answer is validated. If Ollama is down, slow, or returns something unusable, the tool falls back to simple extension rules instead of hanging or crashing.
  • Safety: a dry run first, collision-proof names, and an undo log.
  • UI: a tiny local web page built with the standard library, listening on 127.0.0.1 only. (https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/0q5vy393kwmp75oztr4z.png)

A folder tidier has to read your private files: tax returns, chat exports, notes. With an open-weight model on localhost, those contents never leave my machine, it works with no internet connection, and it costs nothing per file.

It is also swappable. --model accepts any Ollama model, so I could try gemma3:1b for speed and gemma3:4b for quality by changing one flag. With a closed API I would be uploading my Downloads folder to someone else's server and paying per file.
(https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/rml016bakg4swrv7fwqx.png)

The Lazy Payoff

It names files by their content without me opening them, and my files stay on my PC. Honest notes from building it:

  • My first run named both files other.txt. Two causes: Windows PowerShell saves text files as UTF-16, which my code read as garbage, and a 1B model sometimes copies words from the prompt. Decoding UTF-16 properly and giving the model a clearer example fixed it.
  • It runs on CPU, so it is slow per file. A small model suits a one-off tidy or an overnight run, not instant results.
  • It never gets stuck. Without a working model, it still sorts by extension.

Prize Categories

Open-weight models / local inference.

Top comments (0)