技術 約6分で読めます

AIコーディングCLIのHooks機能比較 — Gemini CLI・Claude Code・Codex CLI

AIコーディングCLI御三家(Gemini CLI、Claude Code、Codex CLI)のHooks機能を比較調査した。Googleが公式ブログでGemini CLIのHooks機能を紹介していたのがきっかけ。

調べてみると、3つのツールで設計思想がかなり違って興味深かった。

Hooksとは

AIコーディングCLIにおけるHooksは、エージェントのライフサイクル(ツール実行前後、セッション開始・終了など)に独自の処理を差し込む仕組み。Webフレームワークのミドルウェアに近い。

典型的なユースケース:

  • ツール実行前にバリデーション(危険なコマンドをブロック)
  • シークレットの漏洩防止(ファイル書き込み前にスキャン)
  • ログ収集・トークンコスト最適化
  • セッション開始時にプロジェクト固有のコンテキストを注入

Gemini CLI

2025年7月にGoogleが公式ブログで紹介。v0.26.0以降で利用可能。

設定

.gemini/settings.json に記述する。

{
  "hooks": {
    "BeforeTool": [
      {
        "matcher": "write_file|replace",
        "hooks": [
          {
            "name": "secret-scanner",
            "type": "command",
            "command": "$GEMINI_PROJECT_DIR/.gemini/hooks/scan-secrets.sh",
            "description": "Scan for secrets before writing files"
          }
        ]
      }
    ]
  }
}

イベント一覧

イベントタイミング
SessionStartセッション開始時
SessionEndセッション終了時
BeforeAgentエージェントターン開始前
AfterAgentエージェントターン完了後
BeforeModelLLMリクエスト送信前
AfterModelLLMレスポンス受信後
BeforeToolSelectionツール選択前
BeforeToolツール実行前
AfterToolツール実行後
Notification通知発生時

10種類。特徴的なのはBeforeModelとBeforeToolSelection。LLMへのリクエスト自体に介入できるのはGemini CLIだけ。

通信プロトコル

  • stdinでJSON入力を受け取り、stdoutでJSON出力を返す
  • exit code 0で続行、exit code 2でブロック
  • BeforeModelではモックレスポンスを返すことも可能(LLM呼び出しをスキップ)
  • タイムアウトはデフォルト60秒、カスタマイズ可

設定の階層

プロジェクト → ユーザー → システムの3階層でマージされる。Extensions経由でHooksをバンドル配布できるのもGemini CLIならでは。

Claude Code

Claude Codeも同様のHooks機能を持つ。

設定

.claude/settings.json に記述する。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.claude/hooks/validate-bash.py"
          }
        ]
      }
    ]
  }
}

イベント一覧

イベントタイミング
SessionStartセッション開始時
SessionEndセッション終了時
UserPromptSubmitユーザー入力送信時
PreToolUseツール実行前
PostToolUseツール実行後
PostToolUseFailureツール実行失敗時
PermissionRequest権限リクエスト時
Notification通知発生時
SubagentStartサブエージェント開始時
SubagentStopサブエージェント停止時
Stopエージェント停止時
PreCompactコンテキスト圧縮前

12種類で最多。SubagentStart/Stopはマルチエージェント構成を前提としたイベントで、他のツールにはない。

フックタイプ — 最大の差別化ポイント

Claude Codeのフックには3種類のtypeがある。

type動作
commandシェルコマンドを実行(他ツールと同じ)
promptLLMにプロンプトを送って判断させる
agentLLMエージェントを起動して処理を委任

promptagentはClaude Code固有の機能。フックの判断ロジック自体をLLMに委任できる。たとえば「このBashコマンドは安全か?」をルールベースではなくLLMに判断させるといった使い方ができる。

柔軟性は高いが、LLM呼び出しが発生するのでコストとレイテンシのトレードオフがある。

設定の階層

ユーザー → プロジェクト → ローカルの3階層。

Codex CLI

OpenAIのCodex CLIには正式なHooksシステムが存在しない。GitHub Discussions(#2150)でコミュニティから要望は出ているが、未実装のまま。

唯一のフック的機能: notify

# ~/.codex/config.toml
notify = ["say", "Codex is done"]

エージェントがターンを完了したときに外部コマンドを実行する。通知専用で、ツール実行の前後に介入する機能はない。

代わりにどうしているか

Codex CLIはHooksの代わりに、宣言的な設定でツール実行を制御するアプローチを取っている。

Approval Policy(承認ポリシー): ユーザーへの確認タイミングを4段階で制御。

ポリシー動作
on-requestネットワーク・ワークスペース外書き込み・未信頼コマンドで承認要求
untrustedファイル編集は自動、未知コマンドのみ承認要求
on-failureコマンド失敗時のみ承認要求
never承認プロンプト無効

Sandbox Mode: OS-levelのサンドボックスで物理的に制限する。

モード制限
read-onlyファイル変更・コマンド実行を制限
workspace-writeワークスペース内のみ編集可
danger-full-access制限なし

macOSはSeatbelt、LinuxはLandlock+seccomp、WindowsはWSL sandboxと、OS固有の実装を使う。ここはかなりCodex CLIらしい設計。

Execution Policy: .rulesファイルでコマンドパターンマッチ。

prefix_rule(pattern="git status", decision="allow")
prefix_rule(pattern="rm -rf /", decision="forbidden")

allow(自動実行)、prompt(承認要求)、forbidden(ブロック)の3段階。複数ルール適用時は最も制限的なものが優先される。

比較表

項目Gemini CLIClaude CodeCodex CLI
Hooks有無ありありなし(notify のみ)
イベント数1012
ツール実行前介入BeforeToolPreToolUseExecution Policy
ツール実行後介入AfterToolPostToolUse
LLM呼び出し前介入BeforeModel
LLMによる判断prompt/agent hook
サブエージェント対応SubagentStart/Stop
サンドボックスOS-level sandbox
matcher正規表現正規表現prefix match
設定形式JSONJSONTOML + Starlark風
通信方式stdin/stdout JSONstdin/stdout JSON
拡張配布Extensions

設計思想の違い

3つのツールを並べると、設計思想の違いが見える。

Gemini CLIは最も低レイヤーまで介入できるアプローチ。BeforeModelでLLMリクエスト自体に介入したり、BeforeToolSelectionでツール選択をフィルタしたり、エージェントの内部動作に深く関与できる。Extensions経由でHooksをバンドル配布できるのもエコシステム指向。

Claude Codeはフックの判断ロジック自体をLLMに委任できる唯一のツール。ルールベースで書きにくい曖昧な判断(「このコマンドは安全か?」)をLLMに任せるという割り切り。SubagentStart/Stopのようにマルチエージェント構成を前提としたイベントがあるのも、Agent SDKとの統合を見据えた設計に見える。

Codex CLIはHooksを持たず、宣言的ポリシー + OSサンドボックスで制御する。任意スクリプトの介入を許可しない代わりに、OS-levelのサンドボックスで物理的にセキュリティを担保するという方向性。「コードで柔軟にカスタマイズしたい」より「安全にデフォルトを提供したい」という思想が強い。

どのアプローチが正解かは用途次第だが、個人的にはGemini CLIのBeforeModelが一番面白いと思った。LLMのリクエスト/レスポンスに直接介入できるのは、テスト・デバッグ・コスト最適化で活躍しそう。

参考