Cascade Hooks ermöglichen es Ihnen, benutzerdefinierte Shell-Befehle an entscheidenden Punkten im Workflow von Cascade auszuführen. Diese leistungsfähige Erweiterungsfunktion erlaubt es, Abläufe zu protokollieren, Leitplanken durchzusetzen, Validierungen durchzuführen oder Integrationen mit externen Systemen herzustellen.
Hooks sind für Power-User und Enterprise-Teams konzipiert, die eine fein abgestimmte Kontrolle über das Verhalten von Cascade benötigen. Sie erfordern grundlegende Kenntnisse in Shell-Scripting.
Hooks erschließen ein breites Spektrum an Automatisierungs- und Governance-Funktionen:
- Protokollierung & Analytics: Verfolgen Sie jede gelesene Datei, jede Codeänderung, jeden ausgeführten Befehl, jede Nutzereingabe oder jede Cascade-Antwort für Compliance- und Nutzungsanalysen
- Sicherheitskontrollen: Verhindern Sie, dass Cascade auf sensible Dateien zugreift, gefährliche Befehle ausführt oder Prompts verarbeitet, die gegen Richtlinien verstoßen
- Qualitätssicherung: Führen Sie nach Codeänderungen automatisch Linter, Formatter oder Tests aus
- Benutzerdefinierte Workflows: Integrieren Sie Issue-Tracker, Benachrichtigungssysteme oder Deployment-Pipelines
- Team-Standardisierung: Setzen Sie Coding-Standards und Best Practices in Ihrer Organisation durch
Hooks sind Shell-Befehle, die automatisch ausgeführt werden, wenn bestimmte Cascade-Aktionen stattfinden. Jeder Hook:
- Erhält Kontext (Details zur ausgeführten Aktion) über JSON über die Standardeingabe
- Führt Ihr Skript aus – Python, Bash, Node.js oder jede andere ausführbare Datei
- Gibt ein Ergebnis zurück über Rückgabecode und Ausgabeströme
Bei Pre-Hooks (vor einer Aktion ausgeführt) kann Ihr Skript die Aktion blockieren, indem es mit dem Rückgabecode 2 beendet wird. Dadurch eignen sich Pre-Hooks ideal zur Umsetzung von Sicherheitsrichtlinien oder Validierungsprüfungen.
Hooks werden in JSON-Dateien konfiguriert, die auf drei Ebenen abgelegt werden können. Cascade lädt und zusammenführt Hooks aus allen Standorten und bietet Teams so Flexibilität bei der Verteilung und Verwaltung von Hook-Konfigurationen.
Systemweite Hooks eignen sich ideal für unternehmensweite Richtlinien, die auf gemeinsam genutzten Entwicklungsrechnern durchgesetzt werden. Sie können sie beispielsweise verwenden, um Sicherheitsrichtlinien, Compliance-Vorgaben oder verpflichtende Code-Review-Workflows durchzusetzen. Enterprise-Teams können Hooks außerdem über das Cloud-Dashboard konfigurieren, ohne lokale Dateien verwalten zu müssen.
- macOS:
/Library/Application Support/Windsurf/hooks.json
- Linux/WSL:
/etc/windsurf/hooks.json
- Windows:
C:\ProgramData\Windsurf\hooks.json
Benutzerebenen-Hooks sind ideal für persönliche Präferenzen und optionale Workflows.
- Windsurf-IDE:
~/.codeium/windsurf/hooks.json
- JetBrains-Plugin:
~/.codeium/hooks.json
Hooks auf Workspace-Ebene ermöglichen Teams, projektspezifische Richtlinien gemeinsam mit ihrem Code unter Versionskontrolle zu halten. Sie können benutzerdefinierte Validierungsregeln, projektspezifische Integrationen oder teambezogene Workflows umfassen.
- Speicherort:
.windsurf/hooks.json im Workspace-Root
Hooks aus allen drei Speicherorten werden zusammengeführt. Wenn dasselbe Hook-Ereignis an mehreren Speicherorten konfiguriert ist, werden alle Hooks in folgender Reihenfolge ausgeführt: System → Benutzer → Workspace.
Hier ein Beispiel für die Grundstruktur der Hooks-Konfiguration:
{
"hooks": {
"pre_read_code": [
{
"command": "python3 /path/to/your/script.py",
"show_output": true
}
],
"post_write_code": [
{
"command": "python3 /path/to/another/script.py",
"show_output": true
}
]
}
}
Jeder Hook akzeptiert die folgenden Parameter:
| Parameter | Typ | Beschreibung |
|---|
command | string | Der auszuführende Shell-Befehl. Kann ein beliebiges gültiges ausführbares Programm mit Argumenten sein. |
show_output | boolean | Ob die stdout/stderr-Ausgabe des Hooks in der benutzerseitigen Cascade-UI angezeigt wird. Nützlich zum Debuggen. |
working_directory | string | Optional. Das Verzeichnis, von dem aus der Befehl ausgeführt wird. Standardmäßig das Root Ihres Workspace. |
Zum Parameter working_directory:
- In Multi-Repo-Workspaces ist die Standardeinstellung das Root-Verzeichnis des Repos, an dem aktuell gearbeitet wird
- Relative Pfade werden ausgehend vom Standardpfad (Workspace- oder Repo-Root) aufgelöst
- Absolute Pfade werden unterstützt
- Die Verwendung von
~ für die Erweiterung des Home-Verzeichnisses wird nicht unterstützt
Cascade stellt zwölf Hook-Ereignisse bereit, die die wichtigsten Aktionen im Agent-Workflow abdecken.
Alle Hooks erhalten ein JSON-Objekt mit den folgenden gemeinsamen Feldern:
| Feld | Typ | Beschreibung |
|---|
agent_action_name | string | Der Name des Hook-Ereignisses (z. B. „pre_read_code“, „post_write_code“) |
trajectory_id | string | Eindeutiger Bezeichner für die gesamte Cascade-Konversation |
execution_id | string | Eindeutiger Bezeichner für den einzelnen Agenten-Turn |
timestamp | string | ISO-8601-Zeitstempel, zu dem der Hook ausgelöst wurde |
tool_info | object | Ereignisspezifische Informationen (variieren je nach Hook-Typ) |
In den folgenden Beispielen werden die gemeinsamen Felder der Übersichtlichkeit halber weggelassen. Es gibt zwölf Haupttypen von Hook-Ereignissen:
Wird ausgelöst, bevor Cascade eine Code-Datei liest. Dies kann die Aktion blockieren, wenn der Hook mit Exit-Code 2 endet.
Anwendungsfälle: Dateizugriff einschränken, Lesevorgänge protokollieren, Berechtigungen prüfen
Eingabe-JSON:
{
"agent_action_name": "pre_read_code",
"tool_info": {
"file_path": "/Users/yourname/project/file.py"
}
}
Der file_path kann ein Verzeichnispfad sein, wenn Cascade ein Verzeichnis rekursiv einliest.
Ausgelöst nachdem Cascade eine Code-Datei erfolgreich gelesen hat.
Anwendungsfälle: Erfolgreiche Lesevorgänge protokollieren, Dateizugriffsmuster nachverfolgen
Eingabe-JSON:
{
"agent_action_name": "post_read_code",
"tool_info": {
"file_path": "/Users/yourname/project/file.py"
}
}
Dieser file_path kann ein Verzeichnispfad sein, wenn Cascade ein Verzeichnis rekursiv einliest.
Wird ausgelöst, bevor Cascade eine Code-Datei schreibt oder ändert. Die Aktion kann blockiert werden, wenn der Hook mit Code 2 beendet wird.
Anwendungsfälle: Änderungen an geschützten Dateien verhindern, Dateien vor Änderungen sichern
Eingabe-JSON:
{
"agent_action_name": "pre_write_code",
"tool_info": {
"file_path": "/Users/yourname/project/file.py",
"edits": [
{
"old_string": "def old_function():\n pass",
"new_string": "def new_function():\n return True"
}
]
}
}
Ausgelöst nachdem Cascade eine Code-Datei schreibt oder ändert.
Anwendungsfälle: Linter, Formatter oder Tests ausführen; Codeänderungen protokollieren
Input JSON:
{
"agent_action_name": "post_write_code",
"tool_info": {
"file_path": "/Users/yourname/project/file.py",
"edits": [
{
"old_string": "import os",
"new_string": "import os\nimport sys"
}
]
}
}
Wird ausgelöst, bevor Cascade einen Terminalbefehl ausführt. Dies kann die Aktion blockieren, wenn der Hook mit dem Code 2 beendet wird.
Anwendungsfälle: Gefährliche Befehle blockieren, alle Befehlsausführungen protokollieren, Sicherheitsprüfungen hinzufügen
Input JSON:
{
"agent_action_name": "pre_run_command",
"tool_info": {
"command_line": "npm install package-name",
"cwd": "/Users/yourname/project"
}
}
Wird nachdem Cascade einen Terminalbefehl ausgeführt hat, ausgelöst.
Anwendungsfälle: Befehlsausgaben protokollieren, Folgeaktionen auslösen
Eingabe-JSON:
{
"agent_action_name": "post_run_command",
"tool_info": {
"command_line": "npm install package-name",
"cwd": "/Users/yourname/project"
}
}
Ausgelöst bevor Cascade ein MCP (Model Context Protocol)‑Tool aufruft. Dies kann die Aktion blockieren, wenn der Hook mit Code 2 beendet wird.
Anwendungsfälle: MCP‑Nutzung protokollieren, festlegen, welche MCP‑Tools verwendet werden dürfen
Eingabe‑JSON:
{
"agent_action_name": "pre_mcp_tool_use",
"tool_info": {
"mcp_server_name": "github",
"mcp_tool_arguments": {
"owner": "code-owner",
"repo": "my-cool-repo",
"title": "Fehlerbericht",
"body": "Fehlerbeschreibung hier"
},
"mcp_tool_name": "create_issue"
}
}
Wird ausgelöst, nachdem Cascade erfolgreich ein MCP-Tool aufgerufen hat.
Anwendungsfälle: MCP-Vorgänge protokollieren, API-Nutzung nachverfolgen, MCP-Ergebnisse anzeigen
Eingabe-JSON:
{
"agent_action_name": "post_mcp_tool_use",
"tool_info": {
"mcp_result": "...",
"mcp_server_name": "github",
"mcp_tool_arguments": {
"owner": "code-owner",
"perPage": 1,
"repo": "my-cool-repo",
"sha": "main"
},
"mcp_tool_name": "list_commits"
}
}
Ausgelöst bevor Cascade den Text eines Benutzerprompts verarbeitet. Dies kann die Aktion blockieren, wenn der Hook mit Code 2 beendet wird.
Anwendungsfälle: Sämtliche Benutzerprompts zu Prüfzwecken protokollieren, potenziell schädliche oder gegen Richtlinien verstoßende Prompts blockieren
Input JSON:
{
"agent_action_name": "pre_user_prompt",
"tool_info": {
"user_prompt": "can you run the echo hello command"
}
}
Die Konfigurationsoption show_output gilt für diesen Hook nicht.
Wird asynchron ausgelöst, nachdem Cascade eine Antwort auf den Prompt eines Nutzers abgeschlossen hat. Dieser Hook erhält die vollständige Cascade-Antwort seit der letzten Nutzereingabe.
Anwendungsfälle: Alle Cascade-Antworten zu Prüfzwecken protokollieren, Antwortmuster analysieren, Antworten zur Compliance-Prüfung an externe Systeme senden
Input JSON:
Das Feld response enthält den in Markdown formatierten Inhalt der Antwort von Cascade seit der letzten Benutzereingabe. Dies umfasst Planner-Antworten, Tool-Aktionen (Datei-Lese- und -Schreibvorgänge, Commands) und alle anderen Schritte, die Cascade ausgeführt hat. Es enthält außerdem Informationen darüber, welche rules ausgelöst wurden. Siehe das Beispiel Tracking Triggered Rules, um zu erfahren, wie Sie die Nutzung von Regeln auswerten können.
Die Konfigurationsoption show_output gilt nicht für diesen Hook.
Der Inhalt von response wird aus Verlaufsdaten (Trajectory-Daten) abgeleitet und kann sensible Informationen aus Ihrer Codebasis oder aus Unterhaltungen enthalten. Behandeln Sie diese Daten gemäß den Sicherheits- und Datenschutzrichtlinien Ihrer Organisation.
{
"agent_action_name": "post_cascade_response",
"tool_info": {
"response": "### Planner Response\n\nI'll help you create that file.\n\n*Created file `/path/to/file.py`*\n\n### Planner Response\n\nThe file has been created successfully."
}
}
Das Feld response enthält den in Markdown formatierten Inhalt der Antwort von Cascade seit der letzten Benutzereingabe. Dies umfasst Planner-Antworten, Tool-Aktionen (Datei-Lese- und -Schreibvorgänge, Commands) und alle anderen Schritte, die Cascade ausgeführt hat. Es enthält außerdem Informationen darüber, welche rules ausgelöst wurden. Siehe das Beispiel Tracking Triggered Rules, um zu erfahren, wie Sie die Nutzung von Regeln auswerten können.
Die Konfigurationsoption show_output gilt nicht für diesen Hook.
Der Inhalt von response wird aus Verlaufsdaten (Trajectory-Daten) abgeleitet und kann sensible Informationen aus Ihrer Codebasis oder aus Unterhaltungen enthalten. Behandeln Sie diese Daten gemäß den Sicherheits- und Datenschutzrichtlinien Ihrer Organisation.
post_cascade_response_with_transcript
Wird asynchron ausgelöst, nachdem Cascade eine Antwort auf den Prompt eines Nutzers abgeschlossen hat, ähnlich wie bei post_cascade_response. Anstatt eine Markdown-Zusammenfassung inline bereitzustellen, schreibt dieser Hook das vollständige Gesprächstranskript (vom Beginn der Unterhaltung an) in eine lokale JSONL-Datei und gibt den Dateipfad zurück.
Anwendungsfälle: Enterprise-Audit- und Compliance-Protokollierung, Nachverfolgung von KI-generierten Beiträgen, Einspeisen von Transkripten in externe Observability- oder Analytics-Tools
Eingabe-JSON:
{
"agent_action_name": "post_cascade_response_with_transcript",
"tool_info": {
"transcript_path": "/Users/yourname/.windsurf/transcripts/{trajectory_id}.jsonl"
}
}
Der transcript_path verweist auf eine JSONL-Datei unter ~/.windsurf/transcripts/{trajectory_id}.jsonl. Jede Zeile ist ein JSON-Objekt, das einen einzelnen Schritt in der Konversation darstellt, mit den Feldern type und status sowie schrittspezifischen Daten. Zum Beispiel:
{"status":"done","type":"user_input","user_input":{"rules_applied":{"always_on":["my-rule.md"]},"user_response":"create a hello world file"}}
{"planner_response":{"response":"I'll create a hello world file for you."},"status":"done","type":"planner_response"}
{"code_action":{"new_content":"print('hello world')\n","path":"/path/to/file.py"},"status":"done","type":"code_action"}
{"planner_response":{"response":"I created the file for you."},"status":"done","type":"planner_response"}
Das Transkript enthält detaillierte, vom Kunden verwaltete Daten wie Dateiinhalte, Befehlsausgaben, Tool-Argumente, Suchergebnisse und Regeln, die angewendet wurden. Bitte beachten Sie, dass sich die genaue Struktur jedes Schritts in zukünftigen Versionen ändern kann. Implementieren Sie daher alle Hook-Consumer so, dass sie robust gegenüber Änderungen sind.
Transkriptdateien werden mit 0600-Berechtigungen geschrieben. Windsurf begrenzt das Transkriptverzeichnis automatisch auf 100 Dateien und entfernt die ältesten anhand der Änderungszeit.
Die Konfigurationsoption show_output gilt nicht für diesen Hook.
Diese Tabelle zeigt die wichtigsten Unterschiede zwischen den Hooks post_cascade_response und post_cascade_response_with_transcript:
| post_cascade_response | post_cascade_response_with_transcript |
|---|
| Data scope | Nur die Schritte seit der letzten Nutzereingabe | Die vollständige Unterhaltung vom Anfang an |
| Format | Markdown-Zusammenfassung in tool_info.response | Strukturierte JSONL-Datei unter tool_info.transcript_path |
| Detail level | Kompakte, menschenlesbare Zusammenfassung | Detaillierte, maschinenlesbare Daten (Dateiinhalte, Befehlsausgaben usw.) |
| Delivery | Inline über stdin-JSON | Datei auf dem Datenträger (~/.windsurf/transcripts/) |
Transkriptdateien enthalten sensible Informationen aus Ihrer Codebasis, einschließlich Dateiinhalte, Befehlsausgaben und Gesprächsverlauf. Behandeln Sie diese Dateien gemäß den Sicherheits- und Datenschutzrichtlinien Ihrer Organisation.
Wird ausgelöst, nachdem ein neuer git worktree erstellt und konfiguriert wurde. Der Hook wird im neuen worktree-Verzeichnis ausgeführt.
Anwendungsfälle: .env-Dateien oder andere unversionierte Dateien in den Worktree kopieren, Abhängigkeiten installieren, Setup-Skripte ausführen
Umgebungsvariablen:
| Variable | Beschreibung |
|---|
$ROOT_WORKSPACE_PATH | Der absolute Pfad zum ursprünglichen Workspace. Verwenden Sie diese Variable, um auf Dateien zuzugreifen oder Befehle relativ zum ursprünglichen Repository auszuführen. |
Eingabe-JSON:
{
"agent_action_name": "post_setup_worktree",
"tool_info": {
"worktree_path": "/Users/me/.windsurf/worktrees/my-repo/abmy-repo-c123",
"root_workspace_path": "/Users/me/projects/my-repo"
}
}
Ihre Hook-Skripte übermitteln Ergebnisse über Exit Codes:
| Exit Code | Bedeutung | Effekt |
|---|
0 | Erfolg | Aktion läuft normal weiter |
2 | Blockierender Fehler | Der Cascade-Agent sieht die Fehlermeldung von stderr. Bei Pre-Hooks blockiert dies die Aktion. |
| Jeder andere | Fehler | Aktion läuft normal weiter |
Nur Pre-Hooks (pre_user_prompt, pre_read_code, pre_write_code, pre_run_command, pre_mcp_tool_use) können Aktionen mit Exit Code 2 blockieren. Post-Hooks können nicht blockieren, da die Aktion bereits ausgeführt wurde.
Beachten Sie, dass der Nutzer jede vom Hook erzeugte Standardausgabe und jeden Standardfehler in der Cascade-UI sehen kann, wenn show_output auf true gesetzt ist.
Protokollierung aller Cascade-Aktionen
Protokolliere jede von Cascade ausgeführte Aktion zu Audit‑Zwecken.
Konfiguration:
{
"hooks": {
"post_read_code": [
{
"command": "python3 /Users/yourname/hooks/log_input.py",
"show_output": true
}
],
"post_write_code": [
{
"command": "python3 /Users/yourname/hooks/log_input.py",
"show_output": true
}
],
"post_run_command": [
{
"command": "python3 /Users/yourname/hooks/log_input.py",
"show_output": true
}
],
"post_mcp_tool_use": [
{
"command": "python3 /Users/yourname/hooks/log_input.py",
"show_output": true
}
],
"post_cascade_response": [
{
"command": "python3 /Users/yourname/hooks/log_input.py"
}
]
}
}
Skript (log_input.py):
#!/usr/bin/env python3
import sys
import json
def main():
# Read the JSON data from stdin
input_data = sys.stdin.read()
# Parse the JSON
try:
data = json.loads(input_data)
# Write formatted JSON to file
with open("/Users/yourname/hooks/input.txt", "a") as f:
f.write('\n' + '='*80 + '\n')
f.write(json.dumps(data, indent=2, separators=(',', ': ')))
f.write('\n')
print(json.dumps(data, indent=2))
except json.JSONDecodeError as e:
print(f"Fehler beim Parsen von JSON: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
Dieses Skript protokolliert jeden Hook-Aufruf in einer Logdatei und erzeugt so einen Audit-Trail aller Cascade-Aktionen. Sie können die Eingabedaten transformieren oder nach Bedarf benutzerdefinierte Logik ausführen.
Dateizugriff einschränken
Verhindern Sie, dass Cascade Dateien außerhalb eines bestimmten Verzeichnisses liest.
Konfiguration:
{
"hooks": {
"pre_read_code": [
{
"command": "python3 /Users/yourname/hooks/block_read_access.py",
"show_output": true
}
]
}
}
Skript (block_read_access.py):
#!/usr/bin/env python3
import sys
import json
ALLOWED_PREFIX = "/Users/yourname/my-project/"
def main():
# JSON-Daten aus stdin lesen
input_data = sys.stdin.read()
# JSON parsen
try:
data = json.loads(input_data)
if data.get("agent_action_name") == "pre_read_code":
tool_info = data.get("tool_info", {})
file_path = tool_info.get("file_path", "")
if not file_path.startswith(ALLOWED_PREFIX):
print(f"Zugriff verweigert: Cascade darf nur Dateien unter {ALLOWED_PREFIX} lesen", file=sys.stderr)
sys.exit(2) # Exit-Code 2 blockiert die Aktion
print(f"Zugriff gewährt: {file_path}", file=sys.stdout)
except json.JSONDecodeError as e:
print(f"Fehler beim Parsen von JSON: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
Wenn Cascade versucht, eine Datei außerhalb des zulässigen Verzeichnisses zu lesen, verhindert dieser Hook den Vorgang und zeigt eine Fehlermeldung an.
Gefährliche Commands blockieren
Verhindern Sie, dass Cascade potenziell schädliche Commands ausführt.
Konfiguration:
{
"hooks": {
"pre_run_command": [
{
"command": "python3 /Users/yourname/hooks/block_dangerous_commands.py",
"show_output": true
}
]
}
}
Skript (block_dangerous_commands.py):
#!/usr/bin/env python3
import sys
import json
DANGEROUS_COMMANDS = ["rm -rf", "sudo rm", "format", "del /f"]
def main():
# Read the JSON data from stdin
input_data = sys.stdin.read()
# Parse the JSON
try:
data = json.loads(input_data)
if data.get("agent_action_name") == "pre_run_command":
tool_info = data.get("tool_info", {})
command = tool_info.get("command_line", "")
for dangerous_cmd in DANGEROUS_COMMANDS:
if dangerous_cmd in command:
print(f"Command blockiert: ‚{dangerous_cmd}' ist aus Sicherheitsgründen nicht erlaubt.", file=sys.stderr)
sys.exit(2) # Exit code 2 blocks the command
print(f"Command approved: {command}", file=sys.stdout)
except json.JSONDecodeError as e:
print(f"Error parsing JSON: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
Dieser Hook prüft Commands auf gefährliche Muster und blockiert sie vor der Ausführung.
Blockieren von richtlinienwidrigen Prompts
Verhindern Sie, dass Benutzer Prompts senden, die gegen Organisationsrichtlinien verstoßen.
Config:
{
"hooks": {
"pre_user_prompt": [
{
"command": "python3 /Users/yourname/hooks/block_bad_prompts.py"
}
]
}
}
Skript (block_bad_prompts.py):
#!/usr/bin/env python3
import sys
import json
BLOCKED_PATTERNS = [
"something dangerous",
"bypass security",
"ignore previous instructions"
]
def main():
# JSON-Daten aus stdin lesen
input_data = sys.stdin.read()
# JSON parsen
try:
data = json.loads(input_data)
if data.get("agent_action_name") == "pre_user_prompt":
tool_info = data.get("tool_info", {})
user_prompt = tool_info.get("user_prompt", "").lower()
for pattern in BLOCKED_PATTERNS:
if pattern in user_prompt:
print(f"Prompt blocked: Contains prohibited content. The user cannot ask the agent to do bad things.", file=sys.stderr)
sys.exit(2) # Exit-Code 2 blockiert den Prompt
except json.JSONDecodeError as e:
print(f"Error parsing JSON: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
Dieser Hook überprüft Benutzereingaben, bevor sie verarbeitet werden, und blockiert alle Eingaben, die verbotene Muster enthalten. Wenn eine Eingabe blockiert wird, sieht der Benutzer eine Fehlermeldung in der Cascade-UI.
Cascade-Antworten protokollieren
Erfassen Sie alle Cascade-Antworten für Compliance-Prüfungen oder Analytics.
Konfiguration:
{
"hooks": {
"post_cascade_response": [
{
"command": "python3 /Users/yourname/hooks/log_cascade_response.py"
}
]
}
}
Skript (log_cascade_response.py):
#!/usr/bin/env python3
import sys
import json
from datetime import datetime
def main():
# JSON-Daten von stdin lesen
input_data = sys.stdin.read()
# JSON parsen
try:
data = json.loads(input_data)
if data.get("agent_action_name") == "post_cascade_response":
tool_info = data.get("tool_info", {})
cascade_response = tool_info.get("response", "")
trajectory_id = data.get("trajectory_id", "unknown")
timestamp = data.get("timestamp", datetime.now().isoformat())
# In Datei loggen
with open("/Users/yourname/hooks/cascade_responses.log", "a") as f:
f.write(f"\n{'='*80}\n")
f.write(f"Timestamp: {timestamp}\n")
f.write(f"Trajectory ID: {trajectory_id}\n")
f.write(f"Response:\n{cascade_response}\n")
print(f"Logged Cascade response for trajectory {trajectory_id}")
except json.JSONDecodeError as e:
print(f"Error parsing JSON: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
Dieser Hook protokolliert jede Cascade-Antwort in einer Datei und erzeugt damit einen Audit-Trail aller KI-generierten Inhalte. Sie können dies erweitern, um die Daten an externe Logging-Systeme, Datenbanken oder Compliance-Plattformen weiterzuleiten.
Ausgelöste Regeln nachverfolgen
Verfolgen Sie, welche Regeln während Cascade-Interaktionen angewendet wurden, um Observability und Metriken zu ermöglichen.
Konfiguration:
{
"hooks": {
"post_cascade_response": [
{
"command": "python3 /Users/yourname/hooks/track_rules.py"
}
]
}
}
Skript (track_rules.py):
#!/usr/bin/env python3
import sys
import json
import re
from datetime import datetime
def extract_triggered_rules(response: str) -> dict:
"""
Parst ausgelöste Regeln aus der Cascade-Antwort.
Regeln erscheinen als: - (Rule-Type) Triggered Rule: rule-filename.md
"""
pattern = r"- \(([^)]+)\) Triggered Rule: (.+?)(?:\s*$)"
rules = {}
for match in re.finditer(pattern, response, re.MULTILINE):
rule_type, rule_name = match.groups()
if rule_type not in rules:
rules[rule_type] = []
rules[rule_type].append(rule_name)
return rules
def main():
input_data = sys.stdin.read()
try:
data = json.loads(input_data)
if data.get("agent_action_name") == "post_cascade_response":
response = data.get("tool_info", {}).get("response", "")
trajectory_id = data.get("trajectory_id", "unknown")
timestamp = data.get("timestamp", datetime.now().isoformat())
rules = extract_triggered_rules(response)
total_rules = sum(len(v) for v in rules.values())
# Log to file
with open("/Users/yourname/hooks/rules_usage.log", "a") as f:
f.write(f"\n{'='*60}\n")
f.write(f"Timestamp: {timestamp}\n")
f.write(f"Trajectory: {trajectory_id}\n")
f.write(f"Total rules triggered: {total_rules}\n")
for rule_type, rule_list in rules.items():
if rule_list:
f.write(f" {rule_type}: {', '.join(rule_list)}\n")
print(f"Tracked {total_rules} triggered rules")
except json.JSONDecodeError as e:
print(f"Error parsing JSON: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
Regeltypen:
Always On - Regeln, die immer aktiv sind
Model Decision - Regeln, deren Beschreibungen dem AI-Modell zur bedingten Anwendung angezeigt wurden
Manual - Regeln, die explizit per @-Mention in der Benutzereingabe erwähnt werden
Global - Globale Regeln aus global_rules.md
Glob - Regeln, die durch Dateizugriff mit passenden Glob-Mustern ausgelöst werden
Dies erfasst, welche Regeln dem AI-Modell präsentiert oder durch Dateizugriff ausgelöst wurden, zeigt aber nicht an, ob das AI-Modell einer Regel tatsächlich gefolgt ist. Regeln, die kürzlich bereits im Gespräch angezeigt wurden, werden dedupliziert (Duplikate entfernt) und erscheinen möglicherweise erst später erneut.
Code-Dateien automatisch formatieren, nachdem Cascade sie bearbeitet hat.
Konfiguration:
{
"hooks": {
"post_write_code": [
{
"command": "bash /Users/yourname/hooks/format_code.sh",
"show_output": false
}
]
}
}
Skript (format_code.sh):
#!/bin/bash
# Read JSON from stdin
input=$(cat)
# Extract file path using jq
file_path=$(echo "$input" | jq -r '.tool_info.file_path')
# Format based on file extension
if [[ "$file_path" == *.py ]]; then
black "$file_path" 2>&1
echo "Python-Datei formatiert: $file_path"
elif [[ "$file_path" == *.js ]] || [[ "$file_path" == *.ts ]]; then
prettier --write "$file_path" 2>&1
echo "Formatted JS/TS file: $file_path"
elif [[ "$file_path" == *.go ]]; then
gofmt -w "$file_path" 2>&1
echo "Formatted Go file: $file_path"
fi
exit 0
Dieser Hook führt nach jeder Bearbeitung automatisch den passenden Formatter je nach Dateityp aus.
Umgebungsdateien kopieren und Abhängigkeiten installieren, sobald ein neuer Worktree erstellt wird.
Konfiguration (in .windsurf/hooks.json):
{
"hooks": {
"post_setup_worktree": [
{
"command": "bash $ROOT_WORKSPACE_PATH/hooks/setup_worktree.sh",
"show_output": true
}
]
}
}
Skript (hooks/setup_worktree.sh):
#!/bin/bash
# Umgebungsdateien aus dem ursprünglichen Workspace kopieren
if [ -f "$ROOT_WORKSPACE_PATH/.env" ]; then
cp "$ROOT_WORKSPACE_PATH/.env" .env
echo "Copied .env file"
fi
if [ -f "$ROOT_WORKSPACE_PATH/.env.local" ]; then
cp "$ROOT_WORKSPACE_PATH/.env.local" .env.local
echo "Copied .env.local file"
fi
# Abhängigkeiten installieren
if [ -f "package.json" ]; then
npm install
echo "Installed npm dependencies"
fi
exit 0
Dieser Hook stellt sicher, dass für jeden Worktree automatisch die erforderliche Umgebungskonfiguration eingerichtet und die benötigten Abhängigkeiten installiert werden.
Verwenden Sie Cascade Hooks auf eigenes Risiko: Hooks führen Shell-Befehle automatisch mit den vollen Berechtigungen Ihres Benutzerkontos aus. Für den von Ihnen konfigurierten Code tragen Sie die volle Verantwortung. Schlecht konzipierte oder bösartige Hooks können Dateien verändern, Daten löschen, Anmeldedaten offenlegen oder Ihr System kompromittieren.
- Alle Eingaben validieren: Vertrauen Sie niemals dem Eingabe-JSON ohne Validierung, insbesondere bei Dateipfaden und Befehlen.
- Absolute Pfade verwenden: Verwenden Sie in Ihren Hook-Konfigurationen stets absolute Pfade, um Mehrdeutigkeiten zu vermeiden.
- Sensible Daten schützen: Vermeiden Sie das Protokollieren sensibler Informationen wie API-Schlüssel oder Anmeldedaten.
- Berechtigungen überprüfen: Stellen Sie sicher, dass Ihre Hook-Skripte geeignete Dateisystemberechtigungen haben.
- Vor der Bereitstellung prüfen: Überprüfen Sie jeden Hook-Befehl und jedes Skript, bevor Sie es Ihrer Konfiguration hinzufügen.
- Isoliert testen: Führen Sie Hooks zuerst in einer Testumgebung aus, bevor Sie sie auf Ihrem primären Entwicklungsrechner aktivieren.
- Hooks schnell halten: Langsame Hooks beeinträchtigen die Reaktionsfähigkeit von Cascade. Streben Sie Ausführungszeiten unter 100 ms an.
- Asynchrone Vorgänge nutzen: Für nicht blockierende Hooks sollten Protokollierungen asynchron in eine Warteschlange (Queue) oder eine Datenbank erfolgen.
- Früh filtern: Prüfen Sie den Aktionstyp gleich zu Beginn Ihres Skripts, um unnötige Verarbeitung zu vermeiden.
- JSON immer validieren: Verwenden Sie try-catch-Blöcke, um fehlerhafte Eingaben robust zu behandeln.
- Fehler korrekt protokollieren: Schreiben Sie Fehler auf
stderr, damit sie sichtbar sind, wenn show_output aktiviert ist.
- Sicher ausfallen: Wenn Ihr Hook auf einen Fehler stößt, prüfen Sie, ob er die Aktion blockieren oder sie fortsetzen lassen sollte.
- Mit Logging starten: Implementieren Sie zunächst einen einfachen Logging-Hook, um den Datenfluss nachzuvollziehen.
show_output: true verwenden: Aktivieren Sie während der Entwicklung die Ausgabe, um zu sehen, was Ihre Hooks machen.
- Blockierverhalten testen: Stellen Sie sicher, dass Exit-Code 2 Aktionen in Pre-Hooks ordnungsgemäß blockiert.
- Alle Codepfade prüfen: Testen Sie sowohl Erfolgs- als auch Fehlerfälle in Ihren Skripten.
Enterprise-Organisationen müssen Sicherheitsrichtlinien, Compliance-Anforderungen und Entwicklungsstandards durchsetzen, die von einzelnen Nutzern nicht umgangen werden können. Cascade Hooks unterstützt zwei Methoden der Enterprise-Verteilung:
- Cloud Dashboard – Konfigurieren Sie Hooks über die Team Settings im Windsurf-Dashboard
- System-Level Files – Verteilen Sie Hooks über MDM- oder Konfigurationsmanagement-Tools
Beide Methoden können gemeinsam verwendet werden – Hooks aus allen Quellen werden kombiniert und der Reihe nach ausgeführt.
Konfiguration im Cloud-Dashboard
Team-Administrator:innen können Cascade Hooks direkt über das Windsurf-Dashboard konfigurieren.
Voraussetzungen:
- Enterprise-Plan
TEAM_SETTINGS_UPDATE-Berechtigung
Vorgehensweise:
- Navigieren Sie im Windsurf-Dashboard zu Team Settings
- Suchen Sie den Abschnitt Cascade Hooks
- Geben Sie Ihre Hooks-Konfiguration im JSON-Format ein
- Speichern Sie Ihre Änderungen
Über das Dashboard konfigurierte Hooks werden automatisch an alle Teammitglieder verteilt und beim Start von Windsurf geladen. Cloud-konfigurierte Hooks werden zuerst geladen, gefolgt von systemweiten, benutzerspezifischen und Workspace-spezifischen Hooks.
Wenn mehrere Teamkonfigurationen zusammengeführt werden, werden Hooks pro Aktion kombiniert, anstatt überschrieben zu werden. Das bedeutet, dass Hooks aus allen zutreffenden Teamkonfigurationen gemeinsam ausgeführt werden.
Systemweite Dateibereitstellung
Für Organisationen, die eine dateibasierte Konfiguration bevorzugen oder Hooks offline verwenden müssen, stellen Sie Ihre verpflichtende hooks.json-Konfiguration an diesen betriebssystemspezifischen Speicherorten bereit:
macOS:
/Library/Application Support/Windsurf/hooks.json
Linux/WSL:
Windows:
C:\ProgramData\Windsurf\hooks.json
Legen Sie Ihre Hook-Skripte in ein entsprechendes Systemverzeichnis (z. B. /usr/local/share/windsurf-hooks/ auf Unix-Systemen).
Systemweite Hooks haben Vorrang vor Benutzer- und Workspace-Hooks und können von Endnutzern ohne Root-Rechte nicht deaktiviert werden.
MDM und Konfigurationsmanagement
Enterprise-IT-Teams können systemweite Hooks mit Standardtools bereitstellen:
Mobile Device Management (MDM)
- Jamf Pro (macOS) - Bereitstellung über Konfigurationsprofile oder Skripte
- Microsoft Intune (Windows/macOS) - per PowerShell-Skripten oder Richtlinienbereitstellung
- Workspace ONE, Google Endpoint Management und andere MDM-Lösungen
Konfigurationsmanagement
- Ansible, Puppet, Chef, SaltStack - Nutzen Sie Ihre bestehende Infrastrukturautomatisierung
- Benutzerdefinierte Bereitstellungsskripte - Shell-Skripte, PowerShell oder Ihre bevorzugten Tools
Verifizierung und Auditing
Nach der Bereitstellung prüfen, ob Hooks korrekt installiert sind:
# Verify system hooks are present
ls -la /etc/windsurf/hooks.json # Linux
ls -la "/Library/Application Support/Windsurf/hooks.json" # macOS
# Hook-Ausführung testen (Hook-Ausgabe sollte in Cascade sichtbar sein)
# Have a developer trigger the relevant Cascade action
# Verify users cannot modify system hooks
sudo chown root:root /etc/windsurf/hooks.json
sudo chmod 644 /etc/windsurf/hooks.json
Wichtig: Systemweite Hooks werden vollständig von Ihrem IT- oder Sicherheitsteam verwaltet. Windsurf installiert oder verwaltet keine Dateien in systemweiten Pfaden. Stellen Sie sicher, dass Ihre internen Teams Bereitstellung, Updates und Compliance gemäß den Richtlinien Ihrer Organisation übernehmen.
Workspace-Hooks für Teamprojekte
Für projektspezifische Konventionen können Teams Hooks auf Workspace-Ebene in der Versionsverwaltung verwenden:
# Add to your repository
.windsurf/
├── hooks.json
└── scripts/
└── format-check.py
# Commit to git
git add .windsurf/
git commit -m "Workspace-Hooks für Code-Formatierung hinzufügen"
So können Teams ihre Entwicklungspraktiken standardisieren. Belassen Sie sicherheitskritische Richtlinien auf Cloud- oder Systemebene, und vermeiden Sie es, sensible Informationen in die Versionsverwaltung einzuchecken.