> ## 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.

# Hooks do Cascade

> Execute comandos shell personalizados em pontos-chave do fluxo de trabalho do Cascade para logging, controles de segurança, validação e governança empresarial com pre-hooks e post-hooks.

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.

<Note>
  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.
</Note>

<div id="what-you-can-build">
  ## O que você pode criar
</div>

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

<div id="how-hooks-work">
  ## Como os Hooks funcionam
</div>

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.

<div id="configuration">
  ## Configuração
</div>

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.

<div id="system-level">
  #### Nível do sistema
</div>

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](#cloud-dashboard-configuration) sem precisar gerenciar arquivos locais.

* **macOS**: `/Library/Application Support/Windsurf/hooks.json`
* **Linux/WSL**: `/etc/windsurf/hooks.json`
* **Windows**: `C:\ProgramData\Windsurf\hooks.json`

<div id="user-level">
  #### Nível de usuário
</div>

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`

<div id="workspace-level">
  #### Nível do workspace
</div>

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

<Note>
  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.
</Note>

<div id="basic-structure">
  ### Estrutura básica
</div>

Veja um exemplo da estrutura básica da configuração de hooks:

```json theme={null}
{
  "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.

<div id="configuration-options">
  ### Opções de configuração
</div>

Cada hook aceita os seguintes parâmetros:

| Parâmetro           | Tipo    | Descrição                                                                                                                                      |
| ------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `command`           | string  | O comando de shell a ser executado no **macOS/Linux** (via `bash -c`). É necessário especificar pelo menos um entre `command` e `powershell`.  |
| `powershell`        | string  | Opcional. O comando a ser executado no **Windows** (via `powershell -Command`). Se for omitido no Windows, `command` será usado como fallback. |
| `show_output`       | boolean | Indica se a saída stdout/stderr do hook deve ser exibida na UI do Cascade voltada ao usuário. Útil para depuração.                             |
| `working_directory` | string  | Opcional. O diretório a partir do qual o comando será executado. O padrão é a raiz do seu workspace.                                           |

<div id="cross-platform-behavior">
  #### Comportamento em diferentes plataformas
</div>

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.

| Plataforma  | `command` set | `powershell` set | Resultado                                                |
| ----------- | :-----------: | :--------------: | -------------------------------------------------------- |
| macOS/Linux |       ✓       |    (ignorado)    | Executa `command` via `bash -c`                          |
| macOS/Linux |       ✗       |         ✓        | O hook é ignorado sem aviso                              |
| Windows     |       ✓       |         ✗        | Usa `command` como alternativa via `powershell -Command` |
| Windows     |       ✗       |         ✓        | Executa `powershell` via `powershell -Command`           |
| Windows     |       ✓       |         ✓        | Executa `powershell` via `powershell -Command`           |
| Qualquer    |       ✗       |         ✗        | Erro de validação                                        |

<Note>
  **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
</Note>

<div id="hook-events">
  ## Eventos de hook
</div>

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

<div id="common-input-structure">
  ### Estrutura comum de entrada
</div>

Todos os hooks recebem um objeto JSON com os seguintes campos comuns:

| Campo               | Tipo   | Descrição                                                                                                                                                                                                                                                                                                                                                |
| ------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `agent_action_name` | string | O nome do evento do hook (por exemplo, "pre\_read\_code", "post\_write\_code")                                                                                                                                                                                                                                                                           |
| `trajectory_id`     | string | Identificador exclusivo da conversa completa no Cascade                                                                                                                                                                                                                                                                                                  |
| `execution_id`      | string | Identificador exclusivo de uma única interação do agente                                                                                                                                                                                                                                                                                                 |
| `timestamp`         | string | Timestamp ISO 8601 de quando o hook foi acionado                                                                                                                                                                                                                                                                                                         |
| `model_name`        | string | Nome 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_info`         | object | Informaçõ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:

<div id="pre_read_code">
  ### pre\_read\_code
</div>

É 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**:

```json theme={null}
{
  "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.

<div id="post_read_code">
  ### post\_read\_code
</div>

É 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**:

```json theme={null}
{
  "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.

<div id="pre_write_code">
  ### pre\_write\_code
</div>

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**:

```json theme={null}
{
  "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"
      }
    ]
  }
}
```

<div id="post_write_code">
  ### post\_write\_code
</div>

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**:

```json theme={null}
{
  "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"
      }
    ]
  }
}
```

<div id="pre_run_command">
  ### pre\_run\_command
</div>

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**:

```json theme={null}
{
  "agent_action_name": "pre_run_command",
  "tool_info": {
    "command_line": "npm install package-name",
    "cwd": "/Users/yourname/project"
  }
}
```

<div id="post_run_command">
  ### post\_run\_command
</div>

É acionado **após** o Cascade executar um comando de terminal.

**Casos de uso**: Registrar resultados de comandos, acionar ações subsequentes

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "post_run_command",
  "tool_info": {
    "command_line": "npm install package-name",
    "cwd": "/Users/yourname/project"
  }
}
```

<div id="pre_mcp_tool_use">
  ### pre\_mcp\_tool\_use
</div>

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**:

```json theme={null}
{
  "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"
  }
}
```

<div id="post_mcp_tool_use">
  ### post\_mcp\_tool\_use
</div>

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**:

```json theme={null}
{
  "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"
  }
}
```

<div id="pre_user_prompt">
  ### pre\_user\_prompt
</div>

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**:

```json theme={null}
{
  "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.

<div id="post_cascade_response">
  ### post\_cascade\_response
</div>

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**:

```json theme={null}
{
  "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](/pt-BR/desktop/cascade/memories) foram acionadas. Consulte o exemplo [Rastreamento de regras acionadas](#tracking-triggered-rules) para ver como analisar o uso de regras.

A opção de configuração `show_output` não se aplica a este hook.

<Warning>
  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.
</Warning>

<div id="post_cascade_response_with_transcript">
  ### post\_cascade\_response\_with\_transcript
</div>

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**:

```json theme={null}
{
  "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](https://jsonlines.org/) 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:

```jsonl theme={null}
{"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](/pt-BR/desktop/cascade/memories) 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_response`                            | `post_cascade_response_with_transcript`                                                |
| -------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------- |
| **Escopo dos dados** | Apenas as etapas desde a última entrada do usuário | Toda a conversa desde o início                                                         |
| **Formato**          | Resumo em Markdown em `tool_info.response`         | Arquivo JSONL estruturado em `tool_info.transcript_path`                               |
| **Nível de detalhe** | Resumo condensado, legível por humanos             | Dados detalhados, legíveis por máquina (conteúdo de arquivos, saídas de comandos etc.) |
| **Entrega**          | Inline, via JSON na stdin                          | Arquivo em disco (`~/.windsurf/transcripts/`)                                          |

<Warning>
  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.
</Warning>

<div id="post_setup_worktree">
  ### post\_setup\_worktree
</div>

Acionado **após** a criação e configuração de um novo [git worktree](./worktrees). 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ável               | Descrição                                                                                                                          |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `$ROOT_WORKSPACE_PATH` | O caminho absoluto para o workspace original. Use-o para acessar arquivos ou executar comandos em relação ao repositório original. |

**JSON de entrada**:

```json theme={null}
{
  "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"
  }
}
```

<div id="exit-codes">
  ## Códigos de saída
</div>

Seus scripts de hook comunicam os resultados por meio de códigos de saída:

| Código de saída | Significado     | Efeito                                                                                        |
| --------------- | --------------- | --------------------------------------------------------------------------------------------- |
| `0`             | Sucesso         | A ação prossegue normalmente                                                                  |
| `2`             | Erro bloqueante | O agente Cascade verá a mensagem de erro na stderr. Para pre-hooks, isso **bloqueia** a ação. |
| Qualquer outro  | Erro            | A ação prossegue normalmente                                                                  |

<Warning>
  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.
</Warning>

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.

<div id="example-use-cases">
  ## Exemplos de casos de uso
</div>

<div id="logging-all-cascade-actions">
  ### Registro de todas as ações do Cascade
</div>

Acompanhe todas as ações realizadas pelo Cascade para fins de auditoria.

**Config**:

```json theme={null}
{
  "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`):

```python theme={null}
#!/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.

<div id="restricting-file-access">
  ### Restringir o acesso a arquivos
</div>

Impeça que o Cascade leia arquivos fora de um diretório específico.

**Configuração**:

```json theme={null}
{
  "hooks": {
    "pre_read_code": [
      {
        "command": "python3 /Users/yourname/hooks/block_read_access.py",
        "show_output": true
      }
    ]
  }
}
```

**Script** (`block_read_access.py`):

```python theme={null}
#!/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.

<div id="blocking-dangerous-commands">
  ### Bloqueio de comandos perigosos
</div>

Impeça o Cascade de executar comandos potencialmente perigosos.

**Config**:

```json theme={null}
{
  "hooks": {
    "pre_run_command": [
      {
        "command": "python3 /Users/yourname/hooks/block_dangerous_commands.py",
        "show_output": true
      }
    ]
  }
}
```

**Script** (`block_dangerous_commands.py`):

```python theme={null}
#!/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.

<div id="blocking-policy-violating-prompts">
  ### Bloqueio de prompts que violam políticas
</div>

Impede que os usuários enviem prompts que violem as políticas organizacionais.

**Config**:

```json theme={null}
{
  "hooks": {
    "pre_user_prompt": [
      {
        "command": "python3 /Users/yourname/hooks/block_bad_prompts.py"
      }
    ]
  }
}
```

**Script** (`block_bad_prompts.py`):

```python theme={null}
#!/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.

<div id="logging-cascade-responses">
  ### Registro das respostas do Cascade
</div>

Registre todas as respostas do Cascade para auditoria de conformidade ou análises.

**Configuração**:

```json theme={null}
{
  "hooks": {
    "post_cascade_response": [
      {
        "command": "python3 /Users/yourname/hooks/log_cascade_response.py"
      }
    ]
  }
}
```

**Script** (`log_cascade_response.py`):

```python theme={null}
#!/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.

<div id="tracking-triggered-rules">
  ### Monitorando Regras acionadas
</div>

Acompanhe quais [regras](/pt-BR/desktop/cascade/memories) foram aplicadas durante as interações no Cascade para observabilidade e métricas.

**Configuração**:

```json theme={null}
{
  "hooks": {
    "post_cascade_response": [
      {
        "command": "python3 /Users/yourname/hooks/track_rules.py"
      }
    ]
  }
}
```

**Script** (`track_rules.py`):

```python theme={null}
#!/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

<Note>
  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.
</Note>

<div id="running-code-formatters-after-edits">
  ### Executar formatadores de código após alterações
</div>

Formate automaticamente os arquivos de código depois que o Cascade os modificar.

**Configuração**:

```json theme={null}
{
  "hooks": {
    "post_write_code": [
      {
        "command": "bash /Users/yourname/hooks/format_code.sh",
        "show_output": false
      }
    ]
  }
}
```

**Script** (`format_code.sh`):

```bash theme={null}
#!/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.

<div id="setting-up-worktrees">
  ### Configurando worktrees
</div>

Copie os arquivos de ambiente e instale as dependências quando uma nova worktree for criada.

**Configuração** (em `.windsurf/hooks.json`):

```json theme={null}
{
  "hooks": {
    "post_setup_worktree": [
      {
        "command": "bash $ROOT_WORKSPACE_PATH/hooks/setup_worktree.sh",
        "show_output": true
      }
    ]
  }
}
```

**Script** (`hooks/setup_worktree.sh`):

```bash theme={null}
#!/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.

<div id="best-practices">
  ## Boas práticas
</div>

<div id="security">
  ### Segurança
</div>

<Warning>
  **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.
</Warning>

* **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.

<div id="performance-considerations">
  ### Considerações de desempenho
</div>

* **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.

<div id="error-handling">
  ### Tratamento de erros
</div>

* **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.

<div id="testing-your-hooks">
  ### Testando seus Hooks
</div>

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.

<div id="enterprise-distribution">
  ## Distribuição Enterprise
</div>

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.

<div id="cloud-dashboard-configuration">
  ### Configuração do Dashboard na Nuvem
</div>

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.

<Note>
  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.
</Note>

<div id="system-level-file-deployment">
  ### Implantação de arquivos em nível de sistema
</div>

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.

<div id="mdm-and-configuration-management">
  #### MDM e gerenciamento de configuração
</div>

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

<div id="verification-and-auditing">
  #### Verificação e auditoria
</div>

Após a implantação, verifique se os hooks foram instalados corretamente:

```bash theme={null}
# 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
```

<Note>
  **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.
</Note>

<div id="workspace-hooks-for-team-projects">
  ### Hooks de workspace para projetos do Team
</div>

Para convenções específicas de cada projeto, as equipes podem usar hooks em nível de workspace no controle de versão:

```bash theme={null}
# 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.

<div id="additional-resources">
  ## Recursos adicionais
</div>

* **Integração com MCP**: Saiba mais sobre o [Model Context Protocol no Devin Desktop](/pt-BR/desktop/cascade/mcp)
* **Fluxos de trabalho**: Veja como combinar hooks com os [Cascade Workflows](/pt-BR/desktop/cascade/workflows)
* **Análises**: Acompanhe o uso do Cascade com as [Análises da equipe](/pt-BR/desktop/accounts/analytics)
