フックを使用すると、Qoder CN CLI のエージェント実行フローの主要なポイントで、CLI に依存することなくカスタムロジックを挿入できます。一般的なユースケースとしては、ツールの実行前に危険な操作をインターセプトする、タスクの完了時にデスクトップ通知を送信する、ファイルの書き込み後に自動的にリンターを実行するなどがあります。
フックは JSON 設定ファイルで定義します。コードの変更は不要で、設定ファイルの編集は即座に反映されます。
クイックスタート
以下の例では、フックを使用して危険なコマンドをインターセプトする方法を示します。rm -rf の実行を試みるエージェントを自動的にブロックします。
ステップ 1: スクリプトを作成する
mkdir -p ~/.qoder-cn/hooks
cat > ~/.qoder-cn/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 "Dangerous command blocked: $command" >&2
exit 2
fi
exit 0
EOF
chmod +x ~/.qoder-cn/hooks/block-rm.shステップ 2: 設定ファイルを編集する
~/.qoder-cn/settings.json に以下を追加します:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "~/.qoder-cn/hooks/block-rm.sh"
}
]
}
]
}
}ステップ 3: 結果を確認する
Qoder CN CLI を起動し、rm -rf を含むコマンドを実行するようエージェントに指示します。フックが実行をブロックし、エージェントにプロンプトを表示します。
設定
設定ファイルの場所
フック設定は以下の 3 つのファイルから読み込まれます。3 つのレベルの設定はすべて マージ されて実行されます。
# ユーザーレベル: すべてのプロジェクトに適用されます。
~/.qoder-cn/settings.json
# プロジェクトレベル: 現在のプロジェクトに適用されます。Git にコミットしてチームで共有できます。
${project}/.qoder/settings.json
# プロジェクトレベル (ローカル): 最も優先度が高くなります。.gitignore に追加することを推奨します。
${project}/.qoder/settings.local.json設定形式
{
"hooks": {
"EventName": [
{
"matcher": "match condition",
"hooks": [
{
"type": "command",
"command": "command to run",
"timeout": 60
}
]
}
]
}
}フィールドの説明:
フィールド | 必須 | 説明 |
| はい |
|
| はい | 実行するシェルコマンドです。 |
| いいえ | タイムアウト時間 (秒単位) です。デフォルト:60。 |
| いいえ | マッチ条件を指定します。省略した場合、フックはすべてのインスタンスに適用されます。 |
1 つのイベントに複数のマッチャーグループを設定できます。各グループには複数のフックコマンドを含めることができます。
マッチャールール
matcher フィールドは、フックをトリガーするタイミングを決定します。各イベントは異なるフィールドに対してマッチングを行います。詳細については、各イベントの説明をご参照ください。
構文 | 説明 | 例 |
空白または | すべてにマッチします。 | すべてのツールでトリガーされます。 |
完全一致 | 完全一致でマッチします。 |
|
| 複数の値にマッチします。 |
|
正規表現 | 正規表現でマッチします。 |
|
フックスクリプトの記述
フックスクリプトは標準入力 (stdin) から JSON ペイロードを受け取り、終了コードと標準出力 (stdout) を使用して動作を制御します。このセクションでは、すべてのイベントに共通する入力と出力の形式について説明します。イベント固有のフィールドについては、「サポートされているイベント」をご参照ください。
入力
フックスクリプトは stdin を通じて JSON データを受け取ります。すべてのイベントの入力には、以下の共通フィールドが含まれます。
フィールド | 説明 |
| 現在のセッションの ID です。 |
| 現在の作業ディレクトリです。 |
| フックをトリガーしたイベントの名前です。 |
イベントごとに、この構造にフィールドが追加されます (各イベントの説明をご参照ください)。jq を使用して入力を解析します。
#!/bin/bash
input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name')出力
フックは終了コードと標準出力 (stdout) を使用して動作を制御します。主要なアクションは終了コードによって決まります。0 は成功、2 は操作のブロック (サポートされているイベントの場合)、その他のゼロ以外の値は非ブロッキングエラーを示します。一部のイベントでは、stdout に出力される JSON オブジェクトによって、より詳細な制御が可能ですが、これは終了コードが 0 の場合にのみ解析されます。
環境変数
フックスクリプトの実行中、以下の環境変数が利用可能です。
変数 | 説明 |
| 現在のプロジェクトの作業ディレクトリです。 |
サポートされているイベント
Qoder CN CLI は、セッションライフサイクルのさまざまな段階をカバーする、以下のフックイベントをサポートしています。
SessionStart
セッションの開始時にトリガーされます。
マッチャーフィールド: セッションソース
マッチャー値 | トリガーシナリオ |
| 新しいセッションが開始されます。 |
| 既存のセッションが再開されます。 |
| コンテキストコンパクションが完了します。 |
追加の入力フィールド:
{
"source": "startup",
"model": "Auto"
}SessionEnd
セッションの終了時にトリガーされます。
マッチャーフィールド: 終了理由
マッチャー値 | トリガーシナリオ |
| ユーザーがプロンプトを閉じます (例:Ctrl+D を押す)。 |
| その他の理由でセッションが終了します。 |
追加の入力フィールド:
{
"reason": "prompt_input_exit"
}UserPromptSubmit
ユーザーがプロンプトを送信した後、エージェントが処理する前にトリガーされます。
追加の入力フィールド:
{
"prompt": "Write a sorting function for me"
}PreToolUse
ツールの実行前にトリガーされます。このフックはツールの実行をブロックできます。
マッチャー: ツール名 (Bash、Write、Edit、Read、Glob、Grep、または mcp__server__tool などの MCP ツール名)
追加の入力フィールド:
{
"tool_name": "Bash",
"tool_input": {"command": "rm -rf /tmp/build"},
"tool_use_id": "toolu_01ABC123"
}ツールの実行をブロックする: 終了コード 2 で終了します。stderr に出力された内容は、エラーメッセージとしてエージェントに返されます。完全な例については、クイックスタートセクションをご参照ください。
PostToolUse
ツールの実行が正常に完了した後にトリガーされます。
マッチャーフィールド: ツール名
追加の入力フィールド:
{
"tool_name": "Write",
"tool_input": {"file_path": "/path/to/file.ts", "content": "..."},
"tool_response": "File written successfully",
"tool_use_id": "toolu_01ABC123"
}PostToolUseFailure
ツールの実行が失敗した後にトリガーされます。
マッチャーフィールド: ツール名
追加の入力フィールド:
{
"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
メインエージェントが応答を完了し、保留中のツール呼び出しがない場合にトリガーされます。このフックを使用して、エージェントの停止を防ぎ、作業を続行するよう促すことができます。
エージェントの停止を防ぐ: 終了コード 2 で終了します。その後、システムは stderr の内容をメッセージとして会話に挿入し、エージェントの実行を継続するよう促します。
SubagentStart / SubagentStop
サブエージェントの開始時または停止時にトリガーされます。SubagentStop イベントは Stop と同様で、サブエージェントの停止を防ぐことができます。
マッチャーフィールド: エージェントタイプ名
追加の入力フィールド:
{
"agent_id": "a1b2c3d4",
"agent_type": "task"
}PreCompact
コンテキストコンパクションの前にトリガーされます。
マッチャーフィールド: トリガー方法
マッチャー値 | トリガーシナリオ |
| ユーザーが手動で |
| コンテキストウィンドウがいっぱいになったときに自動的にトリガーされます。 |
追加の入力フィールド:
{
"trigger": "manual",
"custom_instructions": "Keep all tool call results"
}Notification
許可リクエストやタスク完了などの通知イベントでトリガーされます。
マッチャーフィールド: 通知タイプ
マッチャー値 | トリガーシナリオ |
| 許可リクエスト通知です。 |
| エージェントが生成した結果の通知です。 |
追加の入力フィールド:
{
"message": "Agent is requesting permission to run: rm -rf node_modules",
"title": "Permission Required",
"notification_type": "permission"
}PermissionRequest
ツールの実行にユーザーの認可が必要な場合にトリガーされます。
マッチャーフィールド: ツール名
追加の入力フィールド:
{
"tool_name": "Bash",
"tool_input": {"command": "rm -rf node_modules"}
}ユースケース
デスクトップ通知を送信する
このスクリプトは、エージェントがタスクを完了したとき、または認可が必要なときにデスクトップ通知を表示します。以下のスクリプトは macOS 用で、~/.qoder-cn/hooks/notify.sh に配置されています。
#!/bin/bash
input=$(cat)
message=$(echo "$input" | jq -r '.message')
if echo "$message" | grep -q "^Agent"; then
osascript -e 'display notification "Authorization required" with title "Qoder CN CLI"'
else
osascript -e 'display notification "Task completed" with title "Qoder CN CLI"'
fi
exit 0設定:
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "~/.qoder-cn/hooks/notify.sh"
}
]
}
]
}
}変更されたファイルを自動的にリントする
このスクリプトは、エージェントがファイルに書き込むか編集するたびに、自動的にリントを実行します。スクリプトは ${project}/.qoder-cn/hooks/auto-lint.sh に配置されています。
#!/bin/bash
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path')
# JS/TS ファイルのみチェックする
case "$file_path" in
*.js|*.ts|*.jsx|*.tsx)
npx eslint "$file_path" --fix 2>/dev/null
;;
esac
exit 0設定: イベントを PostToolUse、matcher を Write|Edit、command を .qoder-cn/hooks/auto-lint.sh に設定します。
エージェントを実行し続ける
このスクリプトは、エージェントが停止するときに未完了のタスクがないかチェックします。未完了のタスクが見つかった場合、メッセージを挿入してエージェントに作業を続行するよう促します。スクリプトは ~/.qoder-cn/hooks/check-continue.sh に配置されています。
#!/bin/bash
# コミットされていない Git の変更をチェックする
if [ -n "$(git status --porcelain 2>/dev/null)" ]; then
echo "Uncommitted changes detected. Please commit your changes." >&2
exit 2
fi
exit 0設定: イベントを Stop、コマンドを ~/.qoder-cn/hooks/check-continue.sh に設定します。