| name | create-release-pr |
| description | Create a version-bump release PR for the Python SDK based on latest remote main, with a semver suggestion derived from changes since the last release. |
| argument-hint | [VERSION] [--no-pr] |
| disable-model-invocation | true |
| allowed-tools | Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion |
Create a Release PR (Python SDK)
This skill creates a version-bump PR for twilio-agent-connect (the Python SDK).
It branches off the latest remote main, bumps the version in pyproject.toml,
runs uv sync to update uv.lock, and opens a PR.
The version follows semantic versioning. The skill inspects
commits since the last release tag, suggests a bump, and asks the user to confirm
or override it.
What gets changed
A version bump touches exactly two files (the in-code __version__ is dynamic via
importlib.metadata, so it does not need editing):
pyproject.toml — [project].version
uv.lock — the twilio-agent-connect package entry (regenerated by uv sync)
Arguments
$ARGUMENTS (the full argument string):
- Explicit version (optional): a semver string like
1.1.0. If present, skip the
suggestion logic and use this version (still confirm with the user).
--no-pr (optional): commit and push the change on a branch, but don't open the PR —
leave it ready for the user to open manually.
Workflow
Phase 0: Preflight
Verify gh is installed and authenticated against this repo, and that uv is available:
gh repo view twilio/twilio-agent-connect-python --json name --jq '.name'
uv --version
If gh fails for any reason (not installed, not authenticated, no access, network), STOP
and tell the user to run gh auth status / gh auth login. If uv is missing, STOP and
tell the user this skill requires uv (see the repo's make sync).
Phase 1: Sync to latest remote main and check the working tree
The release branch must be based on the latest remote main. Do not rebase or reset the
user's current branch — the branch is cut fresh from origin/main in Phase 3.
cd "$(git rev-parse --show-toplevel)"
git fetch origin
git status --porcelain
If git status --porcelain is non-empty (uncommitted changes exist), warn the user — the
release branch is cut from origin/main, so their uncommitted work won't be included but will
remain on their current branch. Use AskUserQuestion ("Continue?" / "Abort"); on abort, STOP
and confirm nothing was changed.
Exception: if any uncommitted change touches pyproject.toml or uv.lock, STOP
regardless and ask the user to commit or stash those two files first — the skill needs a
clean base for them.
Phase 2: Determine current version and changes since last release
grep -E '^version = ' pyproject.toml | head -1
git tag --sort=-creatordate | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1
git log --oneline <LAST_TAG>..origin/main
git diff --stat <LAST_TAG>..origin/main
git diff <LAST_TAG>..origin/main -- src/
Phase 3: Suggest a semver bump and confirm
Decide the bump from what the code actually changed, not from commit-message prefixes
(this repo doesn't enforce Conventional Commits, so subjects are an unreliable signal). Read
the diff from Phase 2 — focusing on the public API surface under src/tac/ (exported classes,
functions, model fields, function signatures, defaults) — and pick the level by semver intent:
- MAJOR (
X+1.0.0): a backward-incompatible change to the public API — removed/renamed
exports, changed signatures or required params, removed/renamed model fields, changed
defaults or behavior existing callers depend on.
- MINOR (
X.Y+1.0): backward-compatible new capability — new exported API, new optional
params/fields, new channels/adapters/tools.
- PATCH (
X.Y.Z+1): no public-API surface change — bug fixes, internal refactors, docs,
examples, tests, CI/build only.
Commit subjects are a useful hint to skim first, but when a subject and the diff disagree,
trust the diff. If the diff is large, read the parts touching exported symbols rather than
implementation internals.
Pre-1.0 caveat: not applicable here (current series is ≥1.0.0), so use standard semver.
If an explicit version was passed in $ARGUMENTS, skip this analysis and use it as the
suggestion (but still confirm).
Present the decision with AskUserQuestion. State the suggested level and a one-line
rationale grounded in the code change (e.g. "added TwiMLOptions + new optional voice config
fields, no breaking changes → MINOR"):
-
Question: "Current version is X.Y.Z. Since vX.Y.Z: . Suggested next version is A.B.C (). Which version should this release
use?"
-
Options (first = recommended):
A.B.C — " (Recommended)"
- the other two semver candidates (e.g. the patch and major alternatives)
The user can pick one, or choose "Other" to type any custom semver string.
After selection, validate the chosen version:
- It must match
^[0-9]+\.[0-9]+\.[0-9]+$ (allow a pre-release/build suffix only if the
user explicitly typed one).
- It must be strictly greater than the current version. If not, show the conflict and
re-ask rather than proceeding.
Let NEW_VERSION be the confirmed value. Create the release branch from latest remote main:
git checkout -b "release/bump-v${NEW_VERSION}" origin/main
Phase 4: Apply the bump
-
Edit pyproject.toml — change the single [project] version = "..." line (line ~3) to
NEW_VERSION. Use Edit to replace only that line; do not touch ruff/mypy/pytest
version-like fields elsewhere in the file.
-
Regenerate the lockfile:
uv sync
- Confirm only the two expected files changed and the lock updated correctly:
git status --porcelain
git diff --unified=0 pyproject.toml uv.lock
If anything other than pyproject.toml and uv.lock is modified, STOP and show the user
the diff before continuing.
Phase 5: Verify
Run the repo's checks to make sure the bump didn't break anything:
make check
If make check fails, STOP, show the failure, and ask the user how to proceed. Do not open
a PR on a failing tree.
Phase 6: Commit, push, and open the PR
Stage explicitly by path (never git add -A/./-u):
git add pyproject.toml uv.lock
git status
Commit (match the established subject style — see git log for chore: bump version to X):
git commit -m "$(cat <<'EOF'
chore: bump version to NEW_VERSION
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
EOF
)"
(Substitute the real NEW_VERSION before running.)
git push -u origin "release/bump-v${NEW_VERSION}"
If --no-pr was passed: STOP here. Tell the user the branch is pushed and ready, and
print the gh pr create command they can run, plus a compare URL.
Otherwise, read the PR template and open the PR:
-
Read .github/PULL_REQUEST_TEMPLATE.md and fill it in:
- Summary: "Bump version
X.Y.Z → NEW_VERSION." Include a short bullet list of the
notable changes since the last release (grouped: Features / Fixes / Other), derived from
the Phase 2 commit log.
- Type of Change: check Release / version bump.
- Checklist: leave as appropriate (tests pass via
make check).
- SDK Parity: check "Change is Python-specific (no TypeScript update needed)" — a
version bump is Python-specific.
-
Create the PR:
gh pr create \
--base main \
--title "chore: bump version to ${NEW_VERSION}" \
--body "<filled-in PR template>"
Phase 7: Report
Print a short summary:
# Release PR
- Previous version: X.Y.Z
- New version: NEW_VERSION (<bump level>)
- Branch: release/bump-vNEW_VERSION (based on origin/main @ <short sha>)
- Checks: make check passed
- PR: <url, or "not created (--no-pr)">