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

# Hooks

Hooks を使うと、QoderWork の実行フローにおける重要なポイントで、コードを変更することなくカスタムロジックを挿入できます。JSON 設定ファイルを編集するだけで、たとえば次のようなことを実現できます。

* ツール実行前に危険な操作をブロック
* ファイル書き込みのたびに自動で lint を実行し、コードスタイルを統一
* Agent のタスク完了時にデスクトップ通知を送り、画面に張り付く必要をなくす

Prompt による指示とは異なり、Hooks は確定的に動作します。イベントが発火すればスクリプトは必ず実行され、モデルの解釈に結果が左右されることはありません。

## クイックスタート

以下の例では、`rm -rf` のような危険なコマンドをブロックする方法を紹介します。

<Steps>
  <Step title="スクリプトを作成">
    ```bash theme={null}
    mkdir -p ~/.qoderwork/hooks
    cat > ~/.qoderwork/hooks/block-rm.sh << 'EOF'
    #!/bin/bash
    input=$(cat)
    command=$(echo "$input" | jq -r '.tool_input.command')

    if echo "$command" | grep -q 'rm -rf'; then
      echo "危険なコマンドをブロックしました: $command" >&2
      exit 2
    fi

    exit 0
    EOF
    chmod +x ~/.qoderwork/hooks/block-rm.sh
    ```
  </Step>

  <Step title="設定を追加">
    `~/.qoderwork/settings.json` に以下を追加します：

    ```json theme={null}
    {
      "hooks": {
        "PreToolUse": [
          {
            "matcher": "Bash",
            "hooks": [
              {
                "type": "command",
                "command": "~/.qoderwork/hooks/block-rm.sh"
              }
            ]
          }
        ]
      }
    }
    ```
  </Step>

  <Step title="動作を確認">
    QoderWork を開き、Agent に `rm -rf` を含むコマンドを実行させてみてください。Hook が実行をブロックし、エラーメッセージを Agent にフィードバックします。
  </Step>
</Steps>

## Hooks の設定

### 設定ファイルの場所

QoderWork はユーザーレベルの設定ファイルから Hook 設定を読み込みます：

| 場所                           | スコープ        | 説明                           |
| ---------------------------- | ----------- | ---------------------------- |
| `~/.qoderwork/settings.json` | ユーザー（グローバル） | 個人設定、すべての QoderWork セッションに適用 |

<Note>
  ホットリロードはまだサポートされていません — Hook 設定を変更した後は **QoderWork を再起動**してください。
</Note>

### 設定フォーマット

```json theme={null}
{
  "hooks": {
    "イベント名": [
      {
        "matcher": "マッチ条件",
        "hooks": [
          {
            "type": "command",
            "command": "実行するコマンド",
            "timeout": 60
          }
        ]
      }
    ]
  }
}
```

| フィールド     | 必須  | 説明                 |
| --------- | --- | ------------------ |
| `type`    | はい  | `"command"` 固定     |
| `command` | はい  | 実行するシェルコマンド        |
| `timeout` | いいえ | タイムアウト（秒）、デフォルト 60 |
| `matcher` | いいえ | マッチ条件。省略するとすべてにマッチ |

1 つのイベントに複数の matcher グループを定義でき、各グループに複数の Hook コマンドを含めることができます。

### matcher ルール

`matcher` は Hook の発火範囲を決定します。何にマッチするかはイベントによって異なります（各イベントの説明を参照）。

| パターン        | 意味       | 例                                      |
| ----------- | -------- | -------------------------------------- |
| 省略または `"*"` | すべてにマッチ  | すべてのツールで Hook が発火                      |
| 正確な値        | 完全一致     | `"Bash"` は Bash ツールのみで発火               |
| `\|` 区切り    | 複数の値にマッチ | `"Write \| Edit"` は Write または Edit で発火 |
| 正規表現        | 正規表現マッチ  | `"mcp__.*"` はすべての MCP ツールにマッチ          |

## Hook スクリプトの作成

Hook スクリプトは stdin 経由で JSON 入力を受け取り、exit code と stdout で動作を制御します。このセクションではすべてのイベントに共通の入出力フォーマットを説明します。イベント固有のフィールドについては [Hook イベント](#hook-イベント)を参照してください。

<Note>
  QoderWork は現在、Hook スクリプトに環境変数を注入しません。すべてのデータは stdin JSON 経由で渡されます。セッション ID、作業ディレクトリ、ツール情報が必要な場合は、stdin JSON 入力から解析してください。
</Note>

### 入力

Hook スクリプトは **stdin** 経由で JSON データを受け取ります。すべてのイベントに以下の共通フィールドが含まれます：

| フィールド             | 説明                   |
| ----------------- | -------------------- |
| `session_id`      | 現在のセッション ID          |
| `cwd`             | 現在の作業ディレクトリ          |
| `hook_event_name` | この Hook をトリガーしたイベント名 |

各イベントはこれらに加えて固有のフィールドを追加します（各 Hook イベントの説明を参照）。

`jq` で入力を解析：

```bash theme={null}
#!/bin/bash
input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name')
```

### 出力

Hook は exit code と stdout で動作を制御します。

exit code が基本動作を決定します：0 は成功、2 はブロック（stderr の内容が会話に注入され、ブロック可能なイベントでのみ有効）、その他の値は非ブロックエラーです。

stdout JSON（exit 0 の場合のみ解析）は一部のイベントに精細な制御を提供します。サポートされるフィールドは各イベントの説明を参照してください。exit code が 0 以外の場合、stdout は無視されます。

## Hook イベント

### SessionStart

セッション開始時に発火します。

**matcher：** セッションソース

| matcher 値 | 発火シナリオ      |
| --------- | ----------- |
| `startup` | 新しいセッションの開始 |
| `resume`  | 既存セッションの再開  |
| `compact` | コンテキスト圧縮完了後 |

**追加入力フィールド：**

```json theme={null}
{
  "source": "startup",
  "model": "Auto"
}
```

### SessionEnd

セッション終了時に発火します。

**matcher：** 終了理由

| matcher 値           | 発火シナリオ               |
| ------------------- | -------------------- |
| `prompt_input_exit` | ユーザーが入力を終了（Ctrl+D 等） |
| `other`             | その他の理由               |

**追加入力フィールド：**

```json theme={null}
{
  "reason": "prompt_input_exit"
}
```

### UserPromptSubmit

ユーザーが Prompt を送信した後、Agent が処理する前に発火します。

**追加入力フィールド：**

```json theme={null}
{
  "prompt": "ソート関数を書いてください"
}
```

### PreToolUse

ツール実行前に発火します。ツール実行をブロックできます。

**matcher：** ツール名（例：`Bash`、`Write`、`Edit`、`Read`、`Glob`、`Grep`、MCP ツール名は `mcp__server__tool` 形式）

**追加入力フィールド：**

```json theme={null}
{
  "tool_name": "Bash",
  "tool_input": {"command": "rm -rf /tmp/build"},
  "tool_use_id": "toolu_01ABC123"
}
```

**ツール実行のブロック：** exit code 2、stderr の内容がエラーとして Agent に返されます。完全な例は[クイックスタート](#クイックスタート)を参照してください。

### PostToolUse

ツール実行の成功後に発火します。

**matcher：** ツール名

**追加入力フィールド：**

```json theme={null}
{
  "tool_name": "Write",
  "tool_input": {"file_path": "/path/to/file.ts", "content": "..."},
  "tool_response": "File written successfully",
  "tool_use_id": "toolu_01ABC123"
}
```

### PostToolUseFailure

ツール実行の失敗後に発火します。

**matcher：** ツール名

**追加入力フィールド：**

```json theme={null}
{
  "tool_name": "Bash",
  "tool_input": {"command": "npm test"},
  "tool_use_id": "toolu_01ABC123",
  "error": "Command exited with non-zero status code 1",
  "is_interrupt": false
}
```

### Stop

Agent がレスポンスを完了した後に発火します（メイン Agent、保留中のツール呼び出しがない場合）。Agent の停止をブロックして作業を続行させることができます。

**Agent の停止をブロック：** exit code 2、stderr の内容がメッセージとして会話に注入され、Agent は作業を続行します。

### SubagentStart / SubagentStop

サブ Agent の起動・完了時に発火します。SubagentStop は Stop と同様、サブ Agent の停止をブロックできます。

**matcher：** Agent タイプ名

**追加入力フィールド：**

```json theme={null}
{
  "agent_id": "a1b2c3d4",
  "agent_type": "task"
}
```

### PreCompact

コンテキスト圧縮前に発火します。

**matcher：** トリガー方法

| matcher 値 | 発火シナリオ                     |
| --------- | -------------------------- |
| `manual`  | ユーザーが手動で /compact を実行      |
| `auto`    | コンテキストウィンドウが満杯になった時に自動トリガー |

**追加入力フィールド：**

```json theme={null}
{
  "trigger": "manual",
  "custom_instructions": "すべてのツール呼び出し結果を保持"
}
```

### Notification

通知イベント発火時（権限リクエスト、タスク完了等）。

**matcher：** 通知タイプ

| matcher 値    | 発火シナリオ      |
| ------------ | ----------- |
| `permission` | 権限リクエスト通知   |
| `result`     | Agent の結果通知 |

**追加入力フィールド：**

```json theme={null}
{
  "message": "Agent is requesting permission to run: rm -rf node_modules",
  "title": "Permission Required",
  "notification_type": "permission"
}
```

### PermissionRequest

ツール実行にユーザー認可が必要な時に発火します。

**matcher：** ツール名

**追加入力フィールド：**

```json theme={null}
{
  "tool_name": "Bash",
  "tool_input": {"command": "rm -rf node_modules"}
}
```

## シナリオ例

### デスクトップ通知

Agent がタスクを完了した時や権限が必要な時に、デスクトップ通知を表示します。

スクリプト `~/.qoderwork/hooks/notify.sh`（macOS）：

```bash theme={null}
#!/bin/bash
input=$(cat)
message=$(echo "$input" | jq -r '.message')

if echo "$message" | grep -q "^Agent"; then
  osascript -e 'display notification "タスク完了" with title "QoderWork"'
else
  osascript -e 'display notification "権限が必要です" with title "QoderWork"'
fi

exit 0
```

設定：

```json theme={null}
{
  "hooks": {
    "Notification": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "~/.qoderwork/hooks/notify.sh"
          }
        ]
      }
    ]
  }
}
```

### ファイル書き込み後の自動 Lint

Agent がファイルを書き込み・編集するたびに、自動で lint を実行します。

スクリプト `${project}/.qoderwork/hooks/auto-lint.sh`：

```bash theme={null}
#!/bin/bash
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path')

case "$file_path" in
  *.js|*.ts|*.jsx|*.tsx)
    npx eslint "$file_path" --fix 2>/dev/null
    ;;
esac

exit 0
```

設定：イベント `PostToolUse`、matcher `Write|Edit`、command `.qoderwork/hooks/auto-lint.sh`。

### Agent を継続させる

Agent が停止する際に未完了タスクがないかチェックし、コミットされていない git 変更がある場合は Agent の停止をブロックします。

スクリプト `~/.qoderwork/hooks/check-continue.sh`：

```bash theme={null}
#!/bin/bash
if [ -n "$(git status --porcelain 2>/dev/null)" ]; then
  echo "未コミットの変更を検出しました。git commit を完了してください" >&2
  exit 2
fi

exit 0
```

設定：イベント `Stop`、command `~/.qoderwork/hooks/check-continue.sh`。

## 次のステップ

<CardGroup cols={2}>
  <Card title="スキル" icon="wand-magic-sparkles" href="/ja/qoderwork/skills">
    スキルで QoderWork の能力を拡張する
  </Card>

  <Card title="スケジュールタスク" icon="clock" href="/ja/qoderwork/scheduled-tasks">
    タスクを計画的に自動実行する
  </Card>
</CardGroup>
