.github リポジトリの PR テンプレートに「ハマったこと」欄を置く理由
GitHub の組織で複数のリポジトリを運用していて、PR のテンプレートがリポジトリごとにばらばらになっていました。しかも、AI エージェント(Claude Code)に PR を作らせると、テンプレートはそもそも使われていませんでした。この記事は、組織の .github リポジトリに 1 つのテンプレートを置いて全リポジトリの既定にした話と、そのテンプレートに「ハマったこと・試行錯誤」の欄を置いて、あとから機械的に拾える資産にした話です。
症状: テンプレートが「適用されるはず」なのに、PR の本文に出てこない
私は Claude Code に Issue から PR までを作らせています。PR を作るコマンドは `gh pr create` で、エージェントは本文を --body で渡します。このとき、リポジトリに置いた PR テンプレートは使われません。テンプレートが本文欄に差し込まれるのは、GitHub の Web UI で PR を開いたときと、gh pr create を本文なしで対話的に使ったときで、本文を明示して渡せば素通りします。私は「適用されるはず」だと思い込んでいて、エージェントの作った PR にテンプレートの見出しが 1 つも無いことに、しばらく気づきませんでした。
もう 1 つ、リポジトリが増えるにつれて、テンプレートの中身がずれていきました。片方には「ハマったこと」の欄があり、片方には無い。エージェントが PR に何を書くかは、そのリポジトリのテンプレートで決まるので、書き残される物語の質がリポジトリごとに違っていました。
直し方: 組織の .github リポジトリに 1 つ置く
shinobiworks/.github # 公開リポジトリ
.github/
ISSUE_TEMPLATE/
bug_report.yml # Issue Forms(概要 / 再現手順 / 期待 / 実際 / 環境 / ログ)
feature_request.yml # Issue Forms(解決したい課題 / 提案 / 代替案)
config.yml
PULL_REQUEST_TEMPLATE.md # Summary / 関連 Issue / 変更内容 / 動作確認方法 / 🔥 ハマったこと・試行錯誤
README.mdGitHub には、組織(または個人アカウント)に .github という名前の公開リポジトリを置くと、そこに入れた Issue や PR のテンプレートが、個別にテンプレートを持たないリポジトリの既定になる仕組みがあります。各リポジトリからテンプレートを消して、ここ(shinobiworks/.github)に 1 つだけ残しました。以後、テンプレートを直すのは 1 か所です。
エージェント側の対処: テンプレートは取りに行く
--body で素通りする問題は、テンプレートの側では直せません。エージェントの作業手順に「PR を作る前に .github リポジトリのテンプレートを取得し、その見出しの構成に沿って本文を組み立てる」と書きました。Issue Forms(yml)も gh issue create --body では適用されないので、同じようにフィールドの label を見出しに読み替えて本文を組みます。
gh api repos/shinobiworks/.github/contents/.github/PULL_REQUEST_TEMPLATE.md --jq '.content' | base64 -dテンプレートを「自動で差し込まれる物」ではなく「作業の前に読む仕様」として扱う、という置き直しです。
「🔥 ハマったこと・試行錯誤」の欄
テンプレートの最後にこの欄を置いています。書くのは、詰まった点、調査の過程、捨てた実装とその理由。「未来の自分とレビュワーへの申し送り」と説明を付けてあります。無ければ空欄でよい。
この欄を置いた理由は、commit のメッセージには「何をしたか」しか残らないからです。「何に詰まって、どう抜けたか」は、作業の直後に書かないと消えます。エージェントに作業させていると特にそうで、セッションが終わればその文脈はどこにも残りません。PR の本文は、作業の文脈がいちばん濃い時点で書かれ、リポジトリに永久に残る、唯一の場所です。
そして、この欄は機械的に拾えます。私は別の bot に、毎朝、指定したリポジトリの直近 24 時間の commit・PR・Issue を集めさせていて、PR の本文はそのまま素材に入ります。「ハマったこと」の欄があれば、そこを優先して引用するように指示してあります。この bot の設計は 自動投稿 bot の設計を「ネタ→投稿」から「背景→投稿」に変えた に書きました。
拾う側で失敗したこと
bot が PR の本文を素材に含める上限を、最初は 300 文字にしていました。テンプレートの欄は本文の一番下にあるので、冒頭から 300 文字で切ると、まさに欲しい欄が落ちます。上限を 2,000 文字に上げて直しました。欄を置いた PR 自身の「ハマったこと」には、こう書いてあります。
特になし(この欄自体が本 PR の成果物)
残す場所(テンプレートの欄)と拾う側(本文の上限)は、揃えて初めて動きます。片方だけ作っても資産にはなりません。
境界: テンプレートに置く物と、置かない物
- 置く: 見出しの構成(Summary、関連 Issue、変更内容、動作確認方法、ハマったこと)。これは全リポジトリで同じでよい
- 置かない: リポジトリ固有の手順(デプロイの注意、テストのコマンド)。それは各リポジトリの
CLAUDE.mdや README に置く。テンプレートに書くと、他のリポジトリで嘘になる - 欄は用意するが、埋めることは強制しない。「特になし」と書ける欄にしておかないと、埋めるために作り話が書かれる
どこで止まるか
.githubリポジトリの既定は、そのリポジトリ自身にテンプレートが無いときだけ効きます。個別のテンプレートが残っていると、そちらが勝ちます。統一するなら各リポジトリから消す作業が要ります- 組織の既定として効かせるには、
.githubリポジトリを公開にする必要があります。テンプレートの中身は公開情報になります - 欄があっても、書く人(エージェントを含む)が書かなければ空です。私の場合、エージェントの手順書に「この欄は空にしない。調査で判明した非自明な点を書く」と明記して埋まるようになりました
この構成で気をつけること
gh pr create --bodyはテンプレートを使わない。エージェントに作らせるなら、テンプレートを「差し込まれる物」ではなく「先に読む仕様」にする- テンプレートは組織の
.githubリポジトリに 1 つ。リポジトリごとに持たない - 「ハマったこと」の欄は、作業の文脈が消える前に物語を残す唯一の場所。commit には残らない
- 残す場所と拾う側の両方を作る。拾う側の上限や順序で、欄ごと落ちることがある