códigomadrugada

claude-codeia.netprodutividade

Claude Code hooks: automatize tarefas no seu projeto .NET

Hooks do Claude Code disparam scripts quando o agente edita ou executa algo. Configure dotnet format, dotnet test e bloqueios de segurança no seu projeto .NET.

Terminal exibindo hooks do Claude Code rodando dotnet format automaticamente em projeto .NET de madrugada
Código da Madrugada30 de maio de 20266 min de leitura

Você usa o Claude Code pra editar um endpoint, e aí precisa formatar o código, verificar se o teste ainda passa e anotar que arquivo mudou. Toda vez. Manualmente. É trabalho que o agente poderia disparar sozinho enquanto você já está lendo o próximo problema.

Hooks fazem exatamente isso.

O que são hooks

Hooks são scripts que o Claude Code executa automaticamente em resposta a eventos do próprio agente. Quando ele edita um arquivo, roda um comando Bash, ou termina uma sessão, um hook pode disparar antes, depois, ou bloquear a ação completamente.

Diferente do CLAUDE.md, que é instrução em linguagem natural, hooks são automação real: código que roda no seu ambiente, com acesso ao sistema de arquivos, ao SDK e aos seus comandos de CI.

A documentação oficial de hooks lista todos os eventos disponíveis. Para o dia a dia de um dev .NET, os dois mais úteis são PreToolUse (antes de agir, pode bloquear) e PostToolUse (depois de agir, para reagir à mudança).

Onde configurar

A configuração fica em .claude/settings.json na raiz do projeto (o mesmo arquivo onde você define permissões). Você pode commitar esse arquivo com o repositório; o time inteiro recebe os hooks automaticamente.

A estrutura básica:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/meu-script.sh"
          }
        ]
      }
    ]
  }
}

Três coisas pra entender aqui. matcher filtra para quais ferramentas o hook roda. "Edit|Write" significa "quando o Claude Code usar Edit ou Write". O campo command aponta para o script. E ${CLAUDE_PROJECT_DIR} é uma variável que o Claude Code expande pra raiz do projeto, então o path é portável mesmo que o repo esteja em lugares diferentes em máquinas diferentes.

O hook recebe o contexto da ferramenta via stdin como JSON:

{
  "hook_event_name": "PostToolUse",
  "tool_name": "Edit",
  "tool_input": {
    "file_path": "/caminho/para/Pedido.cs",
    "old_string": "...",
    "new_string": "..."
  }
}

Com jq você lê qualquer campo desse JSON no script.

Aprenda Claude Code do jeito certo

Curso completo para devs C# .NET: hooks, CLAUDE.md, sub-agentes e workflows reais.

Ver cursos

Quatro hooks práticos para projetos .NET

1. Formatar código automaticamente após edições

Todo projeto .NET deveria ter .editorconfig com as regras do time. Mas aplicar o formato manualmente depois que o Claude Code edita um arquivo é chato. Um hook PostToolUse faz isso por você:

#!/bin/bash
# .claude/hooks/format-after-edit.sh
FILE=$(jq -r '.tool_input.file_path // empty' < /dev/stdin)

if [[ "$FILE" == *.cs ]]; then
  dotnet format --include "$FILE" --verbosity quiet 2>/dev/null || true
fi

No settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/format-after-edit.sh"
          }
        ]
      }
    ]
  }
}

O || true no final garante que uma falha no dotnet format não quebre o hook e trave o agente. Importante: dê permissão de execução ao script antes de testar (chmod +x .claude/hooks/format-after-edit.sh).

2. Rodar testes quando um arquivo de teste muda

Quando o Claude Code edita um *Tests.cs, faz sentido checar se os testes ainda passam antes de continuar. Mas você não quer rodar a suite inteira a cada edição de qualquer arquivo. Só quando um teste mudou:

#!/bin/bash
# .claude/hooks/test-on-change.sh
FILE=$(jq -r '.tool_input.file_path // empty' < /dev/stdin)

if [[ "$FILE" == *Tests.cs ]] || [[ "$FILE" == *Test.cs ]]; then
  echo "Arquivo de teste modificado, rodando dotnet test..."
  dotnet test --no-build --verbosity minimal 2>&1
fi

Aqui o output do dotnet test aparece no terminal enquanto o Claude Code espera. Se os testes falharem, o agente vê o resultado antes de continuar. Pode usar essa informação na próxima resposta se você perguntar.

Só que tem um detalhe: se sua suite demora mais de 20-30 segundos, o hook trava o fluxo. Pra suites longas, vale rodar só o projeto de testes do arquivo que mudou ou adicionar --filter pra reduzir o escopo.

3. Bloquear comandos destrutivos

PreToolUse roda antes da ferramenta agir. Se o script retornar permissionDecision: "deny", o Claude Code cancela a ação e explica por quê. Útil pra criar uma lista de comandos que nunca podem rodar no projeto, independente do que o agente decida:

#!/bin/bash
# .claude/hooks/block-destructive.sh
COMMAND=$(jq -r '.tool_input.command // empty' < /dev/stdin)

if echo "$COMMAND" | grep -qE 'rm -rf|DROP TABLE|DELETE FROM .+WHERE 1=1'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Comando destrutivo bloqueado pelo hook de segurança do projeto. Revise manualmente antes de executar."
    }
  }'
else
  exit 0
fi

No settings.json, esse hook vai em PreToolUse com matcher: "Bash":

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-destructive.sh"
          }
        ]
      }
    ]
  }
}

Isso não substitui backup e permissões de infra. Mas elimina o caso em que o agente interpreta mal um pedido e tenta deletar algo que não devia.

4. Registrar quais arquivos foram modificados

Em projetos com code review, saber o que o Claude Code tocou numa sessão ajuda. Um hook simples que mantém um log de edições:

#!/bin/bash
# .claude/hooks/audit-log.sh
INPUT=$(cat /dev/stdin)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty')

if [[ -n "$FILE" ]]; then
  echo "$(date '+%Y-%m-%d %H:%M:%S') | $TOOL | $FILE" >> "${CLAUDE_PROJECT_DIR}/.claude/edit-log.txt"
fi

O .claude/edit-log.txt acumula entradas como:

2026-05-30 02:14:33 | Edit | /projeto/src/Api/Controllers/PedidoController.cs
2026-05-30 02:14:51 | Write | /projeto/src/Application/DTOs/PedidoDto.cs

Esse arquivo fica no .gitignore. É ephemeral por sessão, não artefato do repo.

Cuidados pra não travar o fluxo

Hooks síncronos bloqueiam o agente. Por padrão, o Claude Code espera o hook terminar antes de continuar. Um dotnet test de 45 segundos significa 45 segundos parado. Se o hook for de monitoramento e não precisar bloquear, use "async": true na configuração.

Exit codes importam. Exit 0 é sucesso. Exit 2 bloqueia a ação (para PreToolUse). Exit 1 ou qualquer outro valor diferente de 0 e 2 registra um erro no transcript, mas o agente continua. Use isso pra distinguir "bloqueio intencional" de "erro que aconteceu mas não é crítico".

Cuidado com loops. Um hook PostToolUse que edita um arquivo dispara o mesmo hook de novo. Se não houver condição de saída, entra em loop. Sempre condicione: verifique o tipo de arquivo, o nome da ferramenta ou o conteúdo antes de agir.

Vale combinar com CLAUDE.md

Hooks automatizam ações. O CLAUDE.md documenta intenções. Os dois trabalham juntos: você escreve no CLAUDE.md "sempre rode dotnet format antes de commitar" e coloca o hook pra garantir que isso acontece de verdade, mesmo que o agente esqueça ou decida pular.

E se o consumo de tokens tá preocupando (hooks podem adicionar output que vai pro contexto), o post como economizar tokens no Claude Code tem as técnicas que mais fazem diferença pra manter o custo controlado em sessões longas.

Para quem quer ir além do básico, o curso de Claude Code cobre workflows completos com hooks, sub-agentes e automações aplicadas em projetos ASP.NET Core reais.

Perguntas frequentes

O que são hooks no Claude Code?
Hooks são scripts shell (ou chamadas HTTP) que o Claude Code executa automaticamente antes ou depois de usar uma ferramenta: editar arquivo, rodar comando, terminar a sessão. Você configura quais eventos disparam quais scripts em `.claude/settings.json`.
Onde configuro os hooks do Claude Code?
Em `.claude/settings.json` na raiz do projeto, dentro da chave `hooks`. Esse arquivo pode ser commitado com o repositório. Há também o settings global em `~/.claude/settings.json` para hooks que valem em todos os projetos.
Dá pra rodar comandos dotnet nos hooks?
Sim. Qualquer comando shell funciona, incluindo `dotnet format`, `dotnet test`, `dotnet build`. O hook recebe o contexto da ferramenta via stdin em JSON, então você pode condicionar a execução ao tipo de arquivo ou ao conteúdo do comando.
Qual a diferença entre PreToolUse e PostToolUse?
PreToolUse roda antes da ferramenta agir. Dá pra bloquear a ação retornando `permissionDecision: "deny"`. PostToolUse roda depois, quando a ação já aconteceu. Útil para formatar código, rodar testes ou logar o que mudou.
Hooks lentos travam o Claude Code?
Sim. Hooks síncronos bloqueiam o agente até terminar. Se um `dotnet test` demora 40 segundos, o Claude Code fica parado esperando. Use `async: true` para hooks de monitoramento que não precisam bloquear, ou configure `timeout` para limitar o tempo máximo.

Artigos relacionados

Quer aprender C# do zero ao avançado?

Cursos práticos em português, com projetos reais e acesso vitalício.

Conhecer o curso de C#