Übersicht
failproofai besteht aus zwei unabhängigen Subsystemen:- Hook-Handler – Ein schneller CLI-Subprozess, den Claude Code bei jedem Agent-Tool-Aufruf aufruft. Er wertet Richtlinien aus und gibt eine Entscheidung zurück.
- Agent Monitor (Dashboard) – Eine Next.js-Webanwendung zur Überwachung von Agentensitzungen und zur Verwaltung von Richtlinien.
~/.failproofai/ und im .failproofai/-Verzeichnis des Projekts, laufen aber als separate Prozesse und kommunizieren ausschließlich über das Dateisystem.
Hook-Handler
Integration mit Claude Code
Wenn Siefailproofai policies --install ausführen, werden folgende Einträge in ~/.claude/settings.json geschrieben:
failproofai --hook PreToolUse vor jedem Tool-Aufruf als Subprozess auf und übergibt eine JSON-Nutzlast über stdin.
Nutzlastformat
PostToolUse-Ereignissen enthält die Nutzlast zusätzlich tool_result mit der Ausgabe des Tools.
Der Handler begrenzt die stdin-Eingabe auf 1 MB. Nutzlasten, die diesen Wert überschreiten, werden verworfen, und alle Richtlinien erlauben die Ausführung implizit.
Antwortformat
Ablehnen (PreToolUse):- Exit-Code:
2 - Begründung wird in stderr (nicht stdout) geschrieben
- Exit-Code:
0 - Leere stdout-Ausgabe
allow(message) ermöglicht es einer Richtlinie, informativen Kontext an Claude zurückzusenden, auch wenn die Operation erlaubt ist. Der Hook-Handler schreibt das folgende JSON auf stdout (keine Konfigurationsdatei – dies ist die Antwort des Handlers an Claude Code, genau wie Ablehnen- und Anweisen-Antworten oben):
- Exit-Code:
0(die Operation wird erlaubt) - Wenn mehrere Richtlinien
allowmit einer Nachricht zurückgeben, werden ihre Nachrichten mit Zeilenumbrüchen zu einem einzigenadditionalContext-String zusammengefügt - Wenn keine Richtlinie eine Nachricht liefert, ist stdout leer (wie bisher)
Verarbeitungspipeline
src/hooks/handler.ts implementiert die vollständige Pipeline:
Konfigurationsladung
src/hooks/hooks-config.ts implementiert das Laden der Konfiguration aus drei Bereichen.
enabledPolicies– deduplizierte Vereinigung aus allen drei DateienpolicyParams– pro Richtlinien-Schlüssel gewinnt die erste Datei, die ihn definiert, vollständigcustomPoliciesPath– die erste Datei, die diesen Wert definiert, gewinntllm– die erste Datei, die diesen Wert definiert, gewinnt
readHooksConfig() (nur global) zum Lesen und Schreiben, da es nicht mit einem Projekt-cwd aufgerufen wird.
Richtlinienauswertung
src/hooks/policy-evaluator.ts führt Richtlinien der Reihe nach aus.
Für jede Richtlinie:
- Das
params-Schema der Richtlinie nachschlagen (falls vorhanden). policyParams[policy.name]aus der zusammengeführten Konfiguration lesen.- Benutzerdefinierte Werte über die Schema-Standardwerte zusammenführen, um
ctx.paramszu erzeugen. policy.fn(ctx)mit dem aufgelösten Kontext aufrufen.- Wenn das Ergebnis
denyist, sofort abbrechen und diese Entscheidung zurückgeben. - Wenn das Ergebnis
instructist, die Nachricht sammeln und fortfahren. - Wenn das Ergebnis
allowist, zur nächsten Richtlinie übergehen.
- Falls ein
denyzurückgegeben wurde, die Ablehnungsantwort ausgeben. - Falls
instruct-Rückgaben gesammelt wurden, eine einzelne Anweisungsantwort mit allen zusammengefügten Nachrichten ausgeben. - Andernfalls eine Erlauben-Antwort ausgeben (leere stdout-Ausgabe, Exit 0).
Integrierte Richtlinien
src/hooks/builtin-policies.ts definiert alle 39 integrierten Richtlinien als BuiltinPolicyDefinition-Objekte:
params akzeptieren, deklarieren ein PolicyParamsSchema mit Typen und Standardwerten für jeden Parameter. Der Richtlinien-Evaluator injiziert aufgelöste Werte in ctx.params, bevor er fn aufruft. Richtlinienfunktionen lesen ctx.params ohne Null-Prüfung, da Standardwerte immer zuerst angewendet werden.
Musterabgleiche innerhalb von Richtlinien verwenden geparste Befehls-Tokens (argv) statt einfachem String-Matching. Dadurch werden Umgehungen durch Shell-Operator-Injection verhindert (z. B. kann ein Muster für sudo systemctl status * nicht durch Anhängen von ; rm -rf / an den Befehl umgangen werden).
Benutzerdefinierte Richtlinien
src/hooks/custom-hooks-registry.ts implementiert eine globalThis-basierte Registrierung:
src/hooks/custom-hooks-loader.ts lädt die Richtliniendatei des Benutzers:
customPoliciesPathaus der Konfiguration lesen; überspringen, falls nicht vorhanden.- Auf absoluten Pfad auflösen; prüfen, ob die Datei existiert.
- Alle
from "failproofai"-Importe auf den tatsächlichen dist-Pfad umschreiben, sodasscustomPoliciesauf dieselbeglobalThis-Registrierung zeigt. - Transitive lokale Importe rekursiv umschreiben, um ESM-Kompatibilität sicherzustellen.
- Temporäre
.mjs-Dateien schreiben und die Einstiegsdatei perimport()laden. getCustomHooks()aufrufen, um registrierte Hooks abzurufen.- Alle temporären Dateien in einem
finally-Block bereinigen.
~/.failproofai/hook.log protokolliert und der Loader gibt ein leeres Array zurück. Integrierte Richtlinien sind davon nicht betroffen.
Benutzerdefinierte Richtlinien werden nach allen integrierten Richtlinien ausgewertet. Ein deny einer benutzerdefinierten Richtlinie unterbricht zwar weitere benutzerdefinierte Richtlinien (alle integrierten wurden zu diesem Zeitpunkt jedoch bereits ausgeführt).
Aktivitätsprotokollierung
Nach jedem Hook-Ereignis fügt der Handler eine JSONL-Zeile an~/.failproofai/hook-activity.jsonl an:
Dashboard-Architektur
Das Dashboard ist eine Next.js 16-Anwendung, die den App Router mit React Server Components und Server Actions verwendet.- Seitenkomponenten rufen
lib/projects.tsundlib/log-entries.tsauf, um Projekt-/Sitzungsdaten direkt aus dem Dateisystem zu lesen (keine API-Schicht für Lesevorgänge). - Die Policies-Seite verwendet Server Actions für alle Mutationen (Umschalten, Parameteraktualisierung, Installieren/Entfernen).
- Der Sitzungs-Viewer parst das JSONL-Transkriptformat von Claude und rendert eine Zeitleiste mit Nachrichten und Tool-Aufrufen.
- Keine Datenbank – alle persistenten Zustände liegen in einfachen Dateien (
~/.failproofai/,~/.claude/projects/). - Server Actions für Mutationen – keine REST-API für CRUD-Operationen erforderlich.
- React Server Components für Leseseiten – schnelleres initiales Laden, kein Client-Bundle für das Datenabrufen.
- Client-Komponenten nur dort, wo Interaktivität benötigt wird (Richtlinien-Umschalter, Aktivitätssuche, Log-Viewer).

