# SlothSort 🦥: The Zero-Effort, Local AI File Organizer

> Source: <https://dev.to/harshvardhan_bablani_7f75/slothsort-the-zero-effort-local-ai-file-organizer-kp>
> Published: 2026-10-22 17:05:53+00:00

I built **SlothSort**, a background digital butler that rewards peak laziness.

Like most developers, my Downloads folder is a chaotic graveyard of files named Screenshot_10222026.png, invoice_final_v2_FINAL.pdf, and asdfasdf.jpg. I am simply too lazy to rename and organize them manually.

SlothSort is a lightweight Python agent that monitors your messy folders. Channeling true International Sloth Day energy, it waits exactly 24 hours before acting on any new file. Once a file hits the "sloth threshold," the script wakes up, analyzes the file using a local open-weight model to determine context, generates a clean, descriptive file name, and moves it to a neatly categorized directory (like /Invoices, /Work_Docs, or /Images). You do absolutely nothing while your computer does the housekeeping.

(Note: I am running this entirely offline via my terminal. The script detects old files on startup, processes them silently through the local LLM, and prints the new mapped destinations.)

`SlothSort started. Watching /Users/harsh/Downloads for files older than 24 hours...`

SlothSort awakening to process: IMG_9921_rec.jpg

Moved: IMG_9921_rec.jpg -> /Users/dev/Documents/SlothSorted/Images/receipt_scan.jpg

SlothSort awakening to process: Q3_tax_est.pdf

Moved: Q3_tax_est.pdf -> /Users/dev/Documents/SlothSorted/Financials/Q3_tax_estimate.pdf

``` python
import os
import time
import shutil
import json
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import ollama

WATCH_DIR = os.path.expanduser("~/Downloads")
BASE_SORT_DIR = os.path.expanduser("~/Documents/SlothSorted")
SLOTH_THRESHOLD_SECONDS = 86400 # 24 hours

class SlothHandler(FileSystemEventHandler):
    def process_file(self, file_path):
        file_name = os.path.basename(file_path)

        # Skip hidden files or already processing files
        if file_name.startswith('.'):
            return

        # Get file age
        file_stat = os.stat(file_path)
        file_age = time.time() - file_stat.st_mtime

        if file_age > SLOTH_THRESHOLD_SECONDS:
            print(f"SlothSort awakening to process: {file_name}")
            new_name, category = self.ask_local_llm(file_name)

            if new_name and category:
                self.move_and_rename(file_path, new_name, category)

    def ask_local_llm(self, filename):
        prompt = f"""
        You are a highly efficient file organizer. I have a file named '{filename}'.
        Based ONLY on this file name, provide a clean, descriptive file name (keeping the original extension) 
        and a broad folder category for it (e.g., Invoices, Images, Documents, Installers, Code).
        Respond ONLY in strict JSON format like this: {{"new_name": "clean_name.ext", "category": "CategoryName"}}
        """
        try:
            response = ollama.chat(model='llama3.1', messages=[
                {'role': 'user', 'content': prompt}
            ])
            result = json.loads(response['message']['content'])
            return result.get('new_name'), result.get('category')
        except Exception as e:
            print(f"Failed to process {filename} via Ollama: {e}")
            return None, None

    def move_and_rename(self, old_path, new_name, category):
        target_dir = os.path.join(BASE_SORT_DIR, category)
        os.makedirs(target_dir, exist_ok=True)

        new_path = os.path.join(target_dir, new_name)

        # Avoid overwriting existing files
        counter = 1
        while os.path.exists(new_path):
            name, ext = os.path.splitext(new_name)
            new_path = os.path.join(target_dir, f"{name}_{counter}{ext}")
            counter += 1

        shutil.move(old_path, new_path)
        print(f"Moved: {os.path.basename(old_path)} -> {new_path}")

    def on_modified(self, event):
        if not event.is_directory:
            self.process_file(event.src_path)

if __name__ == "__main__":
    print(f"SlothSort started. Watching {WATCH_DIR} for files older than 24 hours...")
    os.makedirs(BASE_SORT_DIR, exist_ok=True)

    event_handler = SlothHandler()
    observer = Observer()
    observer.schedule(event_handler, WATCH_DIR, recursive=False)
    observer.start()

    # Run an initial scan on startup
    for file in os.listdir(WATCH_DIR):
        event_handler.process_file(os.path.join(WATCH_DIR, file))

    try:
        while True:
            time.sleep(3600) # Sleep for an hour, peak sloth behavior
    except KeyboardInterrupt:
        observer.stop()
    observer.join()
```

SlothSort is built entirely on open-source AI and local inference:

```
The Brain: Llama-3.1 (open-weight model) running completely locally via Ollama. I configured the prompt to force strict JSON outputs containing new_name and category keys.

The Harness: Python utilizing the watchdog library to monitor the file system for changes and track file age (os.stat().st_mtime).

The Workflow: When a file crosses the 24-hour threshold, the script sends the file context to the local Ollama API. Upon receiving the parsed JSON response, shutil safely moves and renames the file into the new structured directory tree, automatically handling any name collisions.
```

For a personal file-sorting tool, open innovation is non-negotiable due to privacy and cost.

A closed API approach would require me to upload my personal bank statements, medical PDFs, and private photos to a third-party server just to generate a file name. That is an unacceptable privacy risk for basic desktop utility. By utilizing an open-weight model via Ollama, my data physically never leaves my machine.

Additionally, running this locally means I set it up once and never pay a subscription fee or worry about API token limits. Whether I download 10 files or 10,000, open-source AI makes this background automation completely free, private, and capable of running without a Wi-Fi connection.

The payoff is zero-maintenance organization. I ran the initial startup script today and SlothSort processed over 200 neglected files from my Downloads folder. For the first time in years, my Downloads directory is completely empty, and everything is neatly filed into /Financials, /Project_Assets, and /Random_Junk. It saved me hours of manual renaming and dragging-and-dropping, allowing me to fully embrace the sloth lifestyle this week.

```
Open-Weight Champion

Best Local Automation
```


