AgentSkillsCN

codex-review

向 tmux 窗格中的 Codex 申请代码评审。若 Codex 不存在,则先创建并启动新窗格,再发起评审。实现由多位 Coding Agent 进行多角度评审。适用场景:用于“请求 Codex 评审”“codex-review”“委托其他代理进行评审”等请求。

SKILL.md
--- frontmatter
name: codex-review
description: tmux ペインの Codex にコードレビューを依頼する。Codex がいない場合は新規ペインを作成・起動してからレビューを依頼する。複数 Coding Agent による多角的レビューを実現。Use when: 「Codexにレビュー」「codex-review」「別エージェントにレビュー」などのリクエストで使用。
allowed-tools: Bash(tmux:*), Bash(git diff:*), Bash(git log:*), Bash(git status:*), Bash(sleep:*)

Codex Review スキル

tmux の別ペインで動作する Codex(Coding Agent)にコードレビューを依頼する。 複数の AI Agent を活用し、多角的な観点でのレビューを実現する。

実行フロー

Step 1: tmux セッション確認

bash
tmux list-panes -F '#{pane_index}:#{pane_current_command}:#{pane_pid}' 2>/dev/null

tmux 内で実行されていない場合はエラーを報告して終了する。

Step 2: Codex ペインの検出

自ペインを除外した上で、codex が動作中のペインを検出する。プロセス名チェックを優先し、画面テキスト検索はフォールバックとして使用する。

bash
# 自ペインの番号を取得
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

判定の優先順位:

  1. 自ペインを除外(誤検出防止)
  2. プロセス名に codex が含まれる(最も確実)
  3. 画面テキストに codex が含まれる(フォールバック)

Step 3-A: Codex が見つからない場合 → 新規ペイン作成

bash
# 現在のペイン番号を記録
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 に明示する。

bash
# 例: デフォルトの場合
git diff HEAD --name-only

4-3. 変更コンテキストの要約を作成

現在の会話のコンテキストから、以下を要約文として整理する。この要約をレビュープロンプトに含める。

  • 何を変更したか: 変更内容の概要(機能追加、バグ修正、リファクタリング等)
  • なぜ変更したか: 変更の目的・動機(ユーザーの要求、問題の発見等)
  • どう判断したか: 実装方針を選んだ理由(トレードオフ、設計判断等)
  • スコープ外: 意図的に変更しなかった箇所があれば明記(不要な指摘を防ぐ)

この要約は、Codex が「なぜこの変更が必要だったのか」を理解した上でレビューするために必須。 diff だけでは変更の意図が伝わらず、的外れな指摘が増える。

Step 5: レビューリクエストの送信 ← ループ開始点

再レビュー時は Step 9 からここに戻る。 初回とそれ以降でプロンプト内容が異なる(後述)。

tmux send-keys でレビュー依頼プロンプトを Codex ペインに送信する。

重要: テキストと Enter は必ず別の send-keys コールで送信する。 同時に送ると TUI アプリがペースト操作として一括受信し、Enter が改行文字として処理されてしまう。

bash
# OK: テキストとEnterを分離
tmux send-keys -t <CODEX_PANE> '<レビュープロンプト>'
sleep 0.5
tmux send-keys -t <CODEX_PANE> Enter
bash
# NG: テキストとEnterを同時送信(ペーストとして扱われる)
tmux send-keys -t <CODEX_PANE> '<レビュープロンプト>' Enter

Step 6: Polling でレビュー完了を待機

Codex のレビュー完了を polling で検知する。コンテキスト消費を避けるため、Bash の run_in_background で実行する。

差分検知方式: polling 開始前にマーカーの現在数を記録し、それより増えたら完了と判定する。これにより再レビューループで履歴にマーカーが蓄積しても正しく動作する。

手順:

  1. Step 5 でプロンプト送信した直後、polling 開始前に現在のマーカー数を取得する
  2. バックグラウンドでマーカー数の増加を監視する
bash
# Step 5 送信直後に現在のマーカー数を記録(run_in_background ではない通常の Bash で実行)
BASELINE=$(tmux capture-pane -t <CODEX_PANE> -p -S -1000 | grep -c '\[REVIEW_COMPLETE\]')
bash
# 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 時は以下を含める:

  1. Codex の指摘内容の要約
  2. 判断できない理由(どの情報が不足しているか)
  3. 想定される選択肢

ユーザーの回答を得てから、その指摘を「妥当(採用候補)」か「不当(却下)」に再分類する。

7-2. 指摘がゼロの場合 → ループ終了

Codex から指摘がない(問題なし)と報告された場合、Step 8 をスキップしてループを終了する。ユーザーにレビュー完了(問題なし)を報告する。

7-3. 全指摘の分類が確定したら → Step 8 へ

すべての指摘が「採用候補」または「却下」に分類できた状態で次に進む。

Step 8: 実装方針の決定とユーザー確認

8-1. 修正案の策定

採用候補の各指摘に対して、具体的な修正案を策定する:

  1. 各指摘に対して具体的な実装方法を検討する
  2. 修正が他の箇所に影響しないか確認する
  3. 却下した指摘についても却下理由を整理する

8-2. AskUserQuestion で修正案ごとにユーザー確認(必須)

**修正案が確定したら、必ず AskUserQuestion でユーザーに確認を取る。**自分が妥当と判断した場合でも、ユーザーの承認なしに実装に進んではならない。

**AskUserQuestion の question フィールドには改行(\n)を使い、読みやすく構造化すること。**1行に詰め込まない。

指摘ごとに以下のフォーマットで提示する:

code
【#番号 重要度】指摘タイトル\n
\n
問題: Codex が何を指摘したか\n
判断: 採用/却下とその理由\n
修正案: 具体的にどう直すか

良い例:

code
【#1 critical】Polling がプロンプト内のマーカーを誤検知する\n
\n
問題: 送信プロンプト自体に [REVIEW_COMPLETE] が含まれるため、Codex の応答前に polling が完了と判定してしまう\n
判断: 採用。今回実際に発生した\n
修正案: polling 開始前にマーカー数を記録し、増加分で完了を判定する「差分検知方式」に変更

悪い例:

code
【#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 には進まない)

終了時はユーザーにレビュー完了を報告する。

code
レビューループ:
Step 5 (送信) → Step 6 (polling待機) → Step 7 (妥当性判断) → Step 8 (ユーザー確認) → Step 9 (修正)
  ↑                                  |                |                                      |
  │                              タイムアウト      指摘ゼロ                                    |
  │                                  ↓              ↓                                       |
  ├────── コード修正あり → Step 5 へ戻る(再レビュー)──────────────────────────────────────────┘
  │
  終了 ← critical/high の新規指摘なし or 全指摘「対応しない」でコード変更なし

完了マーカー

レビュープロンプトには必ず以下の指示を含め、Codex にレビュー末尾で完了マーカーを出力させる:

code
レビューの最後に、必ず以下のマーカーを単独行で出力してください:
[REVIEW_COMPLETE]

レビュープロンプトのテンプレート

送信するプロンプトは以下の形式で構成する。 重要: tmux send-keys で送信するため、プロンプトはシングルクォートで囲み、内部のシングルクォートはエスケープする。

初回レビュー(デフォルト: git diff)

Step 4-3 で作成した変更コンテキスト要約を [変更コンテキスト] に埋め込むこと。

code
以下の変更をレビューしてください。

変更の背景: [変更コンテキスト: 何を・なぜ・どう判断して変更したかの要約]
変更ファイル: [4-2 で取得したファイル一覧]
スコープ外: [意図的に変更しなかった箇所があれば記載]

差分は git diff HEAD で確認してください。

レビュー観点:
1. バグ・ロジックエラー
2. セキュリティ脆弱性
3. パフォーマンス問題
4. 設計・アーキテクチャの改善点
5. 可読性・保守性

重要度別に分類して報告してください:
🔴 critical: 致命的問題(必ず修正)
🟡 high: 高優先度(強く推奨)
🟢 medium: 中優先度(推奨)
💬 info: 情報・質問

レビューの最後に、必ず以下のマーカーを単独行で出力してください:
[REVIEW_COMPLETE]

初回レビュー(特定ファイル)

code
以下のファイルをレビューしてください: [ファイルパス]

変更の背景: [変更コンテキスト: 何を・なぜ・どう判断して変更したかの要約]
スコープ外: [意図的に変更しなかった箇所があれば記載]

レビュー観点:
1. バグ・ロジックエラー
2. セキュリティ脆弱性
3. パフォーマンス問題
4. 設計・アーキテクチャの改善点

重要度別に分類して報告してください:
🔴 critical / 🟡 high / 🟢 medium / 💬 info

レビューの最後に、必ず以下のマーカーを単独行で出力してください:
[REVIEW_COMPLETE]

再レビュー(2回目以降)

tmux send-keys で直接送信する。以下のテンプレートの各セクションを実際の内容で埋めて送信すること。

code
前回のレビュー指摘を受けて修正しました。再レビューをお願いします。前回の指摘と対応: [各指摘の要約・判断・対応内容を列挙]。ユーザーとの協議事項: [AskUserQuestion で確認した質問・回答・反映内容]。修正差分は git diff HEAD で確認してください。再レビュー観点: 1.前回指摘が適切に修正されているか 2.修正で新たな問題が発生していないか 3.見落としがないか。重要度別に分類して報告してください: 🔴 critical / 🟡 high / 🟢 medium / 💬 info。最後に [REVIEW_COMPLETE] を単独行で出力してください。
bash
tmux send-keys -t <CODEX_PANE> '<上記テンプレートを埋めたプロンプト>'
sleep 0.5
tmux send-keys -t <CODEX_PANE> Enter

tmux send-keys の注意事項

プロンプトは直接 send-keys で送る

プロンプトは tmux send-keys で直接ペインに送信する。一時ファイルを経由する必要はない。

エスケープ処理

  • シングルクォート ''\'' に置換
  • バッククォート ` → エスケープまたは避ける
  • $ → リテラルとして送りたい場合はエスケープ

利用例

基本的な使い方

code
ユーザー: Codex にレビューして
→ git diff HEAD の変更をレビュー依頼

ブランチ全体のレビュー

code
ユーザー: Codex にこのブランチの変更をレビューして
→ git diff main...HEAD の変更をレビュー依頼

特定ファイル

code
ユーザー: Codex に src/auth.ts をレビューして
→ 指定ファイルのレビュー依頼