Saída longa de teste e build no Claude Code: por que gasta contexto e como cortar

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

Toda saída de comando que o Claude Code lê entra na conversa e é enviada de novo em cada requisição seguinte. Uma suíte verde imprime uma linha por pacote ou teste que não diz nada além de PASS. Rode menos testes, use as flags silenciosas, cuidado com o | tail e deixe a falha inteira. O downshift compact automatiza a última parte: encurta só a saída de sucesso limpa, deixa a falha byte a byte e devolve o exit code real.

Por que a saída longa de teste gasta contexto no Claude Code?

Uma rodada verde de testes é um bolo de comprovantes iguais. Cada linha diz a mesma coisa, passou, e o Claude Code guarda o bolo inteiro no bolso até o fim da sessão.

É assim que o contexto funciona. Quando o Claude roda um comando pela ferramenta Bash, a saída entra na conversa como resultado de ferramenta. A página de custos da Anthropic diz que o Claude Code envia a conversa inteira em toda requisição, e cada chamada de ferramenta gera outra requisição com os resultados. O cache de prompt cobra menos por essa releitura, mas ela continua acontecendo, continua ocupando a janela de contexto e antecipa a compactação automática.

Saída de sucesso é quase toda repetição: uma linha por pacote no go test, uma linha ou um ponto por teste na maioria dos runners, tempos e um resumo. O modelo precisa de um fato só: tudo passou, com exit code 0. Na falha é o contrário. A asserção, o diff e o stack trace são a informação, então a falha precisa ficar inteira.

A regra do resto do guia é essa: encolher o sucesso, nunca a falha.

Como reduzir os tokens da saída de teste sem instalar nada?

Comece pelo que o Claude Code e o seu runner de testes já oferecem.

RecursoO que cortaO porém
Rodar só os testes do focogo test ./pkg/ -run TestName, um nó do pytest, um arquivo de spec em vez da suíte inteiraAntes do merge a suíte completa continua obrigatória
Flags silenciosasgo test sem -v, pytest -q, reporter de pontos ou de resumoAlguns modos silenciosos também encurtam a falha; veja como ela aparece antes
| tail -NFica só com as últimas N linhasO pipe devolve o exit code do tail, e a falha impressa acima das últimas N linhas some
Delegar a execução a um subagenteA saída longa fica no contexto do subagente; só o resumo volta (docs de subagentes)As requisições do subagente também contam no seu uso
/compact e /clear/compact resume a conversa; /clear recomeça do zero sem custoOs dois agem depois do estrago. O /compact lê o contexto inteiro, e a próxima rodada longa enche de novo
Um hook que filtra a saídaA página de custos mostra um hook PreToolUse que reescreve comandos de teste para mostrar só as linhas de falhaO script é seu, e o pipe com grep e head decide quais linhas e qual exit code o Claude vê

O porém do | tail merece atenção, porque agente usa isso o tempo todo. No bash e no zsh, um pipeline devolve o status do último comando, então uma suíte quebrada passando pelo tail parece verde se o pipefail estiver desligado:

go test ./... | tail -5                      # status é o do tail, quase sempre 0
set -o pipefail; go test ./... | tail -5     # status é o do go test quando ele falha

Nenhum desses recursos distingue sucesso de falha. Ou cortam os dois, ou não cortam nenhum.

O que o downshift compact faz com a saída de teste?

O Downshift é um binário Go open source que roda como hooks dentro de agentes de código. O Compactor dele é um comando: downshift compact -- <comando>. Ele roda o seu comando e olha o resultado antes do agente.

  • Exit 0, stderr vazio e saída que ele reconhece: a saída vira um resumo PASS curto, mais uma linha de marcação dizendo quantos bytes foram cortados.
  • Falha, exit diferente de zero ou saída que ele não reconhece: passa byte a byte.
  • O exit code é sempre o do próprio comando.

Ele trabalha com uma allowlist: go test, pytest, vitest, jest, tsc, cargo test, phpunit, playwright test, cypress run, gradle, maven, flutter test e outros. Qualquer outro comando, inclusive npm test, não é envolvido. As formas exatas estão na matriz de harnesses. Para desligar, use "exec": false na configuração do Downshift ou DOWNSHIFT_EXEC=0 no ambiente.

Como fica numa execução real?

Execução única, 2026-10-24, no repositório do Downshift: três pacotes Go, go test simples sem -v, macOS.

Antes: saída crua, 202 bytes

$ go test ./internal/execwrap/ ./internal/telemetry/ ./internal/classify/
ok  	github.com/tiagovilasboas/downshift/internal/execwrap	26.559s
ok  	github.com/tiagovilasboas/downshift/internal/telemetry	1.732s
ok  	github.com/tiagovilasboas/downshift/internal/classify	(cached)

Depois: downshift compact, 167 bytes contando a linha de marcação

$ downshift compact -- go test ./internal/execwrap/ ./internal/telemetry/ ./internal/classify/
Go test: PASS (3 packages ok) under github.com/tiagovilasboas/downshift/internal/
ok execwrap
ok telemetry
ok classify
[downshift compact: compacted 205 to 119 bytes]

De 202 para 167 bytes, cerca de 17% a menos, numa saída que já era curta. A linha de marcação conta a própria execução (205 para 119 bytes antes de a marcação entrar); os tempos dos pacotes mudam entre uma rodada e outra. O go test simples já é enxuto. Os cortes maiores vêm de runners que imprimem uma linha por teste, de flags verbosas e de ferramentas de build.

Fonte: os dois comandos acima, rodados uma vez em 2026-10-24 com downshift v0.1.2-65 (commit 480391dc). Bytes medidos com wc -c. A sua saída vai ser diferente.

O Claude Code reescreve os comandos de teste sozinho?

No Claude Code, sim. O hook PreToolUse do Downshift vê o comando Bash antes de ele rodar e reescreve os comandos da allowlist para a forma compacta, inclusive nos formatos que o agente mais digita:

Comando que o agente escreveO que roda
cd api && go test ./...cd api && downshift compact -- go test ./...
go test ./... 2>&1 | tail -20downshift compact -- go test ./... 2>&1 | tail -20
go build ./... && go test ./...cada trecho envolvido; o && continua parando na primeira falha
gofmt -l .; go test ./pkgsó o trecho do go test é envolvido

Uma regra de deny ou ask que bate com o comando, ou com qualquer parte dele, impede a reescrita. Um comando que já contém downshift compact nunca é envolvido duas vezes. Com | tail -N o pipe continua devolvendo o status do tail, como antes; a reescrita não muda o exit code.

Os outros harnesses, como Codex, Cursor, OpenCode, Antigravity e KiroCrew, não têm canal para reescrever um comando de shell. Neles o próprio agente roda downshift compact -- <comando>. É um comando de shell comum, então funciona igual em qualquer harness e em qualquer sistema operacional.

Quanto a compactação de saída economiza?

A única medição é uma contagem de bytes num corpus sintético, de 2026-10-21: 248 arquivos de saída de comando, dos quais 26 são compactados. Nesses 26 casos de sucesso limpo, 82,3% menos bytes. Nos 248, 23,7% menos, porque a maioria das fixtures é falha ou caso de borda feito para ficar cru. São bytes, não tokens do modelo, medidos em fixtures, não em sessões reais. O seu mix de comandos vai dar outro número. Leia o relatório do corpus.

Perguntas frequentes

Compactar a saída de teste esconde falhas do Claude?

Não. A compactação só roda quando o comando sai com 0, sem nada no stderr, e a saída é reconhecida como sucesso. Falha, exit diferente de zero ou saída desconhecida passam byte a byte.

O downshift compact muda o exit code?

Não. Ele devolve o exit code do próprio comando. Num pipe como | tail -N o shell continua devolvendo o status do último comando, igual a sem o Downshift.

Mandar a saída para o tail não resolve?

Corta o tamanho, mas o pipe devolve o exit code do tail se o pipefail estiver desligado, e uma falha impressa acima das últimas linhas se perde. Ele também apara a saída de falha, que é justamente a parte de que o modelo precisa.

Funciona fora do Claude Code?

Sim, como comando. Só o Claude Code reescreve comandos sozinho pelo hook. No Codex, no Cursor e nos outros harnesses o agente roda downshift compact -- <comando> diretamente.

Como desligo?

Use "exec": false na configuração do Downshift ou DOWNSHIFT_EXEC=0 no ambiente. Uma regra de deny ou ask que bate com um comando também impede a reescrita dele.

Pare de pagar contexto por check verde

Instale o Downshift, veja cada alteração antes com downshift setup --dry-run, e a próxima suíte verde volta como uma linha de resumo enquanto a falha fica inteira. downshift setup --undo restaura os backups.

curl -fsSL https://raw.githubusercontent.com/tiagovilasboas/downshift/main/install.sh | sh && downshift setup

Plugin do Claude Code

/plugin install downshift --marketplace tiagovilasboas/downshift

Guias relacionados

Fontes

  1. Anthropic docsmedido
    code.claude.com/docs/en/costs
    conversa inteira enviada em toda requisição, /compact lê o contexto, /clear, delegar operações verbosas, exemplo de hook de saída de teste (consultado em 2026-10-24)
  2. Anthropic docsmedido
    code.claude.com/docs/en/sub-agents
    isolar operações de alto volume num subagente
  3. Anthropic docsmedido
    code.claude.com/docs/en/hooks
    hooks PreToolUse
  4. Downshift repomedido
    docs/evidence/compaction-corpus-2026-10-21.md
    248 fixtures, 26 compactadas, 82,3% e 23,7%, bytes e não tokens
  5. Downshift repomedido
    docs/reference/harness-matrix.md
    allowlist, formatos compostos e cadeias, reescrita só no Claude Code
  6. Downshift repomedido
    docs/features/compaction.md
    compacta só com exit 0 e stderr vazio; falhas preservadas
  7. Saída do Downshift CLImedido
    go test e downshift compact, execução única em 2026-10-24
    bytes antes e depois