Automated ship workflow that takes a feature branch from "done" to "PR opened" in a single non-interactive pass. Loaded by /ship slash command in both Claude Code and Codex CLI. Use when the user has finished implementing a feature and wants to merge main, run tests, pre-landing review, CHANGELOG, commit, push, and create a PR in one go. Non-interactive by default — only stops for real blockers (merge conflicts, test failures, critical review findings).
This skill describes the automated release pipeline executed by the /ship command. The key property is non-interactivity: when the user invokes /ship, the next thing they should see is the PR URL. No confirmation prompts except for genuine blockers.
Input: current branch state (assumes a feature branch with committed or stageable work).
Output: a GitHub PR URL.
/ship, which means DO IT. Don't ask for confirmation on version bumps, commit messages, or CHANGELOG content.git push only. Never --force.--no-verify, no --no-gpg-sign unless explicitly requested.git branch --show-current.main or master: abort with message "You're on main. Ship from a feature branch."git status (never use -uall). Note uncommitted changes.git diff main...HEAD --stat and git log main..HEAD --oneline to understand what's being shipped.Fetch and merge origin/main into the feature branch, so tests run against the merged state:
git fetch origin main && git merge origin/main --no-edit
Detect the project's test command by reading package.json, Makefile, pyproject.toml, or common conventions:
# Detect and run the project test command:
npm test # Node.js with package.json "scripts.test"
pytest # Python with pyproject.toml or pytest.ini
bundle exec rspec # Ruby
go test ./... # Go
cargo test # Rust
Capture output to /tmp/ship_tests.txt for possible debugging.
Do a two-pass review of the diff (git diff origin/main) to catch structural issues that tests don't catch.
/ship)dangerously* props, Rails html_safe), injection vectors, secret leakage in logsOutput all findings.
CHANGELOG.md exists. If not, create it with a header.git log main..HEAD --oneline for the commit listgit diff main...HEAD for the full diff### Added, ### Changed, ### Fixed, ### Removed## [Unreleased] - YYYY-MM-DD or next semantic version if the project uses SemVerGoal: small, logical, bisectable commits.
type(scope): summary
Co-Authored-By: Claude <[email protected]>
git push -u origin $(git branch --show-current)
Never force-push. If the remote is ahead (unusual), STOP and show the situation.
gh pr create --title "type(scope): summary" --body "$(cat <<'EOF'
## Summary
<bullet points from CHANGELOG>
## Pre-Landing Review
<findings from Step 4, or "No issues found.">
## Test plan
- [x] All tests pass
- [ ] <any manual checks>
EOF
)"
Output the PR URL as the final line. This is the only output the user should need.
git push only./ship, the next thing they see is the PR URL.