O hook de roteamento do Claude Code é seguro? O que o Downshift lê e muda
Downshift por Tiago Vilas Boas. Atualizado em
Este Downshift é uma ferramenta em Go para agentes de código com IA, não a biblioteca React downshift de autocomplete.
Resumo
Um hook de roteamento é um comando local que o Claude Code chama antes de criar um subagente. O Downshift foi feito para que essa chamada seja pequena e previsível: sem rede e sem chamada a modelo para decidir, dois campos reescritos (model e reasoning_effort), todos os outros preservados, qualquer falha deixa o seu subagente intacto, e o texto da tarefa nunca vai para o disco. Cada afirmação abaixo aponta para o arquivo do repositório que a declara. A última seção lista o que o Downshift não faz.
O que um hook do Claude Code pode fazer na minha sessão?
Um hook PreToolUse é um comando que o Claude Code executa antes de uma chamada de ferramenta. A Anthropic documenta que ele pode permitir, bloquear ou substituir a entrada da ferramenta via updatedInput. Ele roda com as suas permissões, então a pergunta não é se hooks são poderosos, e sim o que este hook específico pode tocar. A Anthropic também documenta as falhas: exit 2 bloqueia; qualquer outro código diferente de zero, ou um timeout, não bloqueia, a menos que o hook defina onFailure: "block". Verificado em 2026-10-24
O Downshift se registra no matcher Agent|Task, então vê a criação de subagentes, não toda chamada de ferramenta. Esse escopo vem do downshift setup, descrito em docs/guides/install.md.
O que o Downshift lê e onde ele roda?
Ele lê o payload que o Claude Code envia no stdin, faz o parse estrito e responde no stdout. A decisão inteira é local e determinística: uma tabela de sinais com pontuação, um embedder por hash e uma segunda opinião naive-Bayes, sem chamada de rede e sem LLM no caminho. O documento de design afirma que o caminho quente tem "no network, no LLM, no prompt storage" (docs/design/architecture.md). Não é um proxy HTTP: nada fica entre o Claude Code e a API do modelo.
O código é open source sob Apache-2.0 (LICENSE) e o binário em Go não tem dependências externas (SECURITY.md).
O que exatamente o hook altera em um subagente?
Só dois campos. Quando há motivo para reescrever, a resposta é um updatedInput em que mudam model e, onde o harness aceita, reasoning_effort; todos os campos irmãos são preservados. É uma invariante declarada em AGENTS.md e no fluxo de docs/design/architecture.md, e a suíte de conformidade compartilhada fixa a resposta do subagente intacto: no Claude Code ela é {}, não um allow explícito, então as suas regras de confirmação continuam valendo (docs/reference/harness-matrix.md).
Ele também não edita resultados de ferramentas: o hook PostToolUse devolve {} (mais uma linha de status opcional).
E se o hook travar, quebrar ou receber um payload enorme?
O seu subagente segue sem alteração. O Downshift lê no máximo 1 MiB do stdin, com timeout de leitura de 2 s, roda sob um prazo de 1,5 s, converte panic em allow e carrega o catálogo sob recover. Uma falha nunca sai com o código 2, que é o que bloqueia no Claude Code. Veja a tabela "Trust boundaries" em docs/design/architecture.md. O custo dessa escolha é claro: hook que falhou significa otimização perdida, nunca tarefa bloqueada.
O Downshift guarda meus prompts, o texto da tarefa ou caminhos de arquivo?
Não. O texto da tarefa fica só em memória para extrair características. O log de eventos guarda apenas metadados: nomes de modelo, classes de complexidade, guardrails acionados, contagens de tokens, identificadores com hash e tempos. Texto de prompt, caminhos de arquivo e saída de ferramentas nunca chegam ao disco (docs/domains/observability-telemetry.md). O export para compartilhar tem só contagens: downshift stats --days=30 --export, descrito em docs/reference/stats-export.md; nem o nome de um agente customizado é gravado. Você pode inspecionar o log local, que é um arquivo JSON Lines em ~/.downshift.
Ele pode mandar trabalho de risco para um modelo menor?
O desenho diz que não. O classificador tem categorias de risco (segredos e credenciais, criptografia, pagamentos, operações destrutivas como DROP TABLE, rm -rf ou force-push) que definem um piso, então uma tarefa que toca nelas não recebe um modelo menor (internal/classify/risk.go). Os guardrails R1 a R9 rodam sobre o resultado, e qualquer violação transforma o veredito em "manter o modelo atual". Na dúvida, um downshift, upshift ou escolha de modelo de fronteira sem confiança fica no seu modelo (docs/domains/subagent-routing.md). Cerca de 10% dos spawns também passam intactos como grupo de controle, para você medir o efeito.
É um classificador feito de padrões, não uma prova. Uma tarefa arriscada descrita com palavras que os padrões não cobrem pode parecer rotineira. Para garantia rígida em uma pasta, defina um piso de tier do projeto em .downshift/policy.json.
O que o compactador de saída reescreve nos meus comandos de shell?
É outro recurso, o downshift compact, que envolve comandos de teste e build de uma lista permitida (por exemplo go test, pytest, vitest) para reduzir a saída ao resumo. As regras em docs/reference/harness-matrix.md: o comando precisa começar por uma família permitida e não ter metacaractere de shell, salvo um conjunto curto de formas conhecidas (cd dir && cmd, | tail -N e cadeias separadas por ; e &&). O código de saída real é mantido. Uma regra deny ou ask que case com o comando ou com qualquer segmento interrompe a reescrita, e "exec": false ou DOWNSHIFT_EXEC=0 a desliga. Avisos, erros e saída ambígua são mantidos byte a byte; só resumos de sucesso completos e consistentes são compactados (docs/guides/benchmark-output-cutting.md).
Medido em fixtures sintéticas (corpus de 2026-10-21): 82,3% menos bytes nos 26 de 248 arquivos que compactam, 23,7% nos 248. São bytes, não tokens de LLM.
Como instalo, verifico e desfaço?
Três controles, todos em docs/guides/install.md:
- Verifique o download. O instalador confere o arquivo da release com o
checksums.txt(sha256) e para se houver divergência. As releases também têm uma atestação de proveniência de build do GitHub; com oghinstalado ele rodagh attestation verify, e você pode rodar à mão:gh attestation verify downshift_<ver>_<os>_<arch>.tar.gz --repo tiagovilasboas/downshift. Sem ogh, ele cai para só sha256 e avisa. - Veja antes de gravar.
downshift setup --dry-runmostra o diff de cada harness encontrado e não grava nada. O setup mantém chaves alheias e hooks existentes e salva um backup com data e hora. - Desfaça.
downshift setup --undorestaura o último backup.downshift doctorconfere a instalação.
O que o Downshift não faz? Limites conhecidos
- Não garante a troca. O harness executa o subagente e pode ignorar o
updatedInput. Segundo docs/reference/harness-matrix.md: aplicada e observada no Claude Code (2026-10-06); inferida no Codex; não confirmada no Cursor, onde é descartada nos planos Free e Pro legado; o KiroCrew não tem reescrita no lugar e recebe bloqueio com motivo e nova tentativa; o Grok é só configuração; o OpenCode ainda não foi observado. - Não vê nem edita o subagente. Não executa o filho, não enxerga o contexto dele e nunca edita o que ele devolve.
- O compactador pula o que não consegue provar seguro. Deixa sem envolver
||, um&isolado, pipes para qualquer coisa além detailouhead -N, redirecionamentos de arquivo, heredocs, subshells, aspas, globs e expansões, e recusa a cadeia inteira se um segmento tiver algum deles. - A detecção de risco é por padrões. Veja acima.
- A economia não é garantida. Veja o status; o intervalo do resultado do roteamento começa perto de zero.
- Não é um produto de segurança. É um hook de roteamento de custo que evita ampliar a sua superfície de ataque. Vulnerabilidades vão para o GitHub Private Vulnerability Reporting (SECURITY.md).
Perguntas frequentes
É seguro instalar um hook no Claude Code?
Um hook roda um comando local com as suas permissões, então confira o que ele faz. O Downshift roda localmente, sem rede nem chamada a modelo para decidir, reescreve só model e reasoning_effort, preserva todos os outros campos e deixa o subagente intacto em qualquer falha. Você vê a instalação antes com downshift setup --dry-run e desfaz com downshift setup --undo.
O hook vê meu código ou meus prompts?
Ele recebe o payload da criação do subagente e lê o texto da tarefa em memória para classificá-lo. O texto nunca é gravado. O log local guarda só metadados: contagens, hashes e tempos, sem prompts, texto de tarefa nem caminhos de arquivo.
O que acontece se o hook quebrar?
Ele falha aberto. O stdin tem limite de 1 MiB, com timeout de leitura de 2 s e prazo de 1,5 s, um panic vira subagente intacto, e uma falha nunca sai com o código 2, que bloqueia. O custo de uma falha é uma otimização perdida, não uma tarefa bloqueada.
Um roteador pode mandar código de segredo, auth ou pagamento para um modelo barato?
O Downshift define um piso para essas áreas de risco (segredos, auth, criptografia, pagamentos, operações destrutivas), então elas não recebem um modelo menor, e na dúvida o seu modelo é mantido. A detecção é por padrões, não uma prova; use um piso de tier do projeto para garantia rígida.
Como verifico o download do Downshift?
O instalador confere o checksum sha256 da release. As releases também têm uma atestação de proveniência de build que você verifica com gh attestation verify contra tiagovilasboas/downshift.
Instalar
Rode downshift setup --dry-run antes para ver cada alteração. downshift setup --undo restaura os backups. Passo a passo: /pt-br/docs/install/.
curl -fsSL https://raw.githubusercontent.com/tiagovilasboas/downshift/main/install.sh | sh && downshift setupPlugin do Claude Code
/plugin install downshift --marketplace tiagovilasboas/downshiftGuias relacionados
- Qual modelo cada subagente usa no Claude Code
- Saída longa de teste e build no Claude Code: por que gasta contexto e como cortar
- Qual modelo usar no Claude Code: Opus, Sonnet ou Haiku para cada tarefa
- Is a Claude Code routing hook safe? What Downshift reads and changesEnglish
- Instalar o Downshift: hooks no Claude Code, Codex e Cursor
Fontes
- Anthropic docsdocumentado
code.claude.com/docs/en/hooks
controle de decisão do PreToolUse (updatedInput), códigos de saída, timeouts e onFailure (fetched 2026-10-24) - Downshift repomedido
AGENTS.md
invariantes principais - Downshift repomedido
docs/design/architecture.md
fluxo ponta a ponta, fronteiras de confiança, o que o Downshift não é - Downshift repomedido
docs/reference/harness-matrix.md
matriz de reescrita aplicada, regras e cadeias do compactador - Downshift repomedido
docs/guides/install.md
checksums, atestação, setup --dry-run e --undo - Downshift repomedido
docs/reference/stats-export.md
export só com contagens - Downshift repomedido
SECURITY.md
escopo, reporte, zero dependências - Downshift repomedido
docs/evidence/four-arm-mechanical-2026-10-21.md
bateria de 46 execuções e intervalo