Objetivo: ao final, o consultor implementa um hook que decide (allow, deny, ask, defer) e um que reescreve a chamada antes de executar, redigindo dado sensível em vez de bloquear o trabalho.
PreToolUse vai em JSON no stdout, com exit 0. O campo permissionDecision aceita allow, deny, ask e defer — e defer significa "segue o fluxo normal de permissão".updatedInput reescreve a chamada antes de executar: dá para redigir dado sensível em vez de bloquear, e o trabalho legítimo continua. Ele troca apenas os campos declarados — campos omitidos mantêm o valor original.PostToolUse tem updatedToolOutput, que reescreve o resultado da ferramenta antes de o Claude ver — redação também no caminho de volta.{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Regra Wayon: nenhuma ação automatizada em QAS ou PRD do MRD."
}
}
O hook escreve isso no stdout e sai com exit 0. Exit 0 significa "executei corretamente, interprete meu JSON" — não significa "aprovado". Quem aprova ou nega é o campo permissionDecision. Essa confusão é o assunto da aula 3.2.4.
| Valor | O que faz | Quando usar |
|---|---|---|
allow |
Libera a chamada sem perguntar ao consultor | Ação segura e frequente que não deveria gerar pergunta |
deny |
Barra a chamada e devolve a razão para o Claude | Proibido por política — não há o que perguntar (QAS, PRD) |
ask |
Escala para o consultor decidir | Depende de contexto que o hook não tem |
defer |
Segue o fluxo normal de permissão, como se o hook não opinasse | O hook examinou e concluiu que não é caso dele |
Sempre preencha permissionDecisionReason em deny e ask: é o texto que volta para o Claude (em deny) ou aparece para o consultor (em ask). Um deny sem razão faz o Claude tentar de novo, às cegas.
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": {
"command": "grep '[CPF-ANONIMIZADO]' log-mrd.txt"
}
}
}
Como ler isso: o hook detectou um CPF no comando, trocou por placeholder, e liberou. O Claude executa a versão limpa.
A correção que importa: updatedInput substitui apenas os campos declarados. No exemplo, só command foi trocado — qualquer outro argumento da chamada original permanece intacto. Não é preciso reecoar o que não está mudando.
Material mais antigo (inclusive uma versão anterior do blueprint deste curso) afirmava que
updatedInputsubstitui o objeto de input inteiro, e que era preciso reecoar os campos não alterados. Isso está errado e produz hooks mais frágeis do que o necessário. Está registrado emDIVERGENCIAS-BLUEPRINT-VS-DOC.md.
| Direção | Evento | Campo | Caso de uso |
|---|---|---|---|
| Entrando na ferramenta | PreToolUse |
updatedInput |
O comando que o Claude montou contém dado pessoal |
| Saindo da ferramenta | PostToolUse |
updatedToolOutput |
A saída do comando trouxe dado que não deveria entrar no contexto |
O segundo caso é comum em Basis: você roda uma consulta legítima num log de produção, e o retorno vem cheio de nome de usuário real. updatedToolOutput limpa antes de aquilo virar contexto de sessão — o que resolve, de forma automática, o que a aula 2.8.B1 pedia manualmente.
Regra Wayon Dois hooks são obrigatórios em pasta de projeto de cliente: um
PreToolUseque nega ação em QAS e PRD do sistema do cliente, e um par de redação (updatedInputnoPreToolUseeupdatedToolOutputnoPostToolUse) para CPF, CNPJ e nome de usuário real. O segundo par é o que transforma a política de anonimização da Decisão 1 de uma instrução que o consultor precisa lembrar numa garantia que roda sozinha.
📖 Saída JSON de hooks · Modos de permissão — módulo 2.5
PreToolUse detectou um comando que toca o PRD do MRD. Como ele deve responder?exit 1 não bloqueia — é a pegadinha da aula 3.2.4. E a decisão de negar se expressa em JSON, não em exit code.
permissionDecision: "deny" e a razão, saindo com exit 0Correto. Exit 0 significa "leia meu JSON"; quem nega é o campo permissionDecision.
permissionDecision: "ask", para o consultor decidirask é para o que depende de contexto que o hook não tem. Ação em PRD é proibida por política — não há o que perguntar.
permissionDecision: "deny", forçando o Claude a montar o comando de novo sem o CPFInterrompe trabalho legítimo e depende de o Claude acertar na segunda tentativa — existe caminho melhor.
permissionDecision: "ask", para o consultor remover o CPF manualmenteTransfere trabalho manual para o consultor a cada ocorrência, quando o hook já detectou o padrão e pode corrigir sozinho.
permissionDecision: "allow" com updatedInput trocando o CPF por um placeholderCorreto. É o padrão "redigir em vez de bloquear": o trabalho acontece, o dado pessoal não passa.
updatedInput para trocar o campo command de uma chamada de Bash, o que acontece com os outros argumentos da chamada original?updatedInput substitui apenas os campos declaradosCorreto. Não é preciso reecoar o que não está mudando.
updatedInput substitui o objeto de input inteiroEra o que material antigo afirmava, e está errado: campos omitidos mantêm o valor original.
preserveFields: trueNão existe esse campo — a preservação dos campos omitidos é o comportamento padrão.
PreToolUse com updatedInput, limpando a consulta antes de rodarLimpa o que entra na ferramenta, mas o problema aqui está no que sai dela — a consulta em si era legítima.
PreToolUse com permissionDecision: "deny", barrando consultas a log de produçãoImpediria trabalho legítimo de Basis; a triagem de log é justamente uma das tarefas da faixa (aula 2.8.B1).
PostToolUse com updatedToolOutput, limpando a saída antes de o Claude vê-laCorreto. É a redação no caminho de volta — automatiza o que a aula 2.8.B1 pedia manualmente.