Instalação e configuração dos harnesses
Downshift por Tiago Vilas Boas. Atualizado em 19 de outubro de 2026. Código-fonte no GitHub
Downshift por Tiago Vilas Boas https://github.com/tiagovilasboas/downshift
Guia de referência para pessoas e agentes de código que instalam o Downshift em uma máquina de usuário.
Relacionados: config.md · session-models.md · harness-matrix.md · examples/README.md · Guias em português
Status dos harnesses: o Claude Code está Concluído; Codex e Cursor são Funcionais; Antigravity e KiroCrew são Experimentais (veja Harnesses experimentais); o OpenCode está em Beta (o adaptador e a rota de comunicação estão neste repositório; a integração do plugin está em desenvolvimento). As seções abaixo seguem essa ordem. Definições e evidências: harness-matrix.md.
Verificação de saúde
Depois da instalação:
downshift doctor # versão, diretório de estado (~/.downshift), fonte do catálogo
downshift try "rename userId in auth.ts" claude-code
Teste opcional do adaptador (a partir de um clone deste repositório):
./examples/run-all.sh
A descoberta de disponibilidade e a cota de uso são configuradas à parte. Veja session-discovery.md para a lista de modelos e quota.md para a ponte da barra de status nativa do Claude Code, a coleta de transcrições do Codex, a validade dos dados e o modo de cota obrigatória. Uma descoberta bem-sucedida não prova que há crédito incluído, e instalar uma ponte não prova que ela recebeu uma observação de uso em tempo real.
Quickstart: do zero a um hook funcionando em 2 minutos
Passo 1: instalar (macOS / Linux):
curl -fsSL https://raw.githubusercontent.com/tiagovilasboas/downshift/main/install.sh | sh
O instalador baixa o arquivo da versão e o checksums.txt da mesma release no GitHub e verifica o sha256 antes de instalar qualquer coisa. Se a soma não bater ou o arquivo de checksums faltar, ele para. DOWNSHIFT_SKIP_CHECKSUM=1 instala sem verificação e avisa que fez isso. As releases também estão na página de Releases, com o mesmo checksums.txt.
Proveniência do build (opcional). As releases geradas pelo job release trazem uma atestação de proveniência do build no GitHub. Depois da verificação do sha256, se a CLI gh estiver instalada, o install.sh executa gh attestation verify <arquivo> --repo tiagovilasboas/downshift e imprime Build provenance verified. Por padrão, isso nunca bloqueia: sem gh, sem gh auth login ou com uma release anterior às atestações, ele mostra um aviso e continua só com o sha256. DOWNSHIFT_REQUIRE_ATTESTATION=1 transforma qualquer resultado diferente de "verificado" em erro, e nada é instalado; DOWNSHIFT_SKIP_ATTESTATION=1 pula a checagem. No fim, o instalador diz o que ficou comprovado: "sha256 and GitHub build provenance" ou "sha256 only" (um download íntegro, mas que não prova quem publicou). Ele aceita apenas uma versão estrita vMAJOR.MINOR.PATCH[-prerelease], baixa com curl --proto '=https' --tlsv1.2 e instala por meio de um nome temporário seguido de renomeação. Manualmente: gh attestation verify downshift_<ver>_<os>_<arch>.tar.gz --repo tiagovilasboas/downshift.
O install.sh ainda trata um argumento sem flag como a versão da release. --explicit-upshift pode vir antes ou depois dessa versão. Ele grava "explicit_upshift": true em session-models.json sem remover as listas de harnesses que já estiverem ali. A mesma chave em tempo de execução é DOWNSHIFT_EXPLICIT_UPSHIFT=1. O padrão é desligado. Veja session-models.md.
Passo 2: visualizar e depois ligar os hooks:
downshift setup --dry-run # mostra o diff de cada harness encontrado; não grava nada
downshift setup # pergunta antes, faz backup dos arquivos e depois mescla os hooks
No Claude Code, o setup liga PreToolUse (matcher Agent|Task), PostToolUse, PostToolUseFailure e SubagentStop, configura a barra de status quando não há nenhuma, e define "model": "opusplan" (Opus em modo plan, Sonnet na execução) e "permissions": {"defaultMode": "plan"} (as sessões começam em modo plan) para as chaves que você ainda não definiu. Valores existentes são mantidos, e --no-session-policy pula as duas coisas. O mod "You should know" embutido do Claude Code ("enabledPlugins": {"cc-plugin-you-should-know@builtin": true}) é opt-in, porque cada verificação é uma requisição cobrada ao modelo da sessão: o setup mostra uma sugestão, e downshift setup --you-should-know a grava (/plugin disable cc-plugin-you-should-know@builtin a desliga) (política de sessão principal). Ele também encontra Cursor, Codex, Antigravity e KiroCrew, mantém chaves não relacionadas e hooks existentes, e é idempotente. downshift setup --undo restaura o backup mais recente. O KiroCrew (Experimental) tem um comando de configuração próprio, que gera o wrapper e o registra; veja KiroCrew. O JSON manual está em Configuração manual abaixo.
Passo 3: testar o classificador com os seus próprios prompts:
downshift doctor # checklist: binário, hooks por harness, estado, pontuações
downshift try "rename the userId variable" claude-code # o que seria escolhido, e por quê
Passo 4: confirmar que funciona. Abra uma nova sessão do Claude Code e peça para criar um subagente para uma tarefa trivial. Você verá uma linha assim no stderr:
downshift: TRIVIAL task → downshift to claude-haiku-4-5
Essa linha significa que o hook disparou e emitiu uma reescrita antes de o subagente começar. Se o harness aplicou a reescrita é outro fato. downshift stats separa rewrite_emitted de honrada, e a matriz diz o que está verificado por plano.
Confirmar que a reescrita foi honrada (importante para a validação de saída do beta):
- Peça ao Claude Code: "spawn a subagent to rename the userId variable in auth.ts"
- Abra os logs internos ou o monitor do Claude Code (confira o modelo real do subagente na interface)
- Confirme que ele começou no haiku, e não no modelo de fronteira padrão da sessão
- Isso prova que a reescrita do hook não foi só emitida: ela foi de fato aplicada pelo harness
Passo 5: ver o que aconteceu. downshift stats --days=1 mostra decisões e tokens economizados; downshift session --tree mostra os subagentes desta sessão como uma árvore. No Claude Code, o plugin expõe /downshift:status; o alias manual opcional /downshift está em O comando /downshift.
Passo 6: (opcional) acompanhar ao vivo. downshift watch redesenha a árvore de subagentes da sessão atual (modelo, status final, tokens, motivo) a cada segundo, em todos os harnesses; downshift session --tree imprime uma vez só, e /downshift:status ou /downshift mostra isso dentro do Claude Code. O widget flutuante mais antigo continua disponível: dsmon, widget de monitoramento ao vivo.
Configuração manual (Claude Code)
Use isto no lugar do setup se preferir editar ~/.claude/settings.json por conta própria. O matcher do PreToolUse é Agent|Task. O schema de Task do Claude Code aceita só nomes de família (haiku, sonnet, opus, fable) em model. O Downshift grava o nome de família do catálogo por você, e deixa o subagente como está quando um modelo não tem um.
{
"hooks": {
"PreToolUse": [
{ "matcher": "Agent|Task", "hooks": [{ "type": "command", "command": "downshift claude-code" }] }
]
}
}
Para o status do filho e o uso real, adicione também PostToolUse e PostToolUseFailure (downshift claude-code-post-tool-use) e SubagentStop (downshift claude-code-subagent-stop), como o setup faz.
Testar localmente antes de conectar o hook
Antes de adicionar o hook ao Claude Code, teste a lógica do classificador e do hook localmente:
Teste 1: só o classificador (terminal):
downshift try "rename the userId variable" claude-code
downshift try "rearchitect the payment flow" claude-code
downshift try "implement the CSV export" claude-code
Teste 2: hook completo (JSON):
downshift claude-code < examples/claude-code-pretooluse-session.json
Isso imita exatamente o que o Claude Code vai enviar. A saída é o JSON que o harness vai aplicar, mais o retorno no stderr com a decisão e um ID de feedback para acompanhamento.
Veja examples/ para payloads de exemplo. claude-code-pretooluse-session.json traz uma lista session_models, então mostra uma reescrita de verdade.
⚠️ Só Claude Code Pro/Max/Teams/API. O plano gratuito não tem subagentes reais e bloqueia instalações pela rede. Veja Compatibilidade de planos antes de continuar.
Instalação (Claude Code)
Status: Concluído. Reescrita observada e honrada, uso e fim do filho registrados, plugin e política de sessão (evidência, auditoria de cobrança).
Gere ou instale o binário único (sem runtime, sem dependências):
# Recomendado: instalador de uma linha (macOS / Linux, detecta a arquitetura automaticamente)
# Instala em /usr/local/bin/downshift; não precisa mexer no PATH
curl -fsSL https://raw.githubusercontent.com/tiagovilasboas/downshift/main/install.sh | sh
# Alternativa: toolchain do Go (qualquer plataforma)
go install github.com/tiagovilasboas/downshift/cmd/downshift@latest
Nota sobre o toolchain do Go:
go installcoloca o binário em~/go/bin. Se aparecerdownshift: command not found, adicione o bin do Go ao PATH:export PATH="$HOME/go/bin:$PATH" # sessão atual echo 'export PATH="$HOME/go/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc # permanenteO instalador
curlacima evita isso, porque grava direto em/usr/local/bin.
Binários pré-compilados para macOS (arm64/amd64), Linux (arm64/amd64) e Windows (amd64) estão na página de Releases.
Caminho mais rápido: o downshift setup encontra o Claude Code, o Cursor, o Codex e o Antigravity nesta máquina e mescla todos os hooks (além da barra de status do Claude Code, quando nenhuma estiver configurada) nos arquivos de hook de cada um, usando o caminho absoluto deste binário. Ele mantém as chaves não relacionadas e os hooks existentes, é idempotente, mostra um diff e salva um backup com data e hora. --dry-run não grava nada, --yes pula a pergunta, --undo restaura o backup mais recente. Para configurar o KiroCrew (Experimental), rode downshift setup kirocrew --dry-run e depois downshift setup kirocrew; o comando gera o wrapper, registra o hook nativo e instala a instrução compacta. Veja a seção KiroCrew.
Adicione o hook em ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Agent|Task",
"hooks": [
{ "type": "command", "command": "downshift claude-code" }
]
}
]
}
}
É só isso. A partir da próxima sessão, cada criação de subagente passa pelo hook; se o modelo é reescrito depende da tarefa (com confiança, sem risco) e do plano (matriz de harnesses). Em trabalho natural, a maioria das criações é segurada, e isso é intencional.
Instalação pelo plugin (Claude Code)
Os mesmos quatro hooks e o comando /downshift:status vêm como um plugin do Claude Code cuja raiz é este repositório. Ele precisa do binário downshift no PATH (passo 1 acima) e substitui o passo 2 só para o Claude Code. O downshift setup faz essa instalação por você quando consegue: executa claude plugin marketplace add e claude plugin install downshift@downshift, e depois remove os hooks do Downshift que ele gravou antes no settings.json (o plugin já os traz; manter os dois faria cada criação de subagente ser roteada duas vezes). Ele só instala o plugin quando o claude está no PATH e um shell de login resolve downshift para o mesmo binário que executa o setup, porque os hooks do plugin chamam downshift pelo nome; caso contrário, continua gravando os hooks no settings.json e diz o motivo. --no-plugin sempre mantém os hooks no settings.json. Os outros harnesses continuam usando downshift setup.
/plugin install downshift --marketplace tiagovilasboas/downshift # Claude Code 2.1.275+
ou em dois passos, /plugin marketplace add tiagovilasboas/downshift e depois /plugin install downshift@downshift. O plugin liga PreToolUse, PostToolUse, PostToolUseFailure, SubagentStop e UserPromptSubmit (para a Inteligência de Código do Downshift) a partir de hooks/hooks.json (cada entrada só chama o binário), adiciona as skills downshift-setup, downshift-audit e cost-reducer, e o comando abaixo como /downshift:status. No Claude Code 2.1.287 ou superior, ele também carrega o mod cache-tax incluído: um envio frio em um contexto de 50 mil tokens ou mais é retido uma vez, com o preço estimado da reescrita (reenvie para pagar, ou use /cache-tax guard warn para só ser avisado), e /keepwarm 90m mantém o cache aquecido durante uma pausa, com uma pequena requisição ao modelo a cada 50 minutos ociosos, o que gasta uso. Se você já instalou cache-tax@claude-code-mods, desinstale uma das cópias; o doctor avisa. O marketplace também oferece savvy-progress e filetree, uma instalação para cada (o downshift setup instala os dois no Claude Code; manualmente: /plugin install savvy-progress@downshift, /plugin install filetree@downshift; veja mods/README.md). Ele não configura opusplan, o modo plan, a barra de status nem o mod You should know: isso são configurações, não hooks, e o downshift setup as grava (You should know só com --you-should-know). Defina "model": "opusplan" e "permissions": {"defaultMode": "plan"} em ~/.claude/settings.json por conta própria (ou /model opusplan numa sessão), e /plugin enable cc-plugin-you-should-know@builtin para o You should know (uma requisição cobrada a cada verificação), se quiser isso sem o setup; veja política de sessão principal.
Use um canal só. Um hook de plugin e um hook de configuração com o mesmo comando rodam os dois, então uma sessão ligada pelos dois roteia cada criação duas vezes. O downshift setup pula os hooks quando vê o plugin ativado em ~/.claude/settings.json (ele ainda aplica a política de sessão e a barra de status), e o downshift doctor avisa quando encontra os dois. Para trocar do setup para o plugin, rode antes downshift setup --undo. A detecção lê só o arquivo de configurações do usuário; um plugin ativado pelo .claude/settings.json de um projeto não é visto.
O comando /downshift (Claude Code)
Opcional quando a instalação é manual. É um comando de barra que mostra o que o Downshift fez na sessão atual (uma árvore de subagentes, por que o último rodou onde rodou, pausa e retomada):
mkdir -p ~/.claude/commands
cp commands/status.md ~/.claude/commands/downshift.md # a partir deste repositório
Com o plugin, ele já existe como /downshift:status. Depois, no Claude Code: /downshift:status, /downshift:status --why, /downshift:status --pause, /downshift:status --resume. A cópia manual opcional acima mantém /downshift como alias local. O comando só executa downshift session pela ferramenta Bash, que a linha allowed-tools limita a esse comando. O mesmo downshift session funciona no terminal para qualquer harness. Veja session-view.md.
Inteligência de Código do Downshift (DCI)
O Downshift inclui um mecanismo opcional de inteligência de código que descobre o código do repositório, extrai símbolos AST (Go) e léxicos, pontua a relevância com BM25 e injeta contexto estrutural compacto (até 3.500 bytes UTF-8) pelo UserPromptSubmit no Claude Code.
Por padrão, o DCI está off. Para ativar em um repositório:
downshift dci enable active # injeta contexto nos prompts do Claude Code
downshift dci enable observe # observa e registra telemetria, sem injetar
downshift dci status # mostra o modo ativo e as estatísticas do cache
downshift dci doctor # confere permissões, descoberta e latências
downshift dci benchmark # roda benchmarks locais de desempenho e relevância
Para ver a telemetria e as métricas do DCI:
downshift stats --dci # mostra os prompts, as injeções e as latências do DCI
Veja code-intelligence.md para os detalhes de arquitetura.
Instalação (Cursor)
Status: Funcional. A reescrita é emitida numa criação real de subagente; a aplicação pelo harness não está confirmada, e ela é descartada nos planos Free e Pro legado (evidência, diagnóstico de lacunas).
O protocolo de hooks do Cursor espelha o do Claude Code: a mesma interceptação preToolUse, com updated_input para reescrever o modelo do subagente. Gere o binário e depois adicione o hook em .cursor/hooks.json (nível do projeto) ou ~/.cursor/hooks.json (global):
{
"version": 1,
"hooks": {
"preToolUse": [
{ "command": "downshift cursor", "matcher": "Task" }
]
}
}
O matcher: "Task" limita o hook às criações de subagentes. O Cursor observa o arquivo de configuração e o recarrega ao salvar.
Instalação (Codex)
Status: Funcional. A reescrita é emitida numa criação real de subagente; a aplicação pelo harness é inferida, não observada (evidência).
O Codex cria subagentes por uma ferramenta reservada spawn_agent, no multi_agent_v2. Você não consegue colocar um modelo na chamada visível ao provedor, mas um hook PreToolUse pode injetar o modelo e o reasoning_effort na entrada da ferramenta antes de o filho começar, que é exatamente onde o downshift roda.
Ative as flags de recurso em config.toml:
[features]
hooks = true
[features.multi_agent_v2]
enabled = true
Registre o hook em .codex/hooks.json (projeto) ou ~/.codex/hooks.json (global). O matcher cobre os nomes de ferramenta Agent e o spawn_agent com namespace:
{
"hooks": {
"PreToolUse": [
{
"matcher": "(^Agent$|.*spawn_agent$)",
"hooks": [
{ "type": "command", "command": "downshift codex" }
]
}
]
}
}
Confie no hook antes de testar
O Codex não executa hooks locais recém-configurados até você revisar e confiar no comando exato. Isso é um controle de segurança do Codex, não um erro do downshift. Depois de salvar a configuração, abra o Codex e rode:
/hooks
Revise e confie no hook downshift codex, e depois abra uma nova sessão antes de pedir ao Codex para criar um subagente. Enquanto o hook não for confiável, o Codex o ignora e o subagente mantém o modelo da sessão sem mudança.
No Codex, o downshift roteia dois eixos ao mesmo tempo: o tier do modelo e o esforço de raciocínio (low para trabalho trivial, até high para trabalho de fronteira). Numa sessão que oferece GPT-6 Sol e Luna, um subagente trivial pode ir de gpt-6-sol para gpt-6-luna com esforço baixo, desde que a lista permitida da sessão e o Codex aceitem a entrada reescrita.
O Downshift aplica o esforço de raciocínio escolhido, exceto quando uma trava segura a decisão (o subagente mantém o esforço pedido) ou quando a decisão não tem confiança e não reescreve o modelo. Uma revisão de código é uma tarefa de fronteira, então uma sessão com gpt-5.6-terra roteia o subagente para gpt-5.6-sol com esforço alto. gpt-6-astra está marcado com routing: "explicit_only" no catálogo. Com o explicit_upshift desligado por padrão, o downshift não o escolhe. Se o subagente atual já roda no Astra, o modelo é preservado sem mudança. Defina "explicit_upshift": true em session-models.json, exporte DOWNSHIFT_EXPLICIT_UPSHIFT=1 ou rode install.sh --explicit-upshift para que o upshift o escolha quando ele estiver no conjunto de créditos deste harness (ou quando este harness não informar conjunto de créditos). O claude-fable-5-1-thinking-high do Cursor segue o mesmo princípio de opt-in. O claude-fable-5-1 do Claude Code não é explicit_only; acrescente esse id à lista da sessão para ativá-lo. Para marcar qualquer outro modelo como explicit-only, adicione "routing": "explicit_only" à entrada dele em ~/.downshift/catalog.json (o diretório de estado; ~/.harness-downshift/ só é lido quando é o diretório legado em uso).
Um prompt puramente mecânico, como Use a subagent to only list the .go files, é roteado para gpt-6-luna com esforço baixo, quando esse id exato está na lista permitida da sessão.
A especificação de criação
multi_agent_v2do Codex ainda está evoluindo. O downshift preserva os campos reservados e falha de forma aberta, mas fixe a versão exata do Codex que você usa e mantenha um teste de aceitação com uma criação real.
Lista permitida da sessão
O Downshift só grava um id de modelo quando esse id está na sessão atual. O catálogo fornece tier, custo, família e esforço para os ids que também estão na sessão. Ele nunca adiciona um id que a sessão não tem. Se a lista da sessão não puder ser determinada, o hook deixa o modelo atual sem mudança.
Os hooks do Cursor, do Claude Code e do Codex enviam o modelo ativo, não a lista completa do seletor. O Codex também envia um ID de sessão; o Downshift valida e faz hash desse ID antes de registrar, para que as decisões locais possam ser agrupadas sem guardar o identificador bruto. Registre os ids de modelo selecionáveis em ~/.downshift/session-models.json (legado: ~/.harness-downshift/). Uma lista no nível superior do harness é um fallback; uma lista exata sessions.<harness>.<session_id> tem precedência. As listas são mantidas pelo operador: o Downshift não consulta o seletor de modelos do Codex nem infere a elegibilidade da conta. A exceção é o Claude Code: sem lista de nenhuma fonte, ele infere a sessão pelo modelo atual (a escada de tiers do catálogo abaixo, terminando nesse modelo), então pode fazer downshift, mas nunca upshift além do que a sessão já roda; DOWNSHIFT_INFER_SESSION=off desliga isso. Se um payload do hook trouxer session_models ou available_models, essa lista é usada e o arquivo é ignorado. Detalhes e evidências: session-models.md. session-models.example.json é uma sessão do Cursor de 27/09/2026. É um exemplo, não o padrão para todo usuário.
Para a cota do Cursor, o hook pode ler, offline, uma exportação nativa completa indicada por DOWNSHIFT_CURSOR_NATIVE_FILE, antes do cache de cota canônico. Uma exportação configurada malformada ou desatualizada segura o roteamento. A extensão externa experimental foi testada no Cursor 3.24.9 e não conseguiu acessar a API cursor, que só existe embutida, mesmo com uma flag explícita de API proposta; nenhuma exportação foi gerada. Instalar essa extensão não ativa a coleta nessa versão. Veja o diagnóstico de runtime. A pertinência ao provedor continua sendo a fonte de verdade; não a substitua por uma lista fixa de modelos.
Harnesses experimentais
Experimental (prova de conceito). O KiroCrew roda só em modo de política (bloqueia e tenta de novo, sem reescrita no lugar), e a reescrita do Antigravity usa um envelope
overwriteque não é um campo documentado do fornecedor; cada um tem um filho observado numa build e nenhum registra o fim do filho. Todo recurso continua calculado para eles (regra de camadas,cmd/downshift/conformance_test.go), e os adaptadores, os testes e os hooks ficam no repositório, mas trate-os como provas de conceito, não como instalações suportadas. Instale-os só se você aceitar isso.
Antigravity (Google DeepMind)
Status: Experimental. Um filho observado no desktop 2.21.1 (evidência); nenhum fim de filho registrado.
O Antigravity executa subagentes por invoke_subagent e aceita a modificação de argumentos no protocolo de hook PreToolUse por meio de overwrite.
Registre o hook em ~/.gemini/config/hooks.json:
{
"PreToolUse": [
{
"matcher": "invoke_subagent",
"command": "downshift antigravity"
}
]
}
Quando o Antigravity tenta criar um subagente (por exemplo, herdando o modelo pai ou pedindo pro), o downshift antigravity intercepta a chamada da ferramenta, classifica a última entrada de Subagents que tem um Prompt não vazio (não necessariamente Subagents[0]; linhas finais sem Prompt são ignoradas) e reescreve o Model desse subagente (flash_lite para tarefas mecânicas, flash para o tier intermediário), por meio de um envelope overwrite que não é um campo documentado do fornecedor. O evento de roteamento vai para ~/.downshift/events.jsonl.
KiroCrew (modo de política pelo hook nativo da Kiro CLI)
Status: Experimental. Bloqueio e nova tentativa observados uma vez na Kiro CLI 2.29.0; sem reescrita no lugar (evidência).
Para a Kiro CLI 2.29, registre o Downshift pela configuração persistente agent.kiro_hooks do KiroCrew. O KiroCrew gera a especificação de agente consumida pela Kiro CLI, cujo hook nativo preToolUse roda antes da ferramenta: exit 0 permite; exit 2 bloqueia e devolve o stderr ao agente. Não existe canal updated_input, então o adaptador usa o modo de política. Ele classifica uma criação pendente com um modelo filho explícito e:
- tier certo já →
exit 0, permite em silêncio; - divergência de tier com confiança →
exit 2, bloqueia com uma mensagem que nomeia o modelo para recriar (e, para um tier pequeno, um lembrete para reduzir o contexto e caber na janela menor); - downshift incerto, modelo desconhecido ou ferramenta que não é de subagente →
exit 0, falha de forma aberta. O roteador nunca bloqueia uma criação por causa da própria dúvida.
Use a ferramenta MCP spawn_run do kirocrew-core com os argumentos task e model explícitos. O pipeline nativo use_subagent / crew pode omitir o modelo filho; essas chamadas ficam fora da cobertura do roteamento. O Downshift nunca infere o modelo filho a partir do modelo do pai nem de um título da interface. O classificador é determinístico; o agente precisa tentar de novo uma criação bloqueada com o modelo recomendado.
Configuração automática
Rode os comandos no seu terminal. O modo de prévia mostra o diff sem gravar; depois, execute a configuração:
downshift setup kirocrew --dry-run
downshift setup kirocrew
O Downshift grava um wrapper em ~/.downshift/bin/kirocrew-pre-tool-use.sh (.cmd no Windows), registra-o em agent.kiro_hooks.preToolUse no ~/.kiro/crew/config.json existente e instala a instrução compacta. Se o arquivo de configuração não existir, o KiroCrew ainda não está configurado; se a gravação do wrapper falhar, o arquivo não é alterado. downshift setup --undo restaura os dois. Depois, reinicie o KiroCrew para regenerar a especificação do agente e rode downshift doctor.
O Agent Dashboard do KiroCrew mostra o histórico e a saúde dos agentes a partir do runs.db do ecossistema ao qual está conectado. Ele não lê o diretório de estado do Downshift, então não mostra decisões de roteamento nem economias; use downshift stats para isso.
Configuração manual
Importante: existem dois caminhos de hook.
~/.kiro/agents/kirocrew.jsoné gerado pelo KiroCrew e sobrescrito a cada reinício; edições ali se perdem. O caminho durável de registro é~/.kiro/crew/config.json, viaagent.kiro_hooks.~/.kiro/crew/hooks.jsoné um registro de hooks separado e informativo (umrun_countcrescente prova que foi invocado; o código de saída não bloqueia o caminho da ferramenta). Useconfig.jsonpara a aplicação de políticas. Confirmado na Kiro CLI 2.29.0, em 10/10/2026.
- Gere o binário:
go build -o downshift ./cmd/downshift - Torne executável o wrapper versionado:
O wrapper chama o bináriochmod +x scripts/kirocrew-pre-tool-use.shdownshiftdo repositório com o subcomandokirocrew. Mantenha-o ao lado deste build, no checkout do repositório. - Mescle esta entrada em
~/.kiro/crew/config.json, preservando a configuração e os hooks existentes. Troque o caminho de exemplo pelo caminho absoluto do wrapper no seu checkout:
O KiroCrew mescla{ "agent": { "kiro_hooks": { "preToolUse": [ { "matcher": "*", "command": "/absolute/path/to/downshift/scripts/kirocrew-pre-tool-use.sh" } ] } } }kiro_hookscom os hooks embutidos dele ao gerar a especificação do agente. Ele aceitacommandcomo um caminho absoluto de executável existente, preservacommandematcher, e descartatimeout_ms. Comandos com argumentos de shell são rejeitados. O wrapper carrega o subcomando, então ele sobrevive à geração. Não edite~/.kiro/agents/kirocrew.json: o KiroCrew regenera esse arquivo e suas edições se perderão. - Preencha a lista de modelos da sessão
kirocrewcom os modelos realmente selecionáveis na Kiro CLI instalada. Siga session-models.md para a ordenação e a precedência da descoberta. Sem um alvo elegível conhecido, o modo de política permite a criação sem mudança. - Carregue kirocrew-routing-guide.md nas instruções do agente e reinicie o KiroCrew para que ele regenere a especificação. Confirme que o
preToolUsegerado inclui o wrapper e os hooks embutidos existentes. - Teste de fumaça do adaptador com modelos disponíveis conhecidos (sem criar subagente):
Troque o marcador por um modelo real e atual. Isso verifica só a saída do adaptador; não prova que o harness bloqueia a execução.printf '%s\n' '{"tool_name":"spawn_run","tool_input":{"task":"rename a variable","model":"YOUR_AVAILABLE_FRONTIER_MODEL"}}' \ | ./scripts/kirocrew-pre-tool-use.sh # Uma divergência confiante com um alvo elegível retorna exit 2 e model=...
Os hooks de ferramenta ~/.kiro/crew/hooks.json são informativos: podem executar depois que a ferramenta começa, e o código de saída deles não bloqueia esse caminho. Um run_count crescente prova apenas a invocação. Não use esse registro como aplicação de política, nem mantenha uma duplicata informativa do hook de política nativo.
Evidência de aceitação e cobertura
As instruções vinculadas são o guia inferencial do eixo de comportamento. O hook de política pré-ferramenta nativo é o sensor computacional dessa mesma preocupação. Teste um spawn_run real com uma tarefa trivial e um modelo de fronteira explícito: prove que ele é bloqueado antes de o filho começar e, depois, tente de novo uma vez com o modelo recomendado. Confira o modelo real do filho no registro nativo de subagentes do KiroCrew. Chamadas sem modelo precisam passar sem mudança.
A regeneração da especificação e um reinício seguido desses testes são o sensor computacional de aderência da arquitetura, pareado com este guia de configuração. As decisões de roteamento no events.jsonl do diretório de estado dão observações locais contínuas (padrão ~/.downshift; legado ~/.harness-downshift). Uma decisão bloqueada só prova a aplicação quando pareada com o resultado nativo; ela não prova a execução bem-sucedida do filho, o uso nem a economia. Um observador de conformidade PostToolUse continua sendo uma ferramenta separada de mantenedor (DS-04); esta configuração não instala um. O bloqueio nativo, a nova tentativa e o reconhecimento do modelo servido foram observados em 10/10/2026 com a Kiro CLI 2.29.0; veja a evidência específica da build.
dsmon: widget de monitoramento ao vivo
Prefira
downshift watch. A árvore de sessão ao vivo está embutida no bináriodownshift(sem build separado, em todos os harnesses): veja session-view.md. Odsmoncontinua compilável e está documentado abaixo.
cmd/dsmon é um comando separado neste repositório: um widget flutuante de terminal que mostra trocas de modelo, harness, distribuição de tiers e economia estimada em tokens em tempo real. Ele lê ~/.downshift/events.jsonl e atualiza a cada 800 ms. Sem dependências externas; só a biblioteca padrão do Go.
╭──────────────────────────────────────────────────────╮
│ dsmon downshift monitor │
│ harness kirocrew ◉ live │
│ switches today ──────────────────────────────────── │
│ 04:03 opus → haiku trivial -75% │
│ 04:02 haiku → opus complex ↑ │
│ 04:01 opus → sonnet medium -50% │
│ stats ────────────────────────────────────────────── │
│ 35 events 22↓ 2↑ 8✓ │
│ est. saved ~7K tokens ¹ │
│ ¹ estimated · actual tokens not yet tracked │
╰──────────────────────────────────────────────────────╯
04:03:51 · ctrl+c to quit
Compilar e executar
# Compila o monitor (separado do binário de hook `downshift`)
go build -o dsmon ./cmd/dsmon
# Executa no terminal atual
./dsmon
# Abre uma janela flutuante de terminal (detecta iTerm2 / kitty / Ghostty / Terminal.app)
./cmd/dsmon/launch.sh
O que ele mostra
| Campo | Origem | Observações |
|---|---|---|
| Harness | events.jsonl → campo harness |
Último harness visto hoje |
| Trocas | events.jsonl → verdict + campos de modelo |
Últimas 7 decisões de roteamento |
| Eventos / ↓ ↑ ✓ | events.jsonl |
Contagens de hoje por veredito |
| Economia estimada (tokens) | Tokens de filhos que rodaram em modelo mais barato que o pedido, na visão compartilhada telemetry.TokenSavings |
Observado onde o harness informa tokens; não é cobrança |
| Tokens | Tokens observados do filho, quando o harness os informa | Não vem da fatura do provedor |
Nota sobre o consumo de tokens. O hook de roteamento PreToolUse não recebe dados de uso de tokens. No Claude Code, um hook SubagentStop separado (downshift claude-code-subagent-stop) lê a transcrição do filho concluído e registra as contagens de tokens e o modelo informados; veja session-models.md. As visualizações atuais do Downshift atribuem e comparam esses tokens, sem valores em dólar. Tokens movidos para um modelo mais barato não provam que menos tokens foram consumidos ou que a fatura foi menor. Consulte separadamente o painel de cobrança do provedor para verificar os valores cobrados.
CLI do Grok (configuração, não hook)
A CLI do Grok é a exceção honesta, e vale ser preciso sobre o motivo.
O Grok tem subagentes (spawn_subagent, até cerca de 8 em paralelo) e lê os arquivos de hook do Claude Code / Cursor. Mas o contrato do hook PreToolUse dele é só permitir ou negar: { "decision": "deny", "reason": "…" }. Não há updatedInput documentado, então um hook não consegue reescrever o modelo de um subagente como faz no Claude Code, no Cursor e no Codex. Um hook do downshift no Grok só poderia bloquear uma criação, e isso não é o trabalho dele.
Há uma segunda complicação: até a redação deste texto, o Grok Build traz um único modelo de código (grok-4.6, com raciocínio configurável), não uma escada de modelos pequeno/médio/fronteira. Então, no Grok, o roteamento não é "trocar o modelo": é ajustar o esforço de raciocínio. Trabalho barato roda o grok-4.6 com esforço baixo; as tarefas difíceis rodam com esforço alto. O mesmo princípio, outro botão.
O Grok expõe os dois como configuração de primeira classe, o que é mais robusto que uma reescrita em tempo de execução. Defina o raciocínio por papel de subagente em ~/.grok/config.toml:
# Tipos somente leitura embutidos → raciocínio baixo (barato e rápido).
[subagents.personas.explore]
reasoning_effort = "low"
# Papéis personalizados têm o próprio padrão de raciocínio.
[subagents.roles.reviewer]
description = "Reviews generated changes before commit"
default_capability_mode = "read-only"
reasoning_effort = "low"
[subagents.roles.architect]
description = "Cross-cutting design and migrations"
reasoning_effort = "high" # torque para as curvas difíceis
# Se o seu catálogo ganhar modelos mais baratos ou mais fortes, fixe-os por tipo também:
# [subagents.models]
# explore = "grok-4.6"
A precedência é: substituição explícita na criação → padrão do papel → padrão da persona → sessão pai. Assim, esses fixos valem a não ser que o agente seja instruído de outra forma. downshift try "<prompt>" grok informa qual tier uma tarefa pede; mapeie esse tier para o esforço de raciocínio de um papel na configuração, uma vez.
Se uma build futura do Grok adicionar
updatedInputaoPreToolUse(ou um catálogo multimodelo), um adaptador de hookdownshift grokvira um encaixe direto: o classificador e a política já são independentes de harness. Até lá, a configuração é a alavanca certa e documentada.
Compatibilidade de planos (leia antes de instalar)
Nem todo plano suporta roteamento de modelos de subagentes. Esta é uma restrição rígida no nível do harness, não um bug do Downshift. Matriz de evidências: harness-matrix.md.
Claude Code
| Plano | Existem subagentes? | O roteamento de modelos funciona? |
|---|---|---|
| Free | ❌ Não há subagentes reais | — |
| Pro / Max / Teams | ✅ Sim | ✅ Observado em 06/10/2026 (modelo filho informado pela API) |
| API (direta) | ✅ Sim | Esperado (mesmo caminho de hook); a evidência de 06/10/2026 não registrou o plano |
O Claude Code no plano gratuito roda num contêiner isolado, sem saída de rede; então go install vai falhar. O recurso de subagentes só existe nos planos pagos.
Cursor
| Plano / preço | Existem subagentes? | O roteamento de modelos funciona? |
|---|---|---|
| Free | ✅ Limitado | ⚠️ updated_input.model é ignorado silenciosamente (problema conhecido) |
| Pro (por requisição / legado) | ✅ Sim | ⚠️ o campo model em Task só aceita "fast"; a substituição é descartada silenciosamente |
| Pro / Ultra (por uso) | ✅ Sim | ⚠️ Reescrita emitida; modelo filho não confirmado (P1.6) |
O hook preToolUse do Cursor dispara e o Downshift roda, mas a reescrita de model é descartada silenciosamente nos planos legados e gratuitos. Registrado no fórum do Cursor. Nos planos Pro/Ultra por uso, em que a seleção de modelo de subagentes é ampliada, o Downshift emite a reescrita; se o harness roda o filho nesse modelo não está confirmado (ainda não há prova do modelo filho — P1.6, linha Não confirmado da matriz).
Codex
| Plano | Existem subagentes? | O roteamento de modelos funciona? |
|---|---|---|
Qualquer (com multi_agent_v2 ativado) |
✅ Sim | ✅ Inferido em 02/10/2026 (a criação seguinte pediu o modelo escrito), não observado |
Requer [features] multi_agent_v2 e hooks = true em config.toml.
Resumo
O Downshift atende a todos os harnesses acima a partir do mesmo núcleo, e o Claude Code é o harness principal: o mais completo (modelo de sessão inferido, hooks de uso e de fim do filho, /downshift:status, barra de status) e o mais verificado. Escolha-o quando puder.
O Downshift é mais eficaz em:
- Claude Code Pro / Max / Teams / API: roteamento completo de modelos pelo hook
- Codex com multi_agent_v2 ativado: modelo + reasoning_effort emitidos; a aplicação é inferida, não observada
- Cursor Pro/Ultra em planos por uso: reescrita emitida; modelo filho não confirmado (P1.6)
Em planos gratuitos ou no preço legado do Cursor, o hook roda, mas as reescritas de modelo podem ser ignoradas silenciosamente pelo harness. A ferramenta falha de forma aberta: o subagente é criado mesmo assim, só sem a troca de modelo.
Solução de problemas
downshift: command not found depois do go install
O go install coloca o binário em ~/go/bin, que pode não estar no seu PATH.
export PATH="$HOME/go/bin:$PATH" # sessão atual
echo 'export PATH="$HOME/go/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc # permanente
O instalador curl (install.sh) evita isso, porque grava direto em /usr/local/bin.
O hook roda, mas o modelo não muda (Cursor)
Nos planos gratuitos do Cursor e nos planos legados por requisição, updated_input.model é descartado silenciosamente pelo harness. Este é um problema conhecido do Cursor. O hook dispara e o binário roda (você verá a saída no stderr), mas a reescrita do modelo não tem efeito. Veja Compatibilidade de planos.
Nenhuma saída no stderr: o hook não dispara
Confira o matcher. A ferramenta de subagente do Claude Code é Agent (builds antigas: Task), então o matcher precisa ser "Agent|Task", como o setup e o plugin gravam. Confirme o binário em si com:
# Deve imprimir de imediato uma decisão de permissão em JSON
echo '{"hook_event_name":"PreToolUse","tool_name":"Task","model":"claude-opus-5-5","tool_input":{"prompt":"test"}}' | downshift claude-code
Se isso imprimir JSON, o binário funciona. Se o hook ainda não disparar numa sessão real, confira se o settings.json é um JSON válido e se o caminho para o downshift é o caminho absoluto (ou se ele está no PATH).
go install falha no Claude Code gratuito
O Claude Code gratuito roda num contêiner isolado, sem saída de rede. Instale o binário na sua máquina local primeiro, e depois use o hook: o binário roda na sua máquina, não dentro do contêiner do Claude Code.
O veredito mostra UNKNOWN em vez de DOWNSHIFT
UNKNOWN significa que nenhum modelo atual foi informado. Passe o modelo atual como terceiro argumento para o try:
downshift try "rename the variable" claude-code claude-opus-5-5
# → DOWNSHIFT
No hook em execução, isso é tratado automaticamente: o evento traz o modelo da sessão e o adaptador o lê.