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
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.
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
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.1only. (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)