Skip to main content

preen

PyPI version Downloads CI Documentation License: MIT

Preen is the conformance-and-adoption CLI for the py-canon fleet standard. py-canon defines the standard — a copier template, reusable GitHub workflows, and shared Sphinx configuration. Preen is how repos enter the fleet and stay in it: it scaffolds new packages, retrofits existing ones, pulls template updates, checks conformance, and cuts tag-driven releases.

preen itself requires Python >=3.12, stricter than the >=3.11 floor of the fleet standard it enforces on other repos — the tool can hold itself to a higher bar than the standard it applies.

Install

uv tool install preen   # or: pipx install preen

Use with Claude Code

/plugin marketplace add gojiplus/preen
/plugin install preen@gojiplus

The bundled skill teaches Claude Code to reach for the preen CLI — scaffolding, adoption, checks, and releases — instead of reimplementing its logic.

Commands

Command What it does
preen new NAME Scaffold a new package from the py-canon copier template
preen adopt [PATH] Retrofit an existing repo: mine answers from the repo, copy in the managed files, rewrite [tool.*] in pyproject.toml
preen update [PATH] Pull the latest template changes into an adopted repo (copier update)
preen check [PATH] Run conformance checks (detection only); --strict for CI
preen fix [CHECK] Apply fixes for issues the checks found
preen release [X.Y.Z] Guided release: run checks, confirm, git tag vX.Y.Z, push — the tag triggers the release workflow

Adopting an existing repo

cd my-package
preen adopt
# review the ADOPTION REPORT, then:
uv lock && uv sync --all-groups
preen check

preen adopt mines the copier answers from the repo itself (name, description, and authors from pyproject.toml; org from the git remote), renders the template into a temp directory, and copies in only the managed files: the CI/docs/release workflow shims, .pre-commit-config.yaml and dependabot config (if absent), docs/conf.py (old one backed up), .copier-answers.yml, py.typed, plus LICENSE and CITATION.cff if missing. It rewrites the [tool.ruff] (preserving any repo-specific lint ignores already present, and setting target-version from the repo's own requires-python floor, falling back to py311), [tool.pyright], and [tool.pydoclint] sections to the standard with tomlkit (comments elsewhere survive) and deletes legacy [tool.black], [tool.isort], [tool.flake8], and [tool.mypy] sections.

Pass --release-migration to also convert the build backend to the fleet's current uv_build series. The minimum is the latest tested release and the upper bound prevents an unreviewed backend-series upgrade. An existing project.version is preserved; a legacy dynamic-version project takes its current version from its latest v* tag.

Checks

preen check runs: template (copier adoption + drift against the latest py-canon tag), workflows (the four canon workflows are callers of the reusable workflows, not stale copies), ruff, tests, citation, changelog (Keep a Changelog structure), deps (deptry), deptree (circular imports), depgroups (PEP 735 dependency-groups usage), audit (pip-audit over the locked dependencies), ci-matrix (canon shim, or a matrix covering the requires-python floor), structure, runtime-assets (schema-bearing data formats, pinned Hugging Face revisions), files (README and .gitignore exist), precommit (.pre-commit-config.yaml exists and parses), version (hardcoded version strings), license (PEP 639 license metadata), links, metadata (build backend, requires-python upper bound, PEP 561 py.typed), pydoclint, pyright, and codespell.

Issues carry an impact level: critical blocks release, important can be overridden with informed consent, info is advisory. preen release walks that ladder interactively before tagging. Most checks are detection-only; preen fix license migrates the deprecated { text = ... } license table form to an SPDX string where the mapping is unambiguous, drops redundant License :: classifiers, and adds a missing license-files entry.

Releasing

The fleet standard keeps one explicit version in pyproject.toml, set with uv version X.Y.Z; the matching vX.Y.Z tag identifies the release. preen release runs the checks, then refuses to proceed unless the version is committed in pyproject.toml, is PEP 440-valid, the tag doesn't already exist, and CHANGELOG.md has an entry for it (offering to rename [Unreleased] to the new version and commit that rename if the Unreleased section has content). It then asks for confirmation, tags vX.Y.Z, and pushes the tag; the repo's release workflow does the rest (build, PEP 740 attestations, PyPI trusted publishing, GitHub Release). Use --dry-run to see the plan without acting.

Configuration

Preen reads an optional [tool.preen] section in pyproject.toml:

[tool.preen]
src_layout = true       # expect src/ layout (default: true)
tests_at_root = true    # expect tests/ at the repo root (default: true)
skip_checks = ["links"] # checks to skip by default

Notes

  • pydoclint covers docstring-signature consistency for now; ruff ships equivalent DOC rules ([tool.ruff.lint] external = ["DOC"] reserves the codes), but they're still preview-only, so pydoclint stays until ruff stabilizes them.
  • codespell stays: ruff has no spelling-check rules.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

preen-0.4.1.tar.gz (65.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

preen-0.4.1-py3-none-any.whl (87.7 kB view details)

Uploaded Python 3

File details

Details for the file preen-0.4.1.tar.gz.

File metadata

  • Download URL: preen-0.4.1.tar.gz
  • Upload date:
  • Size: 65.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for preen-0.4.1.tar.gz
Algorithm Hash digest
SHA256 2dcda2461d06d42eaafe1e0dc2450f8ff89e77879162ba9adf222a53d407bee0
MD5 a42458ed7cc319150d3e354f2161eb9c
BLAKE2b-256 740309820516d8991ff6d3f42e6b3844ab13357f99a0832adf0f2dedaee492dc

See more details on using hashes here.

Provenance

The following attestation bundles were made for preen-0.4.1.tar.gz:

Publisher: release.yml on gojiplus/preen

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file preen-0.4.1-py3-none-any.whl.

File metadata

  • Download URL: preen-0.4.1-py3-none-any.whl
  • Upload date:
  • Size: 87.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for preen-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 69a8f1ed40357c6ec47354140a97080638b4e5c98ad8799f1c12094f6e8764bb
MD5 f3d30b1758b29e150a6b215c3a0bb9e4
BLAKE2b-256 f714e25c9b630d69a8efdd635c9d8d4f9af216cfb5aeb44867066da8f079415e

See more details on using hashes here.

Provenance

The following attestation bundles were made for preen-0.4.1-py3-none-any.whl:

Publisher: release.yml on gojiplus/preen

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.4.1 This release

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page