概要
Hooks (フック) は、OpenAI Codex CLIのライフサイクルイベントに反応してカスタムスクリプトを自動実行する仕組みである。
Codexがセッションを開始したとき、ツールを呼び出す直前・直後、ユーザがプロンプトを送信したとき等、各タイミングで任意のシェルコマンドやスクリプトを介入させることができる。
Hooksの主な用途を以下に示す。
| 用途 | 説明 |
|---|---|
| ログ記録 | ツール呼び出しの履歴やセッション情報を外部ファイルやサービスに記録する。 |
| プロンプト検証 | ユーザが送信したプロンプトの内容を検査して、不正なリクエストをブロックする。 |
| メモリ生成 | セッション終了後に要約や作業ログを自動生成して蓄積する。 |
| ツール使用前後処理 | Linterや静的解析ツールをツール呼び出しの前後に実行する。 |
Hooks機能は2026年5月時点では実験的機能 (experimental) として提供されており、将来的に変更・削除される可能性がある。
本番環境への適用前に十分なテストを行うことを推奨する。
Hooksと AGENTS.md はどちらもCodexの動作を制御するが、役割が明確に異なる。
| 項目 | 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 および <プロジェクトルート>/.codex/config.toml の
- 常に実行されるもの
- ユーザ層 (~/.codex/hooks.json 等) のHooks設定
信頼済プロジェクトへの変更方法は ~/.codex/config.toml で project_trust = true を指定するか、初回起動時の確認ダイアログで承認する。
詳細は、Codexの設定 - AGENTS.md#信頼されていないプロジェクトでの動作の 信頼されていないプロジェクトでの動作 セクションを参照すること。
サポートされるHookイベント
下表に、2026年5月時点でサポートされている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 でサポートされている応答フィールドを示す。
| フィールド | 説明 |
|---|---|
systemMessage |
Codexへのフィードバックメッセージ |
continue: false |
後続処理を中断させる。 |
stopReason |
中断理由の文字列 |
現在の制限 (2026年5月)
以下に示す制限が存在する。
PreToolUseはadditionalContextフィールドに未対応である。- Claude Code形式のコンテキスト注入は現時点では使用できない。
PermissionRequestHookではcontinue、stopReason、suppressOutputフィールドに未対応である。
hooks.jsonフォーマット
hooks.json ファイルはJSON形式でHooksを定義する。
PreToolUse と PostToolUse の両方を含む例を以下に示す。
{
"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 フィールドには、下表に示すパターンを指定できる。
| パターン | 説明 | 使用例 |
|---|---|---|
空文字 "" |
全てのイベントにマッチする | 全ツール呼び出しを記録したい場合 |
ワイルドカード * |
全てのイベントにマッチする (空文字と同等) | 全ツール呼び出しを対象にしたい場合 |
| ツール名 (完全一致) | 指定したツール名にのみマッチする | "Bash"、"apply_patch"
|
| 正規表現 | 正規表現パターンにマッチするツール名に適用される | apply_patch" |
startup |
セッション新規開始時にマッチする (SessionStart専用) | 初期化処理を実行したい場合 |
resume |
セッション再開時にマッチする (SessionStart専用) | 再開時のみ処理したい場合 |
clear |
セッションのクリア時にマッチする (SessionStart専用) | クリア後の初期化処理をしたい場合 |
設定パラメータ詳細
| パラメータ | 必須/任意 | 説明 |
|---|---|---|
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を含む。PreToolUse、PostToolUse、PermissionRequestの各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で実装する内容 |
|---|---|---|
| Lint実行 | 「コード変更後は必ずESLintを実行すること」と記述する | PostToolUse の apply_patch matcherでESLintを自動実行する。
|
| コミットメッセージ規約 | Conventional Commitsのフォーマットを記述する | PreToolUse の Bash matcherでコミットメッセージを検証する。
|
| ログ記録 | 「作業ログを記録すること」と記述する | PostToolUse の全ツールmatcherでログを自動記録する。
|
| 危険コマンド防止 | 「rm -rf / を実行しないこと」と記述する | PreToolUse の Bash 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には必ず絶対パスを指定すること。相対パスを指定した場合はエラーになる。
PreToolUseのadditionalContextは現時点で未サポートである。- Claude Code形式のコンテキスト注入が必要な場合は、
systemMessageを使用してCodexにフィードバックを返す代替手段を検討すること。
- Claude Code形式のコンテキスト注入が必要な場合は、
- timeoutを適切に設定する。
- タイムアウト超過時はHookがスキップされる。処理時間が長いスクリプトには余裕を持った
timeout値を設定すること。
- タイムアウト超過時はHookがスキップされる。処理時間が長いスクリプトには余裕を持った
- 並行実行時のレース条件に注意する。
- 複数のHookが並行実行される場合、同一ファイルへの書き込み等でレース条件が発生する可能性がある。ロックファイルやアトミックな書き込み処理等、排他制御を実装することを推奨する。
関連ページ
- Codexの設定 - 機能
- 承認モード (approval mode) とサンドボックスの設定
- Codexの設定 - AGENTS.md
- AGENTS.md と Hooks を組み合わせたワークフロー自動化
- Codexの設定 - サブエージェント
- サブエージェントへの設定継承動作
- Codexの設定 - コマンド
- Codex CLIのコマンドリファレンス