Python Commitizen
Purpose
Guide agents through using the Python commitizen package as the owner for conventional commits, semantic version bumps, changelog generation, release tags, and version-file updates.
When to use this skill
- Adding or reviewing
[tool.commitizen]inpyproject.toml. - Choosing a Commitizen
version_providerfor a Python, uv, mixed Python/Node, or tag-derived release workflow. - Designing
cz bump,cz changelog,cz check, or project wrapper commands. - Debugging version drift, missing release tags, changelog ranges, or conventional-commit parsing.
- Deciding whether Commitizen should replace custom version or changelog scripts.
- Deciding whether a mixed Python/Node repo should keep Commitizen or move to an explicit release-intent workflow such as Changesets.
Scope Boundaries
- Use
ref-sp-dev-package-managementfor general package metadata, changelog ownership, and multi-manifest release policy. - Use
ref-sp-dev-semantic-versioningfor bump meaning, prerelease stability, and dependency-range decisions. - Use
ref-sp-dev-git-commitsfor commit grouping, commit bodies, and day-to-day commit message quality. - Use this skill for Commitizen-specific commands, configuration, and failure modes.
Default Position
Prefer Commitizen when a repo already wants conventional commits and generated changelogs. Let it own the normal release-prep step instead of maintaining separate custom version writers, unless the repo needs behavior Commitizen cannot express.
For Python projects using uv, prefer version_provider = "uv" so Commitizen updates both project.version in pyproject.toml and the matching package version in uv.lock. Use version_files for additional secondary files such as package.json:version or VERSION.
For mixed Python/Node repositories, Commitizen can remain the release owner when one stable bump, one changelog, and one tag describe the whole project. Consider Changesets or another explicit-intent tool only when per-change release summaries, monorepo package-level bumps, or commit-history-independent release notes solve a real workflow problem.
Core Configuration
Keep Commitizen configuration in pyproject.toml for Python projects unless the repo already has a deliberate standalone Commitizen config file.
[dependency-groups]
dev = [
"commitizen>=4.16.0",
]
[tool.commitizen]
name = "cz_conventional_commits"
version_provider = "uv"
version_scheme = "semver2"
version_files = ["package.json:version", "VERSION"]
changelog_file = "CHANGELOG.md"
major_version_zero = true
bump_message = "chore(release): $current_version -> $new_version"
tag_format = "v$version"
Adjust the example to the repo. A pure Python uv package may not need package.json:version or VERSION. A Python-only package that does not need npm-compatible semver prerelease syntax can use the default PEP 440 scheme instead of semver2.
Version Provider Selection
| Provider | Use when | Notes |
|---|---|---|
uv |
Python project uses uv and commits uv.lock |
Updates pyproject.toml and uv.lock; preferred for uv projects. |
pep621 |
Modern Python project uses project.version without uv lock syncing |
Updates pyproject.toml only. |
poetry |
Older Poetry-oriented project needs tool.poetry.version |
Prefer pep621 for Poetry 2+ unless Poetry-specific behavior is required. |
npm |
Node package owns the version | Updates npm manifests; useful outside Python-first repos. |
scm |
Version comes from Git tags via setuptools-scm or similar | Read-only for files; cz bump creates tags but does not update version files. |
commitizen |
The Commitizen config itself should store the version | Flexible, but can create a second version source if the package manager also has a version field. |
version_files can be combined with any provider to update extra version-bearing files during a bump.
Command Patterns
Wrap Commitizen commands in the repo's task runner when possible so contributors use one stable interface.
| Command | What it does | When to use |
|---|---|---|
cz commit |
Opens the interactive conventional-commit prompt. | When creating commits manually and the repo wants guided commit messages. |
cz check --message "..." |
Validates one commit message. | In hooks, CI checks, or review tooling. |
cz bump --get-next --yes |
Prints the next version without editing files. | In release previews, dashboards, or CI metadata. |
cz bump --dry-run --check-consistency --increment PATCH --yes |
Shows the bump, tag, and changelog changes without writing. | Before choosing or confirming a release bump. |
cz bump --check-consistency --increment PATCH --changelog --yes |
Updates versions, changelog, commit, and tag. | Normal stable release preparation. |
cz changelog --dry-run <version> |
Shows changelog output for a version or range. | When checking changelog parsing before release. |
cz version -p |
Prints the project version from Commitizen's configured provider. | In scripts and CI tag checks. |
Use --yes for non-interactive automation. Use --check-consistency before real bumps when version_files are configured so drift is caught early.
Release Workflow Pattern
For a Commitizen-led stable release flow:
- Validate the repo first: tests, lint, type-check, and any version drift check.
- Preview the bump with
cz bump --dry-run --check-consistency --increment <major|minor|patch> --yes. - Run the real prep command with
cz bump --check-consistency --increment <major|minor|patch> --changelog --yes. - Review the version-file changes,
CHANGELOG.md, release commit, and tag. - Push the release commit and tag.
- Let tag-triggered CI publish packages when trusted publishing is configured.
Use project tasks such as release-prepare-preview, release-prepare, and release-publish when the repo defines them. Prefer pushing a tag to CI over publishing from a developer machine when the registry supports trusted publishing.
Commitizen should prepare the release; registry authentication should normally belong to the release workflow. For PyPI and npm, prefer trusted publishers with OIDC over stored publish tokens, and keep id-token: write scoped to the CI jobs that publish.
Changelog Guidance
Commitizen changelogs depend on parseable commit history and matching release tags.
- Use conventional commits that make sense as release notes.
- Keep
changelog_file = "CHANGELOG.md"unless the repo has a strong reason to use another Markdown file. - Use
cz bump --changelogorupdate_changelog_on_bump = trueso the changelog and version bump happen together. - Use
cz changelog --dry-runto inspect generated entries before trusting a new config. - For existing projects adopting Commitizen, define the initial tag or
changelog_start_revintentionally so old non-conforming commits do not pollute generation.
Gotchas
- Commitizen needs a sensible baseline tag to generate release ranges. If a project starts at
0.1.0, create or preserve the matching baseline tag before relying on future generated changelogs. version_provider = "scm"reads from Git and does not update files; do not pair it with expectations thatpyproject.toml, lockfiles, or package manifests will be rewritten.--get-nextcan fail when no eligible commits are found. Use an explicit--incrementor--allow-no-commitwhen a deliberate bump is needed without eligible commits.--allow-no-commitcan still create a changelog entry when changelog generation is enabled. Use it deliberately, not as a default escape hatch.major_version_zero = truekeeps breaking changes in the0.xdevelopment line from bumping to1.0.0; remove it deliberately when the project is ready for stable major version semantics.--check-consistencycatches drift, but if a bump command partially changed files before failing, inspect and restore only those attempted bump changes before retrying. Do not use broad destructive git commands.- Commitizen-generated changelogs are only as good as the commit history. If the team routinely needs richer per-change release notes before merge, that is a reason to evaluate an explicit-intent workflow rather than adding fragile commit-message rules.
Validation
cz version -preturns the same version users see in the package metadata.cz bump --dry-run --check-consistency --increment <part> --yespreviews the expected next version and tag.- Every file in
version_filescontains the current version before a real bump. - The generated changelog uses the intended tag format and commit range.
- Release docs or task names make clear whether Commitizen prepares the release, publishes it, or both.
- Publishing workflows use trusted publishing or document why stored registry tokens remain necessary.
References
- Commitizen docs:
https://commitizen-tools.github.io/commitizen/ - Bump command:
https://commitizen-tools.github.io/commitizen/commands/bump/ - Changelog command:
https://commitizen-tools.github.io/commitizen/commands/changelog/ - Configuration file:
https://commitizen-tools.github.io/commitizen/config/configuration_file/ - Version providers:
https://commitizen-tools.github.io/commitizen/config/version_provider/ - Commit message guidance:
https://commitizen-tools.github.io/commitizen/tutorials/writing_commits/