概要
failproofai には独立した 2 つのサブシステムがあります。- フックハンドラー — エージェントのすべてのツール呼び出しに対して Claude Code が呼び出す高速な CLI サブプロセスです。ポリシーを評価して判定結果を返します。
- エージェントモニター(ダッシュボード) — エージェントセッションの監視とポリシー管理のための Next.js ウェブアプリケーションです。
~/.failproofai/ およびプロジェクトの .failproofai/ ディレクトリ内の設定ファイルを共有しますが、それぞれ独立したプロセスとして動作し、ファイルシステムを通じてのみ通信します。
フックハンドラー
Claude Code との統合
failproofai policies --install を実行すると、~/.claude/settings.json に次のようなエントリが書き込まれます。
failproofai --hook PreToolUse をサブプロセスとして起動し、JSON ペイロードを stdin に渡します。
ペイロードの形式
PostToolUse イベントの場合、ペイロードにはツールの出力を含む tool_result も含まれます。
ハンドラーは stdin の上限を 1 MB に制限しています。これを超えるペイロードは破棄され、すべてのポリシーは暗黙的に allow となります。
レスポンスの形式
Deny(PreToolUse):- 終了コード:
2 - 理由は stdout ではなく stderr に書き込まれます
- 終了コード:
0 - stdout は空
allow(message) を使うと、操作が許可されている場合でも、ポリシーが情報コンテキストを Claude に送り返すことができます。フックハンドラーは以下の JSON を stdout に書き込みます(設定ファイルではなく、上記の deny・instruct レスポンスと同様に、Claude Code へのハンドラーの応答です)。
- 終了コード:
0(操作は許可されます) - 複数のポリシーがメッセージ付きで
allowを返した場合、各メッセージは改行で結合されて 1 つのadditionalContext文字列になります - どのポリシーもメッセージを提供しない場合、stdout は空になります(従来と同じ動作)
処理パイプライン
src/hooks/handler.ts がパイプライン全体を実装しています。
設定の読み込み
src/hooks/hooks-config.ts が 3 スコープの設定読み込みを実装しています。
enabledPolicies— 3 つのファイル全体にわたって重複を排除したユニオンpolicyParams— ポリシーごとのキーで、最初に定義したファイルが完全に優先されますcustomPoliciesPath— 最初に定義したファイルが優先されますllm— 最初に定義したファイルが優先されます
readHooksConfig()(グローバルのみ)を使用します。
ポリシー評価
src/hooks/policy-evaluator.ts がポリシーを順番に実行します。
各ポリシーに対して:
- ポリシーの
paramsスキーマを参照します(存在する場合)。 - マージ済み設定から
policyParams[policy.name]を読み取ります。 - ユーザー指定の値をスキーマのデフォルト値にマージして
ctx.paramsを生成します。 - 解決済みコンテキストで
policy.fn(ctx)を呼び出します。 - 結果が
denyの場合、直ちに処理を停止してその判定を返します。 - 結果が
instructの場合、メッセージを蓄積して次のポリシーに進みます。 - 結果が
allowの場合、次のポリシーに進みます。
denyが返された場合、deny レスポンスを出力します。instructが収集された場合、すべてのメッセージを結合した単一の instruct レスポンスを出力します。- それ以外の場合、allow レスポンスを出力します(stdout 空、終了コード 0)。
組み込みポリシー
src/hooks/builtin-policies.ts が 39 個の組み込みポリシーをすべて BuiltinPolicyDefinition オブジェクトとして定義しています。
params を受け取るポリシーは、各パラメーターの型とデフォルト値を含む PolicyParamsSchema を宣言します。ポリシーエバリュエーターは fn を呼び出す前に解決済みの値を ctx.params に注入します。デフォルト値は常に先に適用されるため、ポリシー関数は null チェックなしで ctx.params を読み取ることができます。
ポリシー内のパターンマッチングは、生の文字列マッチングではなく、解析済みのコマンドトークン(argv)を使用します。これにより、シェル演算子のインジェクションによるバイパスを防止します(例: sudo systemctl status * というパターンは、コマンドに ; rm -rf / を追加してもバイパスできません)。
カスタムポリシー
src/hooks/custom-hooks-registry.ts が globalThis をバックエンドとしたレジストリを実装しています。
src/hooks/custom-hooks-loader.ts がユーザーのポリシーファイルを読み込みます。
- 設定から
customPoliciesPathを読み取り、未設定の場合はスキップします。 - 絶対パスに解決し、ファイルの存在を確認します。
- すべての
from "failproofai"インポートを実際の dist パスに書き換え、customPoliciesが同じglobalThisレジストリに解決されるようにします。 - ESM 互換性を確保するため、推移的なローカルインポートも再帰的に書き換えます。
- 一時的な
.mjsファイルを生成し、エントリファイルをimport()します。 getCustomHooks()を呼び出して登録済みフックを取得します。finallyブロックですべての一時ファイルを削除します。
~/.failproofai/hook.log に記録され、ローダーは空の配列を返します。組み込みポリシーには影響しません。
カスタムポリシーはすべての組み込みポリシーの後に評価されます。カスタムポリシーの deny はそれ以降のカスタムポリシーの評価を短絡しますが、組み込みポリシーはすでに実行済みです。
アクティビティログ
各フックイベントの後、ハンドラーは~/.failproofai/hook-activity.jsonl に JSONL 行を追記します。
ダッシュボードのアーキテクチャ
ダッシュボードは、App Router・React Server Components・Server Actions を使用した Next.js 16 アプリケーションです。- ページコンポーネントは
lib/projects.tsとlib/log-entries.tsを呼び出し、ファイルシステムから直接プロジェクト/セッションデータを読み取ります(読み取りに API レイヤーは不要)。 - Policies ページはすべての変更操作(切り替え、パラメーター更新、インストール/削除)に Server Actions を使用します。
- セッションビューアーは Claude の JSONL トランスクリプト形式をパースし、メッセージとツール呼び出しのタイムラインを表示します。
- データベースなし — すべての永続状態はプレーンファイル(
~/.failproofai/、~/.claude/projects/)に保存されます。 - 変更操作には Server Actions を使用 — CRUD 操作に REST API は不要です。
- 読み取りページには React Server Components を使用 — 初期ロードが高速で、データフェッチのクライアントバンドルが不要です。
- クライアントコンポーネントはインタラクティブな操作が必要な箇所のみ使用(ポリシーの切り替え、アクティビティ検索、ログビューアー)。

