Winnow your media library — organize photos and videos, detect duplicates, and keep the best copies.
Project description
Winnow
Winnow your media library — organize photos and videos, detect duplicates, and keep the best copies. Local-first, offline-capable, and designed as a greenfield rewrite of py-organizer.
Status
Pre-alpha. The published CLI is a skeleton: winnow, winnow --help, and
winnow --version are the only user-facing commands today. Domain models, exception
types, and CI are in place; scanning, deduplication, and organization workflows are
tracked in open issues (see
#2 for the parent epic).
Install
Requirements: Python 3.11+ and a package manager (uv recommended).
From PyPI
Use uv's project workflow so the dependency and command run from the same managed environment:
uv init winnow-demo
cd winnow-demo
uv add winnow-media
uv run winnow --version
Optional dependency groups (face, cv, ai-detect) are declared in pyproject.toml
but not wired to features yet.
From source
git clone https://github.com/lgtm-hq/winnow.git
cd winnow
make setup # uv sync --dev
uv run winnow --help
Usage
Only the commands below work in the current release. There are no media-processing subcommands yet.
uv run winnow # prints version and points to --help
uv run winnow --help # show available options
uv run winnow --version # print package version
Example output:
$ uv run winnow
winnow 0.2.0 — use --help for commands.
$ uv run winnow --version
winnow, version 0.2.0
Planned usage (not implemented)
Future releases will add subcommands for scanning libraries, grouping duplicates, and
applying organization rules. Shapes will follow the domain models in winnow/models/
and the API-first plan in ADR 0001. Do not expect
the examples below to work today:
# PLANNED — not available yet
uv run winnow scan /path/to/photos
uv run winnow duplicates review
uv run winnow organize --dry-run
Features
Available now
- Skeleton CLI — Click entry point with
--helpand--version - Domain models — Pydantic v2 models for media files, duplicates, pipeline steps,
and configuration (
winnow/models/) - Exception hierarchy — structured errors with context
(
winnow/exceptions.py) - Quality bar — lintro lint/format, 85% test coverage gate, multi-version CI
Roadmap
Winnow follows an API-first, CLI-first phasing plan:
| Phase | Focus | Highlights |
|---|---|---|
| Now | Foundation | Models, CLI skeleton, CI/CD, ADRs |
| Phase 1 | Core product | Scan, dedupe, and organize via CLI and API |
| Phase 2 | Web UI | Presentation-only frontend over OpenAPI |
Planned capabilities (not shipped):
- Scan local photo and video libraries with rich metadata extraction
- Detect duplicates via perceptual hashing and related signals
- Rank and keep the best copy; organize or quarantine the rest
- Local SQLite storage; no cloud dependency required
- OpenAPI schema as the stable integration surface for automation and UI
Track progress on the issue board and in the in-repo documentation.
Development
make setup # install dev dependencies (uv sync --dev)
make lint # uv run lintro chk
make fmt # uv run lintro fmt
make test # pytest with 85% coverage gate
make test-integration # opt-in integration tests
See CONTRIBUTING.md for commit conventions, signed commits, and PR expectations.
Documentation
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file winnow_media-0.5.0.tar.gz.
File metadata
- Download URL: winnow_media-0.5.0.tar.gz
- Upload date:
- Size: 347.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6bf41c527f01346a4ab4ca05c3b4acce02a6a6c6f7c33e82fa39d7d76644939
|
|
| MD5 |
8ca86ce3e288c8f3e90e6d152aaa1d27
|
|
| BLAKE2b-256 |
3c13057d2191d5cfa95f257707acf7a4badcf23cc38a63ba5629092a1c5b7bb1
|
Provenance
The following attestation bundles were made for winnow_media-0.5.0.tar.gz:
Publisher:
publish-pypi-on-tag.yml on lgtm-hq/winnow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
winnow_media-0.5.0.tar.gz -
Subject digest:
c6bf41c527f01346a4ab4ca05c3b4acce02a6a6c6f7c33e82fa39d7d76644939 - Sigstore transparency entry: 2194004163
- Sigstore integration time:
-
Permalink:
lgtm-hq/winnow@725b24823026835014b465f9ba65255ba00511d6 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/lgtm-hq
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi-on-tag.yml@725b24823026835014b465f9ba65255ba00511d6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file winnow_media-0.5.0-py3-none-any.whl.
File metadata
- Download URL: winnow_media-0.5.0-py3-none-any.whl
- Upload date:
- Size: 24.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b39d290c0283e60a52e18e8fffc22c4ef865c4ecc5c41ca8c27155456420d67
|
|
| MD5 |
a571563d9a753540a4cf9afd783a5f78
|
|
| BLAKE2b-256 |
83cbf9b10af78b13ea3250e26d90c139f326411a54329492498603d2c02b2153
|
Provenance
The following attestation bundles were made for winnow_media-0.5.0-py3-none-any.whl:
Publisher:
publish-pypi-on-tag.yml on lgtm-hq/winnow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
winnow_media-0.5.0-py3-none-any.whl -
Subject digest:
9b39d290c0283e60a52e18e8fffc22c4ef865c4ecc5c41ca8c27155456420d67 - Sigstore transparency entry: 2194004166
- Sigstore integration time:
-
Permalink:
lgtm-hq/winnow@725b24823026835014b465f9ba65255ba00511d6 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/lgtm-hq
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi-on-tag.yml@725b24823026835014b465f9ba65255ba00511d6 -
Trigger Event:
push
-
Statement type: