Photo Cull is a web app with a portable GUI launcher for quickly browsing folders of photos, assigning ratings, and downloading selected files.
It is designed for fast culling workflows: run locally, work on a browser, and rate images directly from your own filesystem.
Photo Cull provides these core features:
- Directory tree browsing for photo folders.
- Image grid with configurable columns.
- Full-page viewer for focused inspection.
- Star ratings (1 to 5) plus rating removal.
- Metadata display (date/time and EXIF summary when available).
- Sorting and grouping tools for faster review.
- Multi-selection and keyboard-first navigation.
- Download selected files (single file or ZIP archive).
- Start Photo Cull and choose the folder containing your photos.
- Browse folders in the sidebar.
- Select photos and assign ratings.
- Re-sort or group by name/date to review batches.
- Download selected keepers if needed.
In addition to using a mouse/touch on the interface, almost any function in the application can be controlled through keyboard shortcuts, allowing for a faster and more efficient workflow without leaving the keyboard.
Shortcuts are listed in the help box, which is shown pressing the ? key or clicking the "?" button in the top bar.
Photo Cull stores app data outside your original photo files:
.ratings.db: SQLite database of ratings..cache/: generated JPEG thumbnails.
By default, storage location depends on how you launch the app:
photo_cull.py: current working directory unless--data-diris set.photo_cull_portable.py: executable directory unless changed in startup dialog or with--data-dir.
Photo Cull can be run from source or you can download a self-contained, portable executable from the releases.
To run from source, follow this steps:
-
Clone this repository or download the zip archive.
-
Install dependencies
pip install -r requirements.txt
-
Run from Python script (direct server mode)
python photo_cull.py <photo_directory>
Example:
python photo_cull.py "D:/Pictures"Available options:
--data-dir <path>: where.ratings.dband.cacheare stored (default: current working directory).--host <host>: server host (default:127.0.0.1).--port <port>: server port (default:12121).
Example with options:
python photo_cull.py "D:/Pictures" --data-dir "D:/PhotoCullData" --host 127.0.0.1 --port 12121
Then open:
http://127.0.0.1:12121
-
Run portable launcher
python photo_cull_portable.py
What it does:
- Opens a startup dialog to choose photo directory and data directory.
- Starts a local CherryPy server.
- Opens your default browser automatically.
- Remembers last selected directories in
~/.photocull/state.json.
Optional arguments:
- positional
directory: initial photo directory. --data-dir <path>: data directory override.--host <host>: bind host (default:127.0.0.1).--port <port>: preferred port (default:12121, auto-falls back if busy).
Example:
python photo_cull_portable.py "D:/Pictures" --data-dir "D:/PhotoCullData" --port 13000
Use the build script for your platform:
Windows:
build_windows_exe.batOutput: dist\PhotoCull.exe
Linux:
bash build_linux.shOutput: dist/PhotoCull
macOS:
bash build_mac.shOutput: dist/PhotoCull.app
© 2026 Andrea Esuli



