メインコンテンツへスキップ
Hooks を使うと、Qoder IDE や JetBrains プラグインの実行フローにおける重要なポイントで、コードを変更することなくカスタムロジックを挿入できます。JSON 設定ファイルを編集するだけで、たとえば次のようなことを実現できます。
  • ツール実行前に危険な操作をブロック
  • ファイル書き込みのたびに自動で lint を実行し、コードスタイルを統一
  • Agent のタスク完了時にデスクトップ通知を送り、画面に張り付く必要をなくす
Prompt による指示とは異なり、Hooks は確定的に動作します。イベントが発火すればスクリプトは必ず実行され、モデルの解釈に結果が左右されることはありません。

サポートされるイベント

IDE / JB プラグインが現在サポートしている Hook イベントは以下の 5 種類です。
イベント名発火タイミングブロック可能
UserPromptSubmitユーザーが Prompt を送信した後、Agent が処理を開始する前はい
PreToolUseツール実行の前はい
PostToolUseツール実行の成功後いいえ
PostToolUseFailureツール実行の失敗後いいえ
StopAgent がレスポンスを返し終えた時いいえ

クイックスタート

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

スクリプトを作成

mkdir -p ~/.qoder/hooks
cat > ~/.qoder/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/hooks/block-rm.sh
2

設定を追加

~/.qoder/settings.json に以下を追加します。
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "~/.qoder/hooks/block-rm.sh"
          }
        ]
      }
    ]
  }
}
3

動作を確認

IDE を開き、Qoder プラグインパネルで rm -rf を含むコマンドの実行を Agent に指示してください。Hook が実行をブロックし、エラーメッセージを Agent にフィードバックします。

ユースケース

シナリオ対応イベント説明
危険コマンドの遮断PreToolUserm -rfDROP TABLE などの実行前にブロック
ファイルパスの検証PreToolUse指定ディレクトリ内でのみファイルの作成・編集を許可
自動 Lint / フォーマットPostToolUseファイル書き込みのたびに ESLint / Prettier を自動実行
監査ログPostToolUseすべてのツール呼び出しを記録し、セキュリティ監査に活用
失敗時のモニタリングPostToolUseFailureツール実行が失敗した際にアラートを送信、またはエラーログを記録
Prompt の内容チェックUserPromptSubmitユーザー入力に機密情報(パスワード、キーなど)が含まれていないか検出
コンテキストの自動注入UserPromptSubmitPrompt の末尾にプロジェクト規約やコーディング規約を自動付加
デスクトップ通知StopAgent 完了時にシステム通知を表示

仕組み

Hook の利用は、スクリプトを書く → 設定に登録する → 自動で有効になる、という 3 ステップです。 Agent がライフサイクル上の特定のポイント(例: ツール呼び出し前)に到達すると、プラグインは該当するイベントに Hook が登録されているかを確認します。
  1. プラグインは起動時にすべての Hook 設定を読み込む
  2. Agent の実行中にイベントポイント(例: PreToolUse)に到達する
  3. プラグインはそのイベントに登録された Hook グループを順に走査し、matcher で現在のコンテキストと照合する
  4. マッチした Hook は登録順にシェルスクリプトを実行する
  5. スクリプトは stdin からイベントコンテキスト(JSON)を受け取り、exit code と stdout で結果を返す
  6. プラグインはその結果に基づいて後続の動作(続行またはブロック)を決定する

前提条件

  • jq: サンプルスクリプトでは JSON の解析に jq を使用しています。macOS では brew install jq、Linux では apt install jq でインストールしてください。
  • スクリプト権限: すべての Hook スクリプトに実行権限が必要です(chmod +x)。

Hooks の作成

1. 要件の整理: イベントとマッチ範囲を決める

まず、どのタイミングで介入し、どの操作を対象にするかを明確にします。
「いつ」介入するか?              「どの操作」を対象にするか?
       ↓                                     ↓
   イベントを選択                          matcher を設定
要件イベントmatcher
Shell コマンド実行前にチェックしたいPreToolUse"Bash"
ファイルの書き込み・編集後に処理したいPostToolUse"Write|Edit"
ツール実行の失敗を記録したいPostToolUseFailure"Bash" または未指定
すべての Prompt を審査したいUserPromptSubmit未指定(すべてにマッチ)
Agent の停止時に通知したいStop未指定(すべてにマッチ)
MCP ツールのみ対象にしたいPreToolUse"mcp__.*"

2. Hook スクリプトを書く

Hook スクリプトは標準的なシェルスクリプトで、以下の入出力規約に従います。 入力: stdin から JSON 形式のイベントコンテキストを受け取る 出力: exit code で動作を制御する
exit 0   →  続行(操作を許可)
exit 2   →  ブロック(操作を停止し、stderr の内容を会話に注入)
それ以外 →  エラー(操作は続行し、stderr をユーザーに表示)
スクリプトテンプレート:
#!/bin/bash

# 1. Read JSON input from stdin
input=$(cat)

# 2. Extract fields with jq
#    Each event has different fields — see the "Hooks イベント" section
tool_name=$(echo "$input" | jq -r '.tool_name')
tool_input=$(echo "$input" | jq -r '.tool_input')

# 3. Implement your decision logic
if [ "$tool_name" = "Bash" ]; then
  command=$(echo "$input" | jq -r '.tool_input.command')

  # Check for dangerous operations
  if echo "$command" | grep -qE 'rm\s+-rf|DROP\s+TABLE'; then
    # Block: exit 2 + stderr message is fed back to Agent
    echo "Operation denied: $command" >&2
    exit 2
  fi
fi

# 4. Allow
exit 0
exit code に加えて、exit 0 の際に JSON を出力することで、より細かい制御が可能です。
#!/bin/bash
input=$(cat)

# Output JSON for fine-grained control (only parsed when exit 0)
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"This operation is not allowed"}}'
exit 0

3. 設定ファイルへの登録

スクリプトのパスを、設定ファイルの該当イベントに記述します。
{
  "hooks": {
    "EventName": [
      {
        "matcher": "MatchPattern (optional)",
        "hooks": [
          {
            "type": "command",
            "command": "path/to/script"
          }
        ]
      }
    ]
  }
}

4. テストとデバッグ

ターミナルでパイプを使って直接テストできます。
# Simulate a PreToolUse event
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"},"hook_event_name":"PreToolUse"}' \
  | ~/.qoder/hooks/block-rm.sh
echo "Exit code: $?"
stderr 出力(ブロックメッセージ)を確認するには:
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' \
  | ~/.qoder/hooks/block-rm.sh 2>&1

Hooks の設定

設定ファイルの場所

Hook 設定は以下のファイルから読み込まれます。複数レベルの設定はマージされて実行されます(優先度の低い順)。
パススコープ優先度共有可能説明
~/.qoder/settings.jsonグローバル(ユーザー)1(最低)いいえユーザー個人の設定。すべてのプロジェクトに適用
.qoder/settings.jsonプロジェクト2はいGit にコミットしてチームで共有可能
.qoder/settings.local.jsonプロジェクトローカル3いいえgitignore 対象。個人の開発用設定
IDE / JB プラグインと CLI は同じ設定ファイルを共有します。現在のバージョンではホットリロードに未対応のため、設定変更後は IDE の再起動が必要です。

設定フォーマット

{
  "hooks": {
    "EventName": [
      {
        "matcher": "MatchPattern",
        "hooks": [
          {
            "type": "command",
            "command": "command to execute"
          }
        ]
      }
    ]
  }
}
フィールド必須説明
typeはい"command" 固定
commandはい実行するシェルコマンドまたはスクリプトのパス
timeoutいいえタイムアウト(秒)。デフォルトは 30 秒。現在のバージョンではカスタマイズ不可(次バージョンで対応予定)
matcherいいえマッチ条件。未指定の場合はそのイベントのすべてのトリガーにマッチ
1 つのイベントに対して複数の matcher グループを設定でき、各グループには複数の Hook コマンドを含められます。

matcher マッチルール

matcher は Hook の発火対象を絞り込むために使用します。イベントごとにマッチ対象のフィールドが異なります(各イベントの説明を参照)。
記法意味
未指定または "*"すべてにマッチすべてのツールでトリガー
完全一致の値完全一致"Bash" は Bash ツールの時のみトリガー
| 区切り複数の値にマッチ"Write|Edit" は Write または Edit の時にトリガー
正規表現正規表現マッチ"mcp__.*" はすべての MCP ツールにマッチ

ツール名マッピング

Qoder はネイティブのツール名と Claude Code 互換のツール名の 2 セットをサポートしています。Hook の設定ではどちらでも使用でき、プラグイン内部で統一的にマッピングしてからマッチングを行います。たとえば matcher: "Bash"matcher: "run_in_terminal" は同じ意味です。
Qoder ネイティブ名互換名説明
run_in_terminalBashシェルコマンドの実行
read_fileReadファイル内容の読み取り
create_fileWriteファイルの作成・書き込み
search_replaceEditファイルの編集
delete_file-ファイルの削除
grep_codeGrepファイル内容の検索
search_fileGlobファイル名のマッチング
list_dirLSディレクトリの一覧表示
taskTaskサブタスク / サブエージェントの起動
Skill-スキルの呼び出し
search_webWebSearchWeb 検索
fetch_contentWebFetchWeb コンテンツの取得
todo_writeTodoWriteTODO の書き込み
ask_user_question-ユーザーへの質問
search_memory-メモリの検索
update_memory-メモリの更新
switch_mode-モードの切り替え
create_plan-プランの作成
run_preview-Web アプリのプレビュー
mcp__<server>__<tool>同左MCP ツール

Hook スクリプトの書き方

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

入力

Hook スクリプトは stdin から JSON データを受け取ります。すべてのイベントで共通するフィールドは以下のとおりです。
フィールド説明
session_id現在のセッション ID
cwd現在の作業ディレクトリ
hook_event_nameトリガーされたイベント名
transcript_pathセッションコンテキスト JSON ファイルのパス
イベントによっては、上記に加えて追加のフィールドが含まれます(各イベントの説明を参照)。 jq で入力を解析する例:
#!/bin/bash
input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name')

出力

Hook は exit code と stdout で動作を制御します。 exit code による基本動作:
Exit Code意味動作
0成功操作を続行し、stdout の JSON 解析を試みる
2ブロック操作を停止し、stderr の内容を会話に注入(ブロック可能なイベントのみ有効)
その他エラー操作は続行するが、stderr をユーザーに表示
stdout JSON(exit 0 の場合のみ解析)を使うと、一部のイベントでより細かい制御が可能です。サポートされるフィールドの詳細は各イベントの説明を参照してください。exit code が 0 以外の場合、stdout は無視されます。

環境変数

Hook スクリプトの実行時に、プラグインがいくつかの環境変数を自動的に設定します。注入される環境変数の具体的なリストは今後確定予定です。

Hooks イベント

UserPromptSubmit

ユーザーが IDE プラグインパネルで Prompt を送信した後、Agent が処理を開始する前に発火します。Prompt の審査やコンテンツフィルタリング、コンテキストの自動補完などに利用できます。 matcher マッチ: マッチ対象のフィールドはなく、すべてのユーザー入力に対して一律に発火します。 追加入力フィールド:
{
  "session_id": "abc-123",
  "cwd": "/path/to/project",
  "hook_event_name": "UserPromptSubmit",
  "prompt": "Write a sort function for me"
}
Prompt 送信のブロック: exit code 2 を返すと、stderr の内容がエラーメッセージとしてユーザーに表示され、Agent はその Prompt を処理しません。 stdout JSON 出力フィールド(exit 0 の場合):
{
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "## Current Git status\n..."
  }
}
フィールド説明
hookSpecificOutput.hookEventNamestring"UserPromptSubmit" 固定
hookSpecificOutput.additionalContextstring追加コンテキスト情報。Agent の会話に注入される
例: Prompt にプロジェクト規約を自動付加
#!/bin/bash
input=$(cat)
prompt=$(echo "$input" | jq -r '.prompt')

# Automatically append coding standards reminder
echo '{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"Please follow the coding standards in the project .editorconfig."}}'
exit 0

PreToolUse

ツール実行前に発火します。ツールの実行をブロックできます。 最もよく使われるイベントで、危険コマンドの遮断やファイルパスの検証、権限チェックなどに適しています。 matcher マッチ: ツール名(BashWriteEditReadGlobGrep や、MCP ツール名 mcp__server__tool など) 追加入力フィールド:
{
  "session_id": "abc-123",
  "cwd": "/path/to/project",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": { "command": "rm -rf /tmp/build" }
}
ツール実行のブロック: exit code 2 を返すと、stderr の内容がエラーとして Agent に返されます。完全な例はクイックスタートを参照してください。 stdout JSON 出力フィールド(exit 0 の場合):
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "Safe read operation",
    "updatedInput": { "command": "npm test --coverage" },
    "additionalContext": "Added coverage flag"
  }
}
フィールド説明
hookSpecificOutput.hookEventNamestring"PreToolUse" 固定
hookSpecificOutput.permissionDecisionstring"allow"(許可)、"deny"(拒否)、"ask"(ユーザーに確認)
hookSpecificOutput.permissionDecisionReasonstring決定理由。denyask の場合に Agent またはユーザーに表示される
hookSpecificOutput.updatedInputobject変更後のツール入力パラメータ(任意。ツールの呼び出し内容を書き換える場合に使用)
hookSpecificOutput.additionalContextstring追加コンテキスト情報(任意)

PostToolUse

ツール実行の成功後に発火します。ブロックはできません。自動 lint やログ記録、結果の分析などに適しています。 matcher マッチ: ツール名 追加入力フィールド:
{
  "session_id": "abc-123",
  "cwd": "/path/to/project",
  "hook_event_name": "PostToolUse",
  "tool_name": "Write",
  "tool_input": { "file_path": "/path/to/file.ts", "content": "..." },
  "tool_response": "File written successfully"
}
stdout JSON 出力フィールド(exit 0 の場合):
{
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "feedback": "File formatted with Prettier. 3 issues auto-fixed."
  }
}
フィールド説明
hookSpecificOutput.hookEventNamestring"PostToolUse" 固定
hookSpecificOutput.feedbackstringフィードバック情報。ユーザーに表示される(例: lint 結果のサマリー)

PostToolUseFailure

ツール実行の失敗後に発火します。ブロックはできません。エラーの監視やリトライの提案、ログ記録などに適しています。 matcher マッチ: ツール名 追加入力フィールド:
{
  "session_id": "abc-123",
  "cwd": "/path/to/project",
  "hook_event_name": "PostToolUseFailure",
  "tool_name": "Bash",
  "tool_input": { "command": "npm test" },
  "error": "Command exited with non-zero status code 1"
}
フィールド説明
errorstringツール実行のエラーメッセージ

Stop

Agent がレスポンスを返し終えた後(実行待ちのツール呼び出しがない状態)に発火します。ブロックはできません。デスクトップ通知やログ記録、タスクのステータス報告などに適しています。
現在のバージョンでは Stop イベントはブロックに対応していません(exit 2 で Agent に作業を継続させることはできません)。この機能は次のバージョンで対応予定です。
matcher マッチ: マッチ対象のフィールドはなく、Agent の停止時に一律で発火します。 追加入力フィールド:
{
  "session_id": "abc-123",
  "cwd": "/path/to/project",
  "hook_event_name": "Stop",
  "stop_hook_active": true,
  "last_assistant_message": "I have finished writing the sort function."
}
stdout JSON 出力フィールド(exit 0 の場合。次のバージョンで有効化予定):
{
  "decision": "block",
  "reason": "Tests failing. Fix them before completing."
}
フィールド説明
decisionstring"block"(停止をブロックし、Agent に作業を継続させる)
reasonstringブロックの理由。メッセージとして会話に注入される

実用例

危険コマンドの遮断

Agent がシェルコマンドを実行する前に、rm -rfDROP TABLE などの危険な操作が含まれていないかをチェックします。 スクリプト ~/.qoder/hooks/block-dangerous.sh:
#!/bin/bash
input=$(cat)
command=$(echo "$input" | jq -r '.tool_input.command')

# Check for dangerous patterns
if echo "$command" | grep -qE 'rm\s+-rf|DROP\s+TABLE|mkfs|dd\s+if='; then
  echo "Dangerous command blocked: $command" >&2
  exit 2
fi

exit 0
設定: イベント PreToolUse、matcher Bash ,command ~/.qoder/hooks/block-dangerous.sh

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

Agent がファイルを書き込み・編集するたびに、自動で lint を実行します。 スクリプト ${project}/.qoder/hooks/auto-lint.sh:
#!/bin/bash
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path')

# Only lint JS/TS files
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/hooks/auto-lint.sh

ツール失敗時のログ記録

ツールの実行が失敗した際に、自動でログファイルに記録して問題の調査に役立てます。 スクリプト ~/.qoder/hooks/log-failure.sh:
#!/bin/bash
input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name')
error=$(echo "$input" | jq -r '.error')
timestamp=$(date '+%Y-%m-%d %H:%M:%S')

echo "[$timestamp] $tool_name failed: $error" >> ~/.qoder/hooks/failure.log

exit 0
設定: イベント PostToolUseFailure、matcher なし(すべてのツールにマッチ),command ~/.qoder/hooks/log-failure.sh

Agent 完了時のデスクトップ通知

Agent がタスクを完了したらシステム通知を表示します。長時間かかるタスクに便利です。 スクリプト ~/.qoder/hooks/notify-done.sh(macOS):
#!/bin/bash
input=$(cat)
message=$(echo "$input" | jq -r '.last_assistant_message // "Task complete"' | head -c 100)

osascript -e "display notification \"$message\" with title \"Qoder Agent\""

exit 0
設定: イベント Stop、matcher なし,command ~/.qoder/hooks/notify-done.sh

Prompt の内容チェック

ユーザーが Prompt を送信する際に、機密情報(パスワード、キーなど)が含まれていないかをチェックし、意図しない漏洩を防ぎます。 スクリプト ~/.qoder/hooks/check-prompt.sh:
#!/bin/bash
input=$(cat)
prompt=$(echo "$input" | jq -r '.prompt')

# Check for possible credential patterns
if echo "$prompt" | grep -qiE '(password|secret|api_key|token)\s*[:=]\s*\S+'; then
  echo "Sensitive information detected in prompt. Please review and resubmit." >&2
  exit 2
fi

exit 0
設定: イベント UserPromptSubmit、matcher なし,command ~/.qoder/hooks/check-prompt.sh

完全な設定例

以下は 5 つのイベントすべてに Hook を設定した完全な例です。
{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "~/.qoder/hooks/check-prompt.sh"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "~/.qoder/hooks/block-dangerous.sh"
          }
        ]
      },
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": ".qoder/hooks/validate-file-path.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": ".qoder/hooks/auto-lint.sh"
          }
        ]
      }
    ],
    "PostToolUseFailure": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "~/.qoder/hooks/log-failure.sh"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "~/.qoder/hooks/notify-done.sh"
          }
        ]
      }
    ]
  }
}

注意事項

  • タイムアウト: Hook スクリプトのデフォルトタイムアウトは 30 秒です。タイムアウトするとスクリプトは強制終了され、続行(許可)として扱われます。カスタムタイムアウトは次のバージョンで対応予定です。
  • エラー処理: スクリプトが異常終了した場合(exit code が 0 でも 2 でもない場合)、エラーメッセージがユーザーに表示されますが、Agent の処理は中断されず続行されます。
  • スクリプト権限: スクリプトに実行権限が付与されていることを確認してください(chmod +x)。
  • 設定のマージ: 複数レベルの設定ファイルに同一イベントの Hook がある場合、優先度の低い順に実行されます。いずれかの Hook がブロック(exit 2)を返した時点で、以降の Hook は実行されません。
  • jq の依存: サンプルスクリプトでは JSON 解析に jq を使用しています。システムに jq がインストールされていることを確認してください(macOS: brew install jq、Linux: apt install jq)。