現役のITエンジニアが、 システム開発の現場で求められる知識を発信
記事検索
公開

Windows版Codexアプリで始めるHooks活用

生成AI関連

はじめに

WindowsでCodexアプリを使う場合、PowerShellで動くWindows native agentと、WSL2上で動くagentのどちらも選択できます。前回の記事では、Windows環境でCodexアプリを使い始めるための基本と、WSL2を前提にした考え方を整理しました。

生成AI関連
Windowsで始めるCodexアプリ入門

今回は、その次の段階としてCodexのHooksを取り上げます。Hooksは、Codexの作業ライフサイクルの途中で、チーム独自のスクリプトを決まったタイミングで実行するための仕組みです。OpenAIの公式ドキュメントでは、プロンプトの検査、会話ログの送信、作業終了時の検証、ディレクトリごとの追加コンテキスト注入などに使える拡張機構として説明されています(Hooks – Codex)。
本記事では、2026年5月18日時点の公式情報をもとに、Windows版CodexアプリをWSL2前提で使う場合のHooksセットアップ方法と、6種類のhookイベントの活用アイデアを整理します。
なお、本記事で使用しているCodexのバージョンは26.513.40821になります。生成AIツールの更新頻度は早いため、最新版においては再現しない可能性があること、事前にご了承ください。

Codex Hooksのライフサイクル

Hooksは、プロンプト送信前、ツール実行前後、承認要求時、応答終了前などのタイミングでスクリプトを実行できます。

Codex Hooksの基本

Codex Hooksは、特定のタイミングでスクリプトを実行する仕組みです。Hooksは既定で有効です。無効化したい場合は config.toml[features]hooks = false を設定します。管理者が強制的に無効化する場合は、requirements.toml 側でも同様に制御できます。
Hooksの定義場所として、公式ドキュメントでは主に次の形式が案内されています。

場所 使いどころ
~/.codex/hooks.json 個人の全プロジェクトに適用したいhookを置く
~/.codex/config.toml 個人設定と同じファイルでhookを管理する
<repo>/.codex/hooks.json リポジトリ単位で共有するhookを置く
<repo>/.codex/config.toml リポジトリ単位のCodex設定と一緒にhookを管理する

複数の場所に一致するhookがある場合、Codexはそれらをまとめて読み込みます。高い優先度の設定が低い優先度のhookを置き換えるのではなく、条件に一致したhookがすべて実行対象になります。この点は、通常の設定値の上書きとは異なるため注意が必要です。
また、プロジェクトローカルの .codex/ 配下にあるhookは、そのプロジェクトが信頼済みの場合に読み込まれます。未確認のリポジトリに置かれたスクリプトを自動実行しないための仕組みです。非管理下のcommand hookは、実行前にレビューと信頼設定が必要になります。CLIでは /hooks を使って、読み込まれたhookの確認、信頼、無効化を行えます。

Hooksの確認画面 CLI版

Codex CLIで /hooks を開き、読み込まれたhook、信頼状態、無効化状態を確認する画面例

Hooksの確認画面 アプリ版

Codexアプリで /hooks を開き、読み込まれたhook、信頼状態、無効化状態を確認する画面例

2026年5月時点で、実務上まず押さえたいhookイベントは次の6種類です。

イベント 実行タイミング 主な用途
SessionStart セッション開始時や再開時 プロジェクト固有の補足情報を読み込む
UserPromptSubmit ユーザープロンプト送信前 秘密情報や危険な依頼を検査する
PreToolUse ツール実行前 危険なコマンドや編集をブロックする
PermissionRequest Codexが承認を求める直前 承認ポリシーを自動判定する
PostToolUse ツール実行後 実行結果を検査し、追加コンテキストを渡す
Stop Codexが応答を終えようとした時 終了前チェックや追加検証を促す

command hookには、共通してJSONオブジェクトが標準入力で渡されます。たとえば、作業ディレクトリ、セッションID、現在のモデル、hookイベント名などです。イベントごとに、プロンプト本文、ツール名、ツール入力、ツール出力などが追加されます。
重要なのは、Hooksをセキュリティ境界そのものと考えないことです。OpenAIのドキュメントでも、PreToolUse はガードレールであり、完全な強制境界ではないと説明されています。管理者ポリシー、sandbox、権限設定、レビュー運用と組み合わせて使う必要があります。

生成AI関連
AGENTS.mdとは?AIコーディングエージェントに渡す「プロジェクトの取扱説明書」を解説

WSL2上にHooksをセットアップする

ここでは、リポジトリ単位で共有する前提で、.codex/hooks.json.codex/hooks/ にhookを配置する例を示します。Windows版CodexアプリでagentをWSLに切り替えている場合、hookコマンドもWSL側の環境で実行される想定です。
まず、リポジトリルートでディレクトリを用意します。

bash

mkdir -p .codex/hooks
uv init --bare .codex/hooks-runtime

hookスクリプトに外部ライブラリが不要であっても、実行環境を固定したい場合は、専用のuvプロジェクトを置いておくと管理しやすくなります。外部ライブラリが必要になった場合は、次のように追加できます。

bash

uv add detect-secrets --project .codex/hooks-runtime

次に、.codex/hooks.json を作成します。ここで重要なのは、後段の6つのHook活用アイデアを実際に動かすには、6種類のイベントを設定ファイル側でも登録しておく必要があることです。hooks.json に3種類だけ登録している場合、後段で紹介する SessionStartPermissionRequestPostToolUse などのスクリプトを置いても実行されません。
この記事では、次のファイル構成を前提にします。

text

.codex/
  hooks.json
  hooks/
    session_start.py
    user_prompt_guard.py
    pre_tool_use_policy.py
    permission_request_policy.py
    post_tool_use_review.py
    stop_check.py
  hooks-runtime/
    pyproject.toml

以下の hooks.json は、後段で掲載する6つのPythonスクリプトをそれぞれ対応するhookイベントに紐づける設定です。

hooks.json

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup|resume|clear",
        "hooks": [
          {
            "type": "command",
            "command": "bash -lc 'REPO=$(git rev-parse --show-toplevel); uv run --project \"$REPO/.codex/hooks-runtime\" python \"$REPO/.codex/hooks/session_start.py\"'",
            "statusMessage": "Loading session context"
          }
        ]
      }
    ],
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash -lc 'REPO=$(git rev-parse --show-toplevel); uv run --project \"$REPO/.codex/hooks-runtime\" python \"$REPO/.codex/hooks/user_prompt_guard.py\"'",
            "statusMessage": "Checking prompt"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "^Bash$",
        "hooks": [
          {
            "type": "command",
            "command": "bash -lc 'REPO=$(git rev-parse --show-toplevel); uv run --project \"$REPO/.codex/hooks-runtime\" python \"$REPO/.codex/hooks/pre_tool_use_policy.py\"'",
            "statusMessage": "Checking command"
          }
        ]
      }
    ],
    "PermissionRequest": [
      {
        "matcher": "^Bash$",
        "hooks": [
          {
            "type": "command",
            "command": "bash -lc 'REPO=$(git rev-parse --show-toplevel); uv run --project \"$REPO/.codex/hooks-runtime\" python \"$REPO/.codex/hooks/permission_request_policy.py\"'",
            "statusMessage": "Checking approval request"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "^Bash$",
        "hooks": [
          {
            "type": "command",
            "command": "bash -lc 'REPO=$(git rev-parse --show-toplevel); uv run --project \"$REPO/.codex/hooks-runtime\" python \"$REPO/.codex/hooks/post_tool_use_review.py\"'",
            "statusMessage": "Reviewing command output"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash -lc 'REPO=$(git rev-parse --show-toplevel); uv run --project \"$REPO/.codex/hooks-runtime\" python \"$REPO/.codex/hooks/stop_check.py\"'",
            "statusMessage": "Checking completion"
          }
        ]
      }
    ]
  }
}

この設定では、PreToolUsePermissionRequestPostToolUse の対象をBashに絞っています。apply_patch やMCPツールも対象にしたい場合は、matcherを ^Bash$ から Bash|apply_patch|mcp__filesystem__.* のような正規表現へ広げます。ただし、対象を広げるほど標準入力の tool_inputtool_response の形が増えるため、最初はBashから始めるほうが検証しやすいです。
hooks.json だけを置いて、参照先のPythonファイルが存在しない状態にするとhook実行時に失敗します。そのため、上記の6ファイルを .codex/hooks/ に配置します。まず、UserPromptSubmit の簡単なスクリプト例は次のとおりです。標準入力から受け取ったJSONを読み取り、APIキーや秘密鍵らしき文字列が含まれる場合にプロンプト送信をブロックします。

user_prompt_guard.py

import json
import re
import sys


payload = json.load(sys.stdin)
prompt = payload.get("prompt", "")

patterns = [
    r"sk-[A-Za-z0-9_-]{20,}",
    r"-----BEGIN (?:RSA |OPENSSH |EC )?PRIVATE KEY-----",
    r"AKIA[0-9A-Z]{16}",
]

if any(re.search(pattern, prompt) for pattern in patterns):
    print(
        json.dumps(
            {
                "decision": "block",
                "reason": "秘密情報の可能性がある文字列を検出したため、送信を停止しました。",
            },
            ensure_ascii=False,
        )
    )

この例はあくまで最小構成です。本番運用では、検出ルールをチームの情報管理基準に合わせる必要があります。また、過検知と検知漏れの両方が起こり得るため、hookだけに依存せず、入力ルール、権限設定、レビューを組み合わせてください。残りの5ファイルは、後段の各hookイベントの説明で同名のコードブロックとして掲載します。

WSL2利用時の重要な落とし穴

Windows版CodexアプリでWSL2上のプロジェクトを開いている場合でも、Windows版CodexアプリとWSL2内のCodex CLIが同じ設定ディレクトリを参照しているとは限りません。この挙動はHooksを有効化する際に見落としやすい点です。
OpenAIのWindows向けドキュメントでは、Windows版CodexアプリはWindowsネイティブ版Codexと同じく %USERPROFILE%\.codex をCodex homeとして使うと説明されています。一方で、WSL2内でCodex CLIを実行する場合、既定ではLinux側の ~/.codex が使われます。そのため、WSL2内のCLIで /hooks を開いてレビューし、~/.codex/config.tomlhooks.statetrusted_hash が作成されても、Windows版Codexアプリ側では同じ信頼状態として扱われない場合があります。

Windows版Codexアプリでhooksが検出されない画面

Windows版Codexアプリでは、WSL2側でレビュー済みでも No hooks found と表示される場合があります。

この状態では、WSL2側の config.toml には trusted_hash が存在するにもかかわらず、Windows版CodexアプリのHooks画面には No hooks foundProjects with configured hooks will appear here が表示されます。これはhook定義が破損しているというより、レビュー状態を保存したCodex homeがWindows版Codexアプリの参照先と一致していないことが原因です。

WSL2側のconfig.tomlにtrusted_hashが保存されている画面

WSL2側のCodex CLIでレビューすると、Linux側の ~/.codex/config.toml に信頼状態が保存される場合があります。

解消策: CODEX_HOMEをWindows側に向ける

この問題を避けるには、WSL2内のCodex CLIからもWindows版Codexアプリと同じCodex homeを参照するようにします。WSL2のシェルで次の環境変数を設定します。

bash

export CODEX_HOME="/mnt/c/Users/YOUR_WINDOWS_USER/.codex"

毎回設定するのではなく、恒久的に使う場合は ~/.bashrc~/.zshrc に追記します。

bash

echo 'export CODEX_HOME="/mnt/c/Users/YOUR_WINDOWS_USER/.codex"' >> ~/.bashrc
source ~/.bashrc

設定後、次のコマンドでWSL2内のCodex CLIがWindows側のCodex homeを参照する状態になっていることを確認します。

bash

echo "$CODEX_HOME"
ls "$CODEX_HOME"

そのうえで、あらためてCodex CLIまたはWindows版Codexアプリ側で /hooks を開き、対象のhookをレビューして信頼します。すでにWSL2側の ~/.codex/config.tomltrusted_hash が作成済みであっても、CODEX_HOME を切り替えた後はWindows側の %USERPROFILE%\.codex\config.toml に対して再度レビューする、という理解で進めると混乱を避けられます。

CODEX_HOMEをWindows側の.codexへ向けた確認画面

CODEX_HOMEをWindows側の .codex に向けることで、Windows版CodexアプリとWSL2内Codex CLIの設定を共有できます。

整理すると、Windows版CodexアプリでWSL2 agentを使う場合、プロジェクトの場所、agentの実行環境、Codex homeの場所を分けて考える必要があります。WSL2上のフォルダを開いていることは、WSL2側の ~/.codex をWindows版Codexアプリがそのまま使うことを意味しません。HooksをWSL2内CLIとWindows版Codexアプリの両方から扱う場合は、CODEX_HOME を明示して、設定と信頼状態の保存先をそろえておくことが重要です。

業務フロー別に見るHooksの組み合わせ

Hooksは、1つのイベントだけで完結させるよりも、複数のイベントを組み合わせることで効果が出ます。たとえば、プロンプト送信前に機密情報を止め、ツール実行前に危険操作を止め、作業終了前に検証漏れを止める、というように段階ごとに役割を分けます。

Hooks活用マップ

入力、実行、承認、検証、終了の各段階にHooksを配置し、Codexの作業をチームの運用ルールに近づけるイメージ

実務で使いやすい組み合わせ例を整理すると、次のようになります。

業務フロー 使うhook 実現したいこと
機密情報の混入防止 UserPromptSubmitPreToolUse プロンプトやコマンドに秘密情報が含まれる前提を早期に検出する
破壊的操作の抑止 PreToolUsePermissionRequest 削除、強制リセット、権限変更、外部公開などを人間の確認対象にする
テスト実行の徹底 PostToolUseStop 失敗ログを読み取り、未検証のまま終了しないようにする
ドキュメント更新の促進 SessionStartStop API変更や設定変更があった場合にREADMEや設計メモの確認を促す
依存関係追加の統制 PreToolUsePermissionRequestStop パッケージ追加時に理由、影響範囲、ロックファイル差分を確認する
チーム標準の読み込み SessionStartUserPromptSubmit ブランチ種別や作業内容に応じて、必要なルールだけをCodexへ渡す

このように整理しておくと、hookを「便利そうなスクリプト置き場」として増やすのではなく、どのリスクをどの段階で扱うかを設計しやすくなります。

6つのHook活用アイデア

ここからは、6種類のhookイベントごとに、Windows版CodexアプリとWSL2環境で使いやすい活用アイデアを整理します。

1. SessionStartでプロジェクト文脈を補う

SessionStart は、セッション開始時、再開時、クリア時に実行されます。公式ドキュメントでは、sourcestartupresumeclear のいずれかが渡され、標準出力のテキストやJSONの additionalContext を追加の開発者コンテキストとして渡せると説明されています。
活用例としては、リポジトリ内の軽量な運用メモを読み込み、Codexに補足する使い方があります。たとえば、WSL2環境ではプロジェクトの置き場所、Docker利用時の注意点、Windows側パスを避ける理由などを毎回短く渡せます。

session_start.py

import json


context = """
このリポジトリではCodex agentをWSL2で動かします。
依存関係の追加は事前確認を取り、作業終了前に関連テストを実行してください。
Windows側のパスではなく、WSL側のプロジェクトパスを基準に作業してください。
"""

print(
    json.dumps(
        {
            "hookSpecificOutput": {
                "hookEventName": "SessionStart",
                "additionalContext": context.strip(),
            }
        },
        ensure_ascii=False,
    )
)

AGENTS.mdにも同様の内容を書けますが、SessionStartはスクリプトで状況に応じた文脈を生成できる点が異なります。たとえば、現在のブランチ名、未コミット差分の有無、ローカル設定ファイルの存在確認などをもとに、必要な注意だけを渡す設計ができます。

2. UserPromptSubmitで入力を検査する

UserPromptSubmit は、ユーザーのプロンプトがCodexに送られる直前に実行されます。プロンプト本文を受け取れるため、秘密情報の貼り付け、顧客名や個人情報の混入、危険な依頼文の検査に向いています。
実務では、次のような検査が考えられます。

検査対象 hookの動き
APIキーや秘密鍵 送信をブロックし、マスキングして再入力するよう案内する
個人情報を含む可能性が高い文面 送信前に確認を求める
本番データの貼り付け ダミーデータや要約への置き換えを促す
曖昧な大規模変更依頼 先に調査や計画を求める追加コンテキストを渡す
本番障害のログ貼り付け 事象の要約とマスキング後の再入力を促す
顧客固有の設定値 汎用名への置換やサンプル値化を促す

Codexはローカルのコードベースを扱えるため、プロンプトに貼り付ける情報の管理は重要です。UserPromptSubmitを使うと、送信前の最後の確認点をチームのルールとして用意できます。

プロンプト送信ブロックの画面 1

プロンプト送信ブロックの画面 2

UserPromptSubmit hookが秘密情報らしき文字列を検出し、プロンプト送信を停止した画面例

さらに、UserPromptSubmitはブロックだけでなく追加コンテキストの注入にも使えます。たとえば、ユーザーが「本番障害を調査して」と入力した場合に、「まずログの機密情報を確認し、変更前に調査結果を説明する」という指示を追加できます。プロンプトを拒否するほどではないが、作業方針を補正したい場合に有効です。

3. PreToolUseで危険な操作を事前に止める

PreToolUse は、Bash、apply_patch、MCPツール呼び出しなど、対応しているツールの実行前に動きます。Bashの場合は、実行予定のコマンドが tool_input.command に入ります。
たとえば、次のようなコマンドを検出して拒否できます。

対象 判定例
破壊的な削除 rm -rfgit clean -fdxgit reset –hard を含む場合に拒否する
権限変更 chmod -R 777 のような広すぎる権限変更を拒否する
依存関係変更 npm installuv addpip install を承認フローへ誘導する
ネットワーク操作 curlwget、外部デプロイコマンドを検出して理由確認を求める
Git履歴操作 rebase、force push、タグ操作を確認対象にする
生成物の直接編集 generated、dist、build配下の編集を追加説明対象にする

最小限のスクリプト例は次のとおりです。

pre_tool_use_policy.py

import json
import re
import sys


payload = json.load(sys.stdin)
tool_input = payload.get("tool_input", {})
command = tool_input.get("command", "")

blocked_patterns = [
    r"\brm\s+-rf\b",
    r"\bgit\s+reset\s+--hard\b",
    r"\bgit\s+clean\s+-fdx\b",
    r"\bchmod\s+-R\s+777\b",
]

if any(re.search(pattern, command) for pattern in blocked_patterns):
    print(
        json.dumps(
            {
                "hookSpecificOutput": {
                    "hookEventName": "PreToolUse",
                    "permissionDecision": "deny",
                    "permissionDecisionReason": "リポジトリポリシーにより危険なコマンドをブロックしました。",
                }
            },
            ensure_ascii=False,
        )
    )

このhookは特に有用ですが、完全な強制境界ではありません。公式ドキュメントでも、すべてのシェル呼び出しを完全に捕捉するわけではないこと、別のツール経路で同等の作業が行われる可能性があることが説明されています。そのため、sandbox、承認ポリシー、Git差分レビューと併用する前提で設計します。

危険コマンドのブロック画面 1

危険コマンドのブロック画面 2

PreToolUse hookが破壊的なコマンドを検出し、実行前にブロックした画面例

PreToolUseでは、すべてを拒否するのではなく、追加コンテキストだけを返す設計も有効です。たとえば、package.json やロックファイルに触れるコマンドを検出した場合に、「依存関係を追加する場合は、追加理由、代替案、ライセンス、ビルド影響を説明する」という文脈をCodexに渡せます。これにより、変更そのものは進めつつ、レビューに必要な説明を出しやすくなります。

4. PermissionRequestで承認判断を標準化する

PermissionRequest は、Codexがユーザーに承認を求める直前に実行されます。たとえば、権限昇格や管理されたネットワークアクセスが必要な場合です。このhookは、許可、拒否、または通常の承認プロンプトへの委譲を返せます。
PreToolUseが「実行前の一般的な検査」だとすれば、PermissionRequestは「承認が必要な操作に対するチーム標準の判断」を置く場所です。

パターン 返す判断
社内で許可済みの依存取得先 allowで承認プロンプトを省略する
本番環境へ影響するコマンド denyで拒否する
判断に人間の確認が必要な操作 hookでは決めず、通常の承認フローに渡す
一時ディレクトリへの書き込み 作業内容に応じてallowにする
リポジトリ外のファイル操作 denyにするか、通常の承認フローに渡す

PermissionRequest の最小限のスクリプト例は次のとおりです。ここでは本番環境に影響しそうなコマンドやforce pushを拒否し、それ以外は何も返さずに通常の承認フローへ委譲します。最初から自動承認を広く使うより、denyと委譲を中心にしたほうが運用リスクを抑えやすくなります。

permission_request_policy.py

import json
import re
import sys


payload = json.load(sys.stdin)
tool_input = payload.get("tool_input", {})
command = tool_input.get("command", "")

deny_patterns = [
    r"\bgit\s+push\s+--force\b",
    r"\bkubectl\b.*\b(prod|production)\b",
    r"\baws\b.*\b(prod|production)\b",
]

if any(re.search(pattern, command, re.IGNORECASE) for pattern in deny_patterns):
    print(
        json.dumps(
            {
                "hookSpecificOutput": {
                    "hookEventName": "PermissionRequest",
                    "decision": {
                        "behavior": "deny",
                        "message": "本番環境やGit履歴に影響する可能性があるため、承認要求を拒否しました。",
                    },
                }
            },
            ensure_ascii=False,
        )
    )

管理者がポリシーを配布する場合は、requirements.toml とmanaged hooksを組み合わせる方法もあります。公式ドキュメントでは、管理者がhook設定を強制し、実際のスクリプトはMDMなどの端末管理で配布する構成が説明されています。個人の設定に依存させず、チーム全体で同じ承認方針を適用したい場合に有効です。

承認要求の画面 1

承認要求の画面 2

PermissionRequest hookと通常の承認フローを組み合わせ、権限が必要な操作を確認している画面例

特にチーム運用では、「毎回人間が承認する操作」と「ポリシー上は自動承認してよい操作」を分けると運用負荷を下げられます。ただし、自動承認の範囲を広げすぎると本来の確認点が失われます。最初はdenyと通常承認への委譲を中心にし、allowは影響範囲が明確な操作に限定するほうが安全です。

5. PostToolUseで実行結果を読み取る

PostToolUse は、対応ツールの実行後に動きます。Bashの場合は、コマンドが非ゼロ終了した場合にも実行されます。ツール入力に加えて、ツール出力も受け取れるため、テスト結果やLint結果を読み取り、Codexに追加コンテキストを渡す用途に向いています。
たとえば、テスト失敗時にログから失敗ファイルだけを抽出し、次の作業で見るべき範囲をCodexに伝えられます。

post_tool_use_review.py

import json
import sys


payload = json.load(sys.stdin)
tool_response = payload.get("tool_response", {})
text = json.dumps(tool_response, ensure_ascii=False)

if "FAILED" in text or "Error:" in text:
    print(
        json.dumps(
            {
                "decision": "block",
                "reason": "テストまたはコマンド出力に失敗を検出しました。失敗箇所を確認してから次の作業に進んでください。",
                "hookSpecificOutput": {
                    "hookEventName": "PostToolUse",
                    "additionalContext": "直前のコマンド出力に失敗が含まれています。差分を広げる前に原因を説明してください。",
                },
            },
            ensure_ascii=False,
        )
    )

注意点として、PostToolUseは実行後に動くため、すでに発生した副作用を取り消すことはできません。危険な操作を未然に止める用途はPreToolUseやPermissionRequestに寄せ、PostToolUseは結果の解釈や追加検証に使うのが適切です。

テスト失敗検出の画面 1

テスト失敗検出の画面 2

PostToolUse hookがテスト失敗を検出し、Codexに追加確認を促している画面例

PostToolUseは、レビュー観点の自動補足にも使えます。たとえば、テストコマンドの出力にsnapshot更新、型エラー、脆弱性警告、非推奨APIの警告が含まれている場合、それぞれの確認観点を追加できます。人間がログ全体を読む前に、Codex自身へ「次に確認すべきこと」を渡せる点が実務上の利点です。

6. Stopで終了前チェックを挟む

Stop は、Codexがターンを終了しようとした時に実行されます。公式ドキュメントでは、decision: "block" を返すと、ターンを拒否するのではなく、指定した理由を新しい継続プロンプトとしてCodexに渡して作業を続けると説明されています。
この性質は、終了前の品質チェックに適しています。たとえば、直近の応答に「テスト未実行」「確認できませんでした」のような文言がある場合に、次の確認を促せます。

stop_check.py

import json
import sys


payload = json.load(sys.stdin)

if payload.get("stop_hook_active"):
    sys.exit(0)

message = payload.get("last_assistant_message") or ""

markers = ["テストは実行していません", "確認できませんでした", "未検証"]

if any(marker in message for marker in markers):
    print(
        json.dumps(
            {
                "decision": "block",
                "reason": "未検証のまま終了しようとしています。実行できる確認コマンドを探し、実行できない場合は理由と代替確認を明示してください。",
            },
            ensure_ascii=False,
        )
    )

Stop hookは、品質ゲートとして便利です。ただし、無条件に継続させるとループに近い挙動になる可能性があります。hook入力には stop_hook_active が含まれるため、すでにStop hookで継続されたターンかどうかを見て、再実行を抑制する設計にしておくと安全です。

終了前チェックの画面 1

終了前チェックの画面 2

終了前チェックの画面 3

Stop hookが未検証の終了を検出し、追加確認の継続プロンプトを発生させた画面例

Stop hookで扱いやすい確認項目は、作業結果の自己申告に近い領域です。テスト未実行、差分未確認、ドキュメント未更新、手元で再現できなかった事象などは、最後に明示されるだけでもレビューしやすくなります。一方で、Stop hookにすべての品質判定を集約すると、作業の最後に大量の指摘が返る構成になります。できるだけUserPromptSubmit、PreToolUse、PostToolUseで早い段階に分散させ、Stopは最終確認に限定する設計が扱いやすいです。

運用時の注意点

Hooksは強力ですが、導入時にはいくつかの注意点があります。
第一に、hookを複雑にしすぎないことです。Codexの全作業に関わるため、重い処理や不安定な外部API呼び出しを入れると、通常の開発作業まで遅くなります。最初はプロンプト検査、危険コマンド検査、終了前チェックのような小さな用途から始めるのが現実的です。
第二に、チームで共有するhookはコードレビュー対象にすることです。hookはローカルで実行されるスクリプトであり、開発者の端末上のファイルやコマンドに関わります。.codex/hooks.json.codex/hooks/ 配下をGit管理する場合は、通常のアプリケーションコードと同じくレビューします。
第三に、AGENTS.mdやSkillsとの役割分担を明確にすることです。AGENTS.mdは、ビルド手順、テスト方法、コーディング規約のような静的な指示に向いています。Skillsは、特定作業の手順や参照ファイルをまとめる用途に向いています。一方、Hooksは、Codexの実行タイミングに合わせて判定や補足を行う仕組みです。

生成AI関連
生成AIのSkillsとは?仕組み・MCPやカスタム指示との違い・デモまで

役割を整理すると、次のようになります。

仕組み 向いている用途
AGENTS.md プロジェクト全体の静的な作業ルール
Skills 特定タスクの再利用可能な作業手順
Hooks 実行タイミングに応じた検査、補足、ブロック
Rules コマンド承認や権限の明示的な制御

第四に、WindowsとWSL2の境界を曖昧にしないことです。CodexアプリのagentをWSLにした場合、hookもWSL側のコマンドとして設計するほうが一貫します。Windows native agentで使うhookとWSL2 agentで使うhookでは、パス、シェル、インストール済みツールが異なります。チームで共有する場合は、どちらを前提にするかをAGENTS.mdやREADMEに明記しておくと、導入時の混乱を減らせます。

まとめ

Codex Hooksは、Codexの作業ライフサイクルにチーム独自のスクリプトを組み込むための仕組みです。Windows版CodexアプリをWSL2前提で使う場合、Bashやuvを前提にhookスクリプトを整理できるため、Linux寄りの開発環境と合わせやすくなります。
今回紹介した6種類のhookは、それぞれ役割が異なります。SessionStartは作業開始時の文脈補足、UserPromptSubmitは入力検査、PreToolUseは実行前ガード、PermissionRequestは承認判断、PostToolUseは実行結果の解釈、Stopは終了前チェックに向いています。
一方で、hookは万能なセキュリティ機構ではありません。sandbox、承認ポリシー、Rules、Git差分レビュー、AGENTS.md、Skillsと組み合わせ、チームの開発フローの中で段階的に導入することが重要です。まずはプロンプト検査や危険コマンド検査のように効果が見えやすい箇所から始め、運用しながらルールを洗練させるのがよいでしょう。

生成AI活用支援サービスのご紹介

Tech Funでは、お客様のフェーズに合わせ、生成AI活用に向けた支援を3つのパックでご提供しています。

  1. 無料診断パック:業務・プロセスの現状を無料で診断し、生成AI活用の可能性をレポートします。
  2. 検証(PoC)パック:診断で有効性が確認された業務を対象に、プロトタイプ構築を支援します。
  3. コンサルティングサービス:生成AI導入戦略の策定から運用体制構築までを包括的に支援します。

生成AIに限らず、Web・業務システム開発やインフラ設計など、技術領域を問わずご相談を承っています。「何から始めれば良いか分からない」という段階でも構いませんので、ぜひお気軽にお問い合わせください。

執筆・編集

Tech Fun Magazine R&Dチーム
Tech Funの生成AI研究に携わるエンジニアが、最新のAIモデル動向やプロンプト設計、実業務への応用手法など、生成AIに特化した知見を執筆・編集しています。
モデル評価や業務シナリオに応じたAI活用設計など、日々のR&D活動で得られる実践的なノウハウをわかりやすく紹介します。

ARTICLE
生成AI関連記事一覧

生成AI関連

Windows版Codexアプリで始めるHooks活用

生成AI関連

生成AIのSkillsに同梱するPythonスクリプトの便利…

生成AI関連

Windowsで始めるCodexアプリ入門

生成AI関連

Claude DesignとClaude Codeを連携する…

生成AI関連

ChatGPT Workspace Agentsの実務活用例…

生成AI関連

ChatGPT Workspace Agentsとは?チーム…

生成AI関連

Claude Designとは?対話しながらデザイン・プロト…

生成AI関連

AI時代の設計書の在り方を考える

生成AI関連

生成AIのバッチAPIとは

記事一覧を見る