Tool Comparison Matrix (AI Agent Hooks)¶
AI Agent Hooks のイベント体系・レスポンス形式・Stop 制御方式を横断比較する。
Agent Hooks の概要比較は tool-comparison-matrix-ai-agent.md を参照。本ドキュメントはイベント単位の詳細仕様に特化する。
History¶
| 日付 | 内容 |
|---|---|
| 2026-06-27 | Codex (OpenAI) を全セクションに追加 |
| 2026-06-14 | hooks.json 設定方法セクション追加。ツール並び順を A-Z 順に統一 |
| 2026-06-07 | 初版作成。Event Matrix / res Matrix / Stop Block 仕様を整備 |
Event Matrix¶
| イベント | Antigravity | Claude Code | Codex | Copilot CLI | Cursor | Kiro CLI | VS Code |
|---|---|---|---|---|---|---|---|
| 提供元 | Google DeepMind | Anthropic | OpenAI | GitHub (Microsoft) | Anysphere | AWS | Microsoft (GitHub) |
| ドキュメント | antigravity.google | docs.claude.com | developers.openai.com/codex/hooks | docs.github.com | cursor.com | kiro.dev | code.visualstudio.com |
| Session Start | ❌ | ✅ SessionStart | ✅ SessionStart | ✅ sessionStart | ❌ | ❌ | ✅ SessionStart |
| User Prompt Submit | ❌ | ✅ UserPromptSubmit | ✅ UserPromptSubmit | ✅ userPromptSubmitted | ❌ | ✅ userPromptSubmit | ✅ UserPromptSubmit |
| Pre Tool Use | ✅ PreToolUse | ✅ PreToolUse | ✅ PreToolUse | ✅ preToolUse | ✅ preToolUse / beforeShellExecution ※2 | ✅ preToolUse | ✅ PreToolUse |
| Post Tool Use | ✅ PostToolUse ※1 | ✅ PostToolUse | ✅ PostToolUse | ✅ postToolUse | ✅ postToolUse / afterFileEdit ※2 | ✅ postToolUse | ✅ PostToolUse |
| Stop (Turn End) | ✅ Stop | ✅ Stop | ✅ Stop | ✅ agentStop | ✅ stop ※2 | ✅ stop | ✅ Stop |
| Post Tool Failure | ❌ (PostToolUse の err で判別) |
✅ PostToolUseFailure | ❌ (PostToolUse runs for non-zero exit too) | ✅ postToolUseFailure | ❌ | ❌ | ❌ |
| Agent Spawn | ❌ | ✅ SubagentStart | ✅ SubagentStart | ✅ subagentStart | ❌ | ✅ agentSpawn | ✅ SubagentStart |
| Subagent Stop | ❌ | ✅ SubagentStop | ✅ SubagentStop | ✅ subagentStop | ❌ | ❌ | ✅ SubagentStop |
| Session End | ❌ | ✅ SessionEnd | ❌ | ✅ sessionEnd | ❌ | ❌ | ❌ |
| err Occurred | ❌ | ❌ | ❌ | ✅ errorOccurred | ❌ | ❌ | ❌ |
| Notification | ❌ | ✅ Notification | ❌ | ✅ notification | ❌ | ❌ | ❌ |
| Permission req | ❌ | ✅ PermissionRequest | ✅ PermissionRequest | ✅ permissionRequest | ❌ | ❌ | ❌ |
| Compact (Pre/Post) | ❌ | ✅ PreCompact/PostCompact | ✅ PreCompact/PostCompact | ❌ | ❌ | ❌ | ✅ PreCompact |
| File Changed | ❌ | ✅ FileChanged | ❌ | ❌ | ❌ | ❌ | ❌ |
| Config Change | ❌ | ✅ ConfigChange | ❌ | ❌ | ❌ | ❌ | ❌ |
| Task Created/Completed | ❌ | ✅ TaskCreated/Completed | ❌ | ❌ | ❌ | ❌ | ❌ |
| Teammate Idle | ❌ | ✅ TeammateIdle | ❌ | ❌ | ❌ | ❌ | ❌ |
Guidelines¶
→ どのイベントが存在するかの比較。各イベントで何ができるかは res Matrix を参照。
- Claude Code が最もイベント種別が豊富(20 種以上)。細かいライフサイクル制御が可能
- Antigravity は PreInvocation / PostInvocation で Model 呼び出し前後へのステップ注入ポイントを持つ(他ツールにない独自イベント)
- Stop / PreToolUse / PostToolUse に相当するライフサイクルは全 6 ツールに存在するが、hooks.json のイベントキー名はツールごとに異なり、大文字小文字も区別される(例: Claude
Stop≠ Cursorstop)。hook スクリプトは共有可能だが、hook 定義 JSON はターゲット別パッケージに分離する(後述) - VS Code は Claude Code と同じ PascalCase イベント名・
hookSpecificOutput形式を採用するが、GitHub Copilot CLI とは別実装。.github/hooks/*.jsonを共有するが stdin/stdout の JSON 構造が異なる - Cursor は camelCase の汎用イベント(
stop,preToolUse,postToolUse)に加え、ツール種別ごとの細分化イベント(beforeShellExecution/beforeMCPExecution/beforeReadFile/afterFileEdit等)を持つ。StopやPreToolUseなど PascalCase キーは Cursor では一致せず、hook は発火しない - ※1: Antigravity の PostToolUse は観測専用。stdout は
{}のみ。agent へのフィードバックには PreInvocation を使用する - ※2: Cursor の hooks.json はイベント名のケースが厳密一致。
stop/preToolUse/postToolUseが正。Stop/PreToolUse/PostToolUseは無視される(unknown event ではなく、単にマッチしない)
hooks.json 設定方法¶
各ツールで hooks を登録する設定ファイルの形式を示す。イベント名・キー名・構造がツールごとに異なるため、同一パッケージから複数ツール向けに配布する場合はターゲット別に定義ファイルを分離する必要がある。以下の preToolUse 例の lean-ctx-bin … hook rewrite は 形式サンプル(lean-ctx 本体の hook 統合)であり、APM の common-hooks-* は lean-ctx hooks を配布しない。
Copilot CLI¶
設定ファイル: .github/hooks/<name>.json(1 ファイル = 1 hook 定義。複数ファイルを配置可能)
{
"hooks": {
"agentStop": [
{
"type": "command",
"bash": ".github/hooks/scripts/actionlint.sh",
"timeoutSec": 60
}
],
"preToolUse": [
{
"type": "command",
"bash": "npx -y lean-ctx-bin@3.9.12 hook rewrite",
"timeoutSec": 15
}
]
},
"version": 1
}
| 項目 | 値 |
|---|---|
| イベント名 | camelCase (agentStop, preToolUse, postToolUse) |
| コマンドキー | bash |
type フィールド |
"command" (必須) |
version |
1 (トップレベル、必須) |
| タイムアウト | timeoutSec (秒) |
Cursor¶
設定ファイル: .cursor/hooks.json(単一ファイルに全 hook をマージ)
{
"version": 1,
"hooks": {
"stop": [
{
"command": ".cursor/hooks/scripts/actionlint.sh",
"timeoutSec": 60
}
],
"preToolUse": [
{
"command": "npx -y lean-ctx-bin@3.9.12 hook rewrite",
"timeoutSec": 15
}
]
}
}
| 項目 | 値 |
|---|---|
| イベント名 | camelCase (stop, preToolUse, postToolUse, afterFileEdit, beforeShellExecution) |
| ケース厳密一致 | 必須。Stop / PreToolUse / PostToolUse は発火しない(PascalCase は Claude/Codex/VS Code 用) |
| コマンドキー | command (bash はエラー) |
type フィールド |
不要 |
version |
1 (トップレベル、必須。省略するとエラー) |
| タイムアウト | timeoutSec (秒) |
stop の stdout |
{"followup_message":"..."}(非空で次ユーザーメッセージを自動送信。loop_limit デフォルト 5) |
| その他 hook の block | exit 2 + stderr(beforeShellExecution / afterFileEdit 等) |
Claude Code¶
設定ファイル: .claude/settings.json 内の hooks キー、または .claude/hooks/<name>.json
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "./scripts/actionlint.sh",
"timeout": 60
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash|Write",
"hooks": [
{
"type": "command",
"command": "npx -y lean-ctx-bin@3.9.12 hook rewrite",
"timeout": 15
}
]
}
]
}
}
| 項目 | 値 |
|---|---|
| イベント名 | PascalCase (Stop, PreToolUse, PostToolUse) |
| コマンドキー | command |
type フィールド |
"command" (必須) |
version |
不要 |
| タイムアウト | timeout (秒。timeoutSec ではない) |
matcher |
ツール名正規表現フィルタ (空文字 = 全マッチ) |
| ネスト構造 | イベント配列 → { matcher, hooks: [...] } の 2 段ネスト |
Codex¶
設定ファイル: .codex/hooks.json or inline in .codex/config.toml
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "./scripts/actionlint.sh",
"timeout": 600
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash|Write",
"hooks": [
{
"type": "command",
"command": "npx -y lean-ctx-bin@3.9.12 hook rewrite",
"timeout": 15
}
]
}
]
}
}
| 項目 | 値 |
|---|---|
| イベント名 | PascalCase (SessionStart, PreToolUse, PostToolUse, Stop) |
| コマンドキー | command |
type フィールド |
"command" (必須) |
version |
不要 |
| タイムアウト | timeout (秒、デフォルト 600) |
matcher |
✅ (正規表現、Claude Code と同形式) |
| Trust review | 必須 (hash-based) |
Kiro CLI¶
設定ファイル: .kiro/hooks/hooks.json または .kiro/hooks/<name>.json
{
"hooks": {
"stop": [
{
"type": "command",
"command": "./scripts/actionlint.sh",
"timeout": 60
}
],
"preToolUse": [
{
"type": "command",
"command": "npx -y lean-ctx-bin@3.9.12 hook rewrite",
"timeout": 15
}
]
}
}
| 項目 | 値 |
|---|---|
| イベント名 | camelCase (stop, preToolUse, postToolUse) |
| コマンドキー | command |
type フィールド |
"command" (必須) |
version |
不要 |
| タイムアウト | timeout (秒) |
VS Code¶
設定ファイル: .github/hooks/<name>.json(Copilot CLI と同じディレクトリを共有)
{
"hooks": {
"Stop": [
{
"type": "command",
"bash": ".github/hooks/scripts/actionlint.sh",
"timeoutSec": 60
}
],
"PreToolUse": [
{
"type": "command",
"bash": "npx -y lean-ctx-bin@3.9.12 hook rewrite",
"timeoutSec": 15
}
]
},
"version": 1
}
| 項目 | 値 |
|---|---|
| イベント名 | PascalCase (Stop, PreToolUse, PostToolUse) |
| コマンドキー | bash |
type フィールド |
"command" (必須) |
version |
1 (トップレベル、必須) |
| タイムアウト | timeoutSec (秒) |
.github/hooks/ 共有 |
Copilot CLI と同一ディレクトリだがイベント名が異なる。両方のイベントを同一 JSON に記載すると両方で動作する |
Guidelines¶
→ hooks.json のフォーマットはツール間で互換性がない。ターゲット別パッケージに定義を分離する(単一パッケージで Stop を共通キーとして配布する設計は不可)。
| 差異ポイント | Codex | Copilot CLI | Cursor | Claude Code | Kiro CLI | VS Code |
|---|---|---|---|---|---|---|
| コマンドキー | command |
bash |
command |
command |
command |
bash |
| Stop イベント名 | Stop |
agentStop |
stop |
Stop |
stop |
Stop |
| Pre イベント名 | PreToolUse |
preToolUse |
preToolUse |
PreToolUse |
preToolUse |
PreToolUse |
| Post イベント名 | PostToolUse |
postToolUse |
postToolUse |
PostToolUse |
postToolUse |
PostToolUse |
| ケース厳密一致 | ✅ PascalCase | ✅ camelCase | ✅ camelCase | ✅ PascalCase | ✅ camelCase | ✅ PascalCase |
version 必須 |
❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
| タイムアウトキー | timeout |
timeoutSec |
timeoutSec |
timeout |
timeout |
timeoutSec |
| matcher 対応 | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
APM パッケージでの hooks 配布設計¶
APM Hooks and Commands では、ソース hook JSON を Claude 形式(PreToolUse, Stop)または Copilot 形式(preToolUse, agentStop)で記述し、インストール時に各ターゲットの integrator がイベント名をリネームしてマージする。ただし Cursor の hooks.json はイベントキーがケース厳密一致であり、PascalCase の Stop / PreToolUse / PostToolUse をそのまま書くと発火しない(2026-07 実測)。
このため本リポジトリでは hooks はターゲット別サブパッケージに最初から分離する設計とする:
| パッケージ例 | apm.yml の target |
hooks JSON のイベントキー例 |
|---|---|---|
common-hooks-claude |
claude |
Stop, PreToolUse, PostToolUse (PascalCase) |
common-hooks-cursor |
cursor |
stop, preToolUse, postToolUse (camelCase) |
common-hooks-copilot |
copilot |
agentStop, preToolUse, postToolUse |
- やってはいけない: 1 つの hooks パッケージに
Stopキーだけで全ターゲット向けに配布し、マージ時のリネームに任せる(Cursor ではヒットしない) - 正しい:
*-hooks-claude/*-hooks-cursor/*-hooks-copilotのようにターゲット別パッケージを分け、各パッケージの.apm/hooks/*.jsonにそのターゲットのネイティブイベント名を直接記述する。hook スクリプト(scripts/*.sh)は共通化可能 - コンシューマの
dependencies.apmでtargets:を指定し、インストール先 harness を限定する(APM 公式推奨) - Cursor は
version: 1がないとエラーになる。APM 0.27+ の install が生成物にversionを付与する前提とし、リポジトリ固有の postinstall strip には依存しない
res Matrix (Stop / agentStop)¶
| 項目 | Antigravity | Claude Code | Codex | Copilot CLI | Cursor | Kiro CLI | VS Code |
|---|---|---|---|---|---|---|---|
| イベント名 | Stop |
Stop |
Stop |
agentStop / Stop |
stop |
stop |
Stop |
| Block 方式 (推奨) | exit 0 + JSON | exit 2 (stderr) または exit 0 + JSON | exit 0 + JSON または exit 2 + stderr | exit 0 + JSON | exit 0 + JSON (followup_message) |
exit 0 + JSON | exit 0 + JSON (hookSpecificOutput) |
| Block JSON | {"decision":"continue","reason":"..."} |
{"decision":"block","reason":"..."} |
{"decision":"block","reason":"..."} |
{"decision":"block","reason":"..."} |
{"followup_message":"..."} |
{"decision":"block","reason":"..."} |
{"hookSpecificOutput":{"hookEventName":"Stop","decision":"block","reason":"..."}} |
| exit 2 の効果 | hook 自体の失敗として扱われる(agent フィードバックなし) | agent 停止を防止 + stderr が agent へ | reason が agent に届き修正ループに入る | ユーザーに警告表示のみ | ErrorOutput に記録(修正ループにならない) | ユーザーに警告表示のみ | agent に err ctx として注入 |
| exit 0 (JSON 無し) の効果 | agent 通常停止 | agent 通常停止 | agent 通常停止 | agent 通常停止 | 通常完了(follow-up なし) | agent 通常停止 | agent 通常停止 |
| reason の扱い | system msg として会話に注入 | agent のコンテキストに追加 | 新しい continuation prompt として agent に送信 | 新しいプロンプトとして agent に送信 | followup_message として次ユーザーメッセージに自動送信 |
新しいユーザーメッセージとして agent に送信 | agent のコンテキストに追加 |
| ユーザーへの表示 | ❌ (表示なし) | ❌ (表示なし) | ❌ (表示なし) | ❌ (表示なし) | ✅ (Hooks チャンネルに stdout / ErrorOutput) | ❌ (表示なし) | ❌ (表示なし) |
| agent コンテキスト注入 | ✅ reason がコンテキストに入る | ✅ reason がコンテキストに入る | ✅ reason がコンテキストに入る | ✅ reason がコンテキストに入る | ✅ followup_message が次ターンに渡る |
✅ reason がコンテキストに入る | ✅ reason がコンテキストに入る |
| agent が修正アクションを実行 | ✅ 次ターンで reason に基づき行動 | ✅ 次ターンで reason に基づき行動 | ✅ 次ターンで reason に基づき行動 | ✅ 次ターンで reason に基づき行動 | ✅ followup_message 非空時に自動 follow-up |
✅ 次ターンで reason に基づき行動 | ✅ 次ターンで reason に基づき行動 |
| 連続ブロック上限 | 不明 | 8 回 | 不明 (スクリプト側でセーフガード推奨) | ジョブタイムアウトに依存 | loop_limit デフォルト 5 |
不明 | 不明 (AI credits 消費で自然制限) |
| JSON 生成要件 | 有効な JSON 必須 | 有効な JSON 必須 | 有効な JSON 必須 | 有効な JSON 必須 | followup_message 用に jq 推奨 |
有効な JSON 必須 (jq 推奨) | 有効な JSON 必須 |
Stop stdin / stdout Format¶
Antigravity¶
stdin:
{
"executionNum": 5,
"terminationReason": "task_complete",
"error": null,
"fullyIdle": true,
"conversationId": "...",
"workspacePaths": ["/workspace"]
}
stdout:
{ "decision": "continue", "reason": "修正すべき内容" }
Claude Code¶
stdin:
{
"hook_event_name": "Stop",
"session_id": "...",
"cwd": "/workspace",
"transcript_path": "...",
"stop_hook_active": false,
"last_assistant_message": "..."
}
stdout — block decision:
{ "decision": "block", "reason": "修正すべき内容" }
stdout — additionalContext (非エラーフィードバック):
{
"hookSpecificOutput": {
"hookEventName": "Stop",
"additionalContext": "テスト実行してから完了してください"
}
}
Codex¶
stdin:
{
"hook_event_name": "Stop",
"session_id": "...",
"cwd": "/workspace",
"stop_hook_active": false,
"last_assistant_message": "...",
"turn_id": "...",
"transcript_path": "...",
"model": "...",
"permission_mode": "..."
}
stdout — block decision:
{ "decision": "block", "reason": "修正すべき内容" }
Copilot CLI¶
stdin:
{
"hook_event_name": "agentStop",
"session_id": "...",
"cwd": "/workspace",
"transcriptPath": "...",
"stopReason": "..."
}
stdout:
{ "decision": "block", "reason": "修正すべき内容" }
Cursor¶
stdin:
{
"hook_event_name": "stop",
"status": "completed",
"loop_count": 0,
"conversation_id": "...",
"generation_id": "...",
"cursor_version": "3.11.13",
"workspace_roots": ["/workspace"]
}
stdout — 修正ループ用(推奨):
{ "followup_message": "修正すべき内容" }
followup_message が非空のとき、Cursor はそれを次のユーザーメッセージとして自動送信する。loop_count は follow-up 回数、loop_limit(hook 定義、デフォルト 5)で上限を制御する。
stop で exit 2 + stderr を使った場合、Hooks チャンネルの ErrorOutput には出るが stdout は {} のままになり、修正ループには入らない(2026-07 実測)。lint/test ゲートには followup_message を使う。
afterFileEdit / beforeShellExecution 等の 非 stop hook では、引き続き exit 2 + stderr でブロック可能。
Kiro CLI¶
stdin:
{
"hook_event_name": "stop",
"session_id": "...",
"cwd": "/workspace",
"assistant_response": "..."
}
stdout:
{ "decision": "block", "reason": "修正すべき内容" }
VS Code¶
stdin:
{
"hook_event_name": "Stop",
"session_id": "...",
"cwd": "/workspace",
"transcript_path": "...",
"stop_hook_active": false
}
stdout:
{
"hookSpecificOutput": {
"hookEventName": "Stop",
"decision": "block",
"reason": "修正すべき内容"
}
}
Guidelines¶
→ Stop hook は全 6 ツールで agent に修正を強制できる唯一のイベント。lint/test ゲートの第一選択。
- 全ツールで reason が agent のコンテキストに入り、次ターンで agent が修正アクションを実行する
- Kiro CLI / Copilot CLI は exit 0 + JSON が唯一のブロック手段。exit 2 では警告表示のみで修正ループに入らない
- Claude Code は exit 2 でも stderr が agent に届くため修正ループに入る。JSON 方式も併用可能
- Antigravity は
"continue"を使う。stdin にterminationReasonがあることで検出する - Cursor
stopは{"followup_message":"..."}+ exit 0 が修正ループの正規手段。decision:blockJSON は解釈しない。exit 2 + stderr は ErrorOutput 記録のみでstopのゲートには使わない - Cursor の
afterFileEdit等(非stop)は exit 2 + stderr でブロック可能 - JSON は
jq -n --argで生成し、改行文字のエスケープを保証する
res Matrix (PostToolUse)¶
| 項目 | Antigravity | Claude Code | Codex | Copilot CLI | Cursor | Kiro CLI | VS Code |
|---|---|---|---|---|---|---|---|
| イベント名 | PostToolUse |
PostToolUse |
PostToolUse |
postToolUse |
afterFileEdit |
postToolUse |
PostToolUse |
| exit 0 + stdout の効果 | 出力は {} のみ (処理なし) |
JSON output 処理 | JSON output 処理 | STDOUT captured (非表示) | 不明 | STDOUT captured (非表示) | JSON output 処理 |
| exit 2 の効果 | 不明 | STDERR を Claude に表示 (ツール実行済み) | feedback が agent に届く | STDERR をユーザーに警告 | agent にフィードバック | STDERR をユーザーに警告 | agent に err ctx として注入 |
| exit code で block 可能か | ❌ (ツール実行済み) | ❌ (ツール実行済み) | ✅ decision: "block" で tool result を置換 |
❌ (ツール実行済み) | ❌ | ❌ | ✅ decision: "block" で停止可 |
| ユーザーへの表示 | ❌ | ❌ (表示なし) | ❌ (表示なし) | ⚠️ exit 2 時のみ警告表示 | 不明 | ⚠️ exit 2 時のみ警告表示 | ❌ (表示なし) |
| agent コンテキスト注入 | ❌ (出力不可) | ✅ additionalContext で注入 | ✅ additionalContext / decision:block で注入 | ✅ additionalContext で注入 | ✅ agent に渡る | ❌ | ✅ hookSpecificOutput.additionalContext で注入 |
| agent が修正アクションを実行 | ❌ (PostToolUse 単体では不可。Stop で対応) | ✅ 次ツール呼出し時に認識して対応 | ✅ 次ツール呼出し時に認識して対応 | ✅ 次ツール呼出し時に認識して対応 | ✅ 次ターンで対応 | ❌ (フィードバック手段なし) | ✅ additionalContext / block で対応 |
| matcher (ツール名フィルタ) | ✅ (正規表現対応) | ✅ ("Edit\|Write" 等) |
✅ (正規表現対応) | ❌ (全ツール) | ❌ (ファイル編集のみ) | ❌ (全ツール) | ❌ (全ツール) |
PostToolUse stdin / stdout Format¶
Antigravity¶
stdin:
{
"toolCall": { "name": "editFile", "args": { "path": "src/main.go" } },
"result": "...",
"error": null
}
stdout: {} のみ(観測専用)。agent へのフィードバックには PreInvocation の injectSteps を使用:
{
"injectSteps": [{ "ephemeralMessage": "lint結果: エラー3件。修正してください。" }]
}
Claude Code¶
stdin:
{
"hook_event_name": "PostToolUse",
"session_id": "...",
"cwd": "/workspace",
"tool_name": "Edit",
"tool_input": { "file_path": "src/main.go" },
"tool_result": "..."
}
stdout — additionalContext:
{
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "lint結果: エラー3件"
}
}
stdout — updatedToolOutput (結果置換):
{
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"updatedToolOutput": {
"stdout": "[redacted]",
"stderr": "",
"interrupted": false,
"isImage": false
}
}
}
Codex¶
stdin:
{
"hook_event_name": "PostToolUse",
"session_id": "...",
"cwd": "/workspace",
"tool_name": "Edit",
"tool_input": { "file_path": "src/main.go" },
"tool_response": "File edited successfully"
}
stdout — block + additionalContext:
{
"decision": "block",
"reason": "...",
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "lint エラーを修正してください"
}
}
Copilot CLI¶
stdin:
{
"hook_event_name": "postToolUse",
"session_id": "...",
"cwd": "/workspace",
"toolName": "editFiles",
"toolResult": "..."
}
stdout:
{
"modifiedResult": {
"resultType": "success",
"textResultForLlm": "置換後のツール結果"
},
"additionalContext": "agent に伝えたい追加情報"
}
Kiro CLI¶
stdin:
{
"hook_event_name": "postToolUse",
"session_id": "...",
"cwd": "/workspace",
"tool_name": "editFiles",
"tool_input": { "files": ["src/main.go"] }
}
stdout: N/A(フィードバック手段なし。exit 2 + stderr はユーザー警告のみ)
VS Code¶
stdin:
{
"hook_event_name": "PostToolUse",
"session_id": "...",
"cwd": "/workspace",
"tool_name": "editFiles",
"tool_input": { "files": ["src/main.go"] },
"tool_use_id": "tool-123",
"tool_response": "File edited successfully"
}
stdout — block + additionalContext:
{
"decision": "block",
"reason": "Post-processing validation failed",
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "lint エラーを修正してください"
}
}
stdout — additionalContext のみ:
{
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "lint結果: エラー3件"
}
}
Guidelines¶
→ PostToolUse は agent にフィードバックを渡せるツールが限定的。修正を強制するなら Stop hook を使う。
- Claude Code / Copilot CLI / VS Code は
additionalContextで agent のコンテキストに注入し、agent が認識して対応可能 - VS Code は PostToolUse でも
decision: "block"による停止が可能(他ツールにない独自機能) - Kiro CLI / Antigravity は PostToolUse で agent にフィードバックを渡す手段がない
- Antigravity は PreInvocation の
injectStepsで補完する設計 - フォーマッタのように「hook 内で修正して終わり」の処理は PostToolUse で十分(agent の行動不要)
- agent に修正を依頼する場合は Stop hook を使うのが全ツール互換
Stop Block Decision: 実装パターン¶
report_failure 関数を各 hook スクリプトに埋め込み、reason を渡すだけで全 agent に適切なレスポンスを返す。
設計方針¶
- stdin キャプチャ: スクリプト冒頭で stdin を 1 回だけ読み取る(パイプは 2 回読めない)
- Agent 判定: stdin の JSON 構造と環境変数から Agent を特定する(Agent ファースト戦略)
- hook_event 取得: Agent ごとに異なるフィールド名・ケーシングで取得する
- res 構築: Agent と hook_event の組み合わせに応じた JSON を stdout に出力する(Cursor
stopはfollowup_message。非stopの Cursor / unknown は exit 2 + stderr)
判定フロー¶
Agent 判定の優先順位¶
| 優先度 | 判定条件 | Agent |
|---|---|---|
| 1 | terminationReason / toolCall フィールドあり |
Antigravity |
| 2 | stop_hook_active / tool_use_id フィールドが存在する (has() で判定。値が false でも検出) |
VS Code |
| 3 | GITHUB_COPILOT_API_TOKEN 環境変数あり、または transcriptPath / stopReason / toolResult 等の Copilot CLI 固有フィールドあり (transcript_path は VS Code と共通のため除外) |
Copilot CLI |
| 4 | hook_event_name ありかつ cursor_version / generation_id / workspace_roots のいずれかあり、または afterFileEdit 等 Cursor 固有イベント名 |
Cursor |
| 5 | hook_event_name が camelCase の既知値 (stop, postToolUse 等。上記 Cursor 判定を通過したもの) |
Kiro CLI |
| 6 | permission_mode / turn_id フィールドあり (Codex 固有) |
Codex |
| 7 | hook_event_name が PascalCase (上記で Copilot/Codex 除外済み) |
Claude Code |
| 8 | stdin 無し / 判定不可 | fallback (exit 2 + stderr) |
Agent 別レスポンス仕様¶
| Agent | Stop イベント時の stdout | PostToolUse 時の stdout | fallback |
|---|---|---|---|
| Antigravity | {"decision":"continue","reason":"..."} + exit 0 |
N/A (出力 {} のみ) |
exit 0 |
| Claude Code | {"decision":"block","reason":"..."} + exit 0 |
{"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":"..."}} + exit 0 |
exit 2 |
| Codex | {"decision":"block","reason":"..."} + exit 0 |
{"decision":"block","reason":"...","hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":"..."}} + exit 0 |
exit 2 |
| Copilot CLI | {"decision":"block","reason":"..."} + exit 0 |
{"additionalContext":"..."} + exit 0 |
exit 2 |
| Kiro CLI | {"decision":"block","reason":"..."} + exit 0 |
exit 2 + stderr (agent に届かない) |
exit 2 |
| VS Code | {"hookSpecificOutput":{"hookEventName":"Stop","decision":"block","reason":"..."}} + exit 0 |
{"decision":"block","reason":"...","hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":"..."}} + exit 0 |
exit 2 |
| Cursor | {"followup_message":"..."} + exit 0 (stop) |
exit 2 + stderr (afterFileEdit 等) |
exit 2 + stderr |
制約事項¶
jqは有効な JSON 生成に必須。hook スクリプトの依存コマンドとして扱う- apm 配布ではライブラリの自動コピーが非対応のため、関数はスクリプト本体に埋め込む
- 実装例は
.apm/packages/*/.apm/hooks/scripts/*.shを参照。仕様の正は本ドキュメントと各 Agent の公式仕様とする - 無限ループ対策: Claude Code は 8 回で自動停止するが、Kiro CLI / Copilot CLI / Antigravity は上限が不明。スクリプト側で環境変数や一時ファイルを用いた最大試行回数(例: カウンター制限)のセーフガード実装を推奨する
必須評価軸 (MUST) 判定¶
| 評価軸 | Antigravity | Claude Code | Codex | Copilot CLI | Cursor | Kiro CLI | VS Code |
|---|---|---|---|---|---|---|---|
| Problem Fit | 3 | 3 | 3 | 3 | 2 | 3 | 3 |
| Security | 3 | 3 | 3 | 3 | 2 | 2 | 3 |
| op Model | 3 | 3 | 3 | 3 | 2 | 3 | 3 |
| Integration | 3 | 3 | 3 | 3 | 2 | 2 | 3 |
| Cost/TCO | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
| Maintainability | 2 | 3 | 3 | 2 | 2 | 2 | 3 |
| 加重平均 | 2.8 | 3.0 | 3.0 | 2.8 | 2.2 | 2.5 | 3.0 |
- Claude Code: イベント種別最多、decision control 最も柔軟、
additionalContext活用可。全評価軸で最高 - VS Code: Claude Code 互換の
hookSpecificOutput形式を採用。PostToolUse でも block 可能な唯一のツール。.github/hooks/からの設定読み込みで Claude Code 設定と共存可 - Codex: Claude Code と同形式 (PascalCase、matcher、decision JSON)。イベント 10 種で充実。hash-based trust review でセキュリティも高い
- Antigravity: PreInvocation で
injectStepsにより ephemeralMessage 注入可能。Stop で"continue"による修正ループ構築可能。PostToolUse は観測専用 - Copilot CLI: Claude Code に次ぐイベント数。JSON block decision 対応で Stop ループ構築可能
- Kiro CLI: Stop hook の JSON block 対応で修正ループ構築可能。イベント種別は少ないが実用上十分
- Cursor:
stopはfollowup_messageで修正ループ構築可能。decision:blockJSON は非対応。afterFileEdit等は exit 2 + stderr。独自イベント名のため他ツールとの hooks JSON 混在に注意
.apm パッケージでの Hook イベント選定¶
| 観点 | PostToolUse | Stop |
|---|---|---|
| agent が修正アクションを実行するか | Claude Code / Codex / Copilot CLI のみ | ✅ 全ツール |
| Kiro CLI で agent にフィードバックが届くか | ❌ | ✅ |
| Antigravity で agent にフィードバックが届くか | ❌ | ✅ |
| 全ツール互換でスクリプト 1 本で動くか | ❌ (ツール間で出力形式が異なる) | ✅ (decision + reason で統一可) |
| 実行タイミング | ツール実行直後(即時) | ターン完了時(まとめて) |
| 適したユースケース | 自動フォーマット(agent 行動不要) | lint/test エラーの修正ループ |
→ .apm パッケージでは Stop 相当イベントの hook を採用する(定義 JSON はターゲット別)。
- lint/test のエラーを検知して agent に修正させるユースケースでは、Stop 相当イベントが唯一の全ツール互換手段
- PostToolUse は Kiro CLI / Antigravity で agent にフィードバックが届かないため、修正ループに使えない
- hook スクリプトは 1 本で全 agent 対応可能だが、
.apm/hooks/*.jsonのイベントキーはターゲット別パッケージでネイティブ名を使う(Cursor ではstop/preToolUse/postToolUse。Stop/PreToolUse/PostToolUseは不可) report_failure関数で stdin のhook_event_name/terminationReason/cursor_version等を判別し、全 agent に適切な JSON または exit code を返す設計とする(Cursorstop→followup_message、その他 Cursor → exit 2 + stderr)
補足¶
- VS Code の hooks 仕様は code.visualstudio.com/docs/agent-customization/hooks に基づく。GitHub Copilot CLI とは別実装であり、同じ
.github/hooks/ディレクトリを使用するが stdin/stdout の JSON 構造が異なる点に注意 - Cursor の hooks 仕様は cursor.com/docs/hooks に基づく。イベントキーは camelCase 厳密一致(
stop,preToolUse,postToolUse)。stopの修正ループはfollowup_messageが正規 API(exit 2 + stderr は Hooks ログ用でゲートには非推奨) - APM hooks 配布の設計指針は microsoft.github.io/apm — Hooks and Commands を参照。本リポジトリはターゲット別 hooks パッケージ分離を採用
- Antigravity の hooks 仕様は antigravity.google/docs/hooks の正式仕様に基づく。旧 Gemini CLI (geminicli.com) とはイベント名・JSON 形式が異なるため注意
- Antigravity の PostToolUse は観測専用(出力
{}のみ)。agent へのフィードバックには PreInvocation のinjectStepsまたは Stop の{"decision":"continue","reason":"..."}を使用する - 各ツールの hooks 仕様 URL は変更される可能性があるため、定期的に確認する