Pular para o conteúdo principal

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.

Os Hooks do Cascade permitem executar comandos shell personalizados em pontos-chave do fluxo de trabalho do Cascade. Esse poderoso recurso de extensibilidade permite registrar operações, aplicar guardrails, executar verificações de validação ou integrar-se a sistemas externos.
Os hooks foram projetados para usuários avançados e equipes corporativas que precisam de controle detalhado sobre o comportamento do Cascade. Eles exigem conhecimento básico de shell scripting.

O que você pode criar

Hooks desbloqueiam uma ampla gama de recursos de automação e governança:
  • Logging & Analytics: Monitore cada arquivo lido, alteração de código, comando executado, prompt do usuário ou resposta do Cascade para fins de conformidade e análise de uso
  • Security Controls: Impeça o Cascade de acessar arquivos sensíveis, executar comandos perigosos ou processar prompts que violem políticas
  • Quality Assurance: Execute linters, formatadores ou testes automaticamente após modificações no código
  • Custom Workflows: Integre com rastreadores de problemas, sistemas de notificação ou pipelines de deployment
  • Team Standardization: Garanta padrões de código e boas práticas em toda a sua organização

Como os Hooks funcionam

Hooks são comandos de shell executados automaticamente quando determinadas ações do Cascade ocorrem. Cada hook:
  1. Recebe o contexto (detalhes sobre a ação em execução) via JSON na entrada padrão
  2. Executa seu script - Python, Bash, Node.js ou qualquer executável
  3. Retorna um resultado por meio do código de saída e dos fluxos de saída
Para pre-hooks (executados antes de uma ação), seu script pode bloquear a ação encerrando com o código de saída 2. Isso torna os pre-hooks ideais para implementar políticas de segurança ou verificações.

Configuração

Hooks são configurados em arquivos JSON que podem ser colocados em três níveis diferentes. O Cascade carrega e mescla, em cascata, os hooks de todos esses locais, dando às equipes flexibilidade para distribuir e gerenciar as configurações de hooks.

Nível do sistema

Hooks no nível do sistema são ideais para políticas válidas para toda a organização em máquinas de desenvolvimento compartilhadas. Por exemplo, você pode usá-los para aplicar políticas de segurança, requisitos de conformidade ou fluxos obrigatórios de revisão de código. As equipes Enterprise também podem configurar hooks pelo dashboard na nuvem sem precisar gerenciar arquivos locais.
  • macOS: /Library/Application Support/Windsurf/hooks.json
  • Linux/WSL: /etc/windsurf/hooks.json
  • Windows: C:\ProgramData\Windsurf\hooks.json

Nível de usuário

Os hooks no nível de usuário são ideais para preferências pessoais e workflows opcionais.
  • Devin Desktop IDE: ~/.codeium/windsurf/hooks.json
  • Plugin JetBrains: ~/.codeium/hooks.json

Nível do workspace

Os hooks no nível do workspace permitem que as equipes mantenham políticas específicas do projeto sob controle de versão junto com seu código. Eles podem incluir regras de validação personalizadas, integrações específicas do projeto ou workflows específicos da equipe.
  • Localização: .windsurf/hooks.json na raiz do seu workspace
Os hooks dos três locais são mesclados. Se o mesmo evento de hook estiver configurado em vários locais, todos os hooks serão executados em ordem: system → user → workspace.

Estrutura básica

Veja um exemplo da estrutura básica da configuração de hooks:
{
  "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
      }
    ]
  }
}
Neste exemplo, pre_read_code especifica tanto um comando para macOS/Linux quanto um comando do Windows PowerShell. O hook post_write_code especifica apenas command, então será executado em macOS/Linux e, no Windows, usará o PowerShell como alternativa.

Opções de configuração

Cada hook aceita os seguintes parâmetros:
ParâmetroTipoDescrição
commandstringO comando de shell a ser executado no macOS/Linux (via bash -c). É necessário especificar pelo menos um entre command e powershell.
powershellstringOpcional. O comando a ser executado no Windows (via powershell -Command). Se for omitido no Windows, command será usado como fallback.
show_outputbooleanIndica se a saída stdout/stderr do hook deve ser exibida na UI do Cascade voltada ao usuário. Útil para depuração.
working_directorystringOpcional. O diretório a partir do qual o comando será executado. O padrão é a raiz do seu workspace.

Comportamento em diferentes plataformas

Os campos command e powershell permitem definir comandos apropriados para cada plataforma em uma única configuração. Isso é útil para equipes com ambientes mistos de macOS/Linux e Windows.
Plataformacommand setpowershell setResultado
macOS/Linux(ignorado)Executa command via bash -c
macOS/LinuxO hook é ignorado sem aviso
WindowsUsa command como alternativa via powershell -Command
WindowsExecuta powershell via powershell -Command
WindowsExecuta powershell via powershell -Command
QualquerErro de validação
Sobre o parâmetro working_directory:
  • Em workspaces com vários repositórios, o padrão é a raiz do repo que está sendo usado no momento
  • Os caminhos relativos são resolvidos a partir do local padrão (workspace ou raiz do repo)
  • Há suporte a caminhos absolutos
  • Não há suporte ao uso de ~ para expandir o diretório home

Eventos de hook

O Cascade oferece doze eventos de hook que abrangem as ações mais importantes no fluxo de trabalho do agente.

Estrutura comum de entrada

Todos os hooks recebem um objeto JSON com os seguintes campos comuns:
CampoTipoDescrição
agent_action_namestringO nome do evento do hook (por exemplo, “pre_read_code”, “post_write_code”)
trajectory_idstringIdentificador exclusivo da conversa completa no Cascade
execution_idstringIdentificador exclusivo de uma única interação do agente
timestampstringTimestamp ISO 8601 de quando o hook foi acionado
model_namestringNome legível do modelo associado a esta invocação do hook (por exemplo, “Claude Sonnet 4”, “GPT 4.1”). Este é o mesmo rótulo exibido no seletor de modelos do Cascade. O valor pode mudar ao longo do tempo à medida que o Devin Desktop atualiza os nomes de exibição dos modelos. Definido como “Unknown” quando não for possível determinar o modelo.
tool_infoobjectInformações específicas do evento (variam conforme o tipo de hook)
Nos exemplos a seguir, os campos comuns foram omitidos por brevidade. Há doze tipos principais de eventos de hook:

pre_read_code

É acionado antes de o Cascade ler um arquivo de código. Isso pode bloquear a ação se o hook retornar o código 2. Casos de uso: Restringir o acesso a arquivos, registrar operações de leitura, verificar permissões JSON de entrada:
{
  "agent_action_name": "pre_read_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py"
  }
}
Este file_path pode ser o caminho de um diretório quando o Cascade lê um diretório recursivamente.

post_read_code

É acionado após o Cascade ler um arquivo de código com sucesso. Casos de uso: Registrar leituras bem-sucedidas, acompanhar padrões de acesso a arquivos JSON de entrada:
{
  "agent_action_name": "post_read_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py"
  }
}
Este file_path pode ser um caminho para um diretório quando o Cascade lê um diretório de forma recursiva.

pre_write_code

Acionado antes de o Cascade escrever ou modificar um arquivo de código. Isso pode bloquear a ação se o hook for encerrado com o código 2. Casos de uso: Impedir modificações em arquivos protegidos, fazer backup dos arquivos antes das alterações JSON de entrada:
{
  "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

Acionado após o Cascade escrever ou modificar um arquivo de código. Casos de uso: Executar linters, formatadores ou testes; registrar alterações no código JSON de entrada:
{
  "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

Acionado antes de o Cascade executar um comando no terminal. Isso pode bloquear a ação se o hook for encerrado com o código 2. Casos de uso: Bloquear comandos perigosos, registrar todas as execuções de comandos, adicionar verificações de segurança JSON de entrada:
{
  "agent_action_name": "pre_run_command",
  "tool_info": {
    "command_line": "npm install package-name",
    "cwd": "/Users/yourname/project"
  }
}

post_run_command

É acionado após o Cascade executar um comando de terminal. Casos de uso: Registrar resultados de comandos, acionar ações subsequentes JSON de entrada:
{
  "agent_action_name": "post_run_command",
  "tool_info": {
    "command_line": "npm install package-name",
    "cwd": "/Users/yourname/project"
  }
}

pre_mcp_tool_use

Acionado antes de o Cascade invocar uma ferramenta do MCP (Model Context Protocol). Isso pode bloquear a ação se o hook for encerrado com o código 2. Casos de uso: Registrar o uso de ferramentas MCP, restringir quais ferramentas MCP podem ser usadas JSON de entrada:
{
  "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

Acionado após o Cascade invocar com sucesso uma ferramenta MCP. Casos de uso: Registrar operações MCP, acompanhar o uso da API, ver os resultados do MCP JSON de entrada:
{
  "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

Acionado antes que o Cascade processe o texto do prompt de um usuário. Isso pode bloquear a ação se o hook terminar com o código 2. Casos de uso: Registrar todos os prompts dos usuários para auditoria; bloquear prompts potencialmente prejudiciais ou que violem políticas JSON de entrada:
{
  "agent_action_name": "pre_user_prompt",
  "tool_info": {
    "user_prompt": "can you run the echo hello command"
  }
}
A opção de configuração show_output não se aplica a este hook.

post_cascade_response

Acionado de forma assíncrona após o Cascade concluir uma resposta a um prompt do usuário. Este hook recebe a resposta completa do Cascade desde a última mensagem do usuário. Casos de uso: Registrar todas as respostas do Cascade para auditoria, analisar padrões de resposta, enviar respostas para sistemas externos para revisão de conformidade JSON de entrada:
{
  "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."
  }
}
O campo response contém o conteúdo em markdown da resposta do Cascade desde a última entrada do usuário. Isso inclui respostas do planner, ações de ferramentas (leituras e gravações de arquivos, além de comandos) e quaisquer outras etapas executadas pelo Cascade. Também inclui informações sobre quais regras foram acionadas. Consulte o exemplo Rastreamento de regras acionadas para ver como analisar o uso de regras. A opção de configuração show_output não se aplica a este hook.
O conteúdo de response é derivado de dados de trajetória e pode conter informações confidenciais da sua base de código ou das suas conversas. Trate esses dados de acordo com as políticas de segurança e privacidade da sua organização.

post_cascade_response_with_transcript

Acionado de forma assíncrona depois que o Cascade conclui uma resposta ao prompt de um usuário, semelhante a post_cascade_response. Em vez de fornecer um resumo em markdown inline, este hook grava a transcrição completa da conversa (desde o início da conversa) em um arquivo JSONL local e fornece o caminho do arquivo. Casos de uso: registro de auditoria e conformidade do Enterprise, rastreamento de contribuições geradas por IA, envio de transcrições para ferramentas externas de observabilidade ou análises JSON de entrada:
{
  "agent_action_name": "post_cascade_response_with_transcript",
  "tool_info": {
    "transcript_path": "/Users/yourname/.windsurf/transcripts/{trajectory_id}.jsonl"
  }
}
O transcript_path aponta para um arquivo JSONL em ~/.windsurf/transcripts/{trajectory_id}.jsonl. Cada linha é um objeto JSON que representa uma única etapa da conversa, com os campos type e status, além de dados específicos da etapa. Por exemplo:
{"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"}
A transcrição inclui dados detalhados do cliente, como conteúdo de arquivos, saídas de comandos, argumentos de ferramentas, resultados de pesquisa e regras aplicadas. Observe que a estrutura exata de cada etapa pode mudar em versões futuras, portanto, crie qualquer consumidor de hook para ser resiliente. Os arquivos de transcrição são gravados com permissões 0600. O Devin Desktop limita automaticamente o diretório de transcrições a 100 arquivos, removendo os mais antigos com base na data de modificação. A opção de configuração show_output não se aplica a este hook. Esta tabela mostra as principais diferenças entre os hooks post_cascade_response e post_cascade_response_with_transcript:
post_cascade_responsepost_cascade_response_with_transcript
Escopo dos dadosApenas as etapas desde a última entrada do usuárioToda a conversa desde o início
FormatoResumo em Markdown em tool_info.responseArquivo JSONL estruturado em tool_info.transcript_path
Nível de detalheResumo condensado, legível por humanosDados detalhados, legíveis por máquina (conteúdo de arquivos, saídas de comandos etc.)
EntregaInline, via JSON na stdinArquivo em disco (~/.windsurf/transcripts/)
Os arquivos de transcrição conterão informações confidenciais da sua base de código, incluindo conteúdo de arquivos, saídas de comandos e histórico da conversa. Trate esses arquivos de acordo com as políticas de segurança e privacidade da sua organização.

post_setup_worktree

Acionado após a criação e configuração de um novo git worktree. O hook é executado dentro do novo diretório worktree. Casos de uso: Copiar arquivos .env ou outros arquivos não rastreados para o worktree, instalar dependências, executar scripts de configuração Variáveis de ambiente:
VariávelDescrição
$ROOT_WORKSPACE_PATHO caminho absoluto para o workspace original. Use-o para acessar arquivos ou executar comandos em relação ao repositório original.
JSON de entrada:
{
  "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"
  }
}

Códigos de saída

Seus scripts de hook comunicam os resultados por meio de códigos de saída:
Código de saídaSignificadoEfeito
0SucessoA ação prossegue normalmente
2Erro bloqueanteO agente Cascade verá a mensagem de erro na stderr. Para pre-hooks, isso bloqueia a ação.
Qualquer outroErroA ação prossegue normalmente
Somente pre-hooks (pre_user_prompt, pre_read_code, pre_write_code, pre_run_command, pre_mcp_tool_use) podem bloquear ações usando o código de saída 2. Post-hooks não podem bloquear, pois a ação já ocorreu.
Lembre-se de que o usuário pode ver qualquer saída padrão e erro padrão gerados pelos hooks na UI do Cascade se show_output estiver definido como true.

Exemplos de casos de uso

Registro de todas as ações do Cascade

Acompanhe todas as ações realizadas pelo Cascade para fins de auditoria. Config:
{
  "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():
    # Lê os dados JSON da entrada padrão (stdin)
    input_data = sys.stdin.read()
    
    # Faz o parse do JSON
    try:
        data = json.loads(input_data)
        
        # Grava o JSON formatado no arquivo
        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()
Este script adiciona cada invocação de hook a um arquivo de log, criando uma trilha de auditoria de todas as ações do Cascade. Você pode transformar os dados de entrada ou executar lógica personalizada como preferir.

Restringir o acesso a arquivos

Impeça que o Cascade leia arquivos fora de um diretório específico. Configuração:
{
  "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():
    # Lê os dados JSON da entrada padrão (stdin)
    input_data = sys.stdin.read()

    # Analisa o 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)  # Código de saída 2 bloqueia a ação
            
            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 o Cascade tenta ler um arquivo fora do diretório permitido, esse hook bloqueia a operação e exibe uma mensagem de erro.

Bloqueio de comandos perigosos

Impeça o Cascade de executar comandos potencialmente perigosos. Config:
{
  "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():
    # Lê os dados JSON da entrada padrão (stdin)
    input_data = sys.stdin.read()

    # Faz o parse do 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)  # Código de saída 2 bloqueia o 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()
Este hook faz uma varredura nos comandos em busca de padrões perigosos e os bloqueia antes da execução.

Bloqueio de prompts que violam políticas

Impede que os usuários enviem prompts que violem as políticas organizacionais. Config:
{
  "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():
    # Lê os dados JSON da entrada padrão (stdin)
    input_data = sys.stdin.read()

    # Faz o parse do 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)  # Código de saída 2 bloqueia o prompt

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

if __name__ == "__main__":
    main()
Este hook examina os prompts do usuário antes do processamento e bloqueia os que contêm padrões proibidos. Quando um prompt é bloqueado, o usuário vê uma mensagem de erro na UI do Cascade.

Registro das respostas do Cascade

Registre todas as respostas do Cascade para auditoria de conformidade ou análises. Configuração:
{
  "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():
    # Lê os dados JSON da entrada padrão (stdin)
    input_data = sys.stdin.read()

    # Faz o parse do 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 em arquivo
            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()
Esse hook registra cada resposta do Cascade em um arquivo, criando uma trilha de auditoria de todo o conteúdo gerado por IA. Você pode expandi-lo para enviar dados a sistemas externos de logs, bancos de dados ou plataformas de conformidade.

Monitorando Regras acionadas

Acompanhe quais regras foram aplicadas durante as interações no Cascade para observabilidade e métricas. Configuração:
{
  "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:
    """
    Analisa as regras acionadas a partir da resposta do Cascade.
    As regras aparecem como: - (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())

            # Registrar em arquivo
            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()
Tipos de regras:
  • Always On - regras sempre incluídas
  • Model Decision - regras cujas descrições foram mostradas ao modelo para aplicação condicional
  • Manual - regras explicitamente mencionadas com @ na entrada do usuário
  • Global - regras globais de global_rules.md
  • Glob - regras acionadas pelo acesso a arquivos que correspondem a padrões glob
Isso rastreia quais regras foram apresentadas ao modelo ou acionadas pelo acesso a arquivos, mas não indica se o modelo realmente seguiu uma regra. regras que já foram mostradas recentemente na conversa são deduplicadas e podem não aparecer novamente até mais tarde.

Executar formatadores de código após alterações

Formate automaticamente os arquivos de código depois que o Cascade os modificar. Configuração:
{
  "hooks": {
    "post_write_code": [
      {
        "command": "bash /Users/yourname/hooks/format_code.sh",
        "show_output": false
      }
    ]
  }
}
Script (format_code.sh):
#!/bin/bash

# Lê JSON da entrada padrão
input=$(cat)

# Extrai o caminho do arquivo usando jq
file_path=$(echo "$input" | jq -r '.tool_info.file_path')

# Formata com base na extensão do arquivo
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
Este hook executa automaticamente o formatador adequado com base no tipo de arquivo após cada edição.

Configurando worktrees

Copie os arquivos de ambiente e instale as dependências quando uma nova worktree for criada. Configuração (em .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

# Copiar arquivos de ambiente do workspace original
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

# Instalar dependências
if [ -f "package.json" ]; then
    npm install
    echo "Installed npm dependencies"
fi

exit 0
Este hook garante que cada worktree tenha a configuração de ambiente necessária e que as dependências sejam instaladas automaticamente.

Boas práticas

Segurança

Use Cascade Hooks por sua conta e risco: Hooks executam comandos de shell automaticamente com todas as permissões da sua conta de usuário. Você é totalmente responsável pelo código que configurar. Hooks mal projetados ou maliciosos podem modificar arquivos, excluir dados, expor credenciais ou comprometer seu sistema.
  • Valide todos os dados de entrada: Nunca confie no JSON de entrada sem validá-lo, especialmente em caminhos de arquivos e comandos.
  • Use caminhos absolutos: Sempre use caminhos absolutos nas configurações de hook para evitar ambiguidades.
  • Proteja dados sensíveis: Evite registrar em log informações sensíveis, como Chaves de API ou credenciais.
  • Revise as permissões: Garanta que seus scripts de hook tenham as permissões apropriadas no sistema de arquivos.
  • Audite antes da implantação: Revise cada comando e script de hook antes de adicioná-los à sua configuração.
  • Teste de forma isolada: Execute Hooks em um ambiente de teste antes de habilitá-los na sua máquina principal de desenvolvimento.

Considerações de desempenho

  • Mantenha os hooks rápidos: Hooks lentos afetam a capacidade de resposta do Cascade. Procure manter o tempo de execução abaixo de 100 ms.
  • Use operações assíncronas: Para hooks não bloqueantes, considere registrar logs em uma fila ou banco de dados de forma assíncrona.
  • Filtre logo no início: Verifique o tipo de ação no começo do script para evitar processamento desnecessário.

Tratamento de erros

  • Sempre valide o JSON: Use blocos try-catch para lidar com entradas inválidas sem causar falhas.
  • Registre os erros corretamente: Grave os erros em stderr para que fiquem visíveis quando show_output estiver ativado.
  • Falhe com segurança: Se o seu hook encontrar um erro, avalie se ele deve bloquear a ação ou permitir que ela continue.

Testando seus Hooks

  1. Comece com logging: Comece implementando um hook simples de logging para entender o fluxo de dados.
  2. Use show_output: true: Ative a saída durante o desenvolvimento para ver o que seus hooks estão fazendo.
  3. Teste o comportamento de bloqueio: Verifique se o código de saída 2 bloqueia corretamente as ações em pre-hooks.
  4. Verifique todos os fluxos de execução: Teste tanto os cenários de sucesso quanto os de falha nos seus scripts.

Distribuição Enterprise

As organizações Enterprise precisam impor políticas de segurança, requisitos de conformidade e padrões de desenvolvimento que usuários individuais não podem burlar. O Hooks do Cascade oferece suporte a dois métodos de distribuição Enterprise:
  1. dashboard na nuvem - Configure hooks por meio de Configurações da equipe no dashboard do Devin Desktop
  2. Arquivos em nível de sistema - Implante hooks por meio de ferramentas de MDM ou de gerenciamento de configurações
Os dois métodos podem ser usados em conjunto — hooks de todas as fontes são combinados e executados em ordem.

Configuração do Dashboard na Nuvem

Os admins da equipe podem configurar os Hooks do Cascade diretamente no dashboard do Devin Desktop. Requisitos:
  • plano Enterprise
  • permissão TEAM_SETTINGS_UPDATE
Para configurar:
  1. Acesse Configurações da equipe no dashboard do Devin Desktop
  2. Localize a seção Hooks do Cascade
  3. Insira a configuração dos hooks no formato JSON
  4. Salve suas alterações
Os hooks configurados pelo dashboard são distribuídos automaticamente para todos os membros da equipe e carregados quando o Devin Desktop é iniciado. Os hooks configurados na nuvem são carregados primeiro, seguidos pelos hooks no nível do sistema, do usuário e do workspace.
Quando várias configurações de equipe são mescladas, os hooks são combinados por GitHub Action em vez de serem sobrescritos. Isso significa que os hooks de todas as configurações de equipe aplicáveis serão executados juntos.

Implantação de arquivos em nível de sistema

Para organizações que preferem configuração por arquivo ou precisam que os hooks funcionem offline, implante a configuração obrigatória de hooks.json nestes locais específicos de cada sistema operacional: macOS:
/Library/Application Support/Windsurf/hooks.json
Linux/WSL:
/etc/windsurf/hooks.json
Windows:
C:\ProgramData\Windsurf\hooks.json
Coloque seus scripts de hook no diretório de sistema correspondente (por exemplo, /usr/local/share/windsurf-hooks/ em sistemas Unix). Hooks em nível de sistema têm precedência sobre hooks de usuário e de workspace, e não podem ser desativados por usuários finais sem permissões de root.

MDM e gerenciamento de configuração

As equipes de TI corporativa podem implantar hooks no nível do sistema usando ferramentas padrão: Gerenciamento de Dispositivos Móveis (MDM)
  • Jamf Pro (macOS) - Implante por meio de perfis de configuração ou scripts
  • Microsoft Intune (Windows/macOS) - Use scripts do PowerShell ou políticas de implantação
  • Workspace ONE, Google Endpoint Management e outras soluções de MDM
Gerenciamento de configuração
  • Ansible, Puppet, Chef, SaltStack - Use a automação de infraestrutura existente
  • Scripts de implantação personalizados - Scripts de shell, PowerShell ou a ferramenta de sua preferência

Verificação e auditoria

Após a implantação, verifique se os hooks foram instalados corretamente:
# Verificar se os hooks do sistema estão presentes
ls -la /etc/windsurf/hooks.json  # Linux
ls -la "/Library/Application Support/Windsurf/hooks.json"  # macOS

# Testar a execução do hook (a saída do hook deve aparecer no Cascade)
# Peça a um desenvolvedor para acionar a ação relevante no Cascade

# Verificar se os usuários não podem modificar os hooks do sistema
sudo chown root:root /etc/windsurf/hooks.json
sudo chmod 644 /etc/windsurf/hooks.json
Importante: Os hooks em nível de sistema são de responsabilidade exclusiva da sua equipe de TI ou de segurança. O Devin Desktop não implanta nem gerencia arquivos em caminhos de sistema. Garanta que suas equipes internas cuidem da implantação, das atualizações e da conformidade de acordo com as políticas da sua organização.

Hooks de workspace para projetos do Team

Para convenções específicas de cada projeto, as equipes podem usar hooks em nível de workspace no controle de versão:
# Adicione ao seu repositório
.windsurf/
├── hooks.json
└── scripts/
    └── format-check.py

# Faça commit no git
git add .windsurf/
git commit -m "Add workspace hooks for code formatting"
Isso permite que as equipes padronizem as práticas de desenvolvimento. Mantenha as políticas essenciais para a segurança no nível da nuvem ou do sistema e evite versionar informações sensíveis.

Recursos adicionais