Codex Review スキル
tmux の別ペインで動作する Codex(Coding Agent)にコードレビューを依頼する。 複数の AI Agent を活用し、多角的な観点でのレビューを実現する。
実行フロー
Step 1: tmux セッション確認
tmux list-panes -F '#{pane_index}:#{pane_current_command}:#{pane_pid}' 2>/dev/null
tmux 内で実行されていない場合はエラーを報告して終了する。
Step 2: Codex ペインの検出
自ペインを除外した上で、codex が動作中のペインを検出する。プロセス名チェックを優先し、画面テキスト検索はフォールバックとして使用する。
# 自ペインの番号を取得
MY_PANE=$(tmux display-message -p '#{pane_index}')
# 全ペインを走査(自ペインを除外)
for pane_id in $(tmux list-panes -F '#{pane_index}'); do
[ "$pane_id" = "$MY_PANE" ] && continue
# 優先: プロセス名の検索
cmd=$(tmux list-panes -F '#{pane_index}:#{pane_current_command}' | grep "^${pane_id}:" | cut -d: -f2)
if echo "$cmd" | grep -qi 'codex'; then
echo "FOUND:$pane_id"
break
fi
# フォールバック: 画面テキストの検索
content=$(tmux capture-pane -t "$pane_id" -p 2>/dev/null | tail -20)
if echo "$content" | grep -qi 'codex'; then
echo "FOUND:$pane_id"
break
fi
done
判定の優先順位:
- •自ペインを除外(誤検出防止)
- •プロセス名に
codexが含まれる(最も確実) - •画面テキストに
codexが含まれる(フォールバック)
Step 3-A: Codex が見つからない場合 → 新規ペイン作成
# 現在のペイン番号を記録
CURRENT_PANE=$(tmux display-message -p '#{pane_index}')
# 右側に新しいペインを作成し、ペインIDを取得(-P で新ペインの情報を出力)
NEW_PANE=$(tmux split-window -h -c "#{pane_current_path}" -P -F '#{pane_index}')
# 新しいペインで codex を起動
tmux send-keys -t "$NEW_PANE" 'codex'
sleep 0.5
tmux send-keys -t "$NEW_PANE" Enter
# 元のペインにフォーカスを戻す
tmux select-pane -t "$CURRENT_PANE"
# Codex の起動を待つ
sleep 5
$NEW_PANE が Codex ペインの番号として以降のステップで使用される。
Step 3-B: Codex が見つかった場合
検出したペイン番号をそのまま使用する。
Step 4: レビュー対象の特定と変更コンテキストの整理
レビューを依頼する前に、対象・背景・意図を整理する。Codex が的確なレビューを行うために不可欠なステップ。
4-1. レビュー対象の決定
ユーザーの指示に応じてレビュー対象を決定する。
| ユーザー指示 | レビュー対象 | 取得方法 |
|---|---|---|
| 指定なし(デフォルト) | ステージング済み + 未ステージの変更 | git diff HEAD |
| 「最新コミット」 | 直近のコミット | git diff HEAD~1..HEAD |
| 「ブランチの変更」 | ブランチ全体の差分 | git diff main...HEAD |
| 特定ファイル指定 | 指定ファイル | ファイルパスを直接指定 |
4-2. 変更ファイル一覧の取得
diff から変更対象のファイル一覧を取得し、Codex に明示する。
# 例: デフォルトの場合 git diff HEAD --name-only
4-3. 変更コンテキストの要約を作成
現在の会話のコンテキストから、以下を要約文として整理する。この要約をレビュープロンプトに含める。
- •何を変更したか: 変更内容の概要(機能追加、バグ修正、リファクタリング等)
- •なぜ変更したか: 変更の目的・動機(ユーザーの要求、問題の発見等)
- •どう判断したか: 実装方針を選んだ理由(トレードオフ、設計判断等)
- •スコープ外: 意図的に変更しなかった箇所があれば明記(不要な指摘を防ぐ)
この要約は、Codex が「なぜこの変更が必要だったのか」を理解した上でレビューするために必須。 diff だけでは変更の意図が伝わらず、的外れな指摘が増える。
Step 5: レビューリクエストの送信 ← ループ開始点
再レビュー時は Step 9 からここに戻る。 初回とそれ以降でプロンプト内容が異なる(後述)。
tmux send-keys でレビュー依頼プロンプトを Codex ペインに送信する。
重要: テキストと Enter は必ず別の send-keys コールで送信する。 同時に送ると TUI アプリがペースト操作として一括受信し、Enter が改行文字として処理されてしまう。
# OK: テキストとEnterを分離 tmux send-keys -t <CODEX_PANE> '<レビュープロンプト>' sleep 0.5 tmux send-keys -t <CODEX_PANE> Enter
# NG: テキストとEnterを同時送信(ペーストとして扱われる) tmux send-keys -t <CODEX_PANE> '<レビュープロンプト>' Enter
Step 6: Polling でレビュー完了を待機
Codex のレビュー完了を polling で検知する。コンテキスト消費を避けるため、Bash の run_in_background で実行する。
差分検知方式: polling 開始前にマーカーの現在数を記録し、それより増えたら完了と判定する。これにより再レビューループで履歴にマーカーが蓄積しても正しく動作する。
手順:
- •Step 5 でプロンプト送信した直後、polling 開始前に現在のマーカー数を取得する
- •バックグラウンドでマーカー数の増加を監視する
# Step 5 送信直後に現在のマーカー数を記録(run_in_background ではない通常の Bash で実行) BASELINE=$(tmux capture-pane -t <CODEX_PANE> -p -S -1000 | grep -c '\[REVIEW_COMPLETE\]')
# run_in_background: true で実行する(BASELINE は上で取得した値を埋め込む)
BASELINE=<上で取得した値>
ELAPSED=0
TIMEOUT=600
while [ "$ELAPSED" -lt "$TIMEOUT" ]; do
OUTPUT=$(tmux capture-pane -t <CODEX_PANE> -p -S -1000)
COUNT=$(echo "$OUTPUT" | grep -c '\[REVIEW_COMPLETE\]')
if [ "$COUNT" -gt "$BASELINE" ]; then
echo "$OUTPUT"
break
fi
sleep 30
ELAPSED=$((ELAPSED + 30))
done
if [ "$ELAPSED" -ge "$TIMEOUT" ]; then
echo "TIMEOUT: レビュー完了を ${TIMEOUT}秒以内に検知できませんでした"
fi
polling の仕様:
- •実行方法: Bash ツールの
run_in_background: trueを使用し、メインコンテキストを消費しない - •チェック間隔: 30秒
- •完了判定:
[REVIEW_COMPLETE]の出現回数が BASELINE より増加した時点 - •タイムアウト: 10分(600秒)。超過時はユーザーに報告してループを終了する(Step 7 には進まない)
- •結果取得: background タスクの出力を
ReadツールまたはTaskOutputで読み取る
Step 7: レビュー結果の妥当性判断
Codex から返ってきたレビュー内容を以下の観点で精査する。盲目的に受け入れず、必ず自分で判断する。
各指摘を以下の分類に振り分ける:
| 分類 | 条件 | 例 |
|---|---|---|
| 妥当(採用候補) | 明らかなバグ・脆弱性の指摘 | null参照、off-by-one、XSS など |
| 不当(却下) | 文脈の誤解、YAGNI 違反、既存規約との矛盾 | 対象外コードへの言及、過度な抽象化提案 |
| 判断材料不足 | プロジェクト固有の事情が絡み、自分だけでは判断できない | ビジネスロジック、外部制約、技術的負債 |
7-1. 判断材料不足の指摘 → AskUserQuestion で情報収集
判断材料が足りない指摘がある場合、まず AskUserQuestion でユーザーに背景情報を確認する。
AskUserQuestion 時は以下を含める:
- •Codex の指摘内容の要約
- •判断できない理由(どの情報が不足しているか)
- •想定される選択肢
ユーザーの回答を得てから、その指摘を「妥当(採用候補)」か「不当(却下)」に再分類する。
7-2. 指摘がゼロの場合 → ループ終了
Codex から指摘がない(問題なし)と報告された場合、Step 8 をスキップしてループを終了する。ユーザーにレビュー完了(問題なし)を報告する。
7-3. 全指摘の分類が確定したら → Step 8 へ
すべての指摘が「採用候補」または「却下」に分類できた状態で次に進む。
Step 8: 実装方針の決定とユーザー確認
8-1. 修正案の策定
採用候補の各指摘に対して、具体的な修正案を策定する:
- •各指摘に対して具体的な実装方法を検討する
- •修正が他の箇所に影響しないか確認する
- •却下した指摘についても却下理由を整理する
8-2. AskUserQuestion で修正案ごとにユーザー確認(必須)
**修正案が確定したら、必ず AskUserQuestion でユーザーに確認を取る。**自分が妥当と判断した場合でも、ユーザーの承認なしに実装に進んではならない。
**AskUserQuestion の question フィールドには改行(\n)を使い、読みやすく構造化すること。**1行に詰め込まない。
指摘ごとに以下のフォーマットで提示する:
【#番号 重要度】指摘タイトル\n \n 問題: Codex が何を指摘したか\n 判断: 採用/却下とその理由\n 修正案: 具体的にどう直すか
良い例:
【#1 critical】Polling がプロンプト内のマーカーを誤検知する\n \n 問題: 送信プロンプト自体に [REVIEW_COMPLETE] が含まれるため、Codex の応答前に polling が完了と判定してしまう\n 判断: 採用。今回実際に発生した\n 修正案: polling 開始前にマーカー数を記録し、増加分で完了を判定する「差分検知方式」に変更
悪い例:
【#1 critical】Polling がプロンプト内の [REVIEW_COMPLETE] を誤検知する。今回実際に発生。修正案: マーカー出現回数をカウントし、2回以上で完了と判定する
ユーザーの判断を受けて、最終的な実装方針を確定する。
Step 9: 修正の実装 → 再レビュー or 終了
Step 8 でユーザーが承認した方針に基づきコードを修正する。
分岐: 再レビューが必要か判定
| 条件 | アクション |
|---|---|
| 実際にコード修正を行った | Step 5 に戻って再レビュー。再レビュープロンプトに判断経緯とコンテキストを含める |
| 全指摘が「対応しない」とユーザーが判断し、コード修正がない | ループ終了。再レビュー不要 |
ループの終了条件
以下のいずれかを満たした場合にループを終了する:
- •Codex から指摘がゼロ(Step 7-2 で即終了)
- •Codex から新たな critical / high の指摘がない(残りが medium / info のみ → ユーザーに報告するが対応は任意。ループは終了する)
- •ユーザーが全指摘を「対応しない」と判断し、コード変更がない
- •Polling がタイムアウトした(10分経過)→ ユーザーに報告してループを終了する(Step 7 には進まない)
終了時はユーザーにレビュー完了を報告する。
レビューループ: Step 5 (送信) → Step 6 (polling待機) → Step 7 (妥当性判断) → Step 8 (ユーザー確認) → Step 9 (修正) ↑ | | | │ タイムアウト 指摘ゼロ | │ ↓ ↓ | ├────── コード修正あり → Step 5 へ戻る(再レビュー)──────────────────────────────────────────┘ │ 終了 ← critical/high の新規指摘なし or 全指摘「対応しない」でコード変更なし
完了マーカー
レビュープロンプトには必ず以下の指示を含め、Codex にレビュー末尾で完了マーカーを出力させる:
レビューの最後に、必ず以下のマーカーを単独行で出力してください: [REVIEW_COMPLETE]
レビュープロンプトのテンプレート
送信するプロンプトは以下の形式で構成する。 重要: tmux send-keys で送信するため、プロンプトはシングルクォートで囲み、内部のシングルクォートはエスケープする。
初回レビュー(デフォルト: git diff)
Step 4-3 で作成した変更コンテキスト要約を [変更コンテキスト] に埋め込むこと。
以下の変更をレビューしてください。 変更の背景: [変更コンテキスト: 何を・なぜ・どう判断して変更したかの要約] 変更ファイル: [4-2 で取得したファイル一覧] スコープ外: [意図的に変更しなかった箇所があれば記載] 差分は git diff HEAD で確認してください。 レビュー観点: 1. バグ・ロジックエラー 2. セキュリティ脆弱性 3. パフォーマンス問題 4. 設計・アーキテクチャの改善点 5. 可読性・保守性 重要度別に分類して報告してください: 🔴 critical: 致命的問題(必ず修正) 🟡 high: 高優先度(強く推奨) 🟢 medium: 中優先度(推奨) 💬 info: 情報・質問 レビューの最後に、必ず以下のマーカーを単独行で出力してください: [REVIEW_COMPLETE]
初回レビュー(特定ファイル)
以下のファイルをレビューしてください: [ファイルパス] 変更の背景: [変更コンテキスト: 何を・なぜ・どう判断して変更したかの要約] スコープ外: [意図的に変更しなかった箇所があれば記載] レビュー観点: 1. バグ・ロジックエラー 2. セキュリティ脆弱性 3. パフォーマンス問題 4. 設計・アーキテクチャの改善点 重要度別に分類して報告してください: 🔴 critical / 🟡 high / 🟢 medium / 💬 info レビューの最後に、必ず以下のマーカーを単独行で出力してください: [REVIEW_COMPLETE]
再レビュー(2回目以降)
tmux send-keys で直接送信する。以下のテンプレートの各セクションを実際の内容で埋めて送信すること。
前回のレビュー指摘を受けて修正しました。再レビューをお願いします。前回の指摘と対応: [各指摘の要約・判断・対応内容を列挙]。ユーザーとの協議事項: [AskUserQuestion で確認した質問・回答・反映内容]。修正差分は git diff HEAD で確認してください。再レビュー観点: 1.前回指摘が適切に修正されているか 2.修正で新たな問題が発生していないか 3.見落としがないか。重要度別に分類して報告してください: 🔴 critical / 🟡 high / 🟢 medium / 💬 info。最後に [REVIEW_COMPLETE] を単独行で出力してください。
tmux send-keys -t <CODEX_PANE> '<上記テンプレートを埋めたプロンプト>' sleep 0.5 tmux send-keys -t <CODEX_PANE> Enter
tmux send-keys の注意事項
プロンプトは直接 send-keys で送る
プロンプトは tmux send-keys で直接ペインに送信する。一時ファイルを経由する必要はない。
エスケープ処理
- •シングルクォート
'→'\''に置換 - •バッククォート
`→ エスケープまたは避ける - •
$→ リテラルとして送りたい場合はエスケープ
利用例
基本的な使い方
ユーザー: Codex にレビューして → git diff HEAD の変更をレビュー依頼
ブランチ全体のレビュー
ユーザー: Codex にこのブランチの変更をレビューして → git diff main...HEAD の変更をレビュー依頼
特定ファイル
ユーザー: Codex に src/auth.ts をレビューして → 指定ファイルのレビュー依頼