設定
Droidフックはsettings filesで設定します:~/.factory/settings.json- ユーザー設定.factory/settings.json- プロジェクト設定.factory/settings.local.json- ローカルプロジェクト設定(コミットされない)- Enterprise管理ポリシー設定
構造
フックはマッチャーによって整理され、各マッチャーは複数のフックを持つことができます:- matcher: ツール名にマッチするパターン、大文字小文字を区別(
PreToolUseとPostToolUseにのみ適用)- 単純な文字列は完全一致:
CreateはCreateツールのみにマッチ - 正規表現をサポート:
Edit|CreateまたはNotebook.* *を使用してすべてのツールにマッチ。空文字列("")を使用するか、matcherを空白のままにすることもできます。
- 単純な文字列は完全一致:
- hooks: パターンがマッチしたときに実行するコマンドの配列
type:現在"command"のみサポートcommand:実行するbashコマンド($FACTORY_PROJECT_DIR環境変数を使用可能)timeout:(オプション)その特定のコマンドをキャンセルするまでの実行時間(秒)
UserPromptSubmit、Notification、Stop、SubagentStopなどのマッチャーを使用しないイベントについては、matcherフィールドを省略できます:
プロジェクト固有のフックスクリプト
環境変数FACTORY_PROJECT_DIR(DroidがフックコマンドをSpawnしたときのみ利用可能)を使用して、プロジェクトに保存されたスクリプトを参照できます。これにより、Droidの現在のディレクトリに関係なくスクリプトが動作することを保証します:
プラグインフック
プラグインは、ユーザーおよびプロジェクトフックとシームレスに統合されるフックを提供できます。プラグインフックは、プラグインが有効になると自動的に設定にマージされます。 プラグインフックの仕組み:- プラグインフックはプラグインの
hooks/hooks.jsonファイルまたはhooksフィールドのカスタムパスで指定されたファイルで定義されます - プラグインが有効になると、そのフックはユーザーおよびプロジェクトフックとマージされます
- 異なるソースからの複数のフックが同じイベントに応答できます
- プラグインフックは
${DROID_PLUGIN_ROOT}環境変数を使用してプラグインファイルを参照します
Plugin hooks use the same format as regular hooks with an optional
description field to explain the hook’s purpose.Plugin hooks run alongside your custom hooks. If multiple hooks match an event, they all execute in parallel.
${DROID_PLUGIN_ROOT}:プラグインディレクトリの絶対パス${FACTORY_PROJECT_DIR}:プロジェクトルートディレクトリ(プロジェクトフックと同じ)- すべての標準環境変数が利用可能
フックイベント
PreToolUse
Droidがツールパラメータを作成した後、ツール呼び出しを処理する前に実行されます。 一般的なマッチャー:Task- サブdroidタスク(subagents documentationを参照)Execute- シェルコマンドGlob- ファイルパターンマッチングGrep- コンテンツ検索Read- ファイル読み取りEdit- ファイル編集Create- ファイル作成FetchUrl、WebSearch- Web操作
PostToolUse
ツールが正常に完了した直後に実行されます。 PreToolUseと同じマッチャー値を認識します。Notification
Droidが通知を送信するときに実行されます。通知は以下の場合に送信されます:- Droidがツールを使用する許可を必要とする場合。例:「DroidはExecuteの使用許可を必要としています」
- プロンプト入力が少なくとも60秒間アイドル状態の場合。「Droidはあなたの入力を待っています」
UserPromptSubmit
ユーザーがプロンプトを送信したときに、Droidが処理する前に実行されます。これにより、プロンプト/会話に基づいて追加のコンテキストを追加したり、プロンプトを検証したり、特定のタイプのプロンプトをブロックしたりできます。Stop
Droidが応答を完了したときに実行されます。ユーザーの割り込みによって停止が発生した場合は実行されません。SubagentStop
サブdroid(Taskツール呼び出し)が応答を完了したときに実行されます。PreCompact
Droidがコンパクト操作を実行しようとする前に実行されます。 マッチャー:manual-/compactから呼び出されるauto- 自動コンパクトから呼び出される(コンテキストウィンドウが満杯のため)
SessionStart
Droidが新しいセッションを開始するか既存のセッションを再開するときに実行されます(現在内部的には新しいセッションを開始します)。既存の問題やコードベースへの最近の変更などの開発コンテキストの読み込み、依存関係のインストール、または環境変数の設定に役立ちます。 マッチャー:startup- スタートアップから呼び出されるresume---resume、--continue、または/resumeから呼び出されるclear-/clearから呼び出されるcompact- 自動または手動コンパクトから呼び出される
SessionEnd
Droidセッションが終了するときに実行されます。クリーンアップタスク、セッション統計のログ記録、またはセッション状態の保存に役立ちます。 フック入力のreasonフィールドは以下のいずれかになります:
clear- /clearまたは/newコマンドでセッションがクリアされたlogout- ユーザーがログアウトしたprompt_input_exit- プロンプト入力が表示されている間にユーザーが終了したother- その他の終了理由
フック入力
フックは、セッション情報とイベント固有のデータを含むJSONデータをstdinを通じて受信します:PreToolUse入力
tool_inputの正確なスキーマはツールに依存します。
PostToolUse入力
tool_inputとtool_responseの正確なスキーマはツールに依存します。
Notification入力
UserPromptSubmit入力
StopおよびSubagentStop入力
stop_hook_activeは、ストップフックの結果としてDroidがすでに継続している場合にtrueになります。この値をチェックするか、トランスクリプトを処理してDroidが無限に実行されるのを防いでください。
PreCompact入力
manualの場合、custom_instructionsはユーザーが/compactに渡すものから来ます。autoの場合、custom_instructionsは空です。
SessionStart入力
SessionEnd入力
フック出力
フックがDroidに出力を返す方法は2つあります。出力は、ブロックするかどうかと、Droidとユーザーに表示すべきフィードバックを伝えます。シンプル:終了コード
フックは終了コード、stdout、stderrを通じて状態を伝えます:- 終了コード0:成功。
stdoutはトランスクリプトモード(CTRL-R)でユーザーに表示されますが、UserPromptSubmitとSessionStartでは例外で、stdoutがコンテキストに追加されます。 - 終了コード2:ブロッキングエラー。
stderrはDroidに自動的に処理するためにフィードバックされます。以下のフックイベント別の動作を参照してください。 - その他の終了コード:非ブロッキングエラー。
stderrがユーザーに表示され、実行は継続されます。
終了コード2の動作
| フックイベント | 動作 |
|---|---|
PreToolUse | ツール呼び出しをブロックし、stderrをDroidに表示 |
PostToolUse | stderrをDroidに表示(ツールはすでに実行済み) |
Notification | N/A、stderrをユーザーのみに表示 |
UserPromptSubmit | プロンプト処理をブロック、プロンプトを消去、stderrをユーザーのみに表示 |
Stop | 停止をブロック、stderrをDroidに表示 |
SubagentStop | 停止をブロック、stderrをサブdroidに表示 |
PreCompact | N/A、stderrをユーザーのみに表示 |
SessionStart | N/A、stderrをユーザーのみに表示 |
SessionEnd | N/A、stderrをユーザーのみに表示 |
上級:JSON出力
フックは、より洗練された制御のためにstdoutで構造化JSONを返すことができます:
共通JSONフィールド
すべてのフックタイプは以下のオプションフィールドを含めることができます:continueがfalseの場合、Droidはフック実行後に処理を停止します。
PreToolUseの場合、これは"permissionDecision": "deny"とは異なり、特定のツール呼び出しのみをブロックしてDroidに自動フィードバックを提供します。PostToolUseの場合、これは"decision": "block"とは異なり、Droidに自動フィードバックを提供します。UserPromptSubmitの場合、これはプロンプトの処理を防ぎます。StopとSubagentStopの場合、これは任意の"decision": "block"出力より優先されます。- すべての場合において、
"continue" = falseは任意の"decision": "block"出力より優先されます。
stopReasonはcontinueに付随し、ユーザーに表示される理由を示しますが、Droidには表示されません。
PreToolUse決定制御
PreToolUseフックはツール呼び出しを実行するかどうかを制御できます。
"allow"は許可システムをバイパスします。permissionDecisionReasonはユーザーに表示されますが、Droidには表示されません。"deny"はツール呼び出しの実行を防ぎます。permissionDecisionReasonはDroidに表示されます。"ask"はUIでツール呼び出しの確認をユーザーに求めます。permissionDecisionReasonはユーザーに表示されますが、Droidには表示されません。
updatedInputを使用して実行前にツール入力を変更できます:
updatedInputにより、ツールが実行される前にツールの入力パラメータを変更できます。これは変更または追加したいフィールドを含むRecord<string, unknown>オブジェクトです。- これは
"permissionDecision": "allow"と組み合わせてツール呼び出しを変更および承認する際に最も有用です。
The
decision and reason fields are deprecated for PreToolUse hooks.
Use hookSpecificOutput.permissionDecision and
hookSpecificOutput.permissionDecisionReason instead. The deprecated fields
"approve" and "block" map to "allow" and "deny" respectively.PostToolUse決定制御
PostToolUseフックはツール実行後にDroidにフィードバックを提供できます。
"block"は自動的にDroidにreasonでプロンプトします。undefinedは何もしません。reasonは無視されます。"hookSpecificOutput.additionalContext"はDroidが考慮するコンテキストを追加します。
UserPromptSubmit決定制御
UserPromptSubmitフックはユーザープロンプトが処理されるかどうかを制御できます。
"block"はプロンプトの処理を防ぎます。送信されたプロンプトはコンテキストから消去されます。"reason"はユーザーに表示されますが、コンテキストには追加されません。undefinedはプロンプトを正常に続行させます。"reason"は無視されます。"hookSpecificOutput.additionalContext"はブロックされない場合に文字列をコンテキストに追加します。
Stop/SubagentStop決定制御
StopとSubagentStopフックはDroidが継続する必要があるかどうかを制御できます。
"block"はDroidの停止を防ぎます。Droidが続行方法を知るためにreasonを入力する必要があります。undefinedはDroidの停止を許可します。reasonは無視されます。
SessionStart決定制御
SessionStartフックにより、セッション開始時にコンテキストを読み込むことができます。
"hookSpecificOutput.additionalContext"は文字列をコンテキストに追加します。- 複数のフックの
additionalContext値が連結されます。
SessionEnd決定制御
SessionEndフックはセッション終了時に実行されます。セッション終了をブロックすることはできませんが、クリーンアップタスクを実行できます。
終了コード例:Executeコマンド検証
JSON出力例:コンテキスト追加と検証のためのUserPromptSubmit
For
UserPromptSubmit hooks, you can inject context using either method:- Exit code 0 with stdout: Droid sees the context (special case for
UserPromptSubmit) - JSON output: Provides more control over the behavior
JSON出力例:承認付きPreToolUse
MCPツールとの連携
DroidフックはModel Context Protocol (MCP) toolsとシームレスに動作します。MCPサーバーがツールを提供する場合、フックでマッチできる特別な命名パターンで表示されます。MCPツールの命名
MCPツールはmcp__<server>__<tool>のパターンに従います。例:
mcp__memory__create_entities- Memoryサーバーのcreate entitiesツールmcp__filesystem__read_file- Filesystemサーバーのread fileツールmcp__github__search_repositories- GitHubサーバーのsearchツール
MCPツール用フックの設定
特定のMCPツールまたはMCPサーバー全体をターゲットにできます:例
セキュリティに関する考慮事項
免責事項
自己責任で使用してください:Droidフックはシステム上で任意のシェルコマンドを自動的に実行します。フックを使用することにより、以下について承認したものとします:- 設定するコマンドについて全責任を負う
- フックはユーザーアカウントがアクセスできる任意のファイルを変更、削除、アクセスできる
- 悪意のあるまたは不適切に記述されたフックは、データ損失やシステム損傷を引き起こす可能性がある
- Factory AIは一切の保証を提供せず、フック使用によるいかなる損害についても責任を負わない
- 本番環境で使用する前に、安全な環境でフックを十分にテストすべきである
セキュリティのベストプラクティス
より安全なフックを記述するための主要な実践事項:- 入力の検証とサニタイズ - 入力データを盲目的に信頼しない
- シェル変数を常にクォートする -
$VARではなく"$VAR"を使用 - パストラバーサルをブロック - ファイルパスの
..をチェック - 絶対パスを使用 - スクリプトには常に完全パスを指定。Droidの現在ディレクトリに応じて不正に解決される可能性があるため、
./script.shやhooks/script.shなどの相対パスは使用しない。プロジェクトスクリプトには"$FACTORY_PROJECT_DIR"/path/to/script.shを使用するか、グローバルスクリプトには/usr/local/bin/script.shや~/.factory/hooks/script.shなどの完全パスを使用する。 - 機密ファイルをスキップ -
.env、.git/、キーなどを避ける
設定の安全性
設定ファイル内のフックの直接編集は即座に有効になりません。Droid:- スタートアップ時にフックのスナップショットをキャプチャ
- セッション全体でこのスナップショットを使用
- フックが外部で変更された場合に警告
- 変更を適用するために
/hooksメニューでのレビューが必要
フック実行の詳細
- タイムアウト:デフォルトで60秒の実行制限、コマンドごとに設定可能
- 個別のコマンドのタイムアウトは他のコマンドに影響しません
- 並列化:マッチするすべてのフックが並列で実行
- 重複排除:同一のフックコマンドが複数ある場合は自動的に重複排除
- 環境:Droidの環境で現在のディレクトリで実行
FACTORY_PROJECT_DIR環境変数が利用可能で、プロジェクトルートディレクトリ(Droidが開始された場所)の絶対パスが含まれます
- 入力:stdinを通じてJSON
- 出力:
- PreToolUse/PostToolUse/Stop/SubagentStop:トランスクリプト(Ctrl-R)で進行状況表示
- Notification/SessionEnd:デバッグのみにログ(
--debug) - UserPromptSubmit/SessionStart:stdoutがDroidのコンテキストとして追加
デバッグ
基本的なトラブルシューティング
フックが動作しない場合:- 設定を確認 -
/hooksを実行してフックが登録されているか確認 - 構文を検証 - JSON設定が有効であることを確認
- コマンドをテスト - 最初にフックコマンドを手動で実行
- 権限を確認 - スクリプトが実行可能であることを確認
- ログを確認 -
droid --debugを使用してフック実行の詳細を確認
- クォートがエスケープされていない - JSON文字列内で
\"を使用 - 間違ったマッチャー - ツール名が完全に一致することを確認(大文字小文字を区別)
- コマンドが見つからない - スクリプトには完全パスを使用
高度なデバッグ
複雑なフックの問題について:- フック実行を検査 -
droid --debugを使用して詳細なフック実行を確認 - JSONスキーマを検証 - 外部ツールでフック入力/出力をテスト
- 環境変数を確認 - Droidの環境が正しいことを確認
- エッジケースをテスト - 異常なファイルパスや入力でフックを試行
- システムリソースを監視 - フック実行中のリソース枯渇をチェック
- 構造化ログを使用 - フックスクリプトにログを実装
デバッグ出力例
droid --debugを使用してフック実行の詳細を確認:
- 実行中のフック
- 実行されているコマンド
- 成功/失敗ステータス
- 出力またはエラーメッセージ
