> ## Documentation Index
> Fetch the complete documentation index at: https://docs.windsurf.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cascade Hooks

> Cascade のワークフローの要所でカスタムシェルコマンドを実行し、pre-hook / post-hook によってログ取得、セキュリティ制御、検証、Enterprise ガバナンスを実現します。

Cascade Hooks を使うと、Cascade のワークフローの要所でカスタムシェルコマンドを実行できます。この強力な拡張機能により、操作ログの記録、ガードレールの適用、検証の実行、外部システムとの連携が可能になります。

<Note>
  Hooks は、Cascade の動作をきめ細かく制御する必要があるパワーユーザーや Enterprise のチーム向けに設計されています。基本的なシェルスクリプトの知識が必要です。
</Note>

<div id="what-you-can-build">
  ## 何が作れるか
</div>

Hooks は幅広い自動化とガバナンス機能を提供します:

* **Logging & Analytics**: コンプライアンスと利用分析のために、Cascade によるすべてのファイル読み取り、コード変更、コマンド実行、ユーザーから Cascade へ送信されたプロンプト、および Cascade の応答を追跡
* **セキュリティコントロール**: Cascade の機密ファイルへのアクセスや危険なコマンドの実行、ポリシー違反となるプロンプトの処理をブロック
* **品質保証**: コード変更後にリンター、フォーマッター、テストを自動実行
* **カスタムワークフロー**: 課題トラッカー、通知システム、デプロイパイプラインと連携
* **チーム標準化**: 組織全体でコーディング規約とベストプラクティスを遵守させる

<div id="how-hooks-work">
  ## Hooks の仕組み
</div>

Hooks は、特定の Cascade のアクションが発生した際に自動で実行されるシェルコマンドです。各 Hook は次の処理を行います:

1. 標準入力で JSON を受け取り、実行中のアクションに関する詳細な**コンテキストを取得**
2. Python、Bash、Node.js など、任意の実行可能ファイルで**スクリプトを実行**
3. 終了コードと標準出力/標準エラーを通じて**結果を返す**

**プレフック** (アクション実行前に起動) では、スクリプトを終了コード `2` で終了させることで**アクションをブロック**できます。これにより、プレフックはセキュリティポリシーやバリデーションの実装に最適です。

<div id="configuration">
  ## 設定
</div>

Hooks は JSON ファイルで設定でき、3 つの異なるレベルに配置できます。Cascade はすべての場所から Hooks を読み込んで統合し、チームが Hook 設定の配布と管理を柔軟に行えるようにします。

<div id="system-level">
  #### システムレベル
</div>

システムレベルのフックは、共有開発マシンで組織全体に適用されるポリシーの実施に最適です。たとえば、セキュリティポリシーやコンプライアンス要件の順守、必須のコードレビューのワークフローを強制するために使用できます。Enterprise チームは、ローカルファイルを管理することなく、[クラウドダッシュボード](#cloud-dashboard-configuration) からフックを設定することもできます。

* **macOS**: `/Library/Application Support/Windsurf/hooks.json`
* **Linux/WSL**: `/etc/windsurf/hooks.json`
* **Windows**: `C:\ProgramData\Windsurf\hooks.json`

<div id="user-level">
  #### ユーザー レベル
</div>

ユーザー レベルのフックは、個人の嗜好や任意のワークフローに最適です。

* **Windsurf IDE**: `~/.codeium/windsurf/hooks.json`
* **JetBrains プラグイン**: `~/.codeium/hooks.json`

<div id="workspace-level">
  #### ワークスペースレベル
</div>

ワークスペースレベルのフックにより、チームはプロジェクト固有のポリシーをコードと併せてバージョン管理できます。これには、カスタム検証ルール、プロジェクト固有のインテグレーション、チーム固有のワークフローなどが含まれます。

* **場所**: ワークスペースのルートにある `.windsurf/hooks.json`

<Note>
  3 つの場所のフックはすべて\*\*統合 (マージ) \*\*されます。同じフックイベントが複数の場所で設定されている場合、すべてのフックは次の順序で実行されます: system → user → workspace。
</Note>

<div id="basic-structure">
  ### 基本構成
</div>

以下は、hooks 設定の基本的な構成例です。

```json theme={null}
{
  "hooks": {
    "pre_read_code": [
      {
        "command": "python3 /path/to/your/script.py",
        "show_output": true
      }
    ],
    "post_write_code": [
      {
        "command": "python3 /path/to/another/script.py",
        "show_output": true
      }
    ]
  }
}
```

<div id="configuration-options">
  ### 設定オプション
</div>

各フックは次のパラメータを受け付けます。

| Parameter           | Type    | Description                                                      |
| ------------------- | ------- | ---------------------------------------------------------------- |
| `command`           | string  | 実行するシェルコマンド。引数付きの有効な実行可能ファイルであれば任意のものを指定できます。                    |
| `show_output`       | boolean | フックの stdout/stderr の出力をユーザー向けの Cascade の UI に表示するかどうか。デバッグに便利です。 |
| `working_directory` | string  | 省略可。コマンドを実行するディレクトリ。既定はワークスペースのルートです。                            |

<Note>
  **`working_directory` パラメータについて:**

  * 複数リポジトリのワークスペースでは、既定値は現在作業中のリポジトリのルートです
  * 相対パスは既定の場所 (ワークスペースまたはリポジトリのルート) から解決されます
  * 絶対パスも使用できます
  * `~` によるホームディレクトリ展開はサポートされていません
</Note>

<div id="hook-events">
  ## フックイベント
</div>

Cascade は、エージェントのワークフローにおける主要なアクションを網羅する 12 つのフックイベントを提供します。

<div id="common-input-structure">
  ### 共通の入力構造
</div>

すべてのフックは、次の共通フィールドを含む JSON オブジェクトを受け取ります：

| Field               | Type   | Description                                       |
| ------------------- | ------ | ------------------------------------------------- |
| `agent_action_name` | string | フックイベント名 (例：「pre\_read\_code」「post\_write\_code」) |
| `trajectory_id`     | string | Cascade 全体の会話に対する一意の識別子                           |
| `execution_id`      | string | 単一のエージェントのターンに対する一意の識別子                           |
| `timestamp`         | string | フックがトリガーされた時刻の ISO 8601 形式タイムスタンプ                 |
| `tool_info`         | object | イベント固有の情報 (フック種別によって異なる)                          |

以下の例では、簡潔にするため共通フィールドを省略しています。フックイベントには 12 種類の主要タイプがあります：

<div id="pre_read_code">
  ### pre\_read\_code
</div>

Cascade がコードファイルを読み取る**前**にトリガーされます。フックが終了コード 2 で終了した場合、このアクションはブロックされることがあります。

**ユースケース**: ファイルアクセスの制限、読み取り操作のログ記録、権限チェック

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "pre_read_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py"
  }
}
```

Cascade がディレクトリを再帰的に読み込む場合、この `file_path` はディレクトリのパスになることがあります。

<div id="post_read_code">
  ### post\_read\_code
</div>

Cascade がコードファイルの読み取りに成功した**後**にトリガーされます。

**ユースケース**: 成功した読み取りの記録、ファイルアクセスパターンの追跡

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "post_read_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py"
  }
}
```

Cascade がディレクトリを再帰的に読み込む場合、この `file_path` はディレクトリのパスになることがあります。

<div id="pre_write_code">
  ### pre\_write\_code
</div>

Cascade がコードファイルを作成または変更する**前**にトリガーされます。フックが終了コード 2 で終了した場合、この操作はブロックされる可能性があります。

**ユースケース**: 保護対象ファイルへの変更を防止、変更前にファイルをバックアップ

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "pre_write_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py",
    "edits": [
      {
        "old_string": "def old_function():\n    pass",
        "new_string": "def new_function():\n    return True"
      }
    ]
  }
}
```

<div id="post_write_code">
  ### post\_write\_code
</div>

Cascade がコードファイルを作成または変更した**後**にトリガーされます。

**ユースケース**: リンター、フォーマッター、テストの実行／コード変更の記録

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "post_write_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py",
    "edits": [
      {
        "old_string": "import os",
        "new_string": "import os\nimport sys"
      }
    ]
  }
}
```

<div id="pre_run_command">
  ### pre\_run\_command
</div>

Cascade がターミナルコマンドを実行する**前**にトリガーされます。フックが終了コード 2 で終了した場合、このアクションはブロックされます。

**ユースケース**: 危険なコマンドのブロック、すべてのコマンド実行のログ取得、安全性チェックの追加

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "pre_run_command",
  "tool_info": {
    "command_line": "npm install package-name",
    "cwd": "/Users/yourname/project"
  }
}
```

<div id="post_run_command">
  ### post\_run\_command
</div>

Cascade がターミナルコマンドを実行した**後**にトリガーされます。

**ユースケース**: コマンド結果の記録、後続アクションの起動

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "post_run_command",
  "tool_info": {
    "command_line": "npm install package-name",
    "cwd": "/Users/yourname/project"
  }
}
```

<div id="pre_mcp_tool_use">
  ### pre\_mcp\_tool\_use
</div>

Cascade が MCP (Model Context Protocol) ツールを呼び出す**前**にトリガーされます。フックがコード 2 で終了した場合、この操作はブロックされることがあります。

**ユースケース**: MCP の使用状況の記録、利用可能な MCP ツールの制限

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "pre_mcp_tool_use",
  "tool_info": {
    "mcp_server_name": "github",
    "mcp_tool_arguments": {
      "owner": "code-owner",
      "repo": "my-cool-repo",
      "title": "バグ報告",
      "body": "バグの詳細をここに記述"
    },
    "mcp_tool_name": "create_issue"
  }
}
```

<div id="post_mcp_tool_use">
  ### post\_mcp\_tool\_use
</div>

Cascade が MCP ツールの呼び出しに成功した**後**にトリガーされます。

**ユースケース**: MCP の操作ログ、API 使用状況の追跡、MCP 結果の確認

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "post_mcp_tool_use",
  "tool_info": {
    "mcp_result": "...",
    "mcp_server_name": "github",
    "mcp_tool_arguments": {
      "owner": "code-owner",
      "perPage": 1,
      "repo": "my-cool-repo",
      "sha": "main"
    },
    "mcp_tool_name": "list_commits"
  }
}
```

<div id="pre_user_prompt">
  ### pre\_user\_prompt
</div>

Cascade がユーザーのプロンプトのテキストを処理する**前に**トリガーされます。フックが終了コード 2 で終了した場合、この処理はブロックされる可能性があります。

**ユースケース**: 監査のためにすべてのユーザーのプロンプトをログに記録する、有害またはポリシー違反の可能性があるプロンプトをブロックする

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "pre_user_prompt",
  "tool_info": {
    "user_prompt": "can you run the echo hello command"
  }
}
```

`show_output` 設定オプションはこのフックには適用されません。

<div id="post_cascade_response">
  ### post\_cascade\_response
</div>

Cascade がユーザーのプロンプトへの応答を完了した**後**に非同期でトリガーされます。このフックは、直前のユーザー入力以降に生成された Cascade のレスポンス全体を受け取ります。

**ユースケース**: 監査のためにすべての Cascade レスポンスをログに記録する、レスポンスのパターンを分析する、コンプライアンス審査のために外部システムにレスポンスを送信する

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "post_cascade_response",
  "tool_info": {
    "response": "### Planner Response\n\nI'll help you create that file.\n\n*Created file `/path/to/file.py`*\n\n### Planner Response\n\nThe file has been created successfully."
  }
}
```

`response` フィールドには、直近のユーザー入力以降における Cascade の応答内容が Markdown 形式で含まれます。これには、planner の応答、ツールによるアクション (ファイルの読み取り・書き込み・コマンドの実行) 、および Cascade が実行したその他のステップが含まれます。また、どの[ルール](/ja/windsurf/cascade/memories-and-rules)がトリガーされたかに関する情報も含まれます。ルールの発火状況をどのように解析するかについては、[Tracking Triggered Rules](#tracking-triggered-rules) の例を参照してください。

`show_output` 設定オプションは、このフックには適用されません。

<Warning>
  `response` の内容は trajectory データから導出されたものであり、あなたのコードベースや会話からの機密情報を含む場合があります。このデータは、所属組織のセキュリティおよびプライバシーポリシーに従って取り扱ってください。
</Warning>

<div id="post_cascade_response_with_transcript">
  ### post\_cascade\_response\_with\_transcript
</div>

Cascade がユーザーのプロンプトへのレスポンスを完了した**後**に非同期でトリガーされます。`post_cascade_response` と似ていますが、インラインで Markdown 形式の要約を提供する代わりに、このフックは会話の全文 (会話開始時点から) をローカルの JSONL ファイルに書き出し、そのファイルパスを提供します。

**ユースケース**: Enterprise の監査およびコンプライアンスログ、AI 生成コンテンツの貢献度追跡、外部のオブザーバビリティ／Analytics ツールへの会話ログ連携

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "post_cascade_response_with_transcript",
  "tool_info": {
    "transcript_path": "/Users/yourname/.windsurf/transcripts/{trajectory_id}.jsonl"
  }
}
```

`transcript_path` は、`~/.windsurf/transcripts/{trajectory_id}.jsonl` にある [JSONL](https://jsonlines.org/) ファイルを指します。各行は、`type` と `status` フィールドに加えてステップ固有のデータを持つ、会話の 1 ステップを表す JSON オブジェクトです。例えば、次のようになります。

```jsonl theme={null}
{"status":"done","type":"user_input","user_input":{"rules_applied":{"always_on":["my-rule.md"]},"user_response":"create a hello world file"}}
{"planner_response":{"response":"I'll create a hello world file for you."},"status":"done","type":"planner_response"}
{"code_action":{"new_content":"print('hello world')\n","path":"/path/to/file.py"},"status":"done","type":"code_action"}
{"planner_response":{"response":"I created the file for you."},"status":"done","type":"planner_response"}
```

トランスクリプトには、ファイル内容、コマンド出力、ツール引数、検索結果、適用された[ルール](/ja/windsurf/cascade/memories-and-rules)など、顧客が所有する詳細なデータが含まれます。各ステップの正確な構造は将来のバージョンで変更される可能性があるため、フックのコンシューマーを実装する際は、そうした変更にも耐えられるように設計してください。

トランスクリプトファイルは `0600` パーミッションで書き込まれます。Windsurf はトランスクリプトディレクトリ内のファイル数を自動的に 100 件に制限し、更新時刻が最も古いものから順に削除します。

`show_output` 設定オプションはこのフックには適用されません。

次の表は、`post_cascade_response` フックと `post_cascade_response_with_transcript` フックの主な違いを示しています。

|                  | `post_cascade_response`               | `post_cascade_response_with_transcript`          |
| ---------------- | ------------------------------------- | ------------------------------------------------ |
| **Data scope**   | 直前のユーザー入力以降のステップのみ                    | 会話の最初からの全履歴                                      |
| **Format**       | `tool_info.response` 内の Markdown サマリー | `tool_info.transcript_path` にある構造化された JSONL ファイル |
| **Detail level** | 要約された人間可読のサマリー                        | 詳細な機械可読データ (ファイル内容、コマンド出力など)                     |
| **Delivery**     | stdin の JSON によるインライン                 | ディスク上のファイル (`~/.windsurf/transcripts/`)          |

<Warning>
  トランスクリプトファイルには、ファイル内容、コマンド出力、会話履歴など、コードベースからの機密情報が含まれます。これらのファイルは、所属組織のセキュリティおよびプライバシーポリシーに従って取り扱ってください。
</Warning>

<div id="post_setup_worktree">
  ### post\_setup\_worktree
</div>

新しい [git worktree](./worktrees) が作成・設定された**後**にトリガーされます。フックは新しい **worktree** ディレクトリ内で実行されます。

**利用例**: `.env` ファイルやその他の Git で管理されていないファイルを worktree にコピーする、依存関係をインストールする、セットアップスクリプトを実行する

**環境変数**:

| Variable               | Description                                                   |
| ---------------------- | ------------------------------------------------------------- |
| `$ROOT_WORKSPACE_PATH` | 元のワークスペースへの絶対パス。これを使って、元のリポジトリを基準にファイルへアクセスしたりコマンドを実行したりできます。 |

**入力 JSON**:

```json theme={null}
{
  "agent_action_name": "post_setup_worktree",
  "tool_info": {
    "worktree_path": "/Users/me/.windsurf/worktrees/my-repo/abmy-repo-c123",
    "root_workspace_path": "/Users/me/projects/my-repo"
  }
}
```

<div id="exit-codes">
  ## 終了コード
</div>

フックスクリプトは終了コードで結果を伝達します:

| 終了コード | 意味        | 影響                                                                           |
| ----- | --------- | ---------------------------------------------------------------------------- |
| `0`   | 成功        | アクションは通常どおり続行                                                                |
| `2`   | ブロッキングエラー | Cascade エージェントは stderr のエラーメッセージを表示します。pre-hook の場合、このコードでアクションを**ブロック**します。 |
| その他   | エラー       | アクションは通常どおり続行                                                                |

<Warning>
  **pre-hook** (pre\_user\_prompt、pre\_read\_code、pre\_write\_code、pre\_run\_command、pre\_mcp\_tool\_use) のみが、終了コード 2 によってアクションをブロックできます。post-hook は、アクションがすでに実行済みのためブロックできません。
</Warning>

`show_output` が true の場合、ユーザーは Cascade の UI でフックが生成した標準出力と標準エラーを確認できます。

<div id="example-use-cases">
  ## ユースケース例
</div>

<div id="logging-all-cascade-actions">
  ### すべての Cascade アクションをログに記録する
</div>

監査のために、Cascade が行うすべてのアクションを追跡します。

**設定**:

```json theme={null}
{
  "hooks": {
    "post_read_code": [
      {
        "command": "python3 /Users/yourname/hooks/log_input.py",
        "show_output": true
      }
    ],
    "post_write_code": [
      {
        "command": "python3 /Users/yourname/hooks/log_input.py",
        "show_output": true
      }
    ],
    "post_run_command": [
      {
        "command": "python3 /Users/yourname/hooks/log_input.py",
        "show_output": true
      }
    ],
    "post_mcp_tool_use": [
      {
        "command": "python3 /Users/yourname/hooks/log_input.py",
        "show_output": true
      }
    ],
    "post_cascade_response": [
      {
        "command": "python3 /Users/yourname/hooks/log_input.py"
      }
    ]
  }
}
```

**スクリプト** (`log_input.py`) :

```python theme={null}
#!/usr/bin/env python3

import sys
import json

def main():
    # 標準入力からJSONデータを読み込む
    input_data = sys.stdin.read()
    
    # JSONをパースする
    try:
        data = json.loads(input_data)
        
        # フォーマット済みJSONをファイルに書き込む
        with open("/Users/yourname/hooks/input.txt", "a") as f:
            f.write('\n' + '='*80 + '\n')
            f.write(json.dumps(data, indent=2, separators=(',', ': ')))
            f.write('\n')
    
        print(json.dumps(data, indent=2))
    except json.JSONDecodeError as e:
        print(f"JSONパースエラー: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

このスクリプトは、すべてのフック呼び出しをログファイルに追記し、Cascade が実行したすべてのアクションの監査用ログを作成します。入力データを変換したり、必要に応じて独自ロジックを実行したりすることもできます。

<div id="restricting-file-access">
  ### ファイルアクセスの制限
</div>

Cascade が特定のディレクトリの外にあるファイルを読み取らないようにします。

**設定**:

```json theme={null}
{
  "hooks": {
    "pre_read_code": [
      {
        "command": "python3 /Users/yourname/hooks/block_read_access.py",
        "show_output": true
      }
    ]
  }
}
```

**スクリプト** (`block_read_access.py`) :

```python theme={null}
#!/usr/bin/env python3

import sys
import json

ALLOWED_PREFIX = "/Users/yourname/my-project/"

def main():
    # 標準入力からJSONデータを読み込む
    input_data = sys.stdin.read()

    # JSONをパースする
    try:
        data = json.loads(input_data)

        if data.get("agent_action_name") == "pre_read_code":
            tool_info = data.get("tool_info", {})
            file_path = tool_info.get("file_path", "")
            
            if not file_path.startswith(ALLOWED_PREFIX):
                print(f"アクセス拒否: Cascadeは{ALLOWED_PREFIX}配下のファイルのみ読み取り可能です", file=sys.stderr)
                sys.exit(2)  # 終了コード2でアクションをブロック
            
            print(f"アクセス許可: {file_path}", file=sys.stdout)

    except json.JSONDecodeError as e:
        print(f"JSONパースエラー: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

Cascade が許可ディレクトリ外のファイルを読み込もうとすると、このフックが処理をブロックし、エラーメッセージを表示します。

<div id="blocking-dangerous-commands">
  ### 危険なコマンドのブロック
</div>

Cascade が潜在的に有害なコマンドを実行しないようにします。

**設定**:

```json theme={null}
{
  "hooks": {
    "pre_run_command": [
      {
        "command": "python3 /Users/yourname/hooks/block_dangerous_commands.py",
        "show_output": true
      }
    ]
  }
}
```

**スクリプト** (`block_dangerous_commands.py`) :

```python theme={null}
#!/usr/bin/env python3

import sys
import json

DANGEROUS_COMMANDS = ["rm -rf", "sudo rm", "format", "del /f"]

def main():
    # 標準入力からJSONデータを読み込む
    input_data = sys.stdin.read()

    # JSONをパースする
    try:
        data = json.loads(input_data)

        if data.get("agent_action_name") == "pre_run_command":
            tool_info = data.get("tool_info", {})
            command = tool_info.get("command_line", "")

            for dangerous_cmd in DANGEROUS_COMMANDS:
                if dangerous_cmd in command:
                    print(f"Commandがブロックされました: '{dangerous_cmd}' は安全上の理由により許可されていません。", file=sys.stderr)
                    sys.exit(2)  # 終了コード2でCommandをブロック
            
            print(f"Commandが承認されました: {command}", file=sys.stdout)

    except json.JSONDecodeError as e:
        print(f"JSONパースエラー: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

このフックはコマンド内の危険なパターンを検出し、実行前にブロックします。

<div id="blocking-policy-violating-prompts">
  ### ポリシー違反プロンプトのブロック
</div>

組織ポリシーに違反するプロンプトをユーザーが送信できないようにします。

**設定**:

```json theme={null}
{
  "hooks": {
    "pre_user_prompt": [
      {
        "command": "python3 /Users/yourname/hooks/block_bad_prompts.py"
      }
    ]
  }
}
```

**スクリプト** (`block_bad_prompts.py`):

```python theme={null}
#!/usr/bin/env python3

import sys
import json

BLOCKED_PATTERNS = [
    "something dangerous",
    "bypass security",
    "ignore previous instructions"
]

def main():
    # 標準入力からJSONデータを読み取る
    input_data = sys.stdin.read()

    # JSONを解析
    try:
        data = json.loads(input_data)

        if data.get("agent_action_name") == "pre_user_prompt":
            tool_info = data.get("tool_info", {})
            user_prompt = tool_info.get("user_prompt", "").lower()

            for pattern in BLOCKED_PATTERNS:
                if pattern in user_prompt:
                    print(f"Prompt blocked: Contains prohibited content. The user cannot ask the agent to do bad things.", file=sys.stderr)
                    sys.exit(2)  # 終了コード2でプロンプトをブロック

    except json.JSONDecodeError as e:
        print(f"Error parsing JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

このフックは、ユーザーのプロンプトが処理される前にそれを検査し、禁止されたパターンを含むものをブロックします。プロンプトがブロックされると、ユーザーには Cascade の UI 上にエラーメッセージが表示されます。

<div id="logging-cascade-responses">
  ### Cascade レスポンスのログ記録
</div>

コンプライアンス監査や Analytics のために、すべての Cascade レスポンスを記録します。

**設定**:

```json theme={null}
{
  "hooks": {
    "post_cascade_response": [
      {
        "command": "python3 /Users/yourname/hooks/log_cascade_response.py"
      }
    ]
  }
}
```

**スクリプト** (`log_cascade_response.py`):

```python theme={null}
#!/usr/bin/env python3

import sys
import json
from datetime import datetime

def main():
    # 標準入力からJSONデータを読み込む
    input_data = sys.stdin.read()

    # JSONを解析
    try:
        data = json.loads(input_data)

        if data.get("agent_action_name") == "post_cascade_response":
            tool_info = data.get("tool_info", {})
            cascade_response = tool_info.get("response", "")
            trajectory_id = data.get("trajectory_id", "unknown")
            timestamp = data.get("timestamp", datetime.now().isoformat())

            # ファイルにログを記録
            with open("/Users/yourname/hooks/cascade_responses.log", "a") as f:
                f.write(f"\n{'='*80}\n")
                f.write(f"Timestamp: {timestamp}\n")
                f.write(f"Trajectory ID: {trajectory_id}\n")
                f.write(f"Response:\n{cascade_response}\n")

            print(f"Logged Cascade response for trajectory {trajectory_id}")

    except json.JSONDecodeError as e:
        print(f"Error parsing JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

このフックは、Cascade からのすべてのレスポンスをファイルにログとして記録し、AI が生成したすべてのコンテンツの監査証跡を残します。これを拡張して、外部のログシステムやデータベース、コンプライアンスプラットフォームにデータを送信することもできます。

<div id="tracking-triggered-rules">
  ### トリガーされたルールの追跡
</div>

オブザーバビリティとメトリクスのために、Cascade とのやり取り中にどの [ルール](/ja/windsurf/cascade/memories-and-rules) が適用されたかを追跡します。

**設定**:

```json theme={null}
{
  "hooks": {
    "post_cascade_response": [
      {
        "command": "python3 /Users/yourname/hooks/track_rules.py"
      }
    ]
  }
}
```

**スクリプト** (`track_rules.py`) ：

```python theme={null}
#!/usr/bin/env python3

import sys
import json
import re
from datetime import datetime

def extract_triggered_rules(response: str) -> dict:
    """
    Cascadeレスポンスからトリガーされたルールを解析します。
    ルールは次の形式で表示されます: - (Rule-Type) Triggered Rule: rule-filename.md
    """
    pattern = r"- \(([^)]+)\) Triggered Rule: (.+?)(?:\s*$)"
    rules = {}

    for match in re.finditer(pattern, response, re.MULTILINE):
        rule_type, rule_name = match.groups()
        if rule_type not in rules:
            rules[rule_type] = []
        rules[rule_type].append(rule_name)

    return rules

def main():
    input_data = sys.stdin.read()

    try:
        data = json.loads(input_data)

        if data.get("agent_action_name") == "post_cascade_response":
            response = data.get("tool_info", {}).get("response", "")
            trajectory_id = data.get("trajectory_id", "unknown")
            timestamp = data.get("timestamp", datetime.now().isoformat())

            rules = extract_triggered_rules(response)
            total_rules = sum(len(v) for v in rules.values())

            # Log to file
            with open("/Users/yourname/hooks/rules_usage.log", "a") as f:
                f.write(f"\n{'='*60}\n")
                f.write(f"Timestamp: {timestamp}\n")
                f.write(f"Trajectory: {trajectory_id}\n")
                f.write(f"Total rules triggered: {total_rules}\n")
                for rule_type, rule_list in rules.items():
                    if rule_list:
                        f.write(f"  {rule_type}: {', '.join(rule_list)}\n")

            print(f"Tracked {total_rules} triggered rules")

    except json.JSONDecodeError as e:
        print(f"Error parsing JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

**ルールの種類:**

* `Always On` - 常に有効なルール
* `Model Decision` - 条件付き適用のため、その説明が AIモデル に提示されるルール
* `Manual` - ユーザー入力で明示的に @ メンションされたルール
* `Global` - `global_rules.md` に定義されたグローバルルール
* `Glob` - glob パターンに一致するファイルアクセスによってトリガーされるルール

<Note>
  これは、どのルールが AIモデル に*提示*されたか、あるいはファイルアクセスによって*トリガー*されたかを追跡するものであり、AIモデル が実際にそのルールに*従った*かどうかを示すものではありません。会話内ですでに直近で提示されたルールは重複排除され、しばらくのあいだ再表示されない場合があります。
</Note>

<div id="running-code-formatters-after-edits">
  ### 編集後にコードフォーマッタを実行する
</div>

Cascade がコードファイルを変更した後に、自動で整形します。

**設定**:

```json theme={null}
{
  "hooks": {
    "post_write_code": [
      {
        "command": "bash /Users/yourname/hooks/format_code.sh",
        "show_output": false
      }
    ]
  }
}
```

**スクリプト** (`format_code.sh`) :

```bash theme={null}
#!/bin/bash

# 標準入力からJSONを読み込む
input=$(cat)

# jqを使用してファイルパスを抽出する
file_path=$(echo "$input" | jq -r '.tool_info.file_path')

# ファイル拡張子に基づいてフォーマットする
if [[ "$file_path" == *.py ]]; then
    black "$file_path" 2>&1
    echo "Pythonファイルをフォーマットしました: $file_path"
elif [[ "$file_path" == *.js ]] || [[ "$file_path" == *.ts ]]; then
    prettier --write "$file_path" 2>&1
    echo "JS/TSファイルをフォーマットしました: $file_path"
elif [[ "$file_path" == *.go ]]; then
    gofmt -w "$file_path" 2>&1
    echo "Goファイルをフォーマットしました: $file_path"
fi

exit 0
```

このフックは、各編集のたびにファイルの種類に応じて適切なフォーマッタを自動実行します。

<div id="setting-up-worktrees">
  ### ワークツリーのセットアップ
</div>

新しい worktree が作成された際に、環境ファイルをコピーして依存関係をインストールします。

**設定**（`.windsurf/hooks.json` 内）:

```json theme={null}
{
  "hooks": {
    "post_setup_worktree": [
      {
        "command": "bash $ROOT_WORKSPACE_PATH/hooks/setup_worktree.sh",
        "show_output": true
      }
    ]
  }
}
```

**スクリプト** (`hooks/setup_worktree.sh`):

```bash theme={null}
#!/bin/bash

# 元のワークスペースから環境ファイルをコピー
if [ -f "$ROOT_WORKSPACE_PATH/.env" ]; then
    cp "$ROOT_WORKSPACE_PATH/.env" .env
    echo ".envファイルをコピーしました"
fi

if [ -f "$ROOT_WORKSPACE_PATH/.env.local" ]; then
    cp "$ROOT_WORKSPACE_PATH/.env.local" .env.local
    echo ".env.localファイルをコピーしました"
fi

# 依存関係をインストール
if [ -f "package.json" ]; then
    npm install
    echo "npm依存関係をインストールしました"
fi

exit 0
```

このフックにより、各ワークツリーで必要な環境構成と依存関係が自動的にセットアップされます。

<div id="best-practices">
  ## ベストプラクティス
</div>

<div id="security">
  ### セキュリティ
</div>

<Warning>
  **Cascade Hooks の使用は自己責任です**: Hooks は、あなたのユーザーアカウントに付与された権限の範囲でシェルコマンドを自動実行します。設定したコードの結果については、全てあなたの責任となります。設計不備や悪意のある hook により、ファイルの改変、データの削除、認証情報の漏えい、システムの侵害が発生するおそれがあります。
</Warning>

* **すべての入力を検証する**: 特にファイルパスやコマンドに関して、検証されていない入力 JSON を信用しないでください。
* **絶対パスを使用する**: あいまいさを避けるため、hook の設定では常に絶対パスを使用してください。
* **機微情報を保護する**: API キーや資格情報などの機微情報はログに記録しないでください。
* **権限を確認する**: hook スクリプトに適切なファイルシステム権限が設定されていることを確認してください。
* **導入前に精査する**: 設定に追加する前に、すべての hook コマンドとスクリプトをレビューしてください。
* **隔離環境でテストする**: メインの開発マシンで有効化する前に、テスト環境で hook を実行してください。

<div id="performance-considerations">
  ### パフォーマンスに関する考慮事項
</div>

* **フックは高速に**: フックが遅いと Cascade の応答性に影響します。実行時間は 100ms 未満を目指してください。
* **非同期処理の活用**: ブロッキングを避けるため、ログはキューやデータベースに非同期で記録することを検討してください。
* **早期フィルタリング**: 不要な処理を避けるため、スクリプト冒頭でアクションタイプを確認してください。

<div id="error-handling">
  ### エラーハンドリング
</div>

* **常に JSON を検証する**: 不正な入力に優雅に対処できるよう、try-catch ブロックを使用してください。
* **エラーを適切にログ出力する**: `show_output` が有効な場合に見えるよう、エラーは `stderr` に出力してください。
* **安全に失敗する**: フックでエラーが発生した場合、そのアクションをブロックすべきか、処理を続行させるべきかを検討してください。

<div id="testing-your-hooks">
  ### フックのテスト
</div>

1. **ログから始める**: データフローを把握するため、まずはシンプルなロギングフックを実装します。
2. **`show_output: true` を使用する**: 開発中は出力を有効にして、フックの動作を確認します。
3. **ブロック動作をテストする**: pre-hook で終了コード 2 によってアクションが正しくブロックされることを検証します。
4. **すべてのコードパスを確認する**: スクリプトで成功と失敗の両ケースをテストします。

<div id="enterprise-distribution">
  ## Enterprise 配布
</div>

Enterprise 組織では、個々のユーザーが回避できないセキュリティポリシー、コンプライアンス要件、開発標準を徹底する必要があります。Cascade Hooks は、Enterprise 向けの配布方法として次の 2 つをサポートします：

1. **Cloud Dashboard** - Windsurf ダッシュボードの Team Settings からフックを設定します
2. **System-Level Files** - MDM または構成管理ツール経由でフックをデプロイします

これらの方法は併用可能であり、すべてのソースからのフックが統合され、順番に実行されます。

<div id="cloud-dashboard-configuration">
  ### クラウドダッシュボードでの設定
</div>

チーム管理者は、Windsurf ダッシュボードから直接 Cascade Hooks を設定できます。

**要件:**

* Enterprise プラン
* `TEAM_SETTINGS_UPDATE` 権限

**設定手順:**

1. Windsurf ダッシュボードで **Team Settings** に移動します
2. **Cascade Hooks** セクションを見つけます
3. フックの設定を JSON 形式で入力します
4. 変更を保存します

ダッシュボードで設定されたフックは、自動的にすべてのチームメンバーに配布され、Windsurf の起動時に読み込まれます。クラウドで設定されたフックが最初に読み込まれ、その後にシステムレベル、ユーザーレベル、およびワークスペースレベルのフックが読み込まれます。

<Note>
  複数のチーム設定が統合される場合、フックは上書きされるのではなく、アクションごとに結合されます。つまり、該当するすべてのチーム設定のフックがまとめて実行されます。
</Note>

<div id="system-level-file-deployment">
  ### システムレベルでのファイル配布
</div>

ファイルベースの設定を好む、あるいはフックをオフラインでも動作させる必要がある組織では、必須の `hooks.json` 設定を、次の OS 固有の場所にデプロイしてください:

**macOS:**

```
/Library/Application Support/Windsurf/hooks.json
```

**Linux/WSL：**

```
/etc/windsurf/hooks.json
```

**Windows：**

```
C:\ProgramData\Windsurf\hooks.json
```

フック用スクリプトは、対応するシステムディレクトリ (例：Unix システムでは `/usr/local/share/windsurf-hooks/`) に配置してください。

システムレベルのフックは、ユーザーおよびワークスペースのフックよりも優先され、エンドユーザーは root 権限なしに無効化できません。

<div id="mdm-and-configuration-management">
  #### MDM と構成管理
</div>

Enterprise の IT チームは、標準的なツールを用いてシステムレベルのフックをデプロイできます。

**モバイルデバイス管理 (MDM) **

* **Jamf Pro** (macOS) - 構成プロファイルまたはスクリプトでデプロイ
* **Microsoft Intune** (Windows/macOS) - PowerShell スクリプトまたはポリシー配布を使用
* **Workspace ONE**、**Google Endpoint Management**、およびその他の MDM ソリューション

**構成管理**

* **Ansible**、**Puppet**、**Chef**、**SaltStack** - 既存のインフラ自動化基盤を活用
* **カスタムデプロイスクリプト** - シェルスクリプト、PowerShell、またはお使いのツール

<div id="verification-and-auditing">
  #### 検証と監査
</div>

デプロイ後に、フックが正しくインストールされていることを確認してください。

```bash theme={null}
# システムフックの存在を確認
ls -la /etc/windsurf/hooks.json  # Linux
ls -la "/Library/Application Support/Windsurf/hooks.json"  # macOS

# フックの実行をテスト（Cascadeにフックの出力が表示されます）
# 開発者に該当するCascadeアクションを実行させてください

# ユーザーがシステムフックを変更できないことを確認
sudo chown root:root /etc/windsurf/hooks.json
sudo chmod 644 /etc/windsurf/hooks.json
```

<Note>
  **重要**: システムレベルのフックは、IT またはセキュリティチームが一元的に管理します。Windsurf はシステムレベルのパスにファイルを配置・管理しません。組織のポリシーに従い、内部チームがデプロイ、更新、コンプライアンス対応を適切に実施してください。
</Note>

<div id="workspace-hooks-for-team-projects">
  ### チームプロジェクト向けワークスペースフック
</div>

プロジェクト固有の規約に対しては、チームはバージョン管理でワークスペースレベルのフックを利用できます。

```bash theme={null}
# Add to your repository
.windsurf/
├── hooks.json
└── scripts/
    └── format-check.py

# Commit to git
git add .windsurf/
git commit -m "コードフォーマット用のワークスペースフックを追加"
```

これにより、チームは開発プロセスを標準化できます。セキュリティ上重要なポリシーはクラウドまたはシステムレベルで管理し、機密情報をバージョン管理にコミット (登録) することは避けてください。

<div id="additional-resources">
  ## 追加リソース
</div>

* **MCP 連携**: [Windsurf における Model Context Protocol](/ja/windsurf/cascade/mcp) の詳細について学ぶ
* **ワークフロー**: フックを [Cascade Workflows](/ja/windsurf/cascade/workflows) と組み合わせる方法を学ぶ
* **Analytics**: [Team Analytics](/ja/windsurf/accounts/analytics) で Cascade の利用状況を把握する
