Hybrid file organizer for Windows. A C# / .NET 8 / WinUI 3 desktop shell drives a Python core that handles AI classification (DeepSeek, GitHub Models, Ollama), six cleanup scanners, progressive hash + perceptual dedup, and EXIF-aware photo workflows.
src/FileOrganizer.UI/ β C# / WinUI 3 desktop shell (new β v0.2.0)
fileorganizer/ β Python core (legacy PyQt6 GUI + library code)
*.py at repo root β CLI runners + NDJSON sidecars (organize_run, cleanup_run, asset_db, ...)
The shell exists to replace the legacy PyQt6 GUI with a UCX-style
side-tab NavigationView and tile dashboard, while keeping every line of
the AI / dedup / photo logic in Python where the ecosystem lives. The
two halves talk over stdout (text or NDJSON). The legacy PyQt6 GUI
keeps working in parallel until the shell reaches feature parity.
| Page in shell | Status (v0.2.0) | Wraps |
|---|---|---|
| Home | Live | β |
| Organize | Live | organize_run.py |
| Cleanup | Live | cleanup_run.py |
| Files / Duplicates / Photos / Watch / Toolbox | Placeholder | TBD |
Two install paths, pick the one that fits.
Grab the latest release zip from
Releases (look
for ui-v* tags) and extract it anywhere.
shell\FileOrganizer.exe β double-click to launch
organize_run.py Β· cleanup_run.py Β· fileorganizer\ Β· requirements.txt
The shell is self-contained for .NET 8, but the live pages still call
into Python β install Python 3.10+ on PATH (or drop a
.venv\Scripts\python.exe next to the scripts at the extract root, or
set %FILEORGANIZER_PYTHON%), then once:
python -m pip install -r requirements.txtgit clone https://github.com/SysAdminDoc/FileOrganizer.git
cd FileOrganizer
python run.py # auto-installs deps + Ollama, opens the PyQt6 GUIOn first launch this path will:
- Install PyQt6, rapidfuzz, psd-tools, and other dependencies if missing.
- Download and install Ollama if not found.
- Pull the
qwen2.5:7bmodel if not already downloaded.
pwsh src/build.ps1 # Debug build
pwsh src/build.ps1 -Configuration Release # Release buildThe script wraps VS 2026 MSBuild because bare dotnet build against
the .NET 10 SDK fails on the WindowsAppSDK 1.5 AppX/PRI task path. It
also cleans obj/ + bin/ first and runs Restore and Build as
separate invocations to avoid a known MarkupCompilePass2 cascade.
Output: src/FileOrganizer.UI/bin/x64/Debug/net8.0-windows10.0.19041.0/FileOrganizer.exe.
Sort thousands of marketplace downloads (Envato, Creative Market, Freepik) into a clean category tree. The LLM reads folder + filenames, strips marketplace junk, and picks from 384+ built-in categories.
Before:
Downloads/
βββ GraphicRiver - Neon Night Club Party Flyer Template 28394756/
βββ CM_elegant-wedding-invitation-set_4829173/
βββ christmas-slideshow-after-effects-21098345/
βββ ... 2,000 more like this
After:
Organized/
βββ After Effects - Slideshows/
β βββ Christmas Slideshow/
βββ Print - Flyers & Posters/
β βββ Neon Night Club Party Flyer/
βββ Print - Invitations & Events/
β βββ Elegant Wedding Invitation Set/
βββ ...
Drive it from the Organize page in the shell, or directly from the CLI runner β see CLI Batch Runner below.
Six progressive scanners, all wired into the Cleanup page in the shell
(or callable as python cleanup_run.py --scanner <name> --root <path>):
| Scanner | What it finds |
|---|---|
| Empty folders | Recursively-empty directory trees, deepest-first |
| Empty files | Zero-byte files |
| Temp / junk | .tmp, .bak, Thumbs.db, ~$*, .DS_Store, partial downloads |
| Broken / corrupt | Magic-byte mismatches + optional ZIP/TAR integrity check |
| Big files | Files above a configurable MB threshold |
| Old downloads | Files not accessed in N days at the top of a folder |
Results stream live as items are discovered. Cancellation kills the child Python process tree.
- Progressive hash dedup β Size > prefix hash > suffix hash > full SHA-256, plus perceptual image hashing for near-duplicate photos.
- Photos β EXIF metadata, Leaflet geotag map, AI event clustering, optional face detection, thumbnail grid.
- Watch mode β monitor folders, auto-organize new files, system tray.
These all work today through python -m fileorganizer (Path B). Shell
pages will land in subsequent ui-v0.X.Y releases.
# AE pipeline (I:\After Effects β G:\Organized)
python organize_run.py --stats # Show all classified batches
python organize_run.py --preview --quiet # Dry run
python organize_run.py --apply --quiet # Apply all moves
python organize_run.py --retry-errors # Retry failed items
# Design pipeline (G:\Design Unorganized β G:\Organized)
python organize_run.py --source design --preview --quiet
python organize_run.py --source design --apply --quiet
# Plan-first apply
python organize_run.py --source design --preview --plan-out plan.json
python organize_run.py --apply-plan plan.json
python organize_run.py --report <RUN_ID> --output report.md
# Undo
python organize_run.py --undo-last 10
python organize_run.py --undo-all
# Validate sources
python organize_run.py --validatepython asset_db.py --build G:\Organized # Hash every file β SQLite DB
python asset_db.py --stats # DB summary
python asset_db.py --export # asset_fingerprints.json
python asset_db.py --lookup "path/to/folder" # Look up a folderMatch locally-downloaded templates against a community-curated catalog of already-classified assets by SHA-256 β get clean names and categories instantly without an AI API call.
| Provider | Use | Model |
|---|---|---|
| DeepSeek | Heavy classification batches | deepseek-chat |
| GitHub Models | Fast lightweight checks | claude-3-5-haiku |
| Ollama | Local / offline fallback | Any local model |
Set DEEPSEEK_API_KEY to enable DeepSeek routing.
| Model | Size | Speed | Accuracy | Install |
|---|---|---|---|---|
qwen2.5:7b |
4.7 GB | Medium | Best | ollama pull qwen2.5:7b |
llama3.2:3b |
2.0 GB | Fastest | Good | ollama pull llama3.2:3b |
gemma3:4b |
3.3 GB | Fast | Good | ollama pull gemma3:4b |
Six dark themes with live preview: Steam Dark (default), Catppuccin Mocha, OLED Black, GitHub Dark, Nord, Dracula. The WinUI 3 shell uses the Steam Dark palette with a cyan accent and currently does not expose a theme picker.
src/FileOrganizer.UI/
βββ App.xaml(.cs) β brand tokens, DI, crash handler
βββ Views/
β βββ MainWindow.xaml(.cs) β side-tab NavigationView shell
β βββ Pages/
β βββ HomePage β hero + tile grid + cluster cards
β βββ OrganizePage β live, runs organize_run.py
β βββ CleanupPage β live, runs cleanup_run.py over NDJSON
β βββ PlaceholderPage β parameterized stub for unwired routes
βββ Services/
β βββ PythonRunner.cs β text + NDJSON Python invocation
β βββ SidecarRunner.cs β NDJSON for future tools/<name>/<name>.exe
βββ FileOrganizer.UI.csproj
fileorganizer/
βββ classifier.py β 7-level classification engine
βββ categories.py β 384+ canonical category definitions
βββ providers.py β multi-provider AI router (DeepSeek + GH + Ollama)
βββ catalog.py β marketplace lookup + fingerprint DB pre-check
βββ cleanup.py β six cleanup scanners
βββ duplicates.py β progressive hash + perceptual image hash
βββ photos.py β EXIF / faces / events / map markers
βββ files.py β PC file organizer
βββ workers.py β QThread workers (legacy GUI)
βββ main_window.py β legacy PyQt6 main window
βββ ...
repo root:
βββ organize_run.py β CLI batch runner (text-stdout sidecar)
βββ cleanup_run.py β NDJSON sidecar for the Cleanup page
βββ asset_db.py β community SHA-256 fingerprint DB
βββ classify_design.py β DeepSeek batch classifier for design assets
βββ deepseek_research.py β _Review-folder ID resolver
Should I install Path A (shell) or Path B (Python)? β If you want the
new UI and you're on Windows, Path A. If you're on Linux/macOS, or you
need the photo / duplicates / watch features today, Path B. Both share
the same fileorganizer/ package so you can switch later.
Ollama won't install automatically β Download from ollama.com/download, then restart.
Classification is slow β Use DeepSeek for bulk batches (60 items/call, ~1β2s). Ollama is per-item; use it only for small jobs.
Why position-based batch mapping? β AI agents may clean or reformat
folder names in their response. The only reliable mapping is by position:
batch_NNN.json[i] always corresponds to org_index[(N-1)*60 + i]
regardless of name changes.
Why two release tag schemes (v8.x vs ui-v0.x)? β The Python core
and the WinUI 3 shell version independently. Python uses vX.Y.Z, the
shell uses ui-vX.Y.Z, and they release on their own cadences.
| Tool | Best for |
|---|---|
| FileOrganizer (this repo) | Focused file organization β AI classification, cleanup, dedup, photo |
| UniFile | Everything here plus tag-based library, TMDb/TVMaze lookup, LLaVA vision |
Issues and PRs welcome. The codebase is modular β categories in
fileorganizer/categories.py, classification in
fileorganizer/catalog.py, legacy GUI in fileorganizer/main_window.py,
shell in src/FileOrganizer.UI/.
MIT β see LICENSE.
