個人で運用している画像変換サービスの保守に Claude を組み込んで、Issue を起点に PR ができあがる体制を作った(まあ Claude でなくてもいいんだけど)。人間がやるのはトリアージとマージだけ。半年くらい運用して形が固まってきたので書いておく。
全体像
入口は3つあって、どれも最終的に GitHub Issue に合流する。Issue になったあとの流れは共通。
flowchart TD
subgraph 入口
R[AI コードレビューの指摘]
E[エラートラッカーの検知]
C[コードベース調査]
end
R --> T{人間がトリアージ}
E --> T
C --> T
T -->|対応不要| D[既決事項ドキュメントに記録]
T -->|対応する| I[Issue 作成]
I -->|定期実行タスクが検出<br>または人間が指示| P[AI が PR 作成]
P --> REV[AI が PR をレビュー]
REV -->|指摘あり| FIX[人間がトリアージ<br>AI が修正・返信]
FIX --> REV
REV -->|OK| M[人間がマージ]
M --> REL[人間がリリース]
style T fill:#fff3cd,stroke:#b8860b,color:#333
style M fill:#fff3cd,stroke:#b8860b,color:#333
style REL fill:#fff3cd,stroke:#b8860b,color:#333
黄色が人間の仕事。方針は単純で、「やるかどうかの判断」は人間が持って、調査・実装・レビューといった作業は AI に任せる。人間のゲートは3つだけにした。
- 入口のトリアージ(指摘やエラーを Issue にするかどうか)
- PR のマージ
- リリース
逆に言うと、コードを書く・テストを書く・レビューコメントを書く・指摘に対応してコミットする、あたりは基本 AI の仕事になっている。
入口1: AI レビューの指摘
PR には後述する AI レビューが自動で付く。そこでの指摘のうち、その PR のスコープ外だけど直す価値がありそうなもの(ついでに見つかった別の問題とか)を Issue にして、このパイプラインに乗せる。
対応しないと決めた指摘も記録している。「対応不要」と判断したものはリポジトリ内の「レビュー既決事項」ドキュメントに理由付きで追記して、AI はレビュー前にこれを必ず読むルールにした。これをやらないと、AI は同じ指摘を PR のたびに繰り返してくる。再指摘していいのは「状況が変わった根拠を示せる場合だけ」と書いておいた。ただ増えすぎてもコンテキスト消費して困るので、それは今後の課題。
入口2: エラートラッカー
本番エラーは Airbrake で拾っている。新規エラーや急に増えたエラーは、Issueにして AI に調査させる。このときスタックトレースだけ渡すと、AI はその情報だけを元に間違えた解決策を書いてくることがある。なので実際のリクエスト内容(デバッグ用に保存してあるもの)やアクセスログも見てもらう。正しい結論にたどり着くことがおおいので「仮説より先に取得できる情報を見る」を徹底させて調査してもらう。その結果をIssueのコメントとして残してもらう。
入口3: コードベース調査
「この辺の実装を調査して、問題があれば Issue 化して」という使い方。依存ライブラリの更新影響とか、ドキュメントと実装の乖離とか、テストの抜けとか、定常的な棚卸しに向いている。ここは結構雑に依頼している。直接PR書いてもらうこともあるけどIssueは残してもらう。
Issue → PR
Issue ができたら、定期実行タスクが未対応の Issue を見つけて PR を作る。手元の Claude Code に Issue 番号を指定して作らせることが多い。Issue の本文やコメントで @claude をメンションして、GitHub Actions 上の claude-code-action に作らせるルートもある。(API料金かかるけど)
どのルートでも、feature ブランチを切って実装・テスト追加・push・PR 作成までやってくれる。
sequenceDiagram
actor H as 人間
participant GH as GitHub
participant CA as Claude
participant CI as CI<br>(test / lint)
H->>GH: Issue 作成
CA->>GH: 未対応 Issue を検出(定期実行)
Note over H,CA: 手動で Issue 番号を指定したり<br>@claude メンションで起動することもある
CA->>CA: 調査・実装・テスト追加
CA->>GH: feature ブランチを push
CA->>GH: PR 作成(Closes #N)
GH->>CI: テスト・lint が発火
CI-->>GH: 結果を PR に報告
ハマったところをいくつか。
GITHUB_TOKENで push すると CI が発火しない。GitHub の再帰防止の仕様で、GITHUB_TOKENによる push や PR 作成は他の workflow をトリガーしない。AI が作った PR にこそテストを回したいので、リポジトリにインストールした GitHub App のトークンを使うようにした- 同一 Issue / PR での実行は concurrency で直列化した。実装途中でキャンセルされると中途半端なコミットが残るので、cancel はせずキューイング
- AI 自身のトラッキングコメントで再帰起動しないように、actor が bot のときは除外
- ブランチ命名、PR タイトルの言語、ラベル付与、「Issue のスコープを超える変更をしない」みたいなルールは CLAUDE.md に書いておくと PR の品質が安定する
定期実行タスクにしているのはclaude desktopからレビューしてもらいたいため。(もともとはgithub actionsで動かしていたんだけど、claudeのAPIの利用料が思ったより高くなってしまったため移行した。即時性は落ちるけど、毎時実行で困っていない。)ルーティンがgithub eventで動かすことができるようなので定期実行ではなく、github eventで動かすようにした
PR → AI レビュー
PR ができると、定期実行タスクが未レビューの PR を見つけて ルーティンが動いてレビューする。レビュー観点はリポジトリ内にスキル(プロンプト)として置いてあって、インラインコメントで個別指摘、sticky な総評コメントで全体評価を付ける。レビュー済みコミットの SHA をコメント内に埋めておいて、再レビューが要るかどうかを判定している。
レビュー指摘への対応
ここは意図的に全自動にしていない。AI の指摘に AI が自動で対応するループは、誤指摘への過剰対応とか、nits への延々とした対応とか、レビューと修正の無限往復が目に見えているので。無限にやり取りされてトークンを消費するのが嫌だし。
実際は、人間が指摘を読んで対応要否を判断して、対応するものだけ手元の Claude Code に /review-fix <PR番号> で渡す。AI は1指摘1コミットで修正して、各指摘コメントに「AI が代理で対応した」ことを明記して返信する。
flowchart TD
REV[AI レビューの指摘] --> T{人間がトリアージ}
T -->|対応する| FIX["/review-fix<br>AI が修正・コミット・返信"]
T -->|対応不要| DOC[既決事項ドキュメントに追記<br>次回から再指摘されない]
FIX --> CHECK[人間が差分を確認]
CHECK --> M[マージ]
style T fill:#fff3cd,stroke:#b8860b,color:#333
style CHECK fill:#fff3cd,stroke:#b8860b,color:#333
style M fill:#fff3cd,stroke:#b8860b,color:#333
マージとリリースは人間
マージは CI(テスト・lint・シークレットスキャン)のパスをブランチ保護で必須にしたうえで、人間が押す。リリース(本番デプロイ)も人間。そのうちAIに渡してしまいたいので、deploy後のテストや監視のための環境を作成中
半年やってみて
- 最初からこの形を設計したわけではなくて、コードを書くところをAIに寄せて、Issue を作るところ、レビュー、と順々にAI に寄せていったら、結果として判断だけが人間に残った
- 一人でやっていると判断の経緯は脳みそに入っているからドキュメントは要らなかったんだけど、AI が入ったので既決事項をドキュメントに残すようにした。次に動く AI が参照できるので、同じ指摘が繰り返されなくなる
- テストはかなり細かく書く。デグレが起きても見つかるから安心
最終的には全部 AI に任せたいお気持ちはあるけど、その環境を作るのはもうちょっと道のりが長そう。





