Guias

Hooks em todo agente de IA para programação: Claude Code, Cursor, Gemini CLI, GitHub Copilot, Kiro e Factory Droid (2026)

Onde ficam os hooks em cada agente de IA para programação, e como um hook bloqueia um comando?

O Claude Code lê um bloco hooks em .claude/settings.json, o Gemini CLI um bloco hooks em .gemini/settings.json, o Cursor lê .cursor/hooks.json, o Factory Droid .factory/hooks.json, o GitHub Copilot .github/hooks/*.json e o Kiro qualquer arquivo JSON em .kiro/hooks/. Todos enviam o evento ao seu script como JSON no stdin. Para bloquear uma chamada de ferramenta, saia com código 2 no Claude Code, Cursor, Gemini CLI, Factory Droid e na Kiro CLI, ou imprima uma decisão deny em JSON (o Copilot usa permissionDecision, o Cursor usa permission).

Esta página é uma tradução do guia em inglês. Comandos, chaves de configuração e código não foram alterados; em caso de diferença, vale a versão em inglês. Ler em inglês → · Outros idiomas: 简体中文 · 日本語 · 한국어 · Español

Saiba quando a configuração mudar

Quando uma configuração, flag ou regra de permissão dessas ferramentas mudar, você recebe um e-mail semanal (em inglês), conferido na documentação oficial.

Resposta rápida: locais dos arquivos de hooks

  • Claude Code: uma chave hooks em .claude/settings.json (projeto) ou ~/.claude/settings.json (usuário). /hooks mostra o que está configurado.
  • Cursor: .cursor/hooks.json (projeto) ou ~/.cursor/hooks.json (usuário), com "version": 1. Hooks enterprise e de equipe ficam acima de ambos.
  • Gemini CLI: uma chave hooks em .gemini/settings.json (projeto), ~/.gemini/settings.json (usuário) ou /etc/gemini-cli/settings.json (sistema).
  • GitHub Copilot: .github/hooks/*.json para o cloud agent e o Copilot CLI, além de ~/.copilot/hooks/ para a CLI. "version": 1.
  • Kiro: qualquer arquivo .json em .kiro/hooks/ (workspace) ou ~/.kiro/hooks/ (global, CLI V3), com "version": "v1".
  • Factory Droid: .factory/hooks.json (projeto) ou ~/.factory/hooks.json (usuário). /hooks abre o gerenciador de hooks.

Como um hook bloqueia uma chamada de ferramenta

  • Claude Code: um hook PreToolUse que sai com 2 bloqueia a ação e envia seu stderr de volta como motivo.
  • Cursor: saia com 2, ou imprima {"permission": "deny"}. Qualquer outro código diferente de zero falha aberto, a menos que o hook defina failClosed: true.
  • Gemini CLI: saia com 0 e imprima {"decision": "deny", "reason": "..."} (o jeito preferido), ou saia com 2 com o motivo no stderr. Outros códigos só geram aviso.
  • GitHub Copilot: um hook preToolUse imprime {"permissionDecision": "deny", "permissionDecisionReason": "..."}. Não fazer nada permite a chamada.
  • Kiro: na CLI, sair com 2 bloqueia o PreToolUse. Na IDE, qualquer saída diferente de zero bloqueia um hook Pre Tool Use.
  • Factory Droid: sair com 2 no PreToolUse bloqueia a chamada de ferramenta. Outros códigos diferentes de zero são registrados e o Droid continua.

Mesma ideia, nomes de eventos diferentes

  • Antes de uma ferramenta rodar: PreToolUse (Claude Code, Kiro, Factory Droid), preToolUse e beforeShellExecution (Cursor), BeforeTool (Gemini CLI), preToolUse (Copilot).
  • Depois de uma ferramenta rodar: PostToolUse (Claude Code, Kiro, Factory Droid), postToolUse e afterFileEdit (Cursor), AfterTool (Gemini CLI), postToolUse (Copilot).
  • Início da sessão: SessionStart (Claude Code, Kiro, Factory Droid, Gemini CLI), sessionStart (Cursor, Copilot).
  • Agente terminou: Stop (Kiro, Factory Droid), stop (Cursor), agentStop (Copilot).
  • Prompt enviado: UserPromptSubmit (Kiro, Factory Droid), beforeSubmitPrompt (Cursor), userPromptSubmitted (Copilot).

Mesmo hook, quatro sintaxes

Claude Code: .claude/settings.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

Cursor: .cursor/hooks.json

{
  "version": 1,
  "hooks": {
    "beforeShellExecution": [
      {
        "command": ".cursor/hooks/block-risky.sh",
        "matcher": "rm -rf|curl|wget"
      }
    ]
  }
}

Gemini CLI: .gemini/settings.json

{
  "hooks": {
    "BeforeTool": [
      {
        "matcher": "write_file|replace",
        "hooks": [
          {
            "name": "security-check",
            "type": "command",
            "command": "$GEMINI_PROJECT_DIR/.gemini/hooks/security.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}

Kiro: .kiro/hooks/guard-shell.json

{
  "version": "v1",
  "hooks": [
    {
      "name": "Guard shell commands",
      "trigger": "PreToolUse",
      "matcher": "shell",
      "action": {
        "type": "command",
        "command": "./scripts/guard.sh"
      }
    }
  ]
}

Pegadinhas

  • O stdout do Gemini CLI deve conter só o JSON final. JSON inválido é tratado como allow.
  • O Gemini CLI avisa antes de rodar um hook de projeto cujo nome ou comando mudou, por exemplo depois de um git pull.
  • O Copilot passa toolArgs como uma string JSON, então faça o parse duas vezes. O cloud agent trata uma decisão "ask" como "deny" e só carrega hooks da branch padrão.
  • Os hooks de projeto do Cursor rodam a partir da raiz do projeto e os de usuário a partir de ~/.cursor/, então caminhos relativos de scripts são diferentes.
  • As ações de agent prompt do Kiro iniciam um novo loop do agente e consomem créditos. As ações de shell command não.
  • Os matchers do Factory Droid são regex sensíveis a maiúsculas e minúsculas. Use commandRegex para filtrar chamadas Execute pelo texto do comando.

Guia completo de hooks para cada agente

Fontes

Documentação oficial (em inglês) usada para conferir este guia. Versão em inglês revisada em: 2026-10-18

Mais guias em português