Cursor フック完全ガイド: 発火しないことがある理由も解説
Cursor のフックを使うと、エージェントの行動をスクリプトで監視したりブロックしたりできます。すべてのシェルコマンド、MCP 呼び出し、ファイルの読み取りと編集が対象です。強力ですが、失敗しても気づきにくいのが難点です。実際に組み込んでみて学んだことをすべてまとめました。
要点
"version": 1 を含む hooks.json を ~/.cursor/(全プロジェクト)またはリポジトリの .cursor/ に置き、各イベントにコマンドを割り当て、stdout に JSON を出力します。許可、拒否、確認の判断には beforeShellExecution と beforeMCPExecution を使い、壊れたフックがコマンドを通さずにブロックすべき場合は failClosed: true を設定します。フックが無視されているように見えたら、まず Hooks 出力チャネルを開いてください。問題の大半は、パス、信頼されていないワークスペース、不正な JSON、または Cursor CLI がまだ送信しないイベントのどれかです。
Cursor のフックとは
フックとは、エージェントループの決まったタイミングで Cursor が実行するコマンドです。Cursor はこれから起こることを記述した JSON オブジェクトをコマンドの標準入力に送り、終了を待って、標準出力から JSON の応答を読み取ります。観察するだけのフック(編集を記録する、ファイルを整形する)もあれば、判断するフックもあります。beforeShellExecution フックは、コマンドを実行させるか、止めるか、先にあなたに確認するかを決められます。
そのため、フックは 3 つの用途に適しています。ガードレール(人の確認なしに rm -rf や git push --force を実行させない)、自動化(編集のたびに整形や lint を行う)、可視化(エージェントの行動を記録または転送し、エージェントが自分を必要としているタイミングを知る)です。
hooks.json の置き場所
Cursor は 4 つの場所からフックを読み込み、そのすべてを実行します。どのソースのフックでも一致するものはすべて実行され、Cursor がそれらの応答をマージします。
| レベル | ファイル | 備考 |
|---|---|---|
| ユーザー | ~/.cursor/hooks.json | すべてのプロジェクトに適用されます。相対コマンドは ~/.cursor/ を基準に解決されます。 |
| プロジェクト | <project>/.cursor/hooks.json | リポジトリにコミットします。信頼済みのワークスペースでのみ実行されます。相対コマンドはプロジェクトのルートを基準に解決されます。 |
| チーム | Cursor Web ダッシュボード | Enterprise 限定。全メンバーに同期されます。 |
| エンタープライズ | C:\ProgramData\Cursor\hooks.json(Windows)、/Library/Application Support/Cursor/hooks.json(macOS)、/etc/cursor/hooks.json(Linux、WSL) | IT 部門が管理します。 |
応答が食い違う場合は、最も厳しいものが優先されます。どのソースからでも deny は ask に勝ち、ask は allow に勝ちます。動作する最小のファイルは次のとおりです(Cursor のドキュメントにある例です)。
version は 1 でなければなりません。Cursor はファイルを監視し、保存すると再読み込みします。変更が反映されない場合は Cursor を再起動してください。フォーラムの報告の驚くほど多くが、これだけで解決しています。
フックできるイベント
Cursor のドキュメントにある現在の一覧を、用途別にまとめました。
| グループ | イベント | ブロックできるか |
|---|---|---|
| シェルと MCP | beforeShellExecution、afterShellExecution、beforeMCPExecution、afterMCPExecution | 2 つの before… フック: allow、deny、ask |
| 任意のツール | preToolUse、postToolUse、postToolUseFailure | preToolUse: allow または deny(現在 ask は強制されない) |
| ファイル | beforeReadFile、afterFileEdit | beforeReadFile: allow または deny |
| プロンプト | beforeSubmitPrompt | 可能(continue: false を使用) |
| エージェントループ | stop、afterAgentResponse、afterAgentThought、preCompact | 不可(stop はフォローアップメッセージを送れる) |
| サブエージェント | subagentStart、subagentStop | subagentStart: allow または deny(ask は deny として扱われる) |
| セッションとアプリ | sessionStart、sessionEnd、workspaceOpen | 不可 |
| Tab 補完 | beforeTabFileRead、afterTabFileEdit | beforeTabFileRead: allow または deny |
どのイベントも、いくつかの共通フィールド(conversation_id、generation_id、model、hook_event_name、cursor_version、workspace_roots)と、そのイベント固有のフィールドを受け取ります。beforeShellExecution は完全な command とその cwd を受け取り、stop は completed、aborted、error のいずれかの status を受け取ります。
許可、拒否、確認
判断するフックは JSON オブジェクトを 1 つ出力します。シェルフックの場合は次のようになります。
permissionはallow、deny、askのいずれかです。user_messageは Cursor であなたに表示される内容です。agent_messageはエージェントに伝えられる内容で、エージェントは同じコマンドを再試行せずに方針を変えられます。
終了コードは JSON と同じくらい重要です。終了コード 0 は「JSON の内容を使ってほしい」という意味です。終了コード 2 は deny と同じく操作をブロックします。それ以外の終了コードはフックの失敗として扱われ、操作はそのまま進みます。 ただし failClosed を設定している場合は別です。権限フックでは、不正な JSON やスキーマに合わない JSON は操作をブロックします。
Cursor のドキュメントには、beforeShellExecution と beforeMCPExecution で ask がサポートされていると書かれています。しかし 2026 年 3 月、Cursor のスタッフはフォーラムで、フックが強制するのは deny だけで、allow と ask は特にコマンドの許可リストやサンドボックスが有効な場合「basically ignored」(実質的に無視される)と書いています。修正の告知は見つかっていません。ガードレールを確実に効かせる必要があるなら、ask ではなく deny を返し、自分の使っているバージョンでテストしてください。
failClosed と timeout
各フックのエントリには、command と並べてオプションを指定できます。
failClosed: trueにすると、クラッシュ、タイムアウト、0 以外の終了コード、空の出力がブロックとして扱われます。デフォルトはfalseで、壊れたガードはエラーも出さずにすべてを通してしまいます。安全のためのフックなら、ほぼ必ずtrueにすべきです。timeoutの単位は秒です。フックが人の応答を待つなら、十分な余裕を持たせてください。差分を読む人には 5 秒では足りません。matcherはフックを実行する条件を絞り込みます。シェルフックではコマンド文字列全体と照合され、ツールフックではShell、Read、Write、MCP:<tool_name>などのツールの種類と照合されます。
ただしトレードオフがあります。2026 年 7 月、macOS のユーザーが「MainThreadShellExec not initialized」に遭遇しました。Cursor 自身のシェルホストの準備ができておらず、フックがフェイルクローズだったため、エージェントのシェルがブロックされたのです。Cursor のスタッフは修正がリリース済みであると述べ、failClosed: true のままにしておくことを推奨しました。古いビルドでこのエラーが出る場合は、「Developer: Reload Window」が回避策でした。
Windows でのフック
Windows では、Cursor デスクトップアプリはフックのコマンドを PowerShell 経由で実行し、JSON をパイプで渡します。PowerShell スクリプトは $input から読み取り、それ以外のプログラムは通常どおり標準入力から読み取ります。つまずきやすい点が 3 つあります。
- bash スクリプトはそのままでは動きません。 macOS を使うチームメンバーの
guard.shは PowerShell では失敗します。.ps1スクリプトやコンパイル済みのプログラムを使うか、インタープリターを明示的に呼び出してください(python .cursor/hooks/guard.py)。2026 年 1 月のフォーラムのスレッドでは、Git Bash の環境がsyntax error near unexpected token '[Convert]::FromBase64String'で失敗していました。これは PowerShell のコードが bash に渡っている状態です。 - 実行ポリシー。 PowerShell がスクリプトの実行を拒否する場合は、
powershell -NoProfile -ExecutionPolicy Bypass -File …で起動し、JSON を出力して、最後にexit 0で終了します。 - GUI プログラムは早く戻りすぎます。 これには丸 1 日かかりました。フックが GUI サブシステム向けにビルドされた Windows プログラムの場合、PowerShell はそれを起動すると待たずに先へ進みます。Cursor は空の出力を読み取るので、フックは何もしなかったように見えます(
failClosedを有効にしていれば、すべてをブロックします)。フックはコンソールプログラムとしてビルドするか、PowerShell が終了を待つようにラップしてください。
プロジェクトレベルのフックには、信頼済みのワークスペースも必要です。Cursor のスタッフは、フックが何もしないときの確認項目として、Hooks ログの「Hook N produced no output」という行、Settings → Hooks でワークスペースが信頼済みと表示されているか、コンソールの spawn、ENOENT、EPERM、ExecutionPolicy などのエラーを挙げています。
Cursor CLI でのフック
Cursor CLI(cursor-agent)は同じ ~/.cursor/hooks.json と .cursor/hooks.json を読み込みますが、エディターが送るイベントをすべて送ったことはありません。2026 年 1 月の時点で発火したのは 2 つのシェルフックだけでした。4 月には、beforeShellExecution、afterShellExecution、afterFileEdit、postToolUse、stop、sessionStart が CLI で動作することを Cursor のスタッフが確認しましたが、afterAgentResponse と afterAgentThought はまだ動作しませんでした(5 月にも再確認)。この一覧にないイベントは、頼る前にテストしてください。
クラウドエージェントはさらに厳しく、~/.cursor/hooks.json のユーザーレベルのフックはまったく実行されません。
フックが発火しないときのチェックリスト
- Hooks 出力チャネルを開きます(View → Output → Hooks)。または Customize の Hooks タブを開きます。読み込まれたフック、すべての実行、エラーが表示されます。
- JSON ファイル自体を確認します。
"version": 1があるか、イベント名の綴りが正確か(大文字と小文字を区別します)、JSON が有効かを確認します。 - パスを確認します。 相対コマンドは、プロジェクトのフックではプロジェクトのルート、ユーザーのフックでは
~/.cursor/を基準に解決されます。 - ワークスペースを信頼します。 信頼されていないフォルダーでは、プロジェクトのフックは実行されません。
- フックを手動で実行します。 サンプルの JSON をパイプで渡し、stdout を確認します。JSON オブジェクト 1 つ以外の出力(紛れ込んだ
echoや警告)があると、解析に失敗します。 - Cursor を再起動します。 保存するとファイルは再読み込みされますが、フォーラムの報告のいくつかは完全な再起動でしか解決しませんでした。
- 既知の制約を把握します。 許可リストやサンドボックスと併用すると
askとallowが無視されるという報告があります。一部のバージョンではsubagentStart/subagentStopが発火しないという報告もあります。CLI は一部のイベントを送りません。組み込みの Source Control パネルからのコミットはインターセプトされません。pre-commit のフックイベントは存在しません。
フック、自動実行、Auto-review
フックは、Cursor 自身の承認設定(Settings → Agents → Approvals & Execution)とは別物です。自動実行と Auto-review は、Cursor がパネルであなたに確認するかどうかを決め、フックはその上に独自の判断を加えます。「フックは ask を返したのに、コマンドがそのまま実行された」という報告がとても多いのはこのためです。別の権限の経路がすでに許可していたのです。
もう 1 つ、苦労して学んだことがあります。Auto-review を使うと、Cursor は一部のコマンドについて自身のウィンドウで確認することがあります。その質問はフックには届きません。フックのパイプラインではなく、Cursor の内部で起こるからです。
Pet Island の役割
フックに求めているのが「危険なコマンドをすべて見せて、ウィンドウを切り替えずに判断させてほしい」ということなら、Pet Island が Cursor でまさにそれを実現します。フックを自動でインストールし(beforeShellExecution と beforeMCPExecution。failClosed を有効にしてあるので、ヘルパーが止まってもコマンドが通ることはありません)、各リクエストをコマンド全体とともに画面上部の小さなアイランドに表示します。そこで許可または拒否を選ぶ間、Cursor のエージェントは待機します。
Cursor エディターからのコマンドとファイル編集は、アイランドから操作できます。質問とプランはアイランドに表示され、回答は Cursor で行います。Cursor CLI では、コマンドはアイランドから操作でき、その他のイベントは CLI が何を送るかによります。アンインストールすると Pet Island が追加したエントリだけが削除され、あなた自身のフックは残ります。
よくある質問
Cursor のフックは Windows で動作しますか?
はい。デスクトップアプリは PowerShell 経由でフックを実行し、JSON を標準入力で渡します(PowerShell スクリプトでは $input)。macOS 向けに書かれた bash スクリプトには PowerShell 版か Python 版が必要で、GUI サブシステムのプログラムは PowerShell が終了を待つようにラップする必要があります。
フックが ask を返しているのにコマンドが実行されるのはなぜですか?
2026 年 3 月に Cursor のスタッフが述べたところによると、フックが確実に強制するのは deny だけで、allow と ask は許可リストやサンドボックスによって上書きされることがあります。実行してはならないものには deny を使い、Hooks 出力チャネルでフックが実際に何を返したかを確認してください。
failClosed は何をしますか?
failClosed を true にすると、クラッシュ、タイムアウト、0 以外の終了コード、空の出力が操作をブロックします。設定しない場合、壊れたフックは操作をそのまま進めます。
フックのエラーはどこで確認できますか?
Hooks 出力チャネル(View → Output → Hooks)と、Customize の Hooks タブです。
Cursor CLI でフックは動作しますか?
一部は動作します。CLI は同じ hooks.json ファイルを読み込みます。2026 年 5 月時点で Cursor のスタッフが確認したのは、シェルフック、afterFileEdit、postToolUse、stop、sessionStart で、afterAgentResponse と afterAgentThought は動作しません。
Source Control パネルからの git commit をフックで止められますか?
いいえ。Cursor には pre-commit のフックイベントがなく、組み込みの Source Control UI からのコミットはインターセプトされません。その用途には通常の git の pre-commit フックを使ってください。
出典
このページの設定と動作はすべて、2026年10月26日 に以下のページと照らし合わせて確認しました。エージェントは変化が速いため、内容が一致しなくなった場合は公式ページの記述を優先してください。
- Cursor ドキュメント: Hooks
- Cursor フォーラム: フックが期待どおりに実行されない(スタッフ: 強制されるのは deny のみ)
- Cursor フォーラム: beforeShellExecution の allow/ask が無視され、許可リストが優先される
- Cursor フォーラム: フェイルクローズのフックと MainThreadShellExec not initialized
- Cursor フォーラム: フックからの不正な JSON でコマンドが黙って許可された(修正済み)
- Cursor フォーラム: Cursor CLI がすべてのフックイベントを送らない
- Cursor フォーラム: Windows でプロジェクトレベルのフックが実行されない
- Cursor フォーラム: Windows の Git Bash 環境でプロジェクトのフックが失敗する
- Cursor フォーラム: subagentStart と subagentStop が発火しない