Eu estava lançando meu plugin às 3 da manhã quando ele me avisou: 67% de contexto. Vinte minutos depois, ele mesmo quebrou
Eram 3 da manhã e eu estava fechando o release do compact-ops, um plugin de Claude Code que protege a sessão contra a perda de memória do /compact. O uso de contexto bateu 67% e uma notificação apareceu dentro da minha própria sessão: limite cruzado, rode /compact num ponto limpo de parada, aqui está seu plano atual e sua última decisão. Fui eu que escrevi esse aviso. Também fui eu a pessoa que ele salvou.
Vinte minutos depois, a mesma noite me entregou a cena oposta. Rodei o /compact e os três hooks do plugin falharam de uma vez. Durante o release eu tinha mudado a estrutura de diretórios, e a sessão em execução ainda segurava o caminho antigo. A compactação terminou normalmente mesmo assim, porque todo hook é fail-open: se quebra, sai da frente em vez de travar o comportamento padrão. Numa única sessão eu vi o recurso funcionar e vi ele falhar com segurança. Dogfooding melhor que isso não se compra.
O que o /compact joga fora
Quando a janela de contexto enche, o Claude Code comprime a conversa inteira num único resumo interno e descarta as mensagens originais. Vale para o /compact manual e para o automático.
O resumo até se sai bem com código. O que ele derruba é o estado operacional: “o push já foi aprovado”, “essa abordagem a gente já tentou e falhou”, “esse número veio daquele arquivo”. Quando o agente pós-compactação esquece isso, ele volta pedindo permissão que você já deu e tenta de novo a correção que você já enterrou. Quem usa agente todo dia conhece essa tarde perdida.
O compact-ops não substitui o resumo. Ele coloca um seguro por fora, usando só hooks oficiais:
- Antes da compactação, um hook PreCompact faz backup do transcript e chama um LLM separado para escrever um arquivo de estado com 10 seções fixas (plano ativo, decisões da sessão, bloqueios, arquivos em edição, tentativas que falharam…)
- Logo depois da compactação, um hook SessionStart injeta esse estado no contexto novo, junto com uma nota dizendo para reler os arquivos originais antes de confiar em qualquer resumo
- O mesmo estado é injetado quando você roda
claude --resumeno dia seguinte, porque ele fica salvo em~/.claude/compact-ops/por 30 dias, e sobrevive a reboot - Um hook UserPromptSubmit calcula o uso de contexto a cada prompt e avisa uma única vez quando passa de 60%
O algoritmo de compactação continua intocado. Se qualquer hook morrer, o /compact padrão passa direto.
O crédito: isso é um derivado do compact-plus
A ideia central não é minha. O compact-plus do u-ichi (MIT) chegou lá primeiro: hook PreCompact chamando um segundo LLM para salvar estado estruturado antes do resumo engolir tudo. Li o README e quis instalar na hora.
Só que o meu fluxo tinha três desencontros com as premissas dele, então fiz um derivado e mudei exatamente três coisas: o aviso de uso funciona só com o plugin (o original depende de um script de statusline que mora no dotfiles do autor, então numa instalação limpa o aviso nunca dispara), o estado sai do $TMPDIR e vai para um diretório que sobrevive a reboot, e a recuperação também dispara no --resume, não só ao cruzar uma compactação. O backend de LLM ficou Claude puro (Sonnet com fallback para Haiku); o original usa Codex como fallback, o que pressupõe uma assinatura de ChatGPT Pro do lado.
Custo honesto: cada compact passa a gastar uma chamada extra de LLM. Dá para rebaixar para Haiku ou desligar com uma variável de ambiente.
A terceira mancada da noite, já que estamos sendo honestos
O aviso e a falha dos hooks foram as duas cenas boas. A terceira fui eu mesmo. Para testar uma correção do marketplace, instalei uma cópia do plugin com outro nome de marketplace e depois rodei o uninstall da cópia. O uninstall casou só pelo nome do plugin e levou junto a instalação de produção. Fiquei uns minutos olhando para um claude plugin list vazio sem entender o que eu tinha feito.
A regra que ficou no meu log: nunca teste um plugin com o mesmo nome num marketplace diferente; mude o nome do plugin também. A falha foi justamente essa, confiar que o identificador composto era composto de verdade.
Os 6 pontos que endureci antes de abrir o repositório
A v0.1.0 era “funciona na minha máquina”. Antes de tornar o repositório público, passei minha própria revisão mais uma segunda revisão com um CLI independente, e a v0.2.0 saiu com seis correções:
- Permissões. Estado e backup carregam sua conversa crua, incluindo qualquer segredo que uma saída de ferramenta ecoou. Tudo agora nasce com
umask 077, diretórios 700, arquivos 600. - Validação do session_id. O JSON de entrada do hook fluía direto para caminhos de arquivo. Agora passa por uma allowlist antes de tocar o filesystem.
- Validação da saída do LLM. O gerador de estado era confiado depois de checar a primeira linha. Agora as 10 seções precisam existir, senão o estado anterior é preservado.
- jq em passada única. O processamento do transcript disparava jq 3 ou 4 vezes por linha; numa sessão longa isso comia o timeout inteiro do hook. Virou um processo só, em stream.
- Backup com gzip. O JSONL comprime para mais ou menos um décimo do tamanho.
- Log de depuração. A lição de verdade. Design fail-open não atrapalha em produção, e também morre em silêncio absoluto. As três falhas de hook lá do começo só ficaram visíveis porque o harness imprimiu uma linha de erro; o plugin não tinha como me contar o porquê. Agora
COMPACT_OPS_DEBUG=1registra cada falha engolida. Se você vai escrever hook fail-open, escreva o log primeiro. Eu fiz na ordem errada e dei sorte.
Instalar
git clone https://github.com/kenimo49/compact-ops.git
claude plugin marketplace add /path/to/compact-ops --scope user
claude plugin install compact-ops@compact-ops-local
Precisa de Claude Code v2.x, jq e o CLI claude como backend. Linux e macOS. Depois de instalar, é só rodar /compact como sempre. O estado salvo é markdown puro: quando uma retomada de sessão parecer estranha, dá para abrir o arquivo e ler o que a sessão anterior achou que estava passando adiante.
Entrei naquela noite achando que estava lançando um plugin. Saí como o primeiro usuário que ele salvou — e o primeiro que ele viu quebrar. Qual foi a última coisa que o seu agente esqueceu depois de um /compact? Se uma sessão pós-compactação já desfez uma tarde sua com toda a confiança do mundo, conta aí nos comentários.
ken imoto · WebRTC & Voice AI engineer · kenimoto.dev · TabNews
Este artigo foi útil?