write-pr について
write-pr は、tldraw/tldraw 向けにレビュー担当者を意識した PR タイトルと説明を書くスキルです。変更の説明方法や、キャンバス操作の録画手順も定めています。
主な機能
- 01Conventional Commits 形式の PR タイトル
- 02レビュー担当者を意識した説明
- 03バグ修正の変更前後フォーマット
- 04テスト計画とリリースノートの指針
- 05キャンバス操作の録画手順
活用シーン
- 01簡潔な PR 説明の作成
- 02変更前後を示したバグ修正の報告
- 03キャンバス操作の変更への録画添付
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tldraw/ tldraw --skill write-prインストール後、Claude Code で/write-prを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
scripts/example-scenario.mjsrecord-interaction.mjstouched-comments.ts詳細
プルリクエストの書き方
tldraw/tldraw における PR のタイトルと説明の標準。
レビュアーのために書く(最初にこれを読んでください)
これが基本ルールであり、以下はすべてこれに従います。説明は、コードベースのアーキテクチャは知っているが、あなたのコードや差分は読んでいないレビュアーに向けて書いてください。彼らの時間こそが乏しいリソースです。説明の役割は、コードからは得られない枠組みを彼らに与え、あとは邪魔をしないことです。
基本は短く。 数文の枠組み提示が例外ではなく標準です。変更の大きさに長さを合わせてください。1 行の修正なら 1 文で十分であり、新しいシステムならより充実した記述が必要です。長く構造化された説明はより価値があるわけではありません。むしろ価値が低いことのほうが多いのです。なぜなら、枠組みが足場に埋もれてしまうからです。レビュアーがあなたの説明を理解するために自分の AI を必要とするなら、それは失敗です。
粗いものから細かいものへと並べる。 説明は逆ピラミッド型に構成し、最も重要なものを最初に置いてください。読者はどの時点で読むのをやめても、正確で一貫した理解を得られるべきです。ざっと目を通す人は冒頭の数行で目的と動機をつかみ、アプローチを検討する人は設計と決定事項まで読み進め、じっくり読むレビュアーは具体的な詳細へと進みます。その PR が何のためのものかを知るために最後まで読ませるようなことは決してしないでください。
以下をおおよそこの順序で網羅してください。各層は前の層よりも詳細で、変更がそれを必要としなくなった時点でそれぞれ省略可能です。
- 目的、動機、ユースケース。 なぜこの変更を、なぜ今、何のために行うのか。以前は何が問題だったのか、何が欠けていたのか。これは常に最初に来ます。
- より高レベルな変更。 解決策の形 — 差分を行ごとに言い換えるのではなく、振る舞いと構造。
- API 設計と決定事項。 新規または変更された公開インターフェース、選んだアプローチ、除外したものとその理由、そして確信が持てない点。表面化しない決定事項はレビュアーが指摘できません。
- サンプルスニペットと細部。 API、データ構造、使用パターンに触れるものについては、数行のビフォー/アフターが 1 段落よりも多くを語ります。最小限に留めてください。
してはいけないこと:
- 差分を言い換える。ファイルごとの説明も、関数が何をするかの語りも、コードがどのように段階的に動作するかの記述も不要です。レビュアーはコードを読めます。
- コードをなぞるだけの表やリストを生成する。シグネチャをそのまま言い換えただけの
Method | Description表、変更されたすべてのファイルの一覧、自明な名前の用語集など。 - 儀式的な水増し。徹底的に見せるためだけに存在する構造はノイズです。
なぜを決して捏造しない。 動機とトレードオフは、実際の意図 — コミット、リンクされた issue、または作者 — から来なければなりません。ある変更がなぜ行われたのか、何が検討されたのかがわからない場合は、ユーザーに尋ねてください。推測してはいけません。 自信満々だがでっち上げられた根拠は、役立たず以下です。それは誤解を招き、レビュアーが最も信頼する必要があるものだからです。
PR タイトル
セマンティックな PR タイトル(Conventional Commits 形式)を使用してください。
<type>(<scope>): <description>
タイプ
feat- 新機能fix- バグ修正docs- ドキュメントのみrefactor- バグ修正でも新機能追加でもないコード変更perf- パフォーマンス改善test- テストの追加または修正chore- メンテナンスタスク
スコープ(任意)
影響を受ける領域を表す名詞: fix(editor):、feat(sync):、docs(examples):
例
feat(editor): add snap threshold configuration optionfix(arrows): correct binding behavior with rotated shapesdocs: update sync documentationrefactor(store): simplify migration system
PR 本文
バグ修正と改善の PR(bugfix および improvement の変更タイプ)は以下のビフォー/アフターテンプレートを使用します。それ以外はすべてこちらを使用します。
<description paragraph>
### Change type
- [x] `bugfix` | `improvement` | `feature` | `api` | `other`
### Test plan
1. Step to test...
2. Another step...
- [ ] Unit tests
- [ ] End to end tests
### Release notes
- Brief description of changes for users
説明段落
「In order to X, this PR does Y.」で始めます。このスキルの冒頭にあるレビュアー優先のルールに従ってください。
- X はこの作業が必要になった具体的な状況、つまり誰かが実際にやろうとしていたことであり、Y が何をするかの言い換えではありません。「In order to let apps carry undo history across editor rebuilds, this adds an API to carry undo history across editor rebuilds」は循環しています。X が Y を言い換えているだけです。X を実際の目標まで一段上げてください。たとえば「so desktop can reload the editor without losing the user's place, the way HMR preserves component state across a code edit.」のようにします。
- 仮定のシナリオではなく、実際に動機となったケースを挙げてください。why を説明するために例示的なシナリオをでっち上げているなら(「e.g. if someone toggled a plugin…」など)、完成したコードから正当化を逆算していることになります。実際にそれを促したケースを書き出してはいません。代わりにそのケースから前向きに進めてください。
- 動機の代わりに抽象的な仕組みを持ち出さないよう注意してください。SDK に関する真の技術的事実(「editor config is fixed at construction time」)は制約を説明するものであり、なぜ誰もが気にするのかを説明するものではありません。読者が、動かなくなった、あるいは可能になった具体的な事柄を思い描けるようになるまで続けてください。
- 具体的に保ってください - 「improve user experience」のような曖昧な表現は避けてください
- 最初の段落で関連する issue をリンクしてください
- 読者がリンク先の issue も読むことを期待しないでください
バグ修正と改善の PR
バグ修正と改善の PR は、説明段落の代わりに固定された形を使います。同じレビュアー優先のルールが適用されます。この構造があるのは、レビュアーが diff を読まなくても、何が間違っていた(または不足していた)のか、今は何をするのか、そしてなぜなのかを把握できるようにするためです。
This PR fixes a bug where <symptom a user or developer would hit>.
### Before
<what the code did and why that produced the symptom>
### After
<what the code does now>
### Implementation notes
<optional: what exactly changed and how — decisions, trade-offs, anything non-obvious>
### Change type
- [x] `bugfix` | `improvement`
### Test plan
- [x] Unit tests — the new test fails on `main` and passes with this change
### Release notes
- Fix <symptom> | Improve <behavior>
### Code changes
| Section | LOC change |
| --------- | ---------- |
| Core code | +10 / -2 |
| Tests | +5 / -0 |
- Intro — 一文。バグの場合:「This PR fixes a bug where X,」ここで X は観察可能な症状であり、原因や修正ではありません。改善の場合:「This PR improves X so that Y,」ここで Y はユーザーまたは開発者が今できることです。issue があればここでリンクしてください。PR が複数のことを行う場合は、リストではなく二文目(「It also ...」)を追加してください。
- Before — 以前の動作と、それを生み出した仕組み。バグの場合、原因となっている関数やパスを挙げてください。ここは、どのように古いコードが失敗したかの短い説明が入る唯一の場所です。それがレビュアーが修正を照らし合わせて確認する原因だからです。改善の場合、ユーザーまたは開発者が何をしなければならなかったか(あるいはできなかったか)と、コードの何がそうさせていたかを説明してください。
- After — 変更後の動作。コードが今何をするのかを、Before と同じ詳細度で述べてください。あわせて更新された仕様やドキュメントがあれば言及してください。
- Implementation notes — 任意。Before/After の組では伝わらない何かがある場合にのみ含めてください。別の案ではなく選んだアプローチ、変更の微妙な点、意図的に見送ったフォローアップなどです。言うことが何もなければ見出しごと省いてください。ほとんどの小さな修正には何もありません。
### Change type/### Test plan/### Release notes/### API changes/### Code changesの各ブロックはいつもどおり続きます。バグ修正の場合、新しいテストがmainで失敗するかどうかをテストプランに書いてください。
tldraw/tldraw#10117、#10118、#10119 は、この形でのバグ修正の実例です。
録画のビフォー・アフター
バグ修正や改善によってキャンバスのインタラクションの挙動が変わる場合 — ドラッグ、リサイズ、回転、クロップ、ハンドル、ツールのジェスチャーなど、レビュアーが確認するためにローカルで実行しなければならないもの — は、Before セクションと After セクションのそれぞれに短い録画を添付してください。文章は仕組みを説明しますが、録画は症状とその解消を示し、レビュアーはジャンプやジッターの説明よりも録画を信頼します。キャンバス上で視覚的に確認できない変更(データ、API、ドキュメント、ツーリング)の場合は省略してください。
scripts/record-interaction.mjs は、実行中の examples アプリに対してスクリプト化されたインタラクションを 16:9 の MP4 として録画します。tldraw の chrome を非表示にし、可視カーソルを注入し(ヘッドレス録画にはカーソルがありません)、シナリオモジュールを実行し、セットアップのフレームをトリミングし、ffmpeg でトランスコードします。scripts/example-scenario.mjs は出発点です。スクラッチの場所にコピーして、body を PR が影響するインタラクションに変更してください。シナリオはコミットしないでください。
パス上に ffmpeg と Playwright Chromium ビルドが必要です。このリポジトリではインストールスクリプトが無効になっているため、ブラウザは pnpm install ではダウンロードされません。一度 pnpm exec playwright install chromium を実行してください。その後、pnpm dev で examples アプリを配信している状態で、リポジトリのルートから:
# After: the current branch
node skills/write-pr/scripts/record-interaction.mjs <scenario.mjs> <scratch>/after.mp4
# Before: main's versions of the files this branch modifies, hot-reloaded by vite
git diff --name-only --diff-filter=M origin/main...HEAD | xargs git checkout origin/main --
sleep 10
node skills/write-pr/scripts/record-interaction.mjs <scenario.mjs> <scratch>/before.mp4
git diff --name-only --diff-filter=M origin/main...HEAD | xargs git checkout HEAD --
git status --porcelain # must be empty before continuing
チェックアウトは変更されたファイルに限定してください。main からディレクトリ全体をチェックアウトすると、そちらにしか存在しないファイルもステージされ、このブランチで追加されたファイルには復元する main バージョンがありません。このアプローチは作業ツリーがクリーンな場合にのみ使用してください。
録画自体に関するルール:
- 両方で同じシナリオを使う。 2 つの動画はテスト対象のコードだけが異なる必要があり、レビュアーが同じ条件で比較できます。まず After を録画し、シナリオがその挙動を示すことを確認してから、Before を録画してください。
- 症状を一目でわかるようにする。 バグを誇張する入力を選んでください — 大きな回転、長いドラッグ、正方形でない図形など。図形を数ピクセルずらすだけの 15 度の回転は、動画のスケールでは何も起きていないように見えます。
- 添付する前にフレームを確認する。 コンタクトシート(
ffmpeg -i before.mp4 -vf "select='not(mod(n\,15))',scale=320:-1,tile=6x3" -frames:v 1 sheet.png)を出力して目を通してください。Before の録画が After とまったく同じに見える場合は、通常はバグが微妙なのではなく、チェックアウトが反映されていないことを意味します。 - 焼き込みラベルは付けない。
### Beforeと### Afterの見出しがどちらがどちらかをすでに示しています。 - 短く保つ。 数秒のセットアップ、インタラクション、最後に一拍。それぞれ 10 秒未満にしてください。
gh pr create または gh pr edit で添付します(gh 2.99 以降、リポジトリ内で実行、絶対パス)。各ファイルは、それが説明する見出しの直下で、その段落の唯一の内容として本文中で参照すると、gh がその参照をアップロード済みアセットに書き換えます:
gh pr edit <number> --body-file body.md --attach /abs/path/before.mp4 --attach /abs/path/after.mp4
### Before
<mechanism>

### After
<behavior now>

変更の種類
[x]でちょうど 1 つの種類にチェックを入れる- チェックの付いていない項目は削除する
テスト計画
- 該当する場合は手動テストの手順を列挙する
- 手動でテストできない変更の場合は番号付きリストを削除する
- 含まれるテストの種類のチェックボックスにチェックを入れる
リリースノート
- ユーザーに影響する変更を説明する簡潔なメモを書く
- 命令形を使う: 「Add...」「Fix...」「Remove...」
- ユーザーに影響しない内部的な作業(CI、ツーリング、テストなど)の場合はこのセクションを完全に省略する
概念、例、FAQ(レビュアーが本当に必要とする場合のみ)
これらは PR のサイズではなく、レビュアーの必要性を基準にしてください。大きな PR だからといって表を追加する理由にはなりません。変更を追うために共有の語彙や使用例を必要とするレビュアーがいる場合が該当します。ほとんどの大きな PR はその基準を満たしません。満たす場合は、標準の ### Change type / ### Test plan / ### Release notes ブロックの上に関連するセクションを含めてください。
ガードレール: ある行は、コードが語っていないことを語っている場合にのみ、その場所に置く価値があります。シグネチャをそのまま繰り返す Method | Description の表や、自明な名前に対する Concepts の行は diff の重複です — 削除してください。迷ったら、省いてください。
このメニューから、おおよそ次の順序で、当てはまるものだけを使ってください:
- Concepts — PR が導入する新しい用語/型を
Term | Type | Meaning列で示す表。読者が残りの説明を追うために共有の語彙を必要とする場合に使います。 - Module augmentation — PR が拡張可能なインターフェースを公開する場合に、利用者が新しい型をどのように拡張するかを示す短いコードブロック。
- Editor API / Component props — 新しい公開サーフェス向けの
Method | DescriptionおよびProp | Type | Descriptionの表。 - Per-shape / per-feature breakdown — 影響を受ける各 shape/module が新しいシステムの下で何を返すか、または受け付けるかを示す表。
- Example — デフォルト実装が新しいシステムをどのように使うかを示す、現実的でコピー&ペースト可能なコードスニペットと、利用者がそれをどのようにオーバーライドするかを示す 2 つ目のスニペット。
- FAQ — 想定される「How do I…?」という質問と短いコードの回答。下流のユーザーが最初に手を伸ばすであろう、明らかなカスタマイズ経路をカバーします。
- New examples —
apps/examples/src/examples/の下に追加された新しいエントリの箇条書き。それぞれに 1 行の説明を付け、レビュアーが実行可能なデモをどこで探せばよいか分かるようにします。
参考: tldraw/tldraw#8410 は、これらすべてのセクションをまとめた良い実例です。
これらのセクションは ### Change type の前に置きます。標準の ### Change type / ### Test plan / ### Release notes / ### API changes / ### Code changes ブロックは、通常どおり最後にいつもの順序で記載します。
API changes セクション
変更が api-report.md に影響する場合に含めます:
### API changes
- Added `Editor.newMethod()` for X
- Breaking! Removed `Editor.oldMethod()`
- Changed `Editor.method()` to accept optional `options` parameter
Code changes の表
この表は「diff を繰り返さない」という方針に対する意図的な例外です。これは散文のふりをした洞察ではなく、高レベルの索引です。レビュアーがスコープを一目で判断できるようにします — コアコード、テスト、生成物、ツーリングのうちどれがどれだけを占めるか — そしてどこを見るべきかを決められます。常に含めてください。
次の各セクションについて、正味の LOC 変更を含む表を作成してください。すべての行の合計は PR の diff 全体と一致しなければなりません。変更のない行は省略してください。
- Core code — SDK パッケージ(
packages/)のソース。テストと API レポートを除く - Tests — ユニットテスト、e2e テスト(
*.test.*、e2e/) - Automated files — 生成されたファイル(例:
api-report.api.md、スナップショット) - Documentation — ドキュメントサイトと例(
apps/docs/、apps/examples/) - Apps — アプリケーションコード(
apps/dotcom/、apps/mcp-app/、apps/vscode/など)。e2e テストを除く - Templates — スターターテンプレート(
templates/) - Config/tooling — 設定ファイル、ロックファイル、lint 設定、CI、ビルドスクリプト(
.oxlintrc.json、pnpm-lock.yamlなど)
### Code changes
| Section | LOC change |
| --------------- | ---------- |
| Core code | +10 / -2 |
| Tests | +5 / -0 |
| Automated files | +0 / -1 |
| Documentation | +2 / -0 |
| Apps | +3 / -1 |
| Templates | +0 / -0 |
| Config/tooling | +1 / -0 |
関連する issue
この PR が対応する関連 issue を検索してリンクしてください。
コメントの精査
説明文ではなく差分を事前に確認します。追加されたコードと同じくらい注意深く、追加されたコメントを読み、PR を開く前に削ります。
git diff origin/main...HEAD -U0 | grep -nE '^\+\s*(//|/\*|\*)'
出力内容をルートの AGENTS.md の Comments と照らし合わせて判断してください。このセクションが規則であり、ここでは繰り返しません。読み進める際に覚えておくべきテストはひとつです。
良いコメントは仕組みではなく、障害が起きる条件を説明します。
仕組みはすでに画面に表示されています。説明されていないのは、それがないと何が問題になるかです。コードの動作を説明するだけのブロックは、すべて削除できます。「そうでない場合は X」と書かれたブロックは、その文だけを残し、同じことを二度説明する段落は削ります。
問題は種類ではなく長さだと考えてください。 編集が必要な実質的なコメントブロックのほとんどは、すでに現実の要因を示しています。つまり、コメントの種類は適切でも、必要な長さの 2、3 倍になっています。そのため、通常の編集は削除ではなく、要点となる行まで短くすることです。
図、リスト自体が仕様となっている列挙されたケース、出典情報(Issue 番号、「X を試したところ Y になった」など)、不変条件を示すものは、そのまま残すか、最大限でも短くするだけにしてください。packages/* の @public な公開部分に関するドキュメントコメントは API リファレンスです。「コードに書かれていないことを説明している」という同じ基準で評価しますが、余計なものではなく、成果物の一部です。
事後レビューではなく事前に確認してください。今なら安く済みますが、後ではコストがかかります。自分のコードを言い直すコメントは水増しに見え、削除するためにレビューを一往復増やし、マージ後は誰も戻ってきて削除しません。変更の説明は PR 本文の役割です。差分に書くものではありません。
古くなった周辺の記述
追加されたコメントは問題の半分にすぎません。レビュー担当者が指摘することが多いのは、差分では変更されていないものの、差分との整合性がなくなったコメント、ドキュメント、テスト名です。たとえば、動作が変更された関数の上にあるドキュメントコメント、より多くの呼び出しを対象とするようになった catch のログメッセージ、古いパターンを説明したままのドキュメントページなどです。次を実行してください。
npx tsx skills/write-pr/scripts/touched-comments.ts
変更箇所から数行以内にある未変更のコメントと、差分で追加、削除、改名された宣言に言及するドキュメントが一覧表示されます。それぞれについて、新しいコードに照らして記述内容をすべて確認し、修正するか削除してください。このスクリプトはテスト名を対象としないため、変更したテストの周辺にある describe/it のタイトルは自分で読んでください。次に、PR の説明文も同じように確認します。動作を説明する文(「X が Y を行うようになった」「ヘルスチェックが Z を復旧する」、スケジュール、件数など)はすべて、最初の草稿ではなく、最終的な差分の内容に合っていなければなりません。
人間のメモ(正確に保持)
PR の作成者は、説明文の先頭に、🅯 や 👨 などの「人」を表す絵文字を添えて個人的なメモを書くことがよくあります。このブロックは人間が書いたものであり、読者はそのように信頼しています。
- 既存の PR 説明文を更新する際、本文が人を表す絵文字で始まる段落またはセクションから始まっている場合、それを先頭に一字一句そのまま保持しなければなりません。書き換え、折り返し、言い換え、タイトルの変更、「改善」は、わずかであっても行わないでください。
- 人間のメモが 1 段落より長い場合、末尾は
---の水平線で区切られています。人を表す絵文字から---まで(---を含む)をすべて正確に保持してください。 ---がない場合、人間のメモは人を表す絵文字で始まる先頭の段落だけです。- 編集はすべて、人間のメモより下(
---がある場合はその下)にある内容に対して行ってください。 - 新しい PR を作成する場合、人間のメモを作り出さないでください。作成者が追加できるようにしておいてください。
重要
- PR が AI ツールに直接関連する場合を除き、AI による帰属を記載しないでください。
- 説明文にタイトルケースを使わず、文頭のみ大文字にしてください。
- コミットの共同作成者として自分を記載しないでください。
- PR に
api-report.mdの変更が含まれる場合は、必ず API 変更セクションを設けてください。