Sumário
- Qual hook para qual situação
- O que você precisa
- Passo 1 — Crie dois canais
- Passo 2 — Adicione os hooks
- Passo 3 — Teste sem esperar um pedido de verdade
- Passo 4 — Faça o canal de bloqueio tocar
- Como evitar o excesso de notificações
- Rodando o Claude Code remotamente ou em CI
- Solução de problemas
- Perguntas frequentes
- Como receber uma notificação quando o Claude Code precisa de permissão?
- Como saber quando o Claude Code termina uma tarefa?
- A notificação consegue furar o Não Perturbe?
- Isso funciona no Claude Code na web ou em sessões remotas?
- É seguro colocar a URL do webhook no settings.json?
- Conclusão
- Leia também
O Claude Code para em duas situações que importam: ele está bloqueado esperando por você (um pedido de permissão, uma pergunta) ou terminou o trabalho. Se você não está olhando para o terminal, as duas parecem iguais — nada acontece, e a sessão fica parada até você voltar. A solução é um hook: algumas linhas no settings.json que enviam um webhook para o seu celular no instante em que qualquer uma das duas acontece.
Este guia traz a configuração para copiar, explica qual evento de hook usar em cada situação e cobre os detalhes que fazem tudo funcionar de forma confiável: ler a entrada do hook, aspas no shell e como não se afogar em notificações.
Qual hook para qual situação
O Claude Code executa hooks em eventos do ciclo de vida. Dois deles resolvem este problema (referência de hooks):
| Você quer saber quando… | Evento do hook | Matcher / filtro |
|---|---|---|
| O Claude está esperando uma decisão de permissão | Notification | permission_prompt |
| O Claude ficou ocioso esperando sua resposta | Notification | idle_prompt |
| O Claude terminou de responder | Stop | não precisa |
O matcher do hook Notification filtra pelo tipo de notificação, então você escolhe exatamente quais chegam ao celular. A entrada chega como JSON no stdin e inclui notification_type, message, cwd e session_id. Hooks Notification não podem bloquear nem alterar nada — são observadores, que é exatamente o que você quer aqui.
A entrada do Stop inclui last_assistant_message, o texto final que o Claude produziu. É uma linha de resumo de graça para a notificação.
O que você precisa
- Echobell no celular (App Store / Google Play)
curlejqna máquina que roda o Claude Code- Dois minutos
Passo 1 — Crie dois canais
Resista à tentação de mandar tudo para um canal só. No Echobell, crie:
- Claude Blocked, tipo Time Sensitive ou Calling — para pedidos de permissão, em que o agente está parado e cada minuto é perda de processamento e de tempo real
- Claude Done, tipo Normal — um push comum, que dá para ler quando der
Copie a URL do webhook de cada canal. Ela se parece com https://hook.echobell.one/t/<channel-token>. Trate-a como uma senha: quem a tiver pode fazer seu celular tocar.
Guarde as duas como variáveis de ambiente, para que nunca caiam num arquivo de configuração commitado:
export ECHOBELL_CLAUDE_BLOCKED_URL="https://hook.echobell.one/t/<blocked-token>"
export ECHOBELL_CLAUDE_DONE_URL="https://hook.echobell.one/t/<done-token>"
Coloque-as no perfil do seu shell para que o Claude Code as herde.
Passo 2 — Adicione os hooks
Adicione isto a ~/.claude/settings.json para valer em todos os projetos, ou a .claude/settings.local.json para um único repositório:
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{
"type": "command",
"command": "jq -c '{title: \"Claude precisa de permissão\", body: .message, project: (.cwd | split(\"/\") | last)}' | curl -sS -m 10 -X POST -H 'Content-Type: application/json' -d @- \"$ECHOBELL_CLAUDE_BLOCKED_URL\""
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "jq -c '{title: \"Claude terminou\", body: (.last_assistant_message // \"Concluído\" | .[0:200]), project: (.cwd | split(\"/\") | last)}' | curl -sS -m 10 -X POST -H 'Content-Type: application/json' -d @- \"$ECHOBELL_CLAUDE_DONE_URL\""
}
]
}
]
}
}
O que cada parte faz:
jq -c '{...}'lê o JSON do hook no stdin e monta um payload pequeno, de modo que o Echobell receba exatamente os campos que você quer, e não o documento inteiro do hook..cwd | split("/") | lasttransforma/home/me/code/apiemapi, para a notificação dizer qual projeto está pedindo..[0:200]trunca a mensagem final. O worker do Echobell limita o corpo das notificações a 1500 bytes, e a tela de bloqueio mostra bem menos que isso.-m 10dá aocurlum timeout de 10 segundos, para que um problema de rede nunca deixe o Claude Code esperando pelo seu hook.
O Echobell renderiza as chaves que você envia pelos templates do canal, e um canal novo não tem nenhum template que as leia — defina-os nas configurações do canal: template de título {{title}}, template de corpo {{body}}. Adicione {{project}} a qualquer um deles se quiser ver o nome do projeto, por exemplo {{title}} ({{project}}).
Passo 3 — Teste sem esperar um pedido de verdade
Rode o mesmo pipeline à mão, com um payload de hook falso:
echo '{"message":"O Claude precisa da sua permissão para usar o Bash","cwd":"/home/me/code/api","notification_type":"permission_prompt"}' \
| jq -c '{title: "Claude precisa de permissão", body: .message, project: (.cwd | split("/") | last)}' \
| curl -sS -m 10 -X POST -H 'Content-Type: application/json' -d @- "$ECHOBELL_CLAUDE_BLOCKED_URL"
Se o celular acender, o lado do Echobell está funcionando e qualquer problema restante está em como o Claude Code lê a configuração. No Claude Code, rode /hooks para confirmar que os hooks foram carregados; mudanças nas configurações feitas com uma sessão em andamento podem precisar do menu de hooks ou de um reinício para valer.
Passo 4 — Faça o canal de bloqueio tocar
Uma notificação push perde para o Não Perturbe. Um canal Calling se comporta como uma ligação recebida e atravessa o modo Foco do iOS, o que importa mais quando você começa uma tarefa longa e sai para o resto da noite. Se você só quer ser interrompido por alguns pedidos, filtre com uma condição de canal do Echobell sobre as variáveis que você envia, por exemplo project == "api", em vez de editar o hook. Para a lista completa de variáveis, veja a referência de condições.
Como evitar o excesso de notificações
Uma sessão movimentada pode disparar muitos eventos Stop — toda resposta termina com um. Três formas de preservar o sinal:
- Não envie o
Stoppara um canal que toca. Concluir não é urgente; mantenha no Normal. - Use
idle_promptem vez deStopse você só quer saber quando o Claude parou e está esperando por você, e não depois de cada resposta. - Restrinja por projeto com uma condição, para que um repositório de testes não notifique você de jeito nenhum.
Rodando o Claude Code remotamente ou em CI
A mesma abordagem funciona em ambientes na nuvem ou remotos, porque o hook é só uma requisição HTTPS de saída. Nada precisa estar acessível pela internet. Defina as duas variáveis de ambiente nos secrets do ambiente em vez do perfil do shell, e a notificação chega ao seu celular onde quer que a sessão rode.
Solução de problemas
Nada chega, e o teste manual também falha. Verifique se a variável da URL está definida no shell que inicia o Claude Code: echo "$ECHOBELL_CLAUDE_BLOCKED_URL". Uma variável vazia faz o curl falhar em silêncio.
O teste manual funciona, mas o hook não dispara. Confirme o matcher: permission_prompt e idle_prompt são distintos, e um matcher que não corresponde simplesmente nunca executa. Rode /hooks e confira se o JSON é válido — uma vírgula sobrando desativa os hooks do arquivo de configuração inteiro.
O corpo da notificação está em branco. O filtro do jq referenciou um campo que não existe para aquele evento. message existe na entrada de Notification; last_assistant_message existe na entrada de Stop. Use // para fornecer um valor padrão, como na configuração acima.
Dispara com frequência demais. Veja a seção acima — troque Stop por idle_prompt ou adicione uma condição.
Perguntas frequentes
Como receber uma notificação quando o Claude Code precisa de permissão?
Adicione um hook Notification com o matcher permission_prompt que envie um webhook para um canal. O Echobell transforma essa requisição em um push ou em um alerta em formato de ligação no seu celular.
Como saber quando o Claude Code termina uma tarefa?
Adicione um hook Stop. Ele roda quando o Claude termina de responder, e a entrada inclui last_assistant_message, que você pode usar como corpo da notificação.
A notificação consegue furar o Não Perturbe?
Sim, se o canal receptor for um canal Calling. Ele se comporta como uma ligação recebida, que o modo Foco do iOS deixa passar. Um push normal de qualquer app não passa.
Isso funciona no Claude Code na web ou em sessões remotas?
Sim. O hook só faz uma requisição HTTPS de saída, então funciona em qualquer lugar em que a sessão alcance a internet. Informe as URLs dos canais pelos secrets do ambiente.
É seguro colocar a URL do webhook no settings.json?
Prefira uma variável de ambiente, como mostrado acima, para que o token não seja commitado num repositório. Se ele vazar, crie um canal novo e aposente o antigo.
Conclusão
Dois canais, dois hooks e um pipeline jq | curl: um canal Calling ou Time Sensitive para permission_prompt e um canal Normal para Stop. Depois disso, você pode iniciar uma tarefa longa de um agente, sair da sala e ser chamado de volta só quando o agente realmente precisar de você.
Baixe o Echobell para iPhone ou instale pelo Google Play e rode o teste manual acima antes de confiar nele numa tarefa longa.