Vai al contenuto principale

Documentation Index

Fetch the complete documentation index at: https://docs.devin.ai/llms.txt

Use this file to discover all available pages before exploring further.

Gli hook di Cascade ti consentono di eseguire comandi shell personalizzati nei punti chiave del flusso di lavoro di Cascade. Questa potente funzionalità di estensione ti permette di registrare le operazioni, applicare barriere di sicurezza, eseguire controlli di convalida o integrarti con sistemi esterni.
Gli hook sono pensati per utenti esperti e team aziendali che necessitano di un controllo granulare sul comportamento di Cascade. Richiedono conoscenze di base di scripting shell.

Cosa puoi creare

Hooks offrono un’ampia gamma di funzionalità di automazione e governance:
  • Logging e analisi: Tieni traccia di ogni file letto, modifica al codice, comando eseguito, prompt dell’utente o risposta di Cascade ai fini della conformità e dell’analisi dell’utilizzo
  • Controlli di sicurezza: Impedisci a Cascade di accedere a file sensibili, eseguire comandi pericolosi o elaborare prompt che violano le policy
  • Controllo qualità: Esegui automaticamente linter, formatter o test dopo le modifiche al codice
  • Flussi di lavoro personalizzati: Integrali con tracker di issue, sistemi di notifica o pipeline di distribuzione
  • Standardizzazione del team: Applica standard di codifica e best practice in tutta l’organizzazione

Come funzionano gli Hooks

Gli hook sono comandi shell che vengono eseguiti automaticamente quando si verificano specifiche azioni di Cascade. Ogni hook:
  1. Riceve il contesto (i dettagli dell’azione in esecuzione) tramite JSON come input standard
  2. Esegue il tuo script - Python, Bash, Node.js o qualsiasi altro eseguibile
  3. Restituisce un risultato tramite il codice di uscita e i flussi di output
Per i pre-hook (eseguiti prima di un’azione), il tuo script può bloccare l’azione terminando con il codice di uscita 2. Questo rende i pre-hook ideali per implementare policy di sicurezza o controllo di convalida.

Configurazione

Gli hook si configurano in file JSON che possono essere collocati a tre livelli diversi. Cascade carica e unisce gli hook da tutte queste posizioni, offrendo ai team flessibilità nel modo in cui distribuiscono e gestiscono le configurazioni degli hook.

A livello di sistema

Gli hook a livello di sistema sono ideali per applicare policy valide per l’intera organizzazione su macchine di sviluppo condivise. Ad esempio, puoi usarli per imporre policy di sicurezza, requisiti di conformità o flussi di lavoro obbligatori per la revisione del codice. I team Enterprise possono anche configurare gli hook tramite la dashboard cloud senza dover gestire file locali.
  • macOS: /Library/Application Support/Windsurf/hooks.json
  • Linux/WSL: /etc/windsurf/hooks.json
  • Windows: C:\ProgramData\Windsurf\hooks.json

A livello utente

Gli hook a livello utente sono ideali per preferenze personali e flussi di lavoro opzionali.
  • Devin Desktop IDE: ~/.codeium/windsurf/hooks.json
  • Plugin JetBrains: ~/.codeium/hooks.json

A livello di workspace

Gli hook a livello di workspace consentono ai team di tenere sotto controllo di versione le policy specifiche del progetto insieme al codice. Possono includere regole di convalida personalizzate, integrazioni specifiche del progetto o flussi di lavoro specifici del team.
  • Posizione: .windsurf/hooks.json nella radice del workspace
Gli hook di tutte e tre le posizioni vengono combinati. Se lo stesso evento hook è configurato in più posizioni, tutti gli hook verranno eseguiti nell’ordine seguente: sistema → utente → workspace.

Struttura di base

Ecco un esempio della struttura di base della configurazione degli hook:
{
  "hooks": {
    "pre_read_code": [
      {
        "command": "python3 /path/to/your/script.py",
        "powershell": "python3 C:\\path\\to\\your\\script.py",
        "show_output": true
      }
    ],
    "post_write_code": [
      {
        "command": "python3 /path/to/another/script.py",
        "show_output": true
      }
    ]
  }
}
In questo esempio, pre_read_code specifica sia un comando per macOS/Linux sia un comando PowerShell per Windows. L’hook post_write_code specifica solo command, quindi verrà eseguito su macOS/Linux e su Windows userà PowerShell come soluzione di fallback.

Opzioni di configurazione

Ogni hook accetta i seguenti parametri:
ParametroTipoDescrizione
commandstringIl comando shell da eseguire su macOS/Linux (eseguito tramite bash -c). Deve essere specificato almeno uno tra command e powershell.
powershellstringFacoltativo. Il comando da eseguire su Windows (eseguito tramite powershell -Command). Se omesso su Windows, command viene usato come fallback.
show_outputbooleanIndica se visualizzare l’output stdout/stderr dell’hook nella UI di Cascade rivolta all’utente. Utile per il debug.
working_directorystringFacoltativo. La directory da cui eseguire il comando. Per impostazione predefinita, è la radice del workspace.

Comportamento multipiattaforma

I campi command e powershell consentono di definire, in un’unica configurazione, comandi appropriati per ciascuna piattaforma. Questo è utile per i team con parchi macchine misti macOS/Linux e Windows.
Piattaformacommand impostatopowershell impostatoRisultato
macOS/Linux(ignorato)Esegue command tramite bash -c
macOS/LinuxL’hook viene ignorato senza alcun avviso
WindowsUsa command come fallback tramite powershell -Command
WindowsEsegue powershell tramite powershell -Command
WindowsEsegue powershell tramite powershell -Command
QualsiasiErrore di convalida
Informazioni sul parametro working_directory:
  • Nei workspace multi-repo, il valore predefinito è la radice del repo su cui si sta lavorando
  • I percorsi relativi vengono risolti a partire dalla posizione predefinita (workspace o radice del repo)
  • I percorsi assoluti sono supportati
  • L’uso di ~ per espandere la home directory non è supportato

Eventi hook

Cascade offre dodici eventi hook che coprono le azioni più importanti nel flusso di lavoro dell’agente.

Struttura di input comune

Tutti gli hook ricevono un oggetto JSON con i seguenti campi comuni:
CampoTipoDescrizione
agent_action_namestringIl nome dell’evento hook (ad es. “pre_read_code”, “post_write_code”)
trajectory_idstringIdentificatore univoco dell’intera conversazione Cascade
execution_idstringIdentificatore univoco del singolo turno dell’agente
timestampstringTimestamp ISO 8601 che indica quando è stato attivato l’hook
model_namestringNome leggibile del modello associato a questa invocazione dell’hook (ad es. “Claude Sonnet 4”, “GPT 4.1”). È la stessa etichetta mostrata nel selettore dei modelli di Cascade. Il valore può cambiare nel tempo man mano che Devin Desktop aggiorna i nomi visualizzati dei modelli. È impostato su “Unknown” quando non è possibile determinare il modello.
tool_infoobjectInformazioni specifiche dell’evento (variano in base al tipo di hook)
Negli esempi seguenti, i campi comuni sono omessi per brevità. Esistono dodici tipi principali di eventi hook:

pre_read_code

Si attiva prima che Cascade legga un file di codice. Può bloccare l’azione se l’hook termina con il codice 2. Casi d’uso: limitare l’accesso ai file, registrare le operazioni di lettura, verificare le autorizzazioni JSON di input:
{
  "agent_action_name": "pre_read_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py"
  }
}
Questo file_path può essere il percorso di una directory quando Cascade legge una directory in modo ricorsivo.

post_read_code

Si attiva dopo che Cascade ha letto correttamente un file di codice. Casi d’uso: registrare le letture riuscite, monitorare gli schemi di accesso ai file JSON di input:
{
  "agent_action_name": "post_read_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py"
  }
}
Questo file_path può essere il percorso di una directory quando Cascade legge una directory in modo ricorsivo.

pre_write_code

Si attiva prima che Cascade scriva o modifichi un file di codice. Può bloccare l’azione se l’hook termina con il codice 2. Casi d’uso: impedire modifiche ai file protetti, eseguire il backup dei file prima delle modifiche JSON di input:
{
  "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"
      }
    ]
  }
}

post_write_code

Attivato dopo che Cascade scrive o modifica un file di codice. Casi d’uso: Run di linter, formatter o test; registra le modifiche al codice JSON di input:
{
  "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"
      }
    ]
  }
}

pre_run_command

Si attiva prima che Cascade esegua un comando nel terminale. Può bloccare l’action se l’hook termina con il codice 2. Casi d’uso: Bloccare comandi pericolosi, registrare tutte le esecuzioni dei comandi, aggiungere controlli di sicurezza JSON di input:
{
  "agent_action_name": "pre_run_command",
  "tool_info": {
    "command_line": "npm install package-name",
    "cwd": "/Users/yourname/project"
  }
}

post_run_command

Si attiva dopo che Cascade esegue un comando nel terminale. Casi d’uso: registrare i risultati dei comandi, attivare azioni successive JSON di input:
{
  "agent_action_name": "post_run_command",
  "tool_info": {
    "command_line": "npm install package-name",
    "cwd": "/Users/yourname/project"
  }
}

pre_mcp_tool_use

Si attiva prima che Cascade invochi uno strumento MCP (Model Context Protocol). Può bloccare l’azione se l’hook termina con il codice 2. Casi d’uso: Registrare l’utilizzo degli strumenti MCP, limitare quali strumenti MCP possono essere usati JSON di input:
{
  "agent_action_name": "pre_mcp_tool_use",
  "tool_info": {
    "mcp_server_name": "github",
    "mcp_tool_arguments": {
      "owner": "code-owner",
      "repo": "my-cool-repo",
      "title": "Bug report",
      "body": "Description of the bug here"
    },
    "mcp_tool_name": "create_issue"
  }
}

post_mcp_tool_use

Si attiva dopo che Cascade invoca con successo uno strumento MCP. Casi d’uso: Registrare le operazioni MCP, monitorare l’utilizzo dell’API, visualizzare i risultati MCP JSON di input:
{
  "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"
  }
}

pre_user_prompt

Attivato prima che Cascade elabori il testo del prompt di un utente. Questo può bloccare l’azione se l’hook termina con il codice 2. Casi d’uso: registrare tutti i prompt degli utenti a fini di audit, bloccare prompt potenzialmente dannosi o in violazione delle policy JSON di input:
{
  "agent_action_name": "pre_user_prompt",
  "tool_info": {
    "user_prompt": "can you run the echo hello command"
  }
}
L’opzione di configurazione show_output non è applicabile a questo hook.

post_cascade_response

Attivato in modo asincrono dopo che Cascade ha completato una risposta al prompt di un utente. Questo hook riceve l’intera risposta di Cascade successiva all’ultimo input dell’utente. Casi d’uso: Registrare tutte le risposte di Cascade a fini di audit, analizzare i pattern delle risposte, inviare le risposte a sistemi esterni per la revisione della conformità JSON di input:
{
  "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."
  }
}
Il campo response contiene il contenuto in formato Markdown della risposta di Cascade dall’ultimo input dell’utente. Include le risposte del planner, le azioni degli strumenti (letture e scritture di file, comandi) e qualsiasi altro passaggio eseguito da Cascade. Include anche informazioni su quali regole sono state attivate. Consulta l’esempio Tracking Triggered Rules per capire come analizzare l’utilizzo delle regole. L’opzione di configurazione show_output non si applica a questo hook.
Il contenuto di response è derivato dai dati della traiettoria e può contenere informazioni sensibili provenienti dalla tua codebase o dalle tue conversazioni. Gestisci questi dati in conformità con le politiche di sicurezza e privacy della tua organizzazione.

post_cascade_response_with_transcript

Attivato in modo asincrono dopo che Cascade ha completato una risposta al prompt dell’utente, in modo simile a post_cascade_response. Invece di fornire un riepilogo markdown inline, questo hook scrive la trascrizione completa della conversazione (dall’inizio della conversazione) in un file JSONL locale e ne fornisce il percorso. Casi d’uso: registrazione per audit e conformità in ambito Enterprise, monitoraggio dei contributi generati dall’IA, invio delle trascrizioni a strumenti esterni di osservabilità o analisi JSON di input:
{
  "agent_action_name": "post_cascade_response_with_transcript",
  "tool_info": {
    "transcript_path": "/Users/yourname/.windsurf/transcripts/{trajectory_id}.jsonl"
  }
}
Il transcript_path punta a un file JSONL in ~/.windsurf/transcripts/{trajectory_id}.jsonl. Ogni riga contiene un oggetto JSON che rappresenta un singolo passaggio della conversazione, con i campi type e status, oltre ai dati specifici del passaggio. Ad esempio:
{"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"}
La trascrizione include dati dettagliati di proprietà del cliente, come contenuti dei file, output dei comandi, argomenti dei tool, risultati di ricerca e regole applicate. Nota che la struttura esatta di ogni passaggio potrebbe cambiare nelle versioni future, quindi assicurati che gli eventuali consumer degli hook siano robusti a queste variazioni. I file di trascrizione vengono scritti con autorizzazioni 0600. Devin Desktop limita automaticamente la directory delle trascrizioni a 100 file, eliminando i più vecchi in base alla data di modifica. L’opzione di configurazione show_output non si applica a questo hook. Questa tabella mostra le principali differenze tra gli hook post_cascade_response e post_cascade_response_with_transcript:
post_cascade_responsepost_cascade_response_with_transcript
Ambito dei datiSolo i passaggi dall’ultimo input dell’utenteL’intera conversazione dall’inizio
FormatoRiepilogo Markdown in tool_info.responseFile JSONL strutturato in tool_info.transcript_path
Livello di dettaglioRiepilogo condensato, leggibile dagli esseri umaniDati dettagliati leggibili dalla macchina (contenuti dei file, output dei comandi, ecc.)
ConsegnaInline tramite JSON su stdinFile su disco (~/.windsurf/transcripts/)
I file di trascrizione conterranno informazioni sensibili della tua codebase, inclusi contenuti dei file, output dei comandi e cronologia della conversazione. Gestisci questi file in conformità con le policy di sicurezza e privacy della tua organizzazione.

post_setup_worktree

Si attiva dopo la creazione e la configurazione di un nuovo git worktree. L’hook viene eseguito all’interno della directory del nuovo worktree. Casi d’uso: Copiare file .env o altri file non tracciati nel worktree, installare dipendenze, eseguire script di setup Variabili d’ambiente:
VariabileDescrizione
$ROOT_WORKSPACE_PATHIl percorso assoluto del workspace originale. Usalo per accedere ai file o eseguire comandi relativi al repository originale.
JSON di input:
{
  "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"
  }
}

Codici di uscita

I tuoi script hook comunicano i risultati tramite i codici di uscita:
Codice di uscitaSignificatoEffetto
0SuccessoL’action procede normalmente
2Errore bloccanteL’agent Cascade vedrà il messaggio di errore da stderr. Per i pre-hook, questo blocca l’action.
Qualsiasi altroErroreL’action procede normalmente
Solo i pre-hook (pre_user_prompt, pre_read_code, pre_write_code, pre_run_command, pre_mcp_tool_use) possono bloccare le action usando il codice di uscita 2. I post-hook non possono bloccare l’esecuzione, perché l’action è già avvenuta.
Tieni presente che, se show_output è true, l’utente può vedere nella UI di Cascade qualsiasi output standard o errore standard generato da un hook.

Esempi di casi d’uso

Registrazione di tutte le azioni di Cascade

Monitora ogni azione eseguita da Cascade a fini di audit. Configurazione:
{
  "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"
      }
    ]
  }
}
Script (log_input.py):
#!/usr/bin/env python3

import sys
import json

def main():
    # Leggi i dati JSON da stdin
    input_data = sys.stdin.read()
    
    # Analizza il JSON
    try:
        data = json.loads(input_data)
        
        # Scrivi il JSON formattato su 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"Error parsing JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
Questo script aggiunge ogni invocazione di hook a un file di log, creando una traccia di controllo di tutte le azioni di Cascade. Puoi trasformare i dati di input o applicare una logica personalizzata, come ritieni opportuno.

Limitare l’accesso ai file

Impedisci a Cascade di leggere file al di fuori di una directory specifica. configurazione:
{
  "hooks": {
    "pre_read_code": [
      {
        "command": "python3 /Users/yourname/hooks/block_read_access.py",
        "show_output": true
      }
    ]
  }
}
Script (block_read_access.py):
#!/usr/bin/env python3

import sys
import json

ALLOWED_PREFIX = "/Users/yourname/my-project/"

def main():
    # Leggi i dati JSON da stdin
    input_data = sys.stdin.read()

    # Analizza il JSON
    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"Access denied: Cascade is only allowed to read files under {ALLOWED_PREFIX}", file=sys.stderr)
                sys.exit(2)  # Il codice di uscita 2 blocca l'action
            
            print(f"Access granted: {file_path}", file=sys.stdout)

    except json.JSONDecodeError as e:
        print(f"Error parsing JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
Quando Cascade tenta di leggere un file al di fuori della directory consentita, questo hook blocca l’operazione e visualizza un messaggio di errore.

Blocco dei comandi pericolosi

Impedisci a Cascade di eseguire comandi potenzialmente pericolosi. Configurazione:
{
  "hooks": {
    "pre_run_command": [
      {
        "command": "python3 /Users/yourname/hooks/block_dangerous_commands.py",
        "show_output": true
      }
    ]
  }
}
Script (block_dangerous_commands.py):
#!/usr/bin/env python3

import sys
import json

DANGEROUS_COMMANDS = ["rm -rf", "sudo rm", "format", "del /f"]

def main():
    # Leggi i dati JSON da stdin
    input_data = sys.stdin.read()

    # Analizza il 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 blocked: '{dangerous_cmd}' is not allowed for safety reasons.", file=sys.stderr)
                    sys.exit(2)  # Il codice di uscita 2 blocca il comando
            
            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()
Questo hook analizza i comandi per individuare pattern pericolosi e li blocca prima dell’esecuzione.

Blocco dei prompt che violano le policy

Impedisci agli utenti di inviare prompt che violano le policy dell’organizzazione. Configurazione:
{
  "hooks": {
    "pre_user_prompt": [
      {
        "command": "python3 /Users/yourname/hooks/block_bad_prompts.py"
      }
    ]
  }
}
Script (block_bad_prompts.py):
#!/usr/bin/env python3

import sys
import json

BLOCKED_PATTERNS = [
    "something dangerous",
    "bypass security",
    "ignore previous instructions"
]

def main():
    # Leggi i dati JSON da stdin
    input_data = sys.stdin.read()

    # Analizza il JSON
    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)  # Il codice di uscita 2 blocca il prompt

    except json.JSONDecodeError as e:
        print(f"Error parsing JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
Questo hook esamina i prompt dell’utente prima che vengano elaborati e blocca quelli che contengono pattern non consentiti. Quando un prompt viene bloccato, l’utente vede un messaggio di errore nella UI di Cascade.

Registrazione delle risposte di Cascade

Registra tutte le risposte di Cascade per verifiche di conformità o analisi. Configurazione:
{
  "hooks": {
    "post_cascade_response": [
      {
        "command": "python3 /Users/yourname/hooks/log_cascade_response.py"
      }
    ]
  }
}
Script (log_cascade_response.py):
#!/usr/bin/env python3

import sys
import json
from datetime import datetime

def main():
    # Leggi i dati JSON da stdin
    input_data = sys.stdin.read()

    # Analizza il JSON
    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())

            # Registra su file
            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()
Questo hook registra ogni risposta di Cascade in un file, creando una traccia di controllo di tutti i contenuti generati dall’IA. Puoi estenderlo per inviare i dati a sistemi di logging esterni, database o piattaforme di conformità.

Tracciamento delle regole attivate

Monitora quali regole vengono applicate durante le interazioni con Cascade, per l’osservabilità e le metriche. Configurazione:
{
  "hooks": {
    "post_cascade_response": [
      {
        "command": "python3 /Users/yourname/hooks/track_rules.py"
      }
    ]
  }
}
Script (track_rules.py):
#!/usr/bin/env python3

import sys
import json
import re
from datetime import datetime

def extract_triggered_rules(response: str) -> dict:
    """
    Parse triggered rules from the Cascade response.
    Rules appear as: - (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())

            # Scrivi nel file di log
            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()
Tipi di regole:
  • Always On - Regole sempre incluse
  • Model Decision - Regole le cui descrizioni sono state mostrate al modello per un’applicazione condizionale
  • Manual - Regole menzionate esplicitamente con @ nell’input dell’utente
  • Global - Regole globali da global_rules.md
  • Glob - Regole attivate dall’accesso a file che corrispondono a pattern glob
Questo tiene traccia di quali regole sono state presentate al modello o attivate dall’accesso ai file, ma non indica se il modello abbia effettivamente seguito una regola. Le regole già mostrate di recente nella conversazione vengono deduplicate e potrebbero non comparire di nuovo fino a più avanti.

Eseguire i formattatori del codice dopo le modifiche

Formatta automaticamente i file di codice dopo che Cascade li ha modificati. Configurazione:
{
  "hooks": {
    "post_write_code": [
      {
        "command": "bash /Users/yourname/hooks/format_code.sh",
        "show_output": false
      }
    ]
  }
}
Script (format_code.sh):
#!/bin/bash

# Leggi JSON da stdin
input=$(cat)

# Estrai il percorso del file usando jq
file_path=$(echo "$input" | jq -r '.tool_info.file_path')

# Formatta in base all'estensione del file
if [[ "$file_path" == *.py ]]; then
    black "$file_path" 2>&1
    echo "Formatted Python file: $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
Questo hook applica automaticamente il formatter appropriato in base al tipo di file dopo ogni modifica.

Configurazione dei worktree

Copia i file dell’ambiente e installa le dipendenze quando viene creato un nuovo worktree. Config (in .windsurf/hooks.json):
{
  "hooks": {
    "post_setup_worktree": [
      {
        "command": "bash $ROOT_WORKSPACE_PATH/hooks/setup_worktree.sh",
        "show_output": true
      }
    ]
  }
}
Script (hooks/setup_worktree.sh):
#!/bin/bash

# Copia i file environment dal workspace originale
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

# Installa le dependencies
if [ -f "package.json" ]; then
    npm install
    echo "Installed npm dependencies"
fi

exit 0
Questo hook garantisce che ogni worktree disponga automaticamente della configurazione dell’ambiente necessaria e delle dipendenze richieste.

Buone pratiche

Sicurezza

Usa Cascade Hooks a tuo rischio e pericolo: gli hook eseguono automaticamente comandi shell con tutte le autorizzazioni del tuo account utente. Sei interamente responsabile del codice che configuri. Hook progettati male o dannosi possono modificare file, eliminare dati, esporre credenziali o compromettere il sistema.
  • Convalida tutti gli input: non fidarti mai dell’input JSON senza prima convalidarlo, soprattutto per quanto riguarda i percorsi dei file e i comandi.
  • Usa percorsi assoluti: usa sempre percorsi assoluti nelle configurazioni degli hook per evitare ambiguità.
  • Proteggi i dati sensibili: evita di registrare informazioni sensibili come API key o credenziali.
  • Verifica le autorizzazioni: assicurati che gli script degli hook abbiano autorizzazioni del file system appropriate.
  • Controlla prima della distribuzione: controlla ogni comando e script degli hook prima di aggiungerli alla configurazione.
  • Testa in isolamento: esegui gli hook in un ambiente di test prima di abilitarli sulla macchina di sviluppo principale.

Considerazioni sulle prestazioni

  • Mantieni gli hook veloci: gli hook lenti riducono la reattività di Cascade. Punta a tempi di esecuzione inferiori a 100 ms.
  • Usa operazioni asincrone: per hook non bloccanti, valuta la possibilità di inviare i log a una coda o a un database in modo asincrono.
  • Filtra subito: verifica il tipo di action all’inizio dello script per evitare elaborazioni non necessarie.

Gestione degli errori

  • Verifica sempre il JSON: Usa blocchi try-catch per gestire correttamente input non validi.
  • Registra correttamente gli errori: Scrivi gli errori su stderr in modo che siano visibili quando show_output è abilitato.
  • Gestisci gli errori in modo sicuro: Se il tuo hook incontra un errore, valuta se debba bloccare l’action o consentirle di proseguire.

Test dei tuoi hook

  1. Inizia con il logging: inizia implementando un semplice hook di logging per comprendere il flusso dei dati.
  2. Usa show_output: true: abilita l’output durante lo sviluppo per vedere cosa stanno facendo i tuoi hook.
  3. Testa il comportamento di blocco: verifica che il codice di uscita 2 blocchi correttamente le azioni nei pre-hook.
  4. Verifica tutti i percorsi del codice: testa nei tuoi script sia gli scenari di successo sia quelli di errore.

Distribuzione Enterprise

Le organizzazioni Enterprise devono applicare policy di sicurezza, requisiti di conformità e standard di sviluppo che i singoli utenti non possono aggirare. Cascade Hooks supporta due metodi di distribuzione Enterprise:
  1. Cloud Dashboard - Configura gli hook tramite Team Settings nella dashboard di Devin Desktop
  2. File a livello di sistema - Distribuisci gli hook tramite MDM o strumenti di gestione della configurazione
Entrambi i metodi possono essere usati insieme — gli hook da tutte le origini vengono combinati ed eseguiti in ordine.

Configurazione della Cloud Dashboard

Gli admin del team possono configurare i Cascade Hooks direttamente dalla dashboard di Devin Desktop. Requisiti:
  • piano Enterprise
  • autorizzazione TEAM_SETTINGS_UPDATE
Per configurare:
  1. Vai a Team Settings nella dashboard di Devin Desktop
  2. Individua la sezione Cascade Hooks
  3. Inserisci la configurazione degli hook in formato JSON
  4. Salva le modifiche
Gli hook configurati tramite la dashboard vengono distribuiti automaticamente a tutti i membri del team e caricati all’avvio di Devin Desktop. Gli hook configurati nel cloud vengono caricati per primi, seguiti da quelli a livello di sistema, utente e workspace.
Quando vengono unite più configurazioni del team, gli hook vengono combinati per action anziché essere sovrascritti. Ciò significa che gli hook di tutte le configurazioni del team applicabili verranno eseguiti insieme.

Distribuzione dei file a livello di sistema

Per le organizzazioni che preferiscono una configurazione basata su file o hanno bisogno che gli hook funzionino offline, distribuisci la configurazione obbligatoria hooks.json nelle seguenti posizioni specifiche del sistema operativo: macOS:
/Library/Application Support/Windsurf/hooks.json
Linux/WSL:
/etc/windsurf/hooks.json
Windows:
C:\ProgramData\Windsurf\hooks.json
Colloca gli script hook nella directory di sistema corrispondente (ad es. /usr/local/share/windsurf-hooks/ sui sistemi Unix). Gli hook a livello di sistema hanno la precedenza su quelli dell’utente e del workspace e non possono essere disabilitati dagli utenti finali senza autorizzazioni di root.

MDM e gestione della configurazione

I team IT Enterprise possono distribuire hook a livello di sistema utilizzando strumenti standard: Mobile Device Management (MDM)
  • Jamf Pro (macOS) - Distribuzione tramite profili di configurazione o script
  • Microsoft Intune (Windows/macOS) - Usa script PowerShell o la distribuzione tramite criteri
  • Workspace ONE, Google Endpoint Management e altre soluzioni MDM
Gestione della configurazione
  • Ansible, Puppet, Chef, SaltStack - Usa l’automazione dell’infrastruttura esistente
  • Script di distribuzione personalizzati - Script shell, PowerShell o gli strumenti che preferisci

Verifica e audit

Dopo la distribuzione, verifica che gli hook siano installati correttamente:
# Verifica che gli hook di sistema siano presenti
ls -la /etc/windsurf/hooks.json  # Linux
ls -la "/Library/Application Support/Windsurf/hooks.json"  # macOS

# Testa l'esecuzione degli hook (l'output degli hook dovrebbe essere visibile in Cascade)
# Chiedi a uno sviluppatore di attivare l'action pertinente di Cascade

# Verifica che gli utenti non possano modificare gli hook di sistema
sudo chown root:root /etc/windsurf/hooks.json
sudo chmod 644 /etc/windsurf/hooks.json
Importante: Gli hook a livello di sistema sono gestiti interamente dal team IT o di sicurezza. Devin Desktop non distribuisce né gestisce file nei percorsi di sistema. Assicurati che i team interni si occupino della distribuzione, degli aggiornamenti e della conformità in base alle policy della tua organizzazione.

Hook del workspace per i progetti del team

Per convenzioni specifiche di progetto, i team possono usare hook a livello di workspace nel controllo di versione:
# Aggiungi al tuo repository
.windsurf/
├── hooks.json
└── scripts/
    └── format-check.py

# Esegui il commit su git
git add .windsurf/
git commit -m "Add workspace hooks for code formatting"
Questo consente ai team di standardizzare le pratiche di sviluppo. Mantieni le policy critiche per la sicurezza a livello di cloud o di sistema ed evita di archiviare informazioni sensibili nel sistema di controllo versione.

Risorse aggiuntive