概要
failproofai には2つの独立したサブシステムがあります。- フックハンドラー - Claude Code がエージェントのすべてのツール呼び出し時に起動する高速な CLI サブプロセス。ポリシーを評価し、決定を返します。
- エージェントモニター(ダッシュボード) - エージェントセッションの監視とポリシー管理を行う Next.js ウェブアプリケーション。
~/.failproofai/ およびプロジェクトの .failproofai/ ディレクトリにある設定ファイルを共有しますが、それぞれ独立したプロセスとして動作し、ファイルシステムを通じてのみ通信します。
フックハンドラー
Claude Code との統合
failproofai policies --install を実行すると、以下のようなエントリが ~/.claude/settings.json に書き込まれます。
failproofai --hook PreToolUse をサブプロセスとして起動し、stdin に JSON ペイロードを渡します。
ペイロードの形式
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を返した場合、それらのメッセージは改行で結合されて単一の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 が BuiltinPolicyDefinition オブジェクトとして26個のビルトインポリシーをすべて定義しています。
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を読み取り、存在しない場合はスキップします。 - 絶対パスに解決し、ファイルの存在を確認します。
customPoliciesが同じglobalThisレジストリに解決されるよう、すべてのfrom "failproofai"インポートを実際の dist パスに書き換えます。- ESM 互換性を確保するため、推移的なローカルインポートを再帰的に書き換えます。
- 一時的な
.mjsファイルを書き込み、エントリファイルをimport()します。 getCustomHooks()を呼び出して登録済みフックを取得します。finallyブロックですべての一時ファイルを削除します。
~/.failproofai/hook.log に記録され、ローダーは空の配列を返します。ビルトインポリシーには影響しません。
カスタムポリシーはすべてのビルトインポリシーの後に評価されます。カスタムポリシーの deny はそれ以降のカスタムポリシーの実行を短絡させますが(その時点ではすべてのビルトインはすでに実行済みです)。
アクティビティログ
各フックイベントの後、ハンドラーは~/.failproofai/hook-activity.jsonl に JSONL 行を追記します。
ダッシュボードのアーキテクチャ
ダッシュボードは、React Server Components と Server Actions を使用した App Router 採用の Next.js 16 アプリケーションです。- ページコンポーネントは
lib/projects.tsとlib/log-entries.tsを呼び出し、ファイルシステムからプロジェクト/セッションデータを直接読み取ります(読み取りに API レイヤーは不要)。 - ポリシーページはすべての変更操作(切り替え、パラメーター更新、インストール/削除)に Server Actions を使用します。
- セッションビューアーは Claude の JSONL トランスクリプト形式をパースし、メッセージとツール呼び出しのタイムラインをレンダリングします。
- データベースなし - すべての永続状態はプレーンファイル(
~/.failproofai/、~/.claude/projects/)に保存されます。 - 変更操作には Server Actions を使用 - CRUD 操作に REST API は不要。
- 読み取りページには React Server Components を使用 - 初期ロードが高速で、データフェッチのクライアントバンドルが不要。
- クライアントコンポーネントはインタラクティブ性が必要な場合のみ使用(ポリシーの切り替え、アクティビティ検索、ログビューアー)。

