O RTK (Rust Token Killer) é um proxy de linha de comando que intercepta os comandos de shell que um agente de código executa (git status, cargo test, ls, grep) e devolve uma versão filtrada e compacta da saída antes que ela chegue ao contexto do LLM. Ele serve para quem usa Claude Code, Cursor, Codex, Gemini CLI e afins no dia a dia e percebe que boa parte da janela de contexto é gasta com barra de progresso, teste que passou e listagem de diretório. Funciona como um binário único em Rust, ativado por um hook que reescreve os comandos sem o agente perceber.
Este post se baseia na leitura do código e da documentação do repositório rtk-ai/rtk. Na data deste post, o projeto tem 83104 estrelas e licença Apache-2.0.
O que é o RTK e que problema ele resolve?
Quem trabalha com agente de código já viu a cena: o agente roda a suíte de testes, recebe 300 linhas de ok, um traceback no meio e mais 50 linhas de resumo. Tudo isso entra no contexto como token de entrada, a unidade que o modelo lê e que você paga. Multiplique por dezenas de comandos por sessão e a conversa fica cara e lenta, além de empurrar o que importa para fora da janela.
O RTK ataca exatamente esse pedaço. Segundo o README, ele aplica quatro estratégias por tipo de comando:
- Filtragem: remove ruído, como comentários, espaços e boilerplate.
- Agrupamento: junta itens parecidos, como arquivos por diretório e erros por tipo.
- Truncamento: mantém o contexto relevante e corta redundância.
- Deduplicação: colapsa linhas de log repetidas com um contador.
Na prática, git push vira ok main, cargo test mostra só as falhas e git log mostra hash, autor e assunto. A documentação lista mais de 100 comandos suportados, de pytest e go test a docker ps, kubectl logs, aws e pulumi.
Para quem é do mundo PHP, existe uma pasta src/cmds/php/ com módulos para artisan, phpunit, pest, paratest, phpstan, pint e ecs, além de um filtro TOML para composer install. O README só documenta explicitamente o rtk phpt (testes .phpt, com -99% de saída). Como fica a saída filtrada de um php artisan test ou de um phpstan analyse não está descrito na documentação principal; está apenas no código desses módulos.
Como o RTK funciona por dentro?
A arquitetura é descrita no CLAUDE.md do próprio repositório como um proxy de comandos. O fluxo é este:
- O hook do agente recebe o comando antes da execução. Um hook PreToolUse é um gancho que o Claude Code dispara antes de rodar uma ferramenta, e que pode alterar a entrada dela. O hook troca
git statusporrtk git status. - O
src/main.rsroteia o subcomando por um enumCommandsdo Clap até o módulo especializado emsrc/cmds/<ecossistema>/, comogit_cmd.rs,cargo_cmd.rsoupytest_cmd.rs. - O módulo executa o comando real, captura stdout e stderr, aplica o filtro e imprime o resultado. O código de saída do processo filho é propagado com
std::process::exit(code). - A economia é registrada em SQLite (
src/core/tracking.rs), e é dali que sai o painel dortk gain.
Algumas peças merecem atenção:
- Filtros TOML em
src/filters/: para saídas de texto previsíveis (make,terraform plan,rsync,helm), o filtro é declarativo, baseado em regex por linha. Filtros em Rust ficam para saídas estruturadas (JSON, NDJSON) ou que exigem uma máquina de estados, como as fases do pytest. OCONTRIBUTING.mdtraz uma tabela clara de quando usar cada um. - Regras de reescrita em
src/discover/rules.rsesrc/discover/registry.rs: é ali que se decide qual comando virartk <cmd>. - Init por agente em
src/hooks/init/: há um arquivo por integração (claude.rs,cursor.rs,codex.rs,gemini.rse outros). Desde a 0.24 o hook é um "delegador fino" que chamartk rewrite, então a lógica de reescrita mora no binário e não no script. guard::never_worse(raw, filtered): garante que o RTK nunca emite mais bytes que o comando cru.- Fallback: se o filtro falha, a regra do projeto é devolver a saída original. Os hooks saem com código 0 em qualquer erro, para o comando do agente rodar sem modificação.
- Recuperação: quando um comando falha ou é truncado, o RTK guarda a saída completa e imprime algo como
[full output: rtk recall 3f9c2a81d4e7], para o LLM recuperar o conteúdo sem reexecutar o comando.
O projeto tem metas explícitas de menos de 10 ms de inicialização e menos de 5 MB de memória, sem runtime assíncrono e sem I/O de configuração no caminho crítico. O Cargo.toml proíbe unsafe_code e trata warnings como erro.
Como instalar o RTK?
As opções documentadas no README:
# Homebrew (recomendado) brew install rtk # Linux/macOS via script (instala em ~/.local/bin) curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh # Cargo, direto do repositório cargo install --git https://github.com/rtk-ai/rtk
No Windows existe winget install rtk-ai.rtk, e também há binários pré-compilados nas releases.
Um detalhe que pega muita gente: existe outro projeto chamado rtk no crates.io (Rust Type Kit), que não tem nada a ver com este. Por isso a documentação recomenda cargo install --git em vez de cargo install rtk e pede para validar com:
rtk --version rtk gain # se falhar, você instalou o pacote errado
Como ativar o hook no Claude Code?
O comando principal é o rtk init. Para o Claude Code, no modo global:
rtk init -g # hook + RTK.md (recomendado) rtk init -g --auto-patch # sem prompt, útil em automação rtk init -g --hook-only # só o hook, sem RTK.md rtk init -g --no-patch # só imprime as instruções para editar à mão rtk init --show # verifica a instalação
Segundo o INSTALL.md, o rtk init -g instala o hook em ~/.claude/hooks/rtk-rewrite.sh, cria ~/.claude/RTK.md, adiciona uma referência @RTK.md no ~/.claude/CLAUDE.md e pergunta se pode alterar o ~/.claude/settings.json, guardando um backup em settings.json.bak. Depois disso, é preciso reiniciar o Claude Code. Se você já organiza o agente por projeto, vale cruzar com o que escrevi sobre configurar o Claude Code em projetos Laravel com CLAUDE.md, hooks e comandos: o RTK entra como mais um hook PreToolUse na mesma cadeia.
Para os outros agentes, a sintaxe muda pouco: rtk init -g --agent cursor, rtk init -g --codex, rtk init -g --gemini, rtk init --agent cline. A tabela do README mostra que nem todos têm hook de verdade. Windsurf, Cline, Kilo Code e Kimi recebem apenas um arquivo de regras pedindo que o modelo prefixe os comandos com rtk. Isso depende de o modelo obedecer, o que é bem menos confiável que uma reescrita transparente.
Exemplo de uso no dia a dia
Com o hook ativo, você não muda nada no fluxo. O agente roda git status e recebe a versão compacta. Mas os comandos também funcionam direto no terminal:
rtk git status # status agrupado por estado rtk git diff # diff com contexto reduzido rtk grep "Idempotency-Key" app/ # resultados agrupados por arquivo rtk read app/Services/Gateway.php -l aggressive # só assinaturas rtk test vendor/bin/phpunit # wrapper genérico: só falhas rtk err composer install # só erros e warnings
O rtk test <cmd> e o rtk err <cmd> são os curingas para ferramentas sem filtro dedicado: executam o argv diretamente e mostram só falhas ou só erros. Eles não expandem globs, variáveis nem operadores de shell por padrão. Se precisar de sintaxe de shell, a documentação manda usar rtk run -c '<script>' ou --shell <nome>.
Para ver o efeito acumulado:
rtk gain # resumo rtk gain --history # histórico por comando rtk discover # comandos que poderiam ter sido filtrados
E quando um comando não deve ser mexido, há três saídas: rtk proxy <cmd> roda sem filtro mas registra no histórico, RTK_DISABLED=1 <cmd> pula o hook para aquele comando e o config.toml aceita exclusões permanentes:
[hooks] exclude_commands = ["curl", "playwright"]
Uma limitação importante: o hook só pega chamadas da ferramenta Bash. As ferramentas nativas do Claude Code, como Read, Grep e Glob, não passam por ele. Se o agente lê arquivos pelo Read, o RTK não economiza nada ali.
Quanto o RTK economiza de verdade?
Aqui o próprio repositório é honesto, e vale ler com atenção. O README insiste que os percentuais medem redução de saída do bash, não da fatura. A saída do shell é só uma parte dos tokens de entrada, que convivem com o system prompt, o histórico e o seu prompt. E os tokens de entrada são só parte do custo, porque os de saída também entram na conta. Além disso, o RTK não traz tokenizador: as contagens são estimadas como bytes / 4, então os percentuais são confiáveis e os números absolutos, aproximados.
O arquivo FIX_PERF.md vai além e documenta um benchmark interno com 10 pares de VMs com o RTK ligado e desligado. Nessa tarefa, a diferença de custo em dólar foi de −0,2%, praticamente empate. O documento atribui isso a comandos extras que o agente rodou para se recuperar de saídas quebradas. Também é um documento de investigação, não uma conclusão final, mas ele mostra que "90% menos saída" não se converte automaticamente em "90% mais barato".
Se a sua preocupação é custo de LLM, as alavancas maiores costumam ser outras, como as que descrevi em prompt caching e Batch API do Claude. Sobre cache, o README afirma que o RTK não quebra o prompt cache do Claude, porque filtra a saída uma única vez e o resultado fica no histórico normalmente.
Quando vale a pena e quando não?
Vale a pena quando:
- Suas sessões são dominadas por comandos verbosos: suítes de teste grandes, builds,
docker logs,kubectl,git loglongo. - O problema principal é contexto estourando ou o agente se perdendo em ruído, mais do que o custo em si.
- Você usa um agente com hook real (Claude Code, Cursor, Codex, Gemini CLI, Copilot no VS Code), em que a reescrita é transparente.
Provavelmente não vale quando:
- O agente lê arquivos e busca código pelas ferramentas nativas, sem passar pelo Bash.
- Seu fluxo depende de pipelines de shell para contar, ordenar e filtrar (mais sobre isso abaixo).
- Você usa um agente que só aceita arquivo de regras, em que a ativação depende do modelo lembrar de prefixar
rtk.
Cuidados antes de instalar
Como toda ferramenta que se pluga no agente, o RTK roda com as suas permissões e executa comandos em seu nome. Pelo que dá para ver no código e na documentação, ele acessa:
- Arquivos de configuração do agente: o
rtk init -galtera~/.claude/settings.json(com backup), cria~/.claude/hooks/rtk-rewrite.sh,~/.claude/RTK.mde mexe no~/.claude/CLAUDE.md. Para outros agentes, escreve em~/.factory/hooks.json,.trae/hooks.json,~/.gemini/...e equivalentes. Para desfazer:rtk init -g --uninstall. - Banco SQLite local: o histórico de comandos e a saída completa de comandos que falharam ou foram truncados ficam guardados para o
rtk recall. Se você rodaenv,curlcontra APIs autenticadas ou testes que imprimem credenciais, isso pode parar em disco. O[retriever] modeaceitadisabled. Em ambiente que mexe com dado de cliente, o raciocínio é o mesmo que uso para proteger dados e ações em agentes de IA: saiba onde cada saída vai parar. - Rede: o
Cargo.tomlinclui o cliente HTTPureq, usado pela telemetria. Ela é desativada por padrão e exige opt-in nortk initou viartk telemetry enable. Dá para travar de vez comexport RTK_TELEMETRY_DISABLED=1. Um ponto de atenção: oDISCLAIMER.mdainda diz que a coleta é ativa por padrão, contradizendo o README. Na dúvida, rodertk telemetry status. - Instalação via
curl | sh: execute só depois de ler oinstall.sh, ou prefira Homebrew oucargo install --git. - Pipelines: o
FIX_PERF.mdregistra quertk find src -name "*.rs" | xargs wc -lfalhou em todas as VMs do benchmark, porque a saída compacta não é uma lista de caminhos. Registra também um caso pior:cargo clippy ... | tee /tmp/clippy.loggravou o resumo filtrado, e o agente contou zero warnings sem erro nenhum. É um bug de corretude, não de economia. Se você depende de saída parseável por outro programa, adicione esses comandos aoexclude_commandsou usertk proxy. - Formato diferente do original: o projeto diz buscar saídas que pareçam "uma versão mais curta do comando real", mas
git pushvirarok mainé, objetivamente, outro formato. Scripts e CIs que fazem parse de saída não devem passar pelo RTK.
Conclusão prática
Se eu fosse adotar o RTK num projeto Laravel com Claude Code, faria assim: instalaria via Homebrew ou cargo install --git, rodaria rtk init -g --no-patch para revisar o JSON antes de aplicar e começaria com exclude_commands para tudo que alimenta pipe ou parse (find, wc e qualquer coisa que vá para tee). Deixaria [retriever] mode = "disabled" em máquinas com acesso a dados sensíveis e conferiria rtk telemetry status. Depois de uma ou duas semanas, compararia o rtk gain com a fatura real do provedor, não com o painel do próprio RTK. Se o ganho aparecer em contexto mais limpo e menos compactação de conversa, mantenha. Se o agente começar a reexecutar comandos para entender a saída, a economia já foi embora, e o exclude_commands é o lugar de ajustar.