Source of truth: docs/release.rst. If this skill and that file disagree, follow docs/release.rst and update this skill.
The argument is the canonical version to release: X.Y.Z, or X.Y.ZrcN / X.Y.ZbN / X.Y.ZaN with 1 <= N <= 15 (the serial occupies four bits in PYBIND11_VERSION_HEX). Other PEP 440 forms (epochs, post/dev or local versions, and alternate spellings) are outside this workflow, and a0 is reserved for the project's development state. If no argument is given, propose the next version from the current PYBIND11_VERSION_* macros and confirm with the user before you start. The tag will be v followed by that exact version, for example vX.Y.Zrc1.
Confirm the exact version and release base before editing. Pause again before pushing or opening the PR. Everything else can proceed autonomously.
upstream identify the official pybind/pybind11 repository, then run git fetch upstream --prune --tags.master when the release is intended to come from the current line on upstream/master.vX.Y when releasing a maintained line after master has moved on.vX.Y, or merge master into an older release line.chore/prepare-X.Y.Z from the explicit remote ref upstream/<base>; do not rely on a possibly stale local branch.gh auth status works, the account has the required repository release permissions, and nox (or uvx nox) is available.Edit include/pybind11/detail/common.h only — pybind11/_version.py parses it, so it needs no edit:
PYBIND11_VERSION_MAJOR / MINOR / MICRO: plain integers.PYBIND11_VERSION_PATCH is the same integer as MICRO, PYBIND11_VERSION_RELEASE_LEVEL is PY_RELEASE_LEVEL_FINAL, and PYBIND11_VERSION_RELEASE_SERIAL is 0.PYBIND11_VERSION_PATCH is ZrcN / ZbN / ZaN, the level is respectively PY_RELEASE_LEVEL_GAMMA / PY_RELEASE_LEVEL_BETA / PY_RELEASE_LEVEL_ALPHA, and the serial is exactly N in the range 1–15.Before validation, confirm pyproject.toml metadata is current for the selected release line (e.g. supported Python versions), and update it if needed; do not blindly copy metadata from a newer line. Then run nox -s tests_packaging.
nox -s make_changelog. It reads merged PRs labeled needs changelog.docs/changelog.md under the section for this version, and add the intended publication date to the section header. If the release is delayed, publication must confirm that date or update it in a new reviewed commit before tagging.Fixed, Added, Updated, Improved, Removed, etc.), converting imperative suggestions like “Fix ...” or “Add ...”. Prefer wording like “was updated to ...” when it preserves the meaning better than “now ...”; use “now” only when it is the clearest way to avoid ambiguity.New Features, Bug fixes, Internal, Documentation, Tests, CI, etc.). Put non-breaking production-code maintenance that is not user-facing under Internal.git add -u, commit (conventional commits, e.g. chore: prepare X.Y.Z release, with the Assisted-by: trailer).git push <working-remote> HEAD:refs/heads/chore/prepare-X.Y.Z and gh pr create --repo pybind/pybind11 --base <base> --head <owner>:chore/prepare-X.Y.Z). Never force-push an official release ref.--head.When the PR is approved and merged, invoke the publish-release skill for the branch, tag, stable update, GitHub release, and any post-release work. Pass it the exact version and preparation PR URL or number; also retain the selected base and included changelog PR list.