Create a Release PR (TypeScript SDK)
This skill creates a version-bump PR for twilio-agent-connect (the TypeScript SDK).
It branches off the latest remote main, bumps the version in package.json,
runs npm install to update package-lock.json, 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 runtime User-Agent version is read
dynamically from package.json at packages/core/src/clients/base.ts, so it does not
need editing):
package.json— the top-level"version"field (line ~3)package-lock.json— the root package version entries (regenerated bynpm install)
Note: this is a single-version monorepo — the
packages/{core,tools,server}directories have no individualpackage.jsonfiles, so there is only one version to bump.
Arguments
$ARGUMENTS (the full argument string):
- Explicit version (optional): a semver string like
2.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 npm is available:
gh repo view twilio/twilio-agent-connect-typescript --json name --jq '.name'
npm --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 npm is missing, STOP and
tell the user this skill requires npm.
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
package.jsonorpackage-lock.json, 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
# Current version
grep -E '^ "version"' package.json | head -1
# Latest release tag (vMAJOR.MINOR.PATCH)
git tag --sort=-creatordate | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1
# Commits since that tag (use the tag from above; if no tag exists, use the full history)
git log --oneline <LAST_TAG>..origin/main
# The actual code changes since that tag — this is the source of truth for the bump
git diff --stat <LAST_TAG>..origin/main
git diff <LAST_TAG>..origin/main -- packages/ 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 packages/*/src/ and the
root src/index.ts re-exports (exported classes, functions, Zod schema 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 schema 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 a new optional voice config field, no
breaking changes → MINOR"):
Question: "Current version is
X.Y.Z. SincevX.Y.Z: . Suggested next version isA.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
package.json— change the single top-level"version": "..."line (line ~3) toNEW_VERSION. UseEditto replace only that line; do not touch any"version"-like fields insidedependencies/devDependenciesor nested config.Regenerate the lockfile:
npm install
- Confirm only the two expected files changed and the lock updated correctly:
git status --porcelain # expect only package.json and package-lock.json
git diff --unified=0 package.json package-lock.json # sanity-check the version strings
If anything other than package.json and package-lock.json is modified, STOP and show the
user the diff before continuing. (If npm install also refreshed unrelated transitive deps in
the lockfile, note it for the user but it is generally fine.)
Phase 5: Verify
Run the repo's checks to make sure the bump didn't break anything:
npm run build && npm run lint && npm run typecheck && npm test
If any 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 package.json package-lock.json
git status # confirm only these two are staged
Commit (match the established subject style — see git log, which uses a terse vX.Y.Z
subject for release bumps):
git commit -m "$(cat <<'EOF'
vNEW_VERSION
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
EOF
)"
(Substitute the real NEW_VERSION before running, e.g. v2.1.0.)
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.mdand 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 the box that best fits the aggregate release (typically New feature for a MINOR, Breaking change for a MAJOR, Bug fix for a PATCH).
- Checklist: check what applies (tests pass via the Phase 5 checks).
- SDK Parity: check "Change is TypeScript-specific (no Python update needed)" — a version bump is TypeScript-specific.
- Summary: "Bump version
Create the PR:
gh pr create \
--base main \
--title "vNEW_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: build + lint + typecheck + test passed
- PR: <url, or "not created (--no-pr)">