2

Pitch: O que aprendi lendo os logs não documentados do Claude Code, Codex e Mistral Vibe

Quem roda vários agentes de programação ao mesmo tempo ganha um trabalho extra que ninguém pediu: ficar de olho neles. Três sessões do Claude Code, uma delas abre quatro subagentes, um Codex rodando uma migração em outro terminal… e você passa a tarde alternando abas para responder sempre às mesmas perguntas: esse ainda está trabalhando? Travou num comando? Está esperando por mim?

A resposta está no disco. O Claude Code, o Codex e o Mistral Vibe gravam tudo o que fazem em arquivos locais, em tempo real, e nenhum deles documenta o formato. Passei as últimas semanas lendo esses arquivos para construir uma ferramenta, e aqui vai o que aprendi, caso você queira fazer algo parecido.

Claude Code: um JSONL por sessão

Cada sessão fica em ~/.claude/projects/<pasta>/<id-da-sessão>.jsonl. A pasta é o caminho do projeto com todo caractere que não é letra nem dígito trocado por - (/Users/eu/loja-api vira -Users-eu-loja-api). Cada linha é um registro JSON com um type: user e assistant carregam a conversa, e uma mensagem do assistente traz blocos text, thinking e tool_use. O resultado de cada ferramenta volta num registro user seguinte, como um bloco tool_result com o mesmo tool_use_id.

As armadilhas:

  • O uso de tokens vem repetido. A mesma mensagem do assistente é gravada uma vez por bloco de conteúdo, sempre com o mesmo usage. Conte uma vez por message.id, senão uma mensagem com cinco blocos custa cinco vezes mais.
  • Silêncio não é fim. O fim de um turno é uma marca explícita, stop_reason: "end_turn". Até ela chegar, o agente ainda está trabalhando, mesmo depois de um minuto sem escrever nada.
  • Subagentes têm arquivos próprios, em <id-da-sessão>/subagents/*.jsonl. A primeira mensagem de usuário de um subagente é a ordem que ele recebeu.
  • "Precisa de você" não está no transcript. Quando um menu de permissão está aberto, a chamada pendente muitas vezes ainda não foi gravada. O estado confiável fica em ~/.claude/sessions/<pid>.json (status: "waiting"). Mas cuidado: waitingFor: "dialog open" é só um diálogo de slash command aberto, não uma pergunta para você.

Codex: um arquivo "rollout" por thread

O Codex (app e CLI) grava em ~/.codex/sessions/AAAA/MM/DD/rollout-<hora>-<id>.jsonl. A primeira linha é um session_meta com id, cwd, source e, para uma thread filha, parent_thread_id. Use esse campo para ligar filhos e pais, nunca nomes de arquivo ou horários.

Surpresa: na minha máquina, 34 de 57 rollouts eram {"subagent":{"other":"guardian"}}, as revisões automáticas curtas que o Codex roda antes de alguns comandos. Se você mostrar tudo como sessão, a lista se afoga.

Mistral Vibe: dois formatos ao mesmo tempo

O Vibe guarda as sessões em ~/.vibe/logs/session e, desde a versão 2.26, tem dois motores com dois formatos diferentes: o antigo, um arquivo por sessão, e o novo, em logs/session/unified/<id>/, com um snapshot (CURRENT), páginas de histórico em chunks/ e um journal que vai sendo acrescentado. Um leitor precisa entender os dois, porque as duas coisas convivem na mesma máquina.

O que eu fiz com isso

Juntei tudo num app open source, o Agent Standup, que transforma essas sessões numa chamada de equipe ao vivo: o agente principal dá as ordens, os subagentes entram na chamada quando recebem uma tarefa e saem quando terminam, e quem está trabalhando compartilha a tela com o comando e a saída real, ou o diff que está aplicando.

A chamada de demonstração: o agente principal e os subagentes nas mesas

Algumas decisões técnicas, para quem gosta:

  • Zero dependências em runtime. Um servidor Node só com a biblioteca padrão, que lê os JSONL de forma incremental (guarda o offset de cada arquivo e só lê o que foi acrescentado).
  • Não gasta tokens. Nenhum modelo é chamado para "assistir" os agentes: é só leitura de arquivo. Roda local e não envia nada por padrão.
  • Vozes locais. As falas saem de um modelo de voz pequeno (Kokoro) que roda na sua máquina, com a boca sincronizada pelo volume real do áudio.
  • Formatos que mudam sem aviso. Todo leitor é defensivo: campo ausente não quebra nada, e uma sessão ilegível do Codex ou do Vibe derruba só aquela sessão, nunca a lista inteira.

Para testar sem instalar nada (Node 18+):

npx @double_geste/agent-standup@latest --open

Sem sessão ainda? ⚙ → Fonte → Demo mostra uma equipe fictícia. Também existe como extensão do VS Code (e Cursor/Windsurf pela Open VSX) e app para macOS. Licença MIT, interface em português do Brasil: https://agent-standup.com/pt-br/

Fiquei curioso: quantas sessões de agente vocês rodam ao mesmo tempo, e como sabem qual delas está esperando por vocês?

Carregando publicação patrocinada...