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 requires Python >=3.12, matching the floor the fleet standard sets for every repo it checks.

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.

Authority and assessment scope

py-canon STANDARD.md defines fleet requirements. Preen implements checks and adoption for that standard; its version identifies the implementation, not a new standard revision. The bundled skill guides use of the CLI and does not duplicate its checks or establish conformance by itself. Appellation separately governs name-analysis results and empirical evidence.

A check run reports the checks executed and explicit exclusions. --only is a partial assessment. Excluding every check exits with an error, and a successful subset reports only that the executed checks passed. Individual checks may also report unavailable subchecks; retain those notices in evidence. Record the consumer commit, preen version, resolved canon/template revision, configuration, and command alongside the output. A waiver or skip does not prove the underlying requirement is satisfied.

Check implementations live in src/preen/checks; behavioral tests live in tests/test_*_check.py and tests/test_cli.py. Adoption/update fixtures test managed files and preservation of project-owned content. Changes to a fleet rule must coordinate the py-canon requirement and template with the preen implementation and regression tests. Synchronization tests detect copied policy drift; if their remote source cannot be checked, report that test as unverified rather than treating its skip as proof of synchronization.

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. The metadata check accepts newer minimums within that series, including Dependabot patch updates. 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), dropped-args (a parameter a caller accepts but never forwards), duplicate-code (12+ lines of package code copied across modules), 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), pytest-config (pytest settings the standard requires), examples (documented examples still name symbols the package defines), python-floor (requires-python meets the floor the standard declares; off until the fleet migration lands), 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 (typos and British spellings; the standard is US English).

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)
examples_at_root = true  # expect examples/ at the repo root (default: true)
skip_checks = ["links"]  # checks to skip by default
run_doctests = false     # execute `>>>` examples too (default: false)
enforce_python_floor = false  # gate on the standard's Python floor

# URLs the `links` check should not fetch. Some endpoints are real but do not
# answer a bare GET, such as an API base that needs a path. Skipping the whole
# `links` check to silence one of those would stop the README being checked,
# which is where a broken link actually costs a reader something.
link_ignore = ["https://api.example.com/*"]

# Advisory ids `audit` should report but not fail on, for the case where no
# fixed release exists yet. Still shown as info so the exception stays visible.
audit_ignore = ["GHSA-8mgp-746c-j5xp"]

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.
  • duplicate-code runs pylint's similarity checker (R0801), the one pylint rule kept: ruff has no duplicate detector. Mark a deliberate copy with # pylint: disable=duplicate-code.

License

MIT

Metadata

Release files for preen 0.7.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for preen 0.7.2
File Size Uploaded Provenance
preen-0.7.2.tar.gz 116.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for preen 0.7.2
File Interpreter ABI Platform
preen-0.7.2-py3-none-any.whl Python 3 none any Details

Total release size: 256.0 kB

Release files / preen-0.7.2.tar.gz

Download URL preen-0.7.2.tar.gz
Size 116.5 kB
Tags Source
SHA-256 checksum
How to use checksums
4e44988bb30c30ff25ad55cde0e51e570938dd6eb85f19be4021c7873233c54e
BLAKE2b-256 checksum
How to use checksums
5d014c4e01305d35ca6f8bb8c9ceb2ed2970d1728892b04b005068540188c35f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / preen-0.7.2-py3-none-any.whl

Download URL preen-0.7.2-py3-none-any.whl
Size 139.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
182c87543eef85cabb27d880b59becdb3ba1b29d673a43cc1a972d6ee2f03b24
BLAKE2b-256 checksum
How to use checksums
a268adac0b93be6f8b6183b981285e3ecfb57a5d1352965b7c36791eacaede79
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Security for preen 0.7.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for preen-0.7.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page