ship について
ship は、完成したブランチをチェックし、変更履歴を更新してプルリクエストを開くためのスキルです。リリースを考慮した手順を案内し、マージ前に処理を止めます。
主な機能
- 01リポジトリとブランチの前提確認
- 02リリース影響とバージョンの評価
- 03バージョンに合わせた変更履歴の更新
- 04対象を絞ったドキュメント更新
- 05プッシュ前の高速チェック
- 06プルリクエストの作成または更新
活用シーン
- 01完成したブランチのレビュー準備
- 02マージに対応するリリースノートの記録
- 03PR 前のリポジトリ手順の確認
- 04既存のブランチ PR の更新
MCP 対応
`gh` CLI が使えない場合、リポジトリへのアクセスや PR 操作には同等の GitHub MCP 操作を使うよう案内します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jwh3times/ skills --skill shipインストール後、Claude Code で/shipを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
settings/human-follow-up.mdissue-tracker.mdREADME.mdreleases.mdship.mdworkspace.md詳細
Ship
現在のブランチを「コード完成」の状態から「PR がオープンされ、CI に合格できる」状態にします。このマージによって実際に作成されるバージョンを明記した変更履歴も用意します。
開始時に宣言してください:「ship スキルを使って、このブランチの PR をオープンします。」
シェルスニペットは bash(Windows では Git Bash)で実行してください。gh が使えない場合は、同等の GitHub MCP 操作を使用します。CLI がない場合に変わるのはインターフェースであり、手順や完了条件ではありません。
ship は「PR がオープンされた」時点で終了します。マージ、main へのプッシュ、強制プッシュは行わず、テストスイート全体も実行しません。CI がテストを担当するため、ここで実行するとスキルに時間がかかります。
0. 設定
このスキルでは、docs/agents/workspace.md、docs/agents/issue-tracker.md、
docs/agents/human-follow-up.md、docs/agents/releases.md、docs/agents/ship.md を読み込みます。.agents/skills/ship/settings/README.md の手順に従ってこれらを読み込み、不足しているものがあれば補完してください。定義ファイルはその隣にあります。各 discover: の値はここで一度だけ解決し、以降で再利用してください。
Scheme: none の場合、**(release)**と記されたすべての手順を省略します。
1. 事前条件 — いずれかを満たさない場合は停止
-
mainブランチではないこと。 作業はブランチ上で行います。main上にいる場合は停止し、Issue linkのブランチパターン(noneの場合は<type>/<slug>)に従った名前でブランチを作成することを提案してください。 -
作業ツリーがクリーンであること。
git status --porcelainの出力が、手順 0 で書き込んだ設定ファイルだけであること。それらは今回の実行のコミットに含めます。それ以外の出力があれば停止し、現在の変更をコミットするか確認してください。黙ってコミットしてはいけません。回答を得たら、この手順から再開してください。その後にステージする変更はすべて、今回の実行中に行ったものです。 -
GitHub に接続できること。
gh auth statusが成功するか、GitHub MCP からこのリポジトリにアクセスできること。 -
関連リポジトリが手順に準拠していること。
Private companionが設定されており、そのチェックアウトが存在する場合は、Workspace status commandを実行します。関連リポジトリはクリーンで、アップストリームより先行も遅延もしていない必要があります。チェックアウトがない状態は有効です。その場合は報告してください。 -
mainと同期していること。git fetch -q --tags origin git merge-base --is-ancestor origin/main HEAD && echo current || echo behind遅れている場合は、今すぐ
git merge origin/mainを実行することを提案し、競合はユーザーと解決してください。プッシュ済みのブランチをリベースしてはいけません。
常にローカルの main ではなく origin/main を使用してください。ローカルの main が古いと、すでにマージ済みの作業まで差分に誤って含まれます。また、このブランチだけをフェッチしたクローンには、ローカルの main が存在しません。
2. リリースへの影響を評価する(release)
最新のコミットだけでなく、ブランチ全体を確認します。
base="$(git merge-base origin/main HEAD)"
git diff --stat "$base"..HEAD
git log --format='%s%n%b' "$base"..HEAD
git diff "$base"..HEAD
stat と log は索引です。判断する前に、差分と、それが変更するテストやドキュメントを確認します。このプロジェクトへの影響を、該当する最も高いレベルで分類します。
- Major — 既存の公開動作、API、URL、永続化データの形式、設定、デプロイ契約、または定着したユーザーワークフローに互換性のない変更があり、その利用者に移行が必要になります。
0.y系では、ブランチが意図的に1.0.0をリリースするのでない限り、互換性のない変更は minor です。 - Minor — 互換性を保った機能追加、動作の実質的な拡張、またはサポート対象の基準を引き上げる、プラットフォームやツールチェーンの意図的な世代変更です。
- Build — 修正(セキュリティ修正を含む)、依存関係の保守、リファクタリング、テスト、ドキュメント、ツール関連です。機能追加や基準の引き上げはありません。
依存関係のバージョン番号ではなく、このプロジェクトの契約を基準に判断します。リリースメタデータや生成されたミラーは根拠になりません。Scheme: per-merge の場合は、Unreleased の累積内容も対象です。ユーザーが指定したレベルも評価します。評価結果が異なる場合は、両方を示して確認します。
Release level: <major|minor|build> — <one-sentence rationale> を記録します。ステップ 9 と 10 では、この行をそのまま使います。
適用します。 基準となるバージョンは、最新の v* タグ(Skipped tags の Ignore パターンは除外)と、origin/main 上の Version file(git show "origin/main:<file>")のうち、大きい方です。
- Build —
Version fileはorigin/mainの値のままにします。リリースの意図なくブランチで変更されている場合は、元に戻します。 - Minor — 基準バージョンの
<major>.<minor + 1>.0をターゲットにします。 - Major —
<major + 1>.0.0をターゲットにします。
major または minor の場合は、まず Ask before bumping に従い、その後、正確なターゲットを指定して Bump command を実行します。そうすれば、再実行してもバージョンが二重に進まず、同じ値になります。バージョンファイルと、その隣にあるロックファイルの値が一致していることを確認します。ブランチにすでにターゲットが含まれている場合は、そのままにします。別の系列のバージョンが含まれている場合は意図的に更新されたものなので、置き換える前に確認します。
3. ターゲットバージョンを計算する(release)
-
per-merge— まず、origin/mainの最新のマージにタグが付いていることを確認します。git tag --points-at origin/main -l 'v*'出力が空の場合、直近にマージされた変更のタグ付けワークフローがまだ完了していません。そのままでは、次のバージョンで使用済みの番号が繰り返されます。ワークフローの完了を待ち、タグを再取得してもう一度確認します。ワークフロー完了後もタグが付いていない場合は、ユーザーに確認します。その後、
Next-version commandを実行します。このコマンドは SemVer のみを出力する唯一の信頼できる情報源です。ビルド番号を自分で計算してはいけません。同じバージョンをすでに指定している、ほかのオープン PR があるか確認します。
gh pr list --state open --json number,headRefName --jq '.[] | "\(.number) \(.headRefName)"' gh pr diff <number> -- CHANGELOG.md | grep '^+## \['該当する PR がある場合は、レポートにその名前を記載します。後からマージされる方は、次回の
shipでバージョンが付け直されます。 -
cut-on-line— build には確定したターゲットがありません。ワークフローが各マージにタグを付ける場合も、メンテナーがリリースにタグを付ける場合も、次のタグでバージョンが割り当てられます。その前に別のマージが入る可能性もあります。確定した major または minor のターゲットは、ステップ 2 で決めた新しい系列です。
4. スキップされたタグを補完する(リリース)
Scheme: per-merge と Skipped tags: backfill の場合のみ実行します。セクションがないリリース済みバージョンを一覧表示します。
そのまま実行してください。タグは v1.1.5、セクションは 1.1.5 と表示されるため、リストをそのまま見比べると
すべてのタグが欠けているように見えます:
comm -23 \
<(git tag -l 'v*' | sed -nE 's/^v([0-9]+\.[0-9]+\.[0-9]+)$/\1/p' | sort) \
<(sed -nE 's/^## \[([0-9]+\.[0-9]+\.[0-9]+)\].*/\1/p' CHANGELOG.md | sort)
Ignore パターンに一致するバージョンを除外します。残ったものは、それぞれセクションを書かずに行われたマージです。依存関係ボットの PR、またはウェブ UI で作成された PR などが該当します。そこに日付付きのセクションを新しい順に追加します。version にそれぞれのバージョンを設定してタグを確認してください。これはマージコミットなので、マージされたブランチは 2 番目の親です:
git log -1 --format='%cs' "v$version" # the section's date
git log --format='%s%n%b' "v$version^1..v$version^2" # what landed
git diff "v$version^1" "v$version" --stat # manifests and lockfiles it changed
git log -1 --format=%an "v$version^2" # dependabot[bot] for a bot PR
事実に基づいて記述します。パッケージ名とバージョンを挙げ、ロックファイルのみの変更は推移的な変更と記載してください。ボットに起因するとするのは、2 番目の親の作成者がボットの場合に限ります。マージコミットの作成者は、マージをクリックした人です。^2 が存在しない場合(スカッシュまたはファストフォワード)、タグ自身のコミットを確認します。
Skipped tags: roll up の場合、スキップされたタグごとのセクションは作成しません。その変更は、次に記述するセクションにまとめます。
5. ドキュメントを更新する
docs-updater スキルを fix モードで実行し、このブランチの差分のみを対象とします。全体監査は行いません。ハーネスがサブエージェントに対応している場合は、その中で .agents/skills/docs-updater/SKILL.md に従うよう指示して実行します。それ以外の場合は、自分でその手順に従います。サブエージェントはユーザーに質問できないため、まずステップ 0 に従って、ここで設定を完了します。
range="$(git merge-base origin/main HEAD)..HEAD"
変更内容とその理由、ship によってマージ前のブランチで呼び出されたこと、このスキルが変更履歴と Version file を作成することを伝えます。編集内容はコミットせずに残し、ステップ 6 で人間が行う必要があるアクションと、マージ後に実行する必要がある Wiki 検索(Follow-up wiki、または Wiki 内の Doc map 項目)を返します。
関連する編集は別のリポジトリとしてコミットします。このリポジトリにはコミットしません。Companion commit policy が commit または ship の場合は、コミットしてプッシュします。ask の場合は、差分を表示して、まず確認を求めます。いずれの場合も、コミット前のチェックを実行します。
6. 人間によるフォローアップ
このブランチに必要な人間のアクションが残る場合は、PR を作成する前に、それぞれについて .agents/skills/ship/settings/human-follow-up.md の ## Procedure を実行します。docs-updater が返したアクションも含みます。重複させずに調整し、再度 ship する場合は、すでに作成済みの記録を再利用します。フォローアップを変更履歴や PR 本文だけに記載してはいけません。リンクはレポートと非公開の記録に記載し、公開 PR には記載しません。
7. 変更履歴を作成する(リリース)
コミットログではなく、差分から導き出した、ユーザーに見える動作とその影響を記載します。ファイルですでに使われている見出し(Keep a Changelog:Added、Changed、Deprecated、Removed、
Fixed、Security、およびファイルに追加されている見出し)を使い、セクションごとに各見出しを1つずつ記載し、その文体に合わせます。日付は今日の日付、YYYY-MM-DDです。
冪等性。 このブランチが追加したセクションを一覧表示します:
git diff origin/main...HEAD -- CHANGELOG.md | grep '^+## \['
一覧にあるセクションは、以前のshipでこのブランチが追加したものです。別のセクションを積み重ねず、その場で書き換えます。Unreleasedにこのブランチが追加した項目も同様に書き換えます。
per-merge—## [Unreleased]の直下に## [<target>] - <date>を挿入し、このブランチの項目とUnreleasedに蓄積された項目を入れます。UnreleasedはUnreleasedのプレースホルダーに戻します。別のPRが先にマージされたため、このブランチのセクションに古いバージョンが記載されている場合は、そのセクションのバージョン番号をターゲットに変更します。その後、origin/mainをマージします。相手側のセクションは同じ位置にあるため、CHANGELOG.mdでは両方を残し、新しいバージョンを先にします。その後、手順3に戻ります。相手側のマージによってタグが作成されているため、ターゲットが再び変わっています。cut-on-line、ビルド —Unreleasedのプレースホルダーを置き換えて、その下に項目を追加します。日付付きセクションは作成せず、Version fileも編集しません。cut-on-line、確認済みのメジャーまたはマイナー —Unreleasedの下に項目を追加し、その全内容を## [<target>] - <date>に移して、プレースホルダーを戻します。以前のshipですでにカットされている場合は、その中にこのブランチの項目を書き換えます。カットの前後の両方に項目を残してはいけません。
参照リンク。 ファイル末尾にリンクフッターがある場合は、既存の項目のパターンに従って整合性を保ちます。[Unreleased]は最新バージョンからHEADまでの差分を示し、新規またはバージョン番号を変更したセクションには、それぞれ専用のリンクを最新順で追加します。遡及して追加したセクションも対象です。
Changelog checkを実行します。不一致がある場合、マージで実際に作成されるバージョンが示されます。そのバージョンを使って、この手順をやり直します。
8. 高速チェック — 失敗があればプッシュしない
すべてのFast checks項目を、各フォルダーから順番に実行します。条件付きの項目は、対象となるパスに変更がない場合に限りスキップします(git diff --name-only origin/main...HEAD)。フォーマッターとリンターもこれらのファイルを対象とするため、ドキュメントと変更履歴の編集後に実行します。
失敗が1つでもあれば、そこで中止して報告し、プッシュしません。その項目の修正コマンドを提示します。ファイルを書き換える修正を行った後は、リストを最初から再実行します。整形前のソースから生成したミラーは、ソースを整形すると再び古くなるためです。サービスまたはシークレットがないためここでは実行できないチェックは、CIに任せるものとして報告に記載します。
続いて、docs/agents/ship.mdのHook: before PRを実行します。その結果は報告に記載し、指示がある場合はPR本文にも記載します。
9. コミット、プッシュして、PR を作成または更新する
git status --porcelain に変更がある場合に限りコミットします。新しい内容がない再出荷では、空のコミットを作成しません。ステップ 1 で作業ツリーがクリーンであることを確認済みなので、すべてをステージングしても問題ありません。また、コンパニオンは無視されるため、ステージングされることはありません。
git add -A
git commit -m "<Release commit message, with the real version>"
git push -u origin "$(git branch --show-current)"
プッシュが拒否された場合、このチェックアウトにないコミットがリモートにあります。そこで停止して報告してください。強制プッシュは絶対にしないでください。
gh pr list --head "$(git branch --show-current)" --state open --json number,url
- PR がない場合 →
gh pr create --base main。 - PR が存在する場合 →
gh pr edit <number>で本文を更新します。2 つ目の PR は作成しないでください。
本文を一時ファイルに書き込み、--body-file に渡します。リポジトリに PR テンプレート(.github/pull_request_template.md または PULL_REQUEST_TEMPLATE.md)がある場合は、変更履歴の項目と差分をもとに記入します。ステップ 2 の Release level: 行と、per-merge の場合はこのマージで付与されるバージョンを含めます。
課題リンク(設定が none でない場合)。本文は、テンプレートで設けられている位置にリンク行を置いて始めます。
- ブランチの Branch pattern に従って
Nを取得し、課題を読み取ります:gh issue view <N> --json title,state,labels,body。 - この PR によって課題が完了する場合は完了行(
Closes #N)、未完了のまま維持される仕様の一部を担う場合はスライス行(Part of #N)を使います。完了する課題には、それぞれ専用のキーワードを付けます。GitHub はCloses #1 and #2の最初の課題にしかリンクしません。 - ブランチに番号がない場合、ユーザーがフローを免除したときは Waiver line を使います。Exempt 種別の場合はリンク行を付けません。
- ブランチの番号と課題の内容が一致しない場合、または完了とスライスのどちらかが不明確な場合は、PR を作成する前に確認してください。本文を更新する際もリンク行を残します。タイトルに番号を記載しただけではリンクされません。
PR にリンク行がなく、免除対象でもない場合、または Board が設定されているのにリンク先の課題がそのボードにない場合は、警告します。ただし、処理は止めません。Private issue repository にある課題は、公開 PR の本文、コミットメッセージ、公開課題のいずれにも記載してはいけません。マージ後に手動でクローズします。
このステップで公開するものには、プライベートリポジトリ名、リンク、ボード番号、コンパニオンの詳細を含めてはいけません。
10. 報告
- PR の URL とブランチ。
Release level:の行と、その根拠。このマージで付与されるバージョン(per-merge)、新しいライン(cut-on-lineによるカット)、または次のタグでビルドが割り当てられること。同じバージョンを主張する競合 PR があれば、その名前を挙げます。また、再出荷時にはセクション番号が振り直されることを伝えます。- ドキュメントの更新で変更した内容、記載した変更履歴の項目、補完したセクション。マージ後に docs-updater が Wiki 検索を行う必要がある場合は、その旨を伝えます。次の
end-sessionで実行されます。 - 人によるフォローアップ:確認済みの課題リンクと Wiki リンク、未公開の項目とその理由、または未対応事項がないこと。
- 高速チェックの結果、CI に残したチェック、
Hook: before PRの指摘事項、課題リンクに関する警告。 - コンパニオン:存在しない、または同期済みでクリーンな状態、および作成したコンパニオンのコミット。マージされていない PR を、コンパニオンに反映済みのものとして説明してはいけません。
- ステップ 0 で書き込んだ設定ファイル。
完全なテストスイートはここではなく CI で実行されることを明確に伝えてください。このブランチは、高速チェックで確認できた範囲に限って検証済みです。