| name | ship |
| description | Create a release PR to main with version bump and draft a GitHub release |
| argument-hint | [optional version number or extra notes] |
Create a pull request from the current working branch to main, ensure the version is bumped, and draft a GitHub release. The user will review, merge, and publish manually.
Usage
/ship — auto-detect versioning scheme and walk through the process
/ship 2.5.0 — use a specific version
/ship patch — shorthand for semver bump type
Process
Step 1: Preflight checks
Run these commands in parallel to understand the current state:
git status
git branch --show-current
git log main..HEAD --oneline
gh auth status
Verify:
- There are no uncommitted changes. If there are, warn the user and stop.
- The current branch is NOT
main. If it is, warn the user and stop.
- There is at least one commit ahead of
main. If not, inform the user there is nothing to ship.
gh CLI is authenticated. If not, inform the user and stop.
Step 2: Collect all changes since main
git log main..HEAD --pretty=format:"%h %s (by @%an)" --no-merges
Also gather PR numbers if commits came from merged PRs:
git log main..HEAD --pretty=format:"%h %s" --no-merges
For each commit, check if it is associated with a PR:
gh api repos/{owner}/{repo}/commits/{sha}/pulls --jq '.[0].number' 2>/dev/null
Build a list of all changes with their authors and references (commit hash or PR number).
Step 3: Check version and detect versioning scheme
Read the current version from package.json:
node -p "require('./package.json').version"
Detect the versioning scheme:
| Scheme | Pattern | Examples |
|---|
| Semver | MAJOR.MINOR.PATCH | 2.5.0, 1.0.3, 0.9.1 |
| Calendar versioning | Contains year/month/date-like segments | 2026.3.18, 25.03.1 |
If $ARGUMENTS provides a version or bump type, use it:
- Exact version (e.g.,
2.5.0) — use as-is
- Bump type (
major, minor, patch) — calculate the next version from current
If $ARGUMENTS does not specify a version, check if the version was already bumped compared to main:
git show main:package.json | node -p "JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).version"
- If the version is the same as
main, a bump is required — ask the user (see below).
- If the version is already different from
main:
- Semver: the version is already bumped. Use the current version and skip to Step 4.
- Calendar versioning: the version may be stale (bumped days or weeks ago). Always ask the user to confirm — see the calver prompt below.
For semver (when bump is needed), present the options:
Current version: 2.4.1
What version bump do you need?
- patch ->
2.4.2 (bug fixes, small changes)
- minor ->
2.5.0 (new features, backward compatible)
- major ->
3.0.0 (breaking changes)
For calendar versioning (always ask, even if already different from main):
Current version: 2025.12.3
Today's date version: 2026.3.18 (Recommended)
Use today's date as the version, keep current (2025.12.3), or enter a custom one?
If the user picks today's date, update the version. If they choose to keep the current version, skip the bump. If they enter a custom version, use that.
Step 4: Apply version bump
If a version bump is needed (version same as main, or calver and user chose a new version):
Update package.json with the new version. Use a precise edit — only change the "version" field.
Then re-install dependencies to update the lock file:
ni
Commit the version bump:
git add package.json
Also stage the lock file (package-lock.json, pnpm-lock.yaml, yarn.lock, bun.lockb — whichever exists)
git add package-lock.json pnpm-lock.yaml yarn.lock bun.lockb 2>/dev/null
git commit -m "Bump version to "
Push the branch:
git push -u origin $(git branch --show-current)
Step 5: Create the PR to main
Build the PR title using the version and a summary of changes:
Title format: v<version> - <short summary of changes>
The short summary should capture the main themes from the changes (features, fixes, optimizations). Keep it under 72 characters total. Examples:
v2.5.0 - Add dark mode, fix cart calculation, optimize image loading
v2026.3.18 - Redesign settings page, update dependencies
Build the PR body by grouping changes into categories:
## What's in this release
### New features
- Add dark mode toggle (#45)
- Add user onboarding flow (#52)
### Bug fixes
- Fix cart total when discount applied (#48)
- Fix null pointer in auth middleware (a1b2c3d)
### Improvements
- Optimize image loading for product pages (#50)
- Refactor payment utils for reusability (#51)
### Other
- Update dependencies (d4e5f6g)
Grouping rules:
- Scan each change's commit message or PR title to determine the category
- Features: new functionality, "add", "implement", "introduce"
- Bug fixes: "fix", "resolve", "correct", "patch"
- Improvements: "optimize", "refactor", "improve", "update", "enhance", "clean up"
- Other: anything that does not fit the above (config, docs, chore, deps)
- Skip empty categories
- Each item references either
#<PR-number> or <short-commit-hash> depending on what is available
Create the PR:
gh pr create
--base main
--head "$(git branch --show-current)"
--title "v - "
--body "$(cat <<'EOF'
EOF
)"
Step 6: Draft a GitHub release
Create a draft release targeting main with tag v<version>.
Build the release body. List all changes, each in this format:
by @ in #
or if no PR exists for that change:
by @ at
Rules for the release body:
- Use simple English, no emojis
- Remove duplicate entries (same change appearing in multiple commits)
- Skip trivial changes (typo fixes, formatting-only, merge commits)
- Group by category (same groups as the PR body) if there are more than 10 items
- If 10 or fewer items, a flat list is fine
- Each line starts with a capital letter
- Add a "New Contributors" section at the end if there are first-time contributors to the repo (check with
gh api)
gh release create "v"
--target main
--title "v"
--draft
--notes "$(cat <<'EOF'
What's Changed
- Add dark mode toggle by @hta218 in #45
- Fix cart total calculation when discount is applied by @dev2 in #48
- Optimize image loading for product pages by @hta218 in #50
- Update dependencies by @hta218 at a1b2c3d
Full Changelog: https://github.com///compare/v...v
EOF
)"
Always append a "Full Changelog" link at the bottom comparing the previous version tag to the new version.
Step 7: Summary
Output a final summary:
Ship complete!
Version: v
PR:
Release: (draft)
Next steps:
- Review the PR:
- Review the release:
- Merge the PR
- Publish the release
Error Handling
- If
gh CLI is not installed or not authenticated, inform the user and stop
- If there are uncommitted changes, warn and stop — do not auto-commit
- If already on
main, warn the user and stop
- If no commits ahead of
main, inform the user there is nothing to ship
- If
package.json does not exist, skip version bump logic and ask the user for a version string to use in the PR title and release tag
- If
ni fails, show the error and ask the user if they want to continue without updating the lock file
- If PR creation fails (e.g., PR already exists), show the error and provide the URL to the existing PR
- If release creation fails, show the error but still report the PR as successful
- If push fails, show the error and let the user resolve it
Important Notes
- This command does NOT merge the PR or publish the release — the user does that manually
- The release is always created as a draft
- The PR targets
main unless the user specifies otherwise via arguments
- Use
ni (not npm install or pnpm install) to re-install — it auto-detects the package manager
- Do NOT create a git tag locally — the tag is created by GitHub when the release is published
- Keep the PR title concise but descriptive — it becomes the merge commit message
User Arguments
$ARGUMENTS