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.

Supported by

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