on(eventName, handler).
Construa seu primeiro mod antes de começar aqui. Para cada evento e seus campos exatos, consulte a referência ou leia os tipos para sua compilação.
Como um hook manipula um evento
Um hook fica entre um evento e o que Claude Code faria sobre ele, portanto pode observar o evento, reescrevê-lo ou respondê-lo por si mesmo. Ele recebe três argumentos: a API de mods como$, o evento como e e o próximo manipulador como next. Os manipuladores de um evento formam uma cadeia de middleware. next(e) chama o próximo manipulador, que é o hook de outro mod ou, no final da cadeia, o comportamento próprio de Claude Code, e é resolvido para o resultado. O que seu hook faz com next decide qual dos três ele faz.
Observe um evento
Para observar um evento sem alterá-lo, faça seu trabalho e retornenext(e). Este hook registra cada ferramenta que Claude está prestes a usar:
● my-mod: Claude is about to use Bash aparece na transcrição, onde my-mod é o nome do seu plugin. A ferramenta é executada como seria sem o mod.
Para agir após o evento, await next(e), faça seu trabalho e retorne o resultado. Este hook registra cada ferramenta após sua execução:
next(e) foi resolvido.
Reescreva um evento
Para alterar o que Claude Code age, como o texto de um prompt, chamenext com uma cópia modificada do evento. O evento em si é imutável: é congelado em cada profundidade e atribuir a um campo lança um erro. Este hook corta cada prompt antes de ser enviado:
await next(e), depois retorne uma cópia do resultado com um campo substituído.
Responda a um evento
Para manipular um evento você mesmo, retorne um resultado sem chamarnext. Isso interrompe a cadeia, portanto mods posteriores e o comportamento próprio de Claude Code não são executados. Este hook recusa cada comando Bash:
deny como o resultado da ferramenta. Cada evento tem sua própria forma de resultado, que a referência de eventos lista.
Filtre quais eventos um hook manipula
Para executar um hook apenas para alguns eventos, passe um filtro como o segundo argumento paraon. Claude Code chama o filtro de matcher. É um objeto cujos campos são comparados com os do evento, e o hook é executado apenas quando cada campo corresponde. Um campo pode ser um valor, uma matriz de valores permitidos ou uma expressão regular.
Cada linha neste exemplo registra a mesma função, hook, para um conjunto mais estreito de chamadas de ferramentas:
hook é executado uma vez para uma chamada Bash, Edit ou Write, e uma vez para uma chamada a uma ferramenta cujo nome começa com mcp__github__. Uma chamada para qualquer outra ferramenta, como Read, não corresponde a nenhuma das três, portanto hook não é executado para ela.
O nome do evento pode ser um wildcard. 'classic.*' corresponde a cada evento de hook de configurações. '*' corresponde a cada evento exceto os eventos de telemetria, que você conecta por nome ou como 'telemetry.*'.
Registre cada evento uma vez por matcher. Se você chamar on duas vezes para session.start sem um matcher, o módulo falhará ao carregar com on("session.start") is registered twice without a matcher. Coloque tudo o que seu mod faz no início da sessão em um hook.
Hook o que Claude está fazendo
Conecte esses eventos para ver ou alterar uma chamada de ferramenta, um prompt ou um turno conforme acontece. Para cada evento e o que um hook pode retornar, consulte a referência de eventos.Guarde ou altere uma chamada de ferramenta
Um hooktool.call vê cada ferramenta que Claude está prestes a usar, portanto pode recusar a chamada, alterar seus argumentos ou deixá-la passar. tool.call dispara quando Claude Code está prestes a executar uma ferramenta, incluindo chamadas que um subagenteaz e chamadas para ferramentas MCP. e.tool é o nome da ferramenta e os argumentos da ferramenta são campos de e, como e.command para Bash. Quando você chama next(e), Claude Code executa a verificação de permissão e depois a ferramenta.
Este hook recusa um comando Bash que força um push e diz a Claude por quê:
git push --force, o comando não é executado e nenhum prompt de permissão aparece, porque o hook nunca chama next. Claude lê o texto deny como o resultado da ferramenta, portanto escreva-o como uma instrução que Claude pode agir. Cada outro comando Bash é executado como seria sem o mod.
Para agir após uma ferramenta ter sido executada, await next(e), faça seu trabalho e retorne o que next lhe deu. Este hook registra cada arquivo .mdx que Claude altera, com $.ui.log, que adiciona uma linha fraca à transcrição que Claude não lê:
.mdx, uma linha fraca na transcrição nomeia o arquivo. Nada é registrado para outro tipo de arquivo ou para uma chamada que foi recusada ou falhou. A visualização de Claude da chamada não muda, porque o hook retorna o resultado que recebeu.
Para alterar uma chamada, passe argumentos alterados para next. Para tentar novamente uma chamada, chame next(e) novamente: um hook que vê isError no primeiro resultado pode executar a ferramenta uma segunda vez e retornar esse resultado. Para responder a uma chamada você mesmo, retorne um objeto com um campo result, como { result: 'Skipped by my-mod' }, sem chamar next. Quando você faz isso, nenhum prompt de permissão aparece e a ferramenta não é executada, portanto o resultado que você retorna é tudo que Claude aprende sobre o que aconteceu.
Hooks nas configurações gerenciadas de sua organização são executados antes de qualquer hook tool.call de mod, e um bloqueio de um deles é final.
Mantenha uma chamada de ferramenta até o usuário decidir
Um hook pode pausar uma chamada de ferramenta e perguntar ao usuário o que fazer antes de prosseguir. Um hooktool.call pode await antes de chamar next ou retornar, e a chamada de ferramenta permanece pendente até então. Para fazer a pergunta ao usuário, chame $.ui.ask. Ele mostra sua pergunta acima de uma lista numerada de suas opções, no diálogo que Claude usa para lhe fazer uma pergunta, e é resolvido para o rótulo que o usuário escolhe. Após suas opções, o diálogo adiciona uma linha para digitar uma resposta diferente e uma linha Chat about this.
O padrão RISKY neste exemplo corresponde a rm -r, rm -rf, git reset --hard e git push com --force, e perde outras grafias como git push -f. Este módulo pergunta antes de executar um comando Bash que corresponde ao padrão:
rm -rf build, a pergunta aparece com o comando nela, e o comando aguarda a resposta:
- O usuário escolhe Run it: o hook chama
next(e)e a verificação de permissão usual ainda é executada após ele - O usuário escolhe Refuse: o comando não é executado e Claude lê o texto
deny - O usuário digita uma resposta:
$.ui.aské resolvido para o texto digitado. O hook o compara comRun it, portanto qualquer outro texto recusa o comando. - Ninguém responde:
$.ui.askrejeita quando o usuário descarta a pergunta ou escolhe Chat about this, e em uma execuçãoclaude -p, portanto o blococatchdeixa a resposta emRefuse
$.ui.ask, porque esse tempo não conta contra o limite de tempo de 10 segundos do hook. O tempo gasto aguardando uma promessa sua conta. Claude Code pula um hook que expira, portanto o comando mantido seria executado.
Reescreva ou adicione a um prompt
Um hookprompt.submit vê cada prompt antes do turno começar, portanto pode reescrever o texto ou adicionar a ele. e.text é o que foi digitado.
Este hook adiciona o nome da ramificação atual para Claude sempre que um prompt menciona uma solicitação de pull:
open a PR for this change, sua mensagem parece a mesma na transcrição e Claude também lê uma linha como Current branch: feature/auth após ela. Um prompt que não menciona uma solicitação de pull passa inalterado e git não é executado.
Outros eventos cobrem o resto do que Claude lê: prompt.section para cada seção do prompt do sistema, prompt.context para o contexto enviado com a primeira mensagem e skill.prompt para o texto de uma skill. Texto desses hooks que muda entre solicitações invalida o cache de prompt.
Siga um turno
Um turno é tudo o que Claude faz em resposta a um prompt. Conecteturn.start, turn.step e turn.complete para seguir um:
Escreva um hook
turn.step como um gerador assíncrono, porque o evento flui. yield* next(e) encaminha a resposta conforme flui e é avaliado para o resultado terminado. Este hook registra quanto de cada solicitação a API Claude serviu do cache de prompt:
result.usage contém as quatro contagens de token que a API Claude relata para uma solicitação, mais o model que respondeu: input_tokens, output_tokens, cache_read_input_tokens e cache_creation_input_tokens. O hook é executado para solicitações de subagenteaz também, portanto verifique e.agentId quando você quer apenas a conversa principal.
Hook os eventos de hook de configurações
Hooks de configurações são os hooks de comando, HTTP, prompt e agente que você configura em arquivos de configurações. Cada evento de hook de configurações, comoStop, SessionEnd ou PostToolUse, também é um evento nomeado classic. seguido pelo nome do evento de hook de configurações, como classic.Stop. e é o JSON que um hook de configurações recebe em stdin, incluindo transcript_path.
Este hook usa Stop, que dispara quando Claude termina de responder, para registrar onde a transcrição da sessão é salva:
next(e), portanto observa o evento e não muda nada sobre como o turno termina.
Execute ao lado de outros mods
Vários mods podem conectar o mesmo evento e qualquer um deles pode falhar. Se seu mod bloqueia chamadas de ferramentas, verifique sua posição na cadeia e o que acontece quando seu hook falha.A ordem em que os mods são executados
Hooks no mesmo evento formam uma cadeia de middleware. Cadanext de um mod chama o hook do mod seguinte, e o último next atinge o comportamento próprio de Claude Code. O primeiro mod é o mais externo: vê o evento antes dos outros e o resultado após eles, e decide se os outros são executados. Um mod posterior não pode impedir que um anterior veja um evento.
Claude Code ordena a cadeia por onde cada mod vem:
- O guard integrado
sec-default@builtin, um mod integrado em Claude Code que/pluginlista comocc-plugin-sec-default, onde ele carrega, mods que sua organização lista emprependPluginse depois qualquer outro mod que conta como de sua organização e não está emappendPlugins - Mods que você instala
- Mods que sua organização lista em
appendPlugins - Outros mods integrados em Claude Code
dependencies em seu manifesto. Dentro de um módulo, hooks são executados na ordem em que register chamou on.
Onde hooks de configurações são executados na ordem
Os hooksPreToolUse configurados em arquivos de configurações também são executados durante uma chamada de ferramenta, em pontos fixos na cadeia de mods:
- Hooks
PreToolUsede configurações gerenciadas: são executados antes do hooktool.calldo primeiro mod, e um bloqueio de um deles é final, portanto nenhum mod vê a chamada. - Hooks
PreToolUsede cada outro arquivo de configurações e dehooks/hooks.jsonde plugins: são executados após o último mod chamarnext, como parte do comportamento próprio de Claude Code. Um mod que respondetool.callsem chamarnextos impede de serem executados, e um mod que chamanextvê sua decisão no resultado que retorna.
tool.check é o evento onde Claude Code decide se uma chamada de ferramenta pode ser executada. Dispara após esses hooks e as regras de permissão terem decidido, e next(e) é resolvido para sua decisão. Um hook em tool.check pode retornar uma decisão diferente, como { decision: 'allow' }, portanto pode aprovar uma chamada que um hook no segundo grupo bloqueou. Estenda permissões com hooks lista quais decisões prevalecem sobre um mod.
Manipule um hook que falha
Um hook que falha não quebra a sessão e você pode decidir o que acontece em seu lugar. Quando um hook sem um manipulador.catch lança, expira ou retorna um resultado da forma errada, o que acontece a seguir depende se ele tinha chamado next:
- Falhou antes de chamar
next: Claude Code o pula e o próximo manipulador é executado em seu lugar - Falhou após
nextser resolvido: esse resultado permanece e nada é executado uma segunda vez
my-mod: tool.call hook skipped: threw Error: boom. Onde você o lê depende da sessão, como Descubra por que um mod não faz nada lista. Um hook ui.render cujo desenho não valida é relatado diferentemente, como Construa uma árvore a partir de elementos descreve.
Para fazer um hook que bloqueia chamadas falhar fechado, adicione um manipulador de erro .catch que responda em seu lugar. Aqui, guard é sua função de hook:
guard funciona, o manipulador nunca é executado. Quando guard lança ou expira em uma chamada Bash, Claude Code chama o manipulador com o mesmo evento. O manipulador retorna { deny }, portanto o comando não é executado e Claude lê o texto com throw ou timeout no final. Sem o manipulador, Claude Code pularia guard e executaria o comando. O manipulador tem um segundo para responder.
Próximos passos
- Use a API de mods: adicione comandos e ferramentas, chame um modelo e execute trabalho em um temporizador
- Desenhe na interface: mostre o que seus hooks coletam em um painel ou acima do prompt
- Teste um mod: levante qualquer um desses eventos de um teste
- Referência de mods: cada evento, cada método de API de mods e os limites