概要

Hooks (フック) は、OpenAI Codex CLIのライフサイクルイベントに反応してカスタムスクリプトを自動実行する仕組みである。

Codexがセッションを開始したとき、ツールを呼び出す直前・直後、ユーザがプロンプトを送信したとき等、各タイミングで任意のシェルコマンドやスクリプトを介入させることができる。

Hooksの主な用途を以下に示す。

Hooksの主な用途
用途 説明
ログ記録 ツール呼び出しの履歴やセッション情報を外部ファイルやサービスに記録する。
プロンプト検証 ユーザが送信したプロンプトの内容を検査して、不正なリクエストをブロックする。
メモリ生成 セッション終了後に要約や作業ログを自動生成して蓄積する。
ツール使用前後処理 Linterや静的解析ツールをツール呼び出しの前後に実行する。


Hooks機能は2026年5月時点では実験的機能 (experimental) として提供されており、将来的に変更・削除される可能性がある。
本番環境への適用前に十分なテストを行うことを推奨する。

Hooksと AGENTS.md はどちらもCodexの動作を制御するが、役割が明確に異なる。

AGENTS.md と Hooks の役割の違い
項目 AGENTS.md (ガイダンス) Hooks (強制)
制御方式 エージェントへの指示・提案 イベントへの強制的な介入
実行タイミング セッション開始時に一括読み込み 各ライフサイクルイベントで逐次実行
記述形式 Markdown JSON / TOML + 任意のシェルコマンド
主な用途 コーディング規約・ビルド手順の案内 Linter実行、危険コマンドのブロック、監査ログ


AGENTS.mdで「コミット前にlintを実行すること」とガイダンスを書き、Hooksで実際にLinterをPre-commitで強制実行するという組み合わせが典型的な使い方である。


有効化方法

Hooks機能はフィーチャーフラグで有効化する。

~/.codex/config.toml (ユーザグローバル) または <プロジェクトルート>/.codex/config.toml (プロジェクト固有) に以下のセクションを追加する。

 [features]
 codex_hooks = true


フラグを追加した後はCodexを再起動して設定を反映させる。


ファイル配置場所とレイヤー構造

Hooksの設定ファイルは2つのレイヤーに分けて配置できる。

ユーザ層 (常に読み込まれる)

ユーザ層の設定は、プロジェクトの信頼状態に関わらず常に読み込まれる。

  • ~/.codex/hooks.json
    JSON形式のHooks設定ファイル
  • ~/.codex/config.toml[hooks] セクション
    TOML形式でインラインに記述する方法


プロジェクト層 (信頼済プロジェクトのみ)

プロジェクト層の設定は、そのプロジェクトが信頼済み (trusted) の場合のみ読み込まれる。

  • <プロジェクトルート>/.codex/hooks.json
    リポジトリ固有のJSON形式のHooks設定ファイル
  • <プロジェクトルート>/.codex/config.toml[hooks] セクション
    リポジトリ固有のTOML形式のHooks設定


untrustedプロジェクトでのスキップ

プロジェクトが未信頼 (untrusted) の場合、プロジェクト層のHooks設定はスキップされる。

  • スキップされるもの
    <プロジェクトルート>/.codex/hooks.json および <プロジェクトルート>/.codex/config.toml[hooks] セクション
  • 常に実行されるもの
    ユーザ層 (~/.codex/hooks.json 等) のHooks設定


信頼済プロジェクトへの変更方法は ~/.codex/config.tomlproject_trust = true を指定するか、初回起動時の確認ダイアログで承認する。
詳細は、Codexの設定 - AGENTS.md#信頼されていないプロジェクトでの動作信頼されていないプロジェクトでの動作 セクションを参照すること。


サポートされるHookイベント

下表に、2026年5月時点でサポートされているHookイベントを示す。

サポートされる Hookイベント一覧
イベント名 トリガータイミング matcher対応
SessionStart セッションの開始、再開、クリア時 startup / resume / clear
PreToolUse ツール呼び出しの直前 ツール名
PermissionRequest ツールの実行許可要求時 ツール名
PostToolUse ツール呼び出しの直後 ツール名
UserPromptSubmit ユーザがプロンプトを送信した時 非対応
Stop エージェントが応答を停止した時 非対応



PreToolUse / PostToolUse

PreToolUseの主な機能

PreToolUse はツール呼び出しの直前に実行されるHookである。

  • ツール名と完全なコマンド引数を受信できる。
  • 引数の検証やリスクの高いツールのブロックに使用する。
  • systemMessage フィールドを使用して、Codexへのフィードバックを返せる。


下表に、対応するツールを示す。

対応するツール
ツール 説明
Bash シェルコマンドの実行前に介入できる。
apply_patch ファイルへのパッチ適用前に内容を検証できる。
MCPツール呼び出し MCPサーバ経由のツール実行前に介入できる。


PostToolUseの主な機能

PostToolUse はツール呼び出しの直後に実行されるHookである。

  • ツール実行結果の検証や監査に使用する。
  • 自動的な警告メッセージをCodexに返せる。
  • 実行ログをメモリやファイルに記録できる。


下表に、PostToolUse でサポートされている応答フィールドを示す。

PostToolUse でサポートされている応答フィールド
フィールド 説明
systemMessage Codexへのフィードバックメッセージ
continue: false 後続処理を中断させる。
stopReason 中断理由の文字列


現在の制限 (2026年5月)

以下に示す制限が存在する。

  • PreToolUseadditionalContext フィールドに未対応である。
    Claude Code形式のコンテキスト注入は現時点では使用できない。
  • PermissionRequest Hookでは continuestopReasonsuppressOutput フィールドに未対応である。



hooks.jsonフォーマット

hooks.json ファイルはJSON形式でHooksを定義する。

PreToolUsePostToolUse の両方を含む例を以下に示す。

 {
    "PreToolUse": [
       {
          "matcher": "Bash",
          "hooks": [
             {
                "type": "command",
                "command": "/home/user/.codex/hooks/pre-bash-check.sh",
                "statusMessage": "Bashコマンドを検証中...",
                "timeout": 30
             }
          ]
       }
    ],
    "PostToolUse": [
       {
          "matcher": "Bash",
          "hooks": [
             {
                "type": "command",
                "command": "python3 /home/user/.codex/hooks/post-tool-logger.py",
                "statusMessage": "ツール実行ログを記録中...",
                "timeout": 60
             }
          ]
       },
       {
          "matcher": "apply_patch",
          "hooks": [
             {
                "type": "command",
                "command": "/home/user/.codex/hooks/run-linter.sh",
                "statusMessage": "Linterを実行中...",
                "timeout": 120
             }
          ]
       }
    ],
    "SessionStart": [
       {
          "matcher": "startup",
          "hooks": [
             {
                "type": "command",
                "command": "echo 'Codex session started' >> /tmp/codex-session.log"
             }
          ]
       }
    ]
 }


下表に、各フィールドの説明を示す。

各フィールドの説明
フィールド名 説明
matcher イベントをフィルタリングするパターン文字列
ツール名、正規表現、またはワイルドカードを指定できる。
hooks マッチした場合に実行するHookのリスト
type Hookの種類
現時点では "command" のみサポートされる。
command 実行するシェルコマンドまたはスクリプトのパス
statusMessage Hook実行中にCLIに表示されるステータスメッセージ (省略可能)
timeout コマンドのタイムアウト秒数 (省略可能: デフォルトは600秒)



config.toml インライン設定

hooks.json を使用せず、config.toml 内に直接Hooksを記述することもできる。

 [features]
 codex_hooks = true
 
 [[hooks.PreToolUse]]
 matcher = "Bash"
 
    [[hooks.PreToolUse.hooks]]
    type = "command"
    command = "/home/user/.codex/hooks/pre-bash-check.sh"
    statusMessage = "Bashコマンドを検証中..."
    timeout = 30
 
 [[hooks.PostToolUse]]
 matcher = "apply_patch"
 
    [[hooks.PostToolUse.hooks]]
    type = "command"
    command = "/home/user/.codex/hooks/run-linter.sh"
    statusMessage = "Linterを実行中..."
    timeout = 120
 
 [[hooks.SessionStart]]
 matcher = "startup"
 
    [[hooks.SessionStart.hooks]]
    type = "command"
    command = "echo 'Session started' >> /tmp/codex.log"



matcher パターン

matcher フィールドには、下表に示すパターンを指定できる。

matcher パターン一覧
パターン 説明 使用例
空文字 "" 全てのイベントにマッチする 全ツール呼び出しを記録したい場合
ワイルドカード * 全てのイベントにマッチする (空文字と同等) 全ツール呼び出しを対象にしたい場合
ツール名 (完全一致) 指定したツール名にのみマッチする "Bash""apply_patch"
正規表現 正規表現パターンにマッチするツール名に適用される apply_patch"
startup セッション新規開始時にマッチする (SessionStart専用) 初期化処理を実行したい場合
resume セッション再開時にマッチする (SessionStart専用) 再開時のみ処理したい場合
clear セッションのクリア時にマッチする (SessionStart専用) クリア後の初期化処理をしたい場合



設定パラメータ詳細

Hooks設定パラメータ一覧
パラメータ 必須/任意 説明
command 必須 実行するシェルコマンドまたはスクリプトの絶対パス
シェル変数や引数も指定できる。
type 必須 Hookの種類
現在は "command" のみサポートされる。
statusMessage 任意 Hook実行中にCLI画面に表示されるメッセージ
ユーザへの進捗通知に使用する。
timeout 任意 Hookコマンドのタイムアウト秒数。デフォルトは600秒。
タイムアウト超過時はHookをスキップして処理を継続する。
matcher 任意 イベントのフィルタリングパターン
省略時または * 指定時は全イベントにマッチする。



Hookコマンドの入出力

stdin (Hook受信)

Hookコマンドは標準入力 (stdin) からJSON形式のイベント情報を受け取る。

受信するJSONの例を以下に示す。

 {
    "session_id": "sess_abc123def456",
    "transcript_path": "/home/user/.codex/transcripts/sess_abc123def456.jsonl",
    "cwd": "/home/user/projects/my-project",
    "hook_event_name": "PreToolUse",
    "model": "codex-mini-latest",
    "turn_id": "turn_xyz789",
    "tool_name": "Bash",
    "tool_input": {
       "command": "npm test"
    }
 }


下表に、主なフィールドの説明を示す。

共通フィールド
フィールド 説明
session_id 現在のCodexセッションの識別子
transcript_path セッションのトランスクリプト (会話ログ) が保存されているファイルのパス
cwd Codexが起動された時点での作業ディレクトリ
hook_event_name トリガーしたHookイベント名
model 現在使用中のモデル名
turn_id 現在のターン (1回の応答サイクル) の識別子
ターンスコープHookはこの値を含む。


stdout (Hook応答)

HookコマンドはJSONを標準出力 (stdout) に返すことにより、Codexの動作を制御できる。

応答JSONの例を以下に示す。

 {
    "continue": true,
    "stopReason": "",
    "systemMessage": "コマンドの検証に成功しました。",
    "suppressOutput": false
 }


下表に、応答フィールドの説明を示す。

共通応答フィールド
フィールド 説明
continue false に設定すると、後続の処理 (ツール実行またはエージェントの継続) を中断する。
stopReason continue: false 時に表示される中断理由のメッセージ。
systemMessage Codexのコンテキストに追加されるシステムメッセージ。
エージェントへのフィードバックに使用する。
suppressOutput true に設定すると、ツールの出力をエージェントのコンテキストから除外する。


exit code 0 かつ 出力なし (または空のJSON) の場合は正常終了として処理を継続する。


Windows管理型Hooks

Windows環境では、組織の管理者がシステム全体に適用する強制Hooksを設定できる。

Windows管理型Hooksの設定

requirements.toml で管理者が管理型Hooksを定義する。

管理型Hooksのディレクトリは hooks.windows_managed_dir 設定キーで指定する。

 [hooks]
 windows_managed_dir = "C:\\ProgramData\\Codex\\ManagedHooks"


Linux / MacOS環境では、同様の用途に hooks.managed_dir を使用する。

 [hooks]
 managed_dir = "/etc/codex/managed-hooks"


管理型Hooksに関する重要な注意事項を以下に示す。

  • Windows管理型Hooksのパスは絶対パスで指定しなければならない。
    相対パスを指定した場合はエラーになる。

  • Codexは設定読み込み前にパスの存在確認と絶対パス検証を行う。
    ディレクトリが存在しない場合はエラーが発生する。

  • 管理型HooksはユーザによるHooks設定よりも高い優先度で実行される。



実行動作

Hooksの実行に関する動作仕様を以下に示す。

  • 複数のmatcherにマッチした全てのHookが実行される。
    1つのイベントに対して複数のmatcherがマッチした場合、該当する全てのHookが実行される。

  • 複数の command 型Hookは並行して実行される。
    同一matcher内に複数のHookを定義した場合、それらは並列で実行される。

  • exit code 0 かつ 無出力の場合は成功とみなす。
    この場合、Hookは処理をそのまま継続する。

  • ターンスコープのHookは turn_id を含む。
    PreToolUsePostToolUsePermissionRequest の各HookはstdinのJSONに turn_id が含まれる。

  • タイムアウト超過時はHookをスキップして処理を継続する。
    timeout で指定した秒数を超過した場合、そのHookは強制終了されて後続処理が継続される。



実用例

Pre-commit Linter Hook (ESLint)

apply_patch ツール実行後にESLintを自動実行するHookの設定例を以下に示す。

  • .codex/config.toml の設定
     [features]
     codex_hooks = true
     
     [[hooks.PostToolUse]]
     matcher = "apply_patch"
     
        [[hooks.PostToolUse.hooks]]
        type = "command"
        command = "/home/user/.codex/hooks/run-eslint.sh"
        statusMessage = "ESLintを実行中..."
        timeout = 60
    

  • ~/.codex/hooks/run-eslint.sh の内容
     #!/usr/bin/env sh
     set -euo pipefail
     
     # stdinからイベント情報を読み込む
     INPUT=$(cat)
     CWD=$(echo "$INPUT" | python3 -c "import sys, json; print(json.load(sys.stdin)['cwd'])")
     
     cd "$CWD"
     
     # ESLintを実行する
     if ! npx eslint --ext .js,.ts,.jsx,.tsx . 2>&1; then
        # Lint失敗時はCodexへフィードバックを返す
        echo '{"systemMessage": "ESLintでエラーが検出されました。修正してから再度コミットしてください。"}'
        exit 0
     fi
     
     # 成功時は空のJSONを返す
     echo '{}'
    


Post-Tool Logging Hook

全てのツール呼び出しをログファイルに記録するHookの設定例を以下に示す。

  • ~/.codex/hooks.json の設定
     {
        "PostToolUse": [
           {
              "matcher": "*",
              "hooks": [
                 {
                    "type": "command",
                    "command": "python3 /home/user/.codex/hooks/post-tool-logger.py",
                    "timeout": 10
                 }
              ]
           }
        ]
     }
    

  • ~/.codex/hooks/post-tool-logger.py の内容
     #!/usr/bin/env python3
     import sys
     import json
     import datetime
     
     LOG_FILE = "/home/user/.codex/logs/tool-usage.log"
     
     def main():
        try:
           data = json.load(sys.stdin)
        except json.JSONDecodeError:
           sys.exit(0)
     
        log_entry = {
           "timestamp": datetime.datetime.utcnow().isoformat() + "Z",
           "session_id": data.get("session_id", ""),
           "turn_id": data.get("turn_id", ""),
           "tool_name": data.get("tool_name", ""),
           "cwd": data.get("cwd", "")
        }
     
        with open(LOG_FILE, "a", encoding="utf-8") as f:
           f.write(json.dumps(log_entry, ensure_ascii=False) + "\n")
     
        # 成功を示す空のJSONを返す
        print(json.dumps({}))
     
     if __name__ == "__main__":
        main()
    


リスクアセスメントHook

危険なコマンドのブロックとリスクの高い操作への警告を行うHookの設定例を以下に示す。

  • ~/.codex/hooks.json の設定
     {
        "PreToolUse": [
           {
              "matcher": "Bash",
              "hooks": [
                 {
                    "type": "command",
                    "command": "python3 /home/user/.codex/hooks/risk-assessment.py",
                    "statusMessage": "コマンドのリスクを評価中...",
                    "timeout": 10
                 }
              ]
           }
        ]
     }
    

  • ~/.codex/hooks/risk-assessment.py の内容
     #!/usr/bin/env python3
     import sys
     import json
     import re
     
     # ブロックするコマンドパターン
     BLOCKED_PATTERNS = [
        r"rm\s+-rf\s+/",           # ルートディレクトリの再帰削除
        r"rm\s+-rf\s+~",           # ホームディレクトリの再帰削除
        r":\s*\(\s*\)\s*{.*}.*;",  # Fork bomb
     ]
     
     # 警告を表示するコマンドパターン
     WARNING_PATTERNS = [
        r"\bsudo\b",               # sudo使用
        r"\bdrop\s+database\b",    # データベース削除
        r"\btruncate\b",           # テーブルの全削除
     ]
     
     def main():
        try:
           data = json.load(sys.stdin)
        except json.JSONDecodeError:
           print(json.dumps({}))
           sys.exit(0)
     
        command = data.get("tool_input", {}).get("command", "")
     
        # ブロック対象パターンの確認
        for pattern in BLOCKED_PATTERNS:
           if re.search(pattern, command, re.IGNORECASE):
              result = {
                 "continue": False,
                 "stopReason": f"危険なコマンドパターンが検出されたため実行をブロックしました: {pattern}"
              }
              print(json.dumps(result, ensure_ascii=False))
              sys.exit(0)
     
        # 警告対象パターンの確認
        for pattern in WARNING_PATTERNS:
           if re.search(pattern, command, re.IGNORECASE):
              result = {
                 "systemMessage": f"注意: リスクの高いコマンドが検出されました。意図した操作かどうかを確認してから実行してください。"
              }
              print(json.dumps(result, ensure_ascii=False))
              sys.exit(0)
     
        # 問題なければ空のJSONを返す
        print(json.dumps({}))
     
     if __name__ == "__main__":
        main()
    



AGENTS.md と Hooks の併用

AGENTS.mdのガイダンスとHooksの強制実行を組み合わせることにより、より確実なワークフロー自動化を実現できる。

AGENTS.md と Hooks の役割分担
タスク AGENTS.mdに記述する内容 Hooksで実装する内容
Lint実行 「コード変更後は必ずESLintを実行すること」と記述する PostToolUseapply_patch matcherでESLintを自動実行する。
コミットメッセージ規約 Conventional Commitsのフォーマットを記述する PreToolUseBash matcherでコミットメッセージを検証する。
ログ記録 「作業ログを記録すること」と記述する PostToolUse の全ツールmatcherでログを自動記録する。
危険コマンド防止 「rm -rf / を実行しないこと」と記述する PreToolUseBash matcherで実際にブロックする。


AGENTS.mdに「コミット前にpre-commit lintを実行すること」と記述しても、エージェントが従わない場合がある。
PreToolUse HookでLinterを強制実行することにより、エージェントの判断に依存せず確実に品質チェックを通過させることができる。


プラグインバンドルHooks

スキルやプラグインに対して、Hooksを同梱して配布できる。

プラグイン内にHooksスクリプトをバンドルすることにより、インストールするだけでLinter、フォーマッタ、テストランナーが自動的に設定されるプラグインを作成できる。

プラグインにHooksをバンドルする場合の構成例を以下に示す。

my-codex-plugin/
├── plugin.toml       # プラグイン定義ファイル
├── hooks/
│   ├── pre-tool.sh   # PreToolUse Hook スクリプト
│   └── post-tool.py  # PostToolUse Hook スクリプト
└── config/
    └── hooks.json    # Hooks設定ファイル


プラグイン化することで以下に示すメリットが得られる。

  • チームメンバー全員に同一のHooks設定を配布できる。
  • Hooksスクリプトのバージョン管理をプラグインとして一元管理できる。
  • マーケットプレイスを通じてHooksのセットを公開・共有できる。



注意事項

Hooksを使用する時の注意事項を以下に示す。

  • 実験的機能であることを理解する。
    2026年5月時点でHooksは実験的機能であり、将来的にAPI仕様や動作が変更・削除される可能性がある。本番環境への適用前に十分なテストを行うこと。

  • untrustedプロジェクトではプロジェクト層のHooksがスキップされる。
    セキュリティ上の理由から、信頼されていないプロジェクトではリポジトリ配下のHooks設定が読み込まれない。重要なセキュリティHooksはユーザ層 (~/.codex/hooks.json) に配置すること。

  • Windowsの管理型Hooksは絶対パスが必須である。
    hooks.windows_managed_dir には必ず絶対パスを指定すること。相対パスを指定した場合はエラーになる。

  • PreToolUseadditionalContext は現時点で未サポートである。
    Claude Code形式のコンテキスト注入が必要な場合は、systemMessage を使用してCodexにフィードバックを返す代替手段を検討すること。

  • timeoutを適切に設定する。
    タイムアウト超過時はHookがスキップされる。処理時間が長いスクリプトには余裕を持った timeout 値を設定すること。

  • 並行実行時のレース条件に注意する。
    複数のHookが並行実行される場合、同一ファイルへの書き込み等でレース条件が発生する可能性がある。ロックファイルやアトミックな書き込み処理等、排他制御を実装することを推奨する。



関連ページ