Real-time file monitoring that watches your Downloads folder and sorts files by type — automatically.
Grouper is a background daemon that monitors your Downloads folder (or any folder) and automatically moves files into categorized subfolders based on their file type. No more cluttered Downloads folder.
Unlike one-shot scripts, Grouper runs continuously using OS-native file system APIs, handles partial downloads gracefully, supports undo, sends desktop notifications, and can live in your system tray.
- Real-time monitoring — Uses OS-native file system APIs via
watchdog(no polling) - 13 built-in categories — Images, Videos, Music, Documents, Archives, Code, Data, Executables, Fonts, Design, eBooks, Torrents, DiskImages
- Smart duplicate handling — Rename (
photo (1).jpg), skip, or overwrite - Undo system — Reverse any file move with
grouper undo - Desktop notifications — Know when files are organized
- System tray — Runs silently with right-click menu (pause, resume, undo, quit)
- One-time scan — Organize existing files with
grouper scan - Stability checks — Waits for downloads to complete before moving
- YAML configuration — Fully customizable rules, paths, and behavior
- Move history — Track everything with
grouper history - Cross-platform — Windows, macOS, Linux
- Windows: No extra dependencies.
- Linux (Ubuntu/Debian): To support the system tray icon, you must install the following:
sudo apt update sudo apt install libayatana-appindicator3-1
# Clone the repository
git clone https://github.com/MagCha/Grouper.git
cd Grouper
# Create virtual environment
python -m venv venv
# Activate it
# Windows:
.\venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate
# Install dependencies
pip install -r requirements.txtTo have Grouper start automatically when you log in, follow these steps:
- Press
Win + R, typeshell:startup, and press Enter. - Create a new Shortcut in that folder.
- For the Target, use:
"C:\path\to\Grouper\venv\Scripts\pythonw.exe" -m grouper start --tray - For Start in, use:
C:\path\to\Grouper(Note: Usingpythonw.exeensures the app runs silently without a terminal window).
- Create a file at
~/.config/autostart/grouper.desktop. - Paste the following content (adjust paths to your project):
[Desktop Entry] Type=Application Name=Grouper Comment=Automated File Organizer Exec=/home/user/Grouper/venv/bin/python -m grouper start --tray Path=/home/user/Grouper Terminal=false Categories=Utility;
- Save and make it executable:
chmod +x ~/.config/autostart/grouper.desktop
# Start real-time monitoring
python -m grouper start
# Start with system tray icon
python -m grouper start --tray
# One-time scan of existing files
python -m grouper scan ~/Downloads
# Undo the last move
python -m grouper undo
# Undo the last 5 moves
python -m grouper undo -n 5
# View move history
python -m grouper history
# Check status and stats
python -m grouper status
# Validate your config
python -m grouper config --validate +========================================+
| GROUPER |
| Automated File Organizer |
+========================================+
Watching: C:\Users\you\Downloads
Destination: C:\Users\you\Sorted
Categories: 13
Duplicates: rename
Log file: C:\Users\you\.grouper\grouper.log
[*] Watching: C:\Users\you\Downloads
[*] Grouper is running. Press Ctrl+C to stop.
[OK] Moved: photo.jpg -> Images/photo.jpg (2.4 MB)
[OK] Moved: report.pdf -> Documents/report.pdf (156.0 KB)
[OK] Moved: song.mp3 -> Music/song.mp3 (4.8 MB)
Edit config.yaml to customize Grouper:
grouper:
watch_folders:
- "~/Downloads"
destination_base: "~/Sorted"
duplicate_strategy: "rename" # rename | skip | overwrite
stability_delay: 3 # seconds to wait for downloads
ignore_patterns:
- "*.crdownload"
- "*.part"
- "*.tmp"
notifications: true
system_tray: true
logging:
level: "INFO"
file: "~/.grouper/grouper.log"
# Add custom rules
custom_rules:
"Blender":
extensions: [".blend", ".blend1"]| Category | Extensions |
|---|---|
| Images | jpg, jpeg, png, gif, bmp, svg, webp, ico, tiff, heic... |
| Videos | mp4, mkv, avi, mov, wmv, flv, webm, m4v... |
| Music | mp3, wav, flac, aac, ogg, wma, m4a, opus... |
| Documents | pdf, doc, docx, txt, rtf, pptx, xlsx, csv, md... |
| Archives | zip, rar, 7z, tar, gz, bz2, xz, iso... |
| Code | py, js, ts, html, css, java, cpp, go, rs, rb... |
| Data | json, xml, yaml, toml, ini, cfg, env... |
| Executables | exe, msi, dmg, deb, rpm, apk... |
| Fonts | ttf, otf, woff, woff2 |
| Design | psd, ai, fig, sketch, blend, stl, obj, fbx... |
| eBooks | epub, mobi, azw, azw3, djvu |
| Torrents | torrent |
| DiskImages | img, vhd, vmdk, ova |
Downloads Folder
|
v
[Watchdog Observer] ---> [Event Queue] ---> [Worker Thread]
|
[Stability Check]
|
[Rule Engine]
|
[Organizer] ---> Destination Folder
|
[History Manager] (JSON)
|
[Desktop Notification]
Key design decisions:
- Queue + worker thread — Observer never blocks on I/O
- Stability check — Waits for file size to stabilize before moving
- Debouncing — Collapses rapid duplicate events
- JSON history — Enables undo with full move tracking
Grouper/
├── grouper/
│ ├── core/ # Watcher, organizer, rules, history
│ ├── config/ # YAML loader, defaults, validation
│ ├── ui/ # System tray, notifications
│ ├── cli/ # Click-based CLI commands
│ └── utils/ # Logging, path helpers
├── tests/ # pytest test suite (30 tests)
├── config.yaml # User configuration
├── pyproject.toml # Modern Python packaging
└── requirements.txt
# Run all tests
python -m pytest tests/ -v
# With coverage
python -m pytest tests/ -v --cov=grouper- Python 3.10+
- watchdog — OS-native file system monitoring
- PyYAML — Configuration
- click — CLI framework
- plyer — Desktop notifications
- pystray + Pillow — System tray
- pytest — Testing
MIT License. See LICENSE for details.