O hook Notification do Claude Code roda sempre que o Claude Code envia uma notificação, geralmente porque há um prompt de permissão esperando (permission_prompt) ou porque o Claude terminou e você não respondeu (idle_prompt). Ele é programado para quando você parece estar ausente: permission_prompt dispara depois que o prompt fica cerca de seis segundos sem nenhuma tecla pressionada, e idle_prompt cerca de 60 segundos depois que o Claude terminou. O hook recebe o texto da notificação como JSON, não pode bloquear nada e serve para efeitos colaterais, como um alerta no desktop ou um push para o seu celular.
01Os tipos de notificação
O matcher de um hook Notification é o tipo de notificação. Deixe vazio para rodar em todos, ou liste os que você quer separados por |. Os tipos que você provavelmente vai usar:
permission_promptO Claude precisa que você aprove o uso de uma ferramenta (ou a requisição de rede de um comando em sandbox) e o prompt já esperou cerca de seis segundosidle_promptO Claude terminou de responder há cerca de 60 segundos e você não digitou nada desde entãoelicitation_dialogUm servidor MCP abriu um formulário e você não digita há cerca de seis segundoselicitation_url_dialogUm servidor MCP pediu para você abrir uma URL e você não digita há cerca de seis segundosauth_successAutenticação concluídaExistem outros, como agent_needs_input e agent_completed para sessões em segundo plano na visualização de agentes, e um conjunto de tipos quota_auto_resume_* para esperas por limite de uso. A referência de hooks tem a lista completa e atualizada.
02As regras de timing
Esta é a parte que pega muita gente de surpresa. O hook Notification segue o mesmo timing das notificações de desktop do próprio Claude Code, então, numa sessão de terminal, ele só dispara quando você se distrai:
permission_promptinicia um timer de cerca de seis segundos quando o prompt aparece. Cada tecla digitada reinicia o timer. Se você responder rápido, ele nunca dispara.idle_promptdispara cerca de 60 segundos depois que o Claude termina, e só se você não digitou nada desde então e nenhum agente em background ainda estiver rodando. Ele não dispara enquanto o Claude Code espera um limite de uso ser resetado.- Uma solicitação que chega enquanto outro diálogo está aberto é cronometrada a partir da sua chegada, então a notificação pode chegar até você enquanto ela ainda espera atrás do diálogo aberto.
Hosts que respondem permissões pelo Agent SDK, como o Claude Desktop e a extensão do VS Code, cronometram o permission_prompt de outro jeito: cerca de seis segundos após a solicitação, sem adiamento pela digitação, e ignorado se você ou um hook PermissionRequest responder antes.
Se você quer um sinal sem atraso, use outro evento:
PermissionRequestStopNotification com idle_prompt03O que o hook recebe
Além dos campos comuns (session_id, transcript_path, cwd, hook_event_name), um hook Notification recebe a message da notificação, um title opcional e o notification_type:
{
"session_id": "abc123",
"transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
"cwd": "/Users/...",
"hook_event_name": "Notification",
"message": "Claude needs your permission",
"title": "Permission needed",
"notification_type": "permission_prompt"
}
A message é o texto do próprio Claude Code, então é seguro exibi-la como está. O cwd é útil quando você roda várias sessões e quer saber qual projeto está pedindo.
04O que o hook pode e não pode fazer
Um hook Notification não pode bloquear, atrasar nem alterar a notificação. O exit code e o stderr são ignorados, e o Claude Code descarta systemMessage e continue da saída JSON. Ele serve apenas para efeitos colaterais.
Existe um campo de saída que ele pode usar: terminalSequence. Hooks rodam sem terminal, então não conseguem escrever escape sequences diretamente, mas podem entregar uma ao Claude Code para que ele a emita. Assim, um hook pode disparar uma notificação nativa do terminal no iTerm2, Ghostty, Kitty, WezTerm, Windows Terminal e outros, até dentro do tmux. Só funciona numa sessão interativa com a interface do Claude Code na tela.
A configuração preferredNotifChannel também não impede o hook. Mesmo com as notificações nativas desativadas, o evento Notification continua disparando. Essa configuração só muda como o próprio Claude Code avisa você; veja o guia do terminal bell.
05Exemplos
Handlers diferentes por tipo
Rode um script separado para prompts de permissão e outro para lembretes de inatividade:
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [{ "type": "command", "command": "~/.claude/hooks/permission-alert.sh" }]
},
{
"matcher": "idle_prompt",
"hooks": [{ "type": "command", "command": "~/.claude/hooks/idle-alert.sh" }]
}
]
}
}
Torne cada script executável com chmod +x. Os comandos de notificação de desktop para Mac, Windows e Linux estão em como receber uma notificação quando o Claude Code terminar, então não vamos repeti-los aqui.
Mostrar a mensagem real e o projeto
Este script (macOS e Linux) coloca a mensagem do Claude Code e a pasta do projeto na notificação, em vez de um texto fixo:
#!/bin/bash
# ~/.claude/hooks/notify.sh
input=$(cat)
msg=$(jq -r '.message // "Claude Code needs your attention"' <<<"$input")
project=$(basename "$(jq -r '.cwd // "."' <<<"$input")")
if command -v osascript >/dev/null 2>&1; then
osascript -e 'on run argv' \
-e 'display notification (item 1 of argv) with title (item 2 of argv)' \
-e 'end run' "$msg" "Claude Code: $project"
elif command -v notify-send >/dev/null 2>&1; then
notify-send "Claude Code: $project" "$msg"
fi
exit 0
Passar o texto como argumentos (on run argv) evita quebrar o AppleScript quando a mensagem tem aspas. É preciso ter o jq instalado.
Uma notificação nativa do terminal
O exemplo da própria Anthropic usa terminalSequence com OSC 777, que Ghostty, Warp e urxvt entendem:
#!/bin/bash
input=$(cat)
title="Claude Code"
body=$(jq -r '.message // "Needs your attention"' <<<"$input")
seq=$(printf '\033]777;notify;%s;%s\007' "$title" "$body")
jq -nc --arg seq "$seq" '{terminalSequence: $seq}'
Para iTerm2, Windows Terminal ou WezTerm, use OSC 9, e para Kitty, OSC 99. Qualquer coisa fora das sequências permitidas é ignorada.
06Onde o Claude Code Notifier se encaixa
Um hook Notification que chama um serviço de push leva o alerta até o seu celular, e para muita gente isso basta. O guia do ntfy mostra esse caminho.
O que falta é a resposta. Quando o permission_prompt dispara, o Claude está esperando um diálogo que um hook Notification não consegue responder. O Claude Code Notifier resolve isso com os hooks que conseguem: PermissionRequest para devolver sua decisão e PreToolUse em AskUserQuestion para devolver sua resposta. A ferramenta de linha de comando gratuita, ccn, roda em Mac, Windows e Linux e mostra notificações de desktop por conta própria. Com o app de iPhone ou Android pareado, você pode permitir uma vez, permitir para a sessão ou negar pelo celular. Se você digitou nos últimos 30 segundos, nada espera pelo celular e o terminal pergunta normalmente. É um projeto independente, não feito pela Anthropic. A instalação está na página do ccn.
07Perguntas frequentes
Por que meu Notification hook nunca dispara?
Na maioria das vezes, porque você ainda está no teclado. Cada tecla adia o permission_prompt, e o idle_prompt só dispara se você ficou cerca de um minuto sem digitar depois que o Claude terminou. Para testar, provoque um prompt de permissão, mude para outra janela e espere pelo menos seis segundos. Se ainda assim não disparar, confira se o /hooks lista o hook e veja o checklist de troubleshooting.
O que é idle_prompt?
É o tipo de notificação que o Claude Code envia quando o Claude terminou de responder há cerca de 60 segundos e você não digitou nada desde então. É um lembrete de que é a sua vez, não um sinal instantâneo de "pronto". Para isso, use um hook Stop.
Um Notification hook pode aprovar uma permissão?
Não. Hooks Notification não têm controle de decisão, então nada do que eles imprimem responde ao prompt. Use um hook PermissionRequest para permitir ou negar, como descrito no guia do PermissionRequest.
O Notification hook roda se eu definir preferredNotifChannel como notifications_disabled?
Sim. Essa configuração só muda a forma como o próprio Claude Code avisa você. O evento Notification e os seus hooks continuam rodando.
Por que recebo duas notificações?
A notificação nativa do Claude Code e o seu hook rodam em paralelo. No iTerm2, no Ghostty ou no Kitty, você pode ver as duas. Desative uma delas, por exemplo com preferredNotifChannel, ou mantenha só o hook.