<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ai-Memory | AkitaOnRails.com</title><link>https://akitaonrails.github.io/tags/ai-memory/</link><description>Blog do Fabio Akita do Canal do YouTube 'Akitando' falando sobre tecnologia, carreira e coisas geek.</description><generator>Hugo -- gohugo.io</generator><language>pt-BR</language><lastBuildDate>Mon, 19 Oct 2026 23:20:48 +0000</lastBuildDate><atom:link href="https://akitaonrails.github.io/tags/ai-memory/index.xml" rel="self" type="application/rss+xml"/><item><title>AI-MEMORY 2.0 - o melhor sistema de memória para agentes e times</title><link>https://akitaonrails.github.io/2026/09/02/ai-memory-2-0-melhor-sistema-memoria-agentes-e-times/</link><guid isPermaLink="true">https://akitaonrails.github.io/2026/09/02/ai-memory-2-0-melhor-sistema-memoria-agentes-e-times/</guid><pubDate>Wed, 02 Sep 2026 11:00:00 -0300</pubDate><description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; a &lt;a href="https://github.com/akitaonrails/ai-memory/releases/tag/v2.0.0"target="_blank" rel="noopener"&gt;ai-memory 2.0 já está no ar&lt;/a&gt;, com formato aberto OKF, embeddings locais ligados por padrão e suporte de verdade a vários agentes e a um time inteiro trabalhando no mesmo projeto em paralelo. Abaixo vai o pitch completo.&lt;/p&gt;
&lt;p&gt;Em julho eu publiquei &lt;a href="https://akitaonrails.github.io/2026/07/20/novidades-no-meu-ai-memory-cada-vez-melhor-pra-usar-com-suas-ias/"&gt;Novidades no meu AI-MEMORY&lt;/a&gt;, onde mostrei o &lt;code&gt;ai-memory run&lt;/code&gt;: trocar de Claude Code pra Codex sem perder a linha de trabalho. Naquele dia estávamos na versão 1.17.1.&lt;/p&gt;
&lt;p&gt;Hoje saiu a &lt;strong&gt;2.0&lt;/strong&gt;. E dessa vez não vou repetir como os hooks funcionam nem como uma sessão vira página de wiki. Isso já está nos textos anteriores. Aqui eu quero falar de onde o ai-memory chegou frente à concorrência, o que a 2.0 traz e por que ela mereceu virar um &amp;ldquo;2&amp;rdquo;.&lt;/p&gt;</description><content:encoded><![CDATA[<p><strong>TL;DR:</strong> a <a href="https://github.com/akitaonrails/ai-memory/releases/tag/v2.0.0"target="_blank" rel="noopener">ai-memory 2.0 já está no ar</a>, com formato aberto OKF, embeddings locais ligados por padrão e suporte de verdade a vários agentes e a um time inteiro trabalhando no mesmo projeto em paralelo. Abaixo vai o pitch completo.</p>
<p>Em julho eu publiquei <a href="/2026/07/20/novidades-no-meu-ai-memory-cada-vez-melhor-pra-usar-com-suas-ias/">Novidades no meu AI-MEMORY</a>, onde mostrei o <code>ai-memory run</code>: trocar de Claude Code pra Codex sem perder a linha de trabalho. Naquele dia estávamos na versão 1.17.1.</p>
<p>Hoje saiu a <strong>2.0</strong>. E dessa vez não vou repetir como os hooks funcionam nem como uma sessão vira página de wiki. Isso já está nos textos anteriores. Aqui eu quero falar de onde o ai-memory chegou frente à concorrência, o que a 2.0 traz e por que ela mereceu virar um &ldquo;2&rdquo;.</p>
<p>Se você nunca ouviu falar do projeto, o resumo é curto. O ai-memory é um servidor de memória de longo prazo pros seus agentes de código. Ele captura o que aconteceu na sessão, consolida em páginas Markdown e devolve o contexto certo pro próximo agente, seja qual for o harness ou a máquina.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20260902132131_screenshot-2026-09-02_13-20-02.png" alt="Navegador web do ai-memory 2.0 mostrando a lista de projetos da wiki, com o aviso de backup pré-migração para o formato OKF e cartões de vários projetos como ai-memory, akitaonrails-hugo e outros"  loading="lazy" /></p>
<p>Essa é a interface web que vem junto, boa pra auditar o que os agentes gravaram e pra navegar entre os projetos. Repare que cada projeto vive separado, com sua própria contagem de páginas, tudo saído das sessões de verdade.</p>
<h2>Por que virou 2.0<span class="hx:absolute hx:-mt-20" id="por-que-virou-20"></span>
    <a href="#por-que-virou-20" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Pra mim, o primeiro número de uma versão carrega um compromisso.</p>
<p>A família 1.x cresceu rápido demais. Saímos da 1.1 e chegamos na 1.39 em pouco mais de dois meses, empilhando funcionalidade atrás de funcionalidade em releases menores. Funcionou pra iterar, mas embaralhou o significado dos números.</p>
<p>A 2.0 arruma isso. Ela junta as poucas mudanças que quebram compatibilidade num único major, e a partir daqui o versionamento passa a seguir <a href="https://github.com/akitaonrails/ai-memory/blob/main/CONTRIBUTING.md"target="_blank" rel="noopener">Semantic Versioning</a> de verdade. Correção vira patch. Funcionalidade nova vira minor. Só quebra de formato ou de contrato vira major, e sempre com aviso. O novo guia de contribuição deixa essa regra explícita pra qualquer PR.</p>
<p>A quebra principal é o novo formato em disco. Na primeira vez que você sobe a 2.0, ela migra sua wiki sozinha. Antes de mexer em qualquer coisa, ela compacta todo o seu diretório de dados num backup verificado com data no nome. Se o backup não puder ser gravado e conferido, a migração aborta e o servidor se recusa a subir. Nada de &ldquo;confia em mim&rdquo;.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20260902131952_screenshot-2026-09-02_13-16-17.png" alt="Diálogo do ai-memory 2.0 avisando que a memória foi migrada para o formato OKF v0.2, com o caminho do backup verificado e os passos de rollback"  loading="lazy" /></p>
<p>Esse é o aviso que aparece uma vez, depois da migração: ele diz onde ficou o backup, o tamanho do arquivo e como voltar atrás se algo parecer errado. Quando você confirma que está tudo certo, é só apagar o backup e o lembrete some.</p>
<h2>OKF: sua memória não fica presa no ai-memory<span class="hx:absolute hx:-mt-20" id="okf-sua-memória-não-fica-presa-no-ai-memory"></span>
    <a href="#okf-sua-mem%c3%b3ria-n%c3%a3o-fica-presa-no-ai-memory" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Essa é a mudança que mais me deixou satisfeito.</p>
<p>A partir da 2.0 a wiki do ai-memory é, nativamente, um bundle no <strong>Open Knowledge Format</strong>, o formato aberto que o Google publicou em 2026. Cada página de memória é um arquivo OKF válido: Markdown comum com metadados padronizados. Não existe passo de exportação que gera uma cópia divergente. Os arquivos da wiki já são os arquivos OKF.</p>
<p>Na prática isso quer dizer que sua memória deixou de ser refém do meu projeto. Você pode ler tudo com <code>grep</code>, abrir no Obsidian, versionar no Git ou entregar o bundle pra um colega que usa outra ferramenta compatível com OKF. Tem até um <code>ai-memory export-okf</code> pra empacotar um projeto inteiro num tarball validado.</p>
<p>Sempre foi essa a tese: modelo e harness são alugados, a memória do projeto é sua. Agora o formato reforça isso por escrito.</p>
<h2>Embeddings locais, ligados por padrão<span class="hx:absolute hx:-mt-20" id="embeddings-locais-ligados-por-padrão"></span>
    <a href="#embeddings-locais-ligados-por-padr%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Até a 1.x, busca semântica de verdade dependia de você configurar um provider de embeddings. Ou pagava uma API e mandava cada página e cada query pra fora, ou subia um Ollama do lado. As duas opções têm custo.</p>
<p>A 2.0 traz um provider <code>local</code> que roda o modelo de embeddings dentro do próprio processo, em Rust puro, com o <code>all-MiniLM-L6-v2</code>. Sem chave de API, sem servidor externo, sem GPU e sem mandar seus dados pra lugar nenhum. E agora vem ligado por padrão. Na primeira execução ele baixa o modelo (uns 87 MB, com checksum fixo) em background e liga a busca híbrida no próximo restart.</p>
<p>O ganho é mensurável. No benchmark LongMemEval-S, o hit@5 sobe de 0.617 só com full-text para 0.779 com os embeddings locais. Se por algum motivo você não quiser, um <code>embedding_provider = &quot;none&quot;</code> desliga.</p>
<p>Detalhe que importa: escolhi <code>candle</code> de propósito, em vez do runtime nativo que a concorrência usa. Foi justamente essa camada nativa que gerou um tipo de crash recorrente em outros projetos de memória. Preferi não herdar o problema.</p>
<h2>Vários agentes ao mesmo tempo, no mesmo projeto<span class="hx:absolute hx:-mt-20" id="vários-agentes-ao-mesmo-tempo-no-mesmo-projeto"></span>
    <a href="#v%c3%a1rios-agentes-ao-mesmo-tempo-no-mesmo-projeto" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Aqui começa a parte que motivou boa parte do trabalho antes da 2.0.</p>
<p>O caso do <code>ai-memory run</code> que mostrei em julho era sequencial: fecho o Claude, abro o Codex, continuo. Mas e quando eu deixo dois ou três harnesses abertos ao mesmo tempo no mesmo projeto? Claude numa aba, Codex noutra, OpenCode numa terceira.</p>
<p>O ai-memory trata isso sem ninguém pisar no pé do outro. Cada chamada de memória descobre sozinha a qual projeto pertence, a partir do diretório da sessão. O ponteiro de &ldquo;projeto atual&rdquo; agora é por ator, então dois harnesses no mesmo checkout mantêm cada um a sua noção de contexto. E a identidade do projeto vem do nome do checkout. O caminho absoluto no disco não pesa, então o mesmo projeto no laptop e no desktop cai no mesmo lugar.</p>
<p>Quando duas janelas gravam na mesma página, a segunda não apaga a primeira. Ela cria uma versão nova que passa a ser a mais recente, e a anterior continua alcançável na cadeia de versões. Regravar algo idêntico não gera versão nova. Todas as escritas passam por um único writer, com fila e backpressure, então uma rajada não corrompe nada.</p>
<p>Isso não é teoria. Tem teste de aceitação chamando Claude, Codex, OpenCode, Pi, Crush e mais alguns de verdade, dentro de uma mesma workstream, cobrindo lease, adoção de sessão e entrega de contexto entre harnesses.</p>
<h2>Um time inteiro no mesmo projeto<span class="hx:absolute hx:-mt-20" id="um-time-inteiro-no-mesmo-projeto"></span>
    <a href="#um-time-inteiro-no-mesmo-projeto" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O segundo cenário é o que dá título ao post. Aqui já são várias pessoas, um time inteiro apontando os agentes pro mesmo servidor.</p>
<p>A forma de rodar é simples. Alguém sobe um servidor, normalmente um container num homelab ou numa máquina da rede, e cada pessoa aponta os agentes dela pra aquela URL. HTTPS entra na frente com um proxy reverso, se você quiser. O banco continua sendo um SQLite só.</p>
<p>Todo mundo enxerga as mesmas páginas do projeto. O que uma pessoa aprendeu numa sessão, o agente da outra recupera. E cada sessão nova recebe um briefing com o estado do projeto logo no início. Vou ser honesto com o termo &ldquo;tempo real&rdquo;. O que existe é um store central compartilhado, com leitura imediata, mais o briefing na abertura. A nota que um colega gravou aparece na hora pra próxima consulta ou próxima sessão de qualquer um. Uma sessão que já está rodando só recebe a novidade na consulta seguinte ou na próxima abertura, sem interrupção no meio.</p>
<p>O que muda no modo multiusuário é a atribuição. Cada escrita registra quem fez. Existe log de auditoria e a interface mostra &ldquo;editado por fulano&rdquo;. Isso já vem no pacote, de graça. E não existe permissão por página, de propósito. A atribuição serve pra registrar autoria; qualquer pessoa autenticada pode escrever, e o histórico é que guarda quem foi.</p>
<p>Tem uma distinção de segurança importante entre o que é compartilhado e o que é pessoal. As páginas são de todos. Mas o handoff é um bastão de um dono só: exatamente uma sessão pega, e um segundo <code>accept</code> não rouba o bastão de ninguém. O handoff que você deixou pendente não é entregue nem consumido por um colega. Do mesmo jeito, os &ldquo;slots&rdquo; de &ldquo;no que estou trabalhando agora&rdquo; são por pessoa, então o seu contexto pessoal não vaza no briefing do time inteiro.</p>
<p>Também existe uma bateria de testes de concorrência real cobrindo esses casos: escrita simultânea, isolamento por ator sob carga, o bastão do handoff que não é roubado e os slots pessoais que não vazam.</p>
<h2>Onde o ai-memory fica frente à concorrência<span class="hx:absolute hx:-mt-20" id="onde-o-ai-memory-fica-frente-à-concorrência"></span>
    <a href="#onde-o-ai-memory-fica-frente-%c3%a0-concorr%c3%aancia" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Antes da 2.0 fizemos outra rodada de pesquisa sobre o cenário de 2026, documentada no repositório. Ela foi a base pra decidir o que a 2.0 precisava cobrir. Vou resumir o campo.</p>
<p>Tem o <strong>agentmemory</strong>, que é um MCP server em TypeScript preso a um sidecar nativo e a uma superfície gigante de dezenas de ferramentas. Tem o <strong>basic-memory</strong>, em Python, Markdown no disco, mas com captura manual: você tem que pedir pra ele lembrar. Tem o <strong>cognee</strong>, que junta grafo, vetor e relacional num pipeline pesado que pede vários gigas de RAM. Tem o <strong>MemPalace</strong>, que viralizou com quase 50 mil estrelas em duas semanas por causa de um número de benchmark que, auditado, se mostrou inflado, além de sofrer de corrupção quando duas escritas acontecem juntas. E tem os grafos temporais como <strong>Zep</strong>, os &ldquo;memory OS&rdquo; como <strong>Letta</strong> (o antigo MemGPT) e os extratores de fato como o <strong>Mem0</strong>.</p>
<p>Tem ainda a memória nativa que o próprio Claude Code passou a ligar por padrão. Essa eu trato como o funil que apresenta a categoria pras pessoas. Como concorrente ela fica limitada: presa a uma máquina, presa a um agente, sem busca de verdade e sem história de time.</p>
<p>A 2.0 fecha as lacunas que a pesquisa apontou. Passamos a publicar benchmark reproduzível com o LongMemEval, rodando o servidor de verdade. Ganhamos o formato aberto OKF. Ganhamos ligações tipadas entre páginas, com <code>causes</code>, <code>fixes</code> e <code>contradicts</code>, que ainda alimentam uma checagem de contradição sem gastar LLM. Ganhamos consulta com <code>as_of</code>, pra perguntar o que a gente sabia sobre um assunto numa certa data. Ganhamos os embeddings locais. E ganhamos uma passada opcional de &ldquo;experiência&rdquo; que revê várias sessões pra achar padrões que só aparecem no conjunto.</p>
<p>Agora a parte que interessa pra quem vai escolher. O que o ai-memory tem que os outros não têm, tudo junto:</p>
<ul>
<li><strong>Ele te acompanha entre agentes.</strong> Mais de vinte harnesses alimentam uma memória só, e o handoff aqui é um protocolo de verdade: tipado, com dono e reivindicado uma vez só.</li>
<li><strong>Ele te acompanha entre máquinas.</strong> A memória vive num servidor que é seu. O projeto que você largou no desktop é o que você retoma no laptop.</li>
<li><strong>Ele funciona pra time.</strong> Autenticação multiusuário, atribuição por pessoa e log de auditoria já vêm no pacote, de graça.</li>
<li><strong>Sua memória é Markdown puro.</strong> A fonte da verdade é uma wiki versionada no Git. O banco é um índice derivado que dá pra reconstruir a qualquer momento a partir dos arquivos, sem vector store pra ficar de babá e sem nada preso num blob binário.</li>
<li><strong>Ele captura o trabalho sozinho e em silêncio.</strong> Sem cerimônia de &ldquo;lembra disso&rdquo;. E o caminho padrão roda com zero chamada de LLM.</li>
<li><strong>Ele é um binário só.</strong> Sem sidecar, sem três bancos pra sincronizar. Todas as escritas passam por um único writer, com um teto de escrita que a gente mediu de verdade, com teste real. Foi exatamente esse desenho que evitou a corrupção de escrita concorrente que derrubou os outros.</li>
</ul>
<p>Nenhum concorrente entrega esse conjunto. Alguns têm um ou outro pedaço. O ai-memory tem o pacote, e agora com paridade nos itens onde antes ficava atrás.</p>
<h2>A 2.0 é de todo mundo<span class="hx:absolute hx:-mt-20" id="a-20-é-de-todo-mundo"></span>
    <a href="#a-20-%c3%a9-de-todo-mundo" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Quando escrevi o post de julho, quinze pessoas tinham PR mergeado no projeto. Hoje são cerca de setenta. Faz tempo que isso deixou de ser um programinha de fim de semana.</p>
<p>Os números até a 2.0: mais de 1.500 commits, <strong>371 pull requests mergeados</strong> e <strong>181 issues fechadas</strong>. Isso saiu de gente usando de verdade e mandando correção, funcionalidade e documentação.</p>
<p>Preciso agradecer em especial ao <a href="https://github.com/djalmajr"target="_blank" rel="noopener">Djalma Júnior</a>, que sozinho passou de 50 PRs mergeados, e ao <a href="https://github.com/samirhvbr"target="_blank" rel="noopener">Samir Hanna Verza</a>, com mais de 20. Logo atrás vêm <a href="https://github.com/lhzapata"target="_blank" rel="noopener">lhzapata</a>, <a href="https://github.com/pedrofjr"target="_blank" rel="noopener">pedrofjr</a>, <a href="https://github.com/mrpaiva"target="_blank" rel="noopener">mrpaiva</a>, <a href="https://github.com/lucasliet"target="_blank" rel="noopener">lucasliet</a>, <a href="https://github.com/lihuiyang1024"target="_blank" rel="noopener">lihuiyang1024</a>, <a href="https://github.com/Murillofilho86"target="_blank" rel="noopener">Murillofilho86</a> e <a href="https://github.com/matheus-rodrigues00"target="_blank" rel="noopener">Matheus Rodrigues</a>. E tem uma cauda longa de dezenas de outras pessoas com PR mergeado que seria injusto tentar listar inteira aqui.</p>
<p>Se você quer entrar nessa, o <a href="https://github.com/akitaonrails/ai-memory/blob/main/CONTRIBUTING.md"target="_blank" rel="noopener">guia de contribuição</a> foi reescrito pra deixar tudo claro: como configurar o ambiente, os gates que o CI cobra, a regra do CHANGELOG e a política de versionamento. Bug fix costuma sair rápido no próximo patch. Funcionalidade pequena, como um novo harness ou provider, entra no próximo minor. Tem issue marcada pra quem está começando.</p>
<h2>Como pegar a 2.0<span class="hx:absolute hx:-mt-20" id="como-pegar-a-20"></span>
    <a href="#como-pegar-a-20" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A página do projeto tem todos os métodos de instalação, incluindo AUR, Homebrew e binários de release:</p>
<ul>
<li><a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">ai-memory no GitHub</a></li>
<li><a href="https://github.com/akitaonrails/ai-memory/releases/tag/v2.0.0"target="_blank" rel="noopener">Notas da release v2.0.0</a></li>
</ul>
<p>Depois de atualizar, na primeira execução deixe a migração fazer o backup e converter sua wiki pro formato OKF. Se você usa o modo gerenciado, reinstale os hooks dos harnesses que pretende usar.</p>
<h2>Conclusão<span class="hx:absolute hx:-mt-20" id="conclusão"></span>
    <a href="#conclus%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A 1.x provou que a ideia funcionava. A 2.0 é a versão que eu recomendaria sem asterisco pra outra pessoa botar num time.</p>
<p>O formato é aberto, então sua memória não fica presa. A busca semântica roda local, então você não paga nem vaza. Vários agentes e várias pessoas trabalham no mesmo projeto sem se atropelar. E o desenho de um binário só, com um writer só, é o que evita justamente os problemas que afundaram metade da concorrência.</p>
<p>LLM e assinatura eu continuo alugando de quem estiver melhor no mês. A memória do projeto fica comigo, com o time, e agora num formato que ninguém tira de mim.</p>
]]></content:encoded><category>ai-memory</category><category>agentes-de-codigo</category><category>open-source</category></item><item><title>Novidades no meu AI-MEMORY: cada vez melhor pra usar com suas IAs</title><link>https://akitaonrails.github.io/2026/07/20/novidades-no-meu-ai-memory-cada-vez-melhor-pra-usar-com-suas-ias/</link><guid isPermaLink="true">https://akitaonrails.github.io/2026/07/20/novidades-no-meu-ai-memory-cada-vez-melhor-pra-usar-com-suas-ias/</guid><pubDate>Mon, 20 Jul 2026 21:00:00 -0300</pubDate><description>&lt;p&gt;Faz pouco mais de um mês que publiquei &lt;a href="https://akitaonrails.github.io/2026/06/16/ai-memory-memoria-longo-prazo-karpathy-wiki-auto-aprendizado-hermes-projetos/"&gt;ai-memory: memória de longo prazo (Karpathy Wiki) e auto-aprendizado (Hermes) pros seus projetos&lt;/a&gt;. Foi dia 16 de junho. Naquele texto eu expliquei como sessões viravam páginas Markdown, como o auto-improve promovia aprendizados e por que memória ruim pode ser pior que amnésia.&lt;/p&gt;
&lt;p&gt;No mesmo dia saiu a versão 1.1.0. Hoje, 20 de julho, estamos na &lt;strong&gt;1.17.1&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Versão sozinha não quer dizer grande coisa, então fui contar o que aconteceu de verdade desde o horário daquele post. Foram &lt;strong&gt;31 releases, 55 pull requests mergeados e 46 issues fechadas&lt;/strong&gt;. Eu contei &lt;strong&gt;24 grupos de funcionalidades novas voltadas ao usuário&lt;/strong&gt; no &lt;a href="https://github.com/akitaonrails/ai-memory/blob/main/CHANGELOG.md"target="_blank" rel="noopener"&gt;CHANGELOG&lt;/a&gt;, ignorando correções, documentação e detalhes internos da mesma entrega. Se eu quebrasse a nova família &lt;code&gt;ai-memory run&lt;/code&gt; em auto-seleção, adoção de sessão, suporte a Crush, &lt;code&gt;--yolo&lt;/code&gt;, busca e recuperação, passava disso fácil.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Faz pouco mais de um mês que publiquei <a href="/2026/06/16/ai-memory-memoria-longo-prazo-karpathy-wiki-auto-aprendizado-hermes-projetos/">ai-memory: memória de longo prazo (Karpathy Wiki) e auto-aprendizado (Hermes) pros seus projetos</a>. Foi dia 16 de junho. Naquele texto eu expliquei como sessões viravam páginas Markdown, como o auto-improve promovia aprendizados e por que memória ruim pode ser pior que amnésia.</p>
<p>No mesmo dia saiu a versão 1.1.0. Hoje, 20 de julho, estamos na <strong>1.17.1</strong>.</p>
<p>Versão sozinha não quer dizer grande coisa, então fui contar o que aconteceu de verdade desde o horário daquele post. Foram <strong>31 releases, 55 pull requests mergeados e 46 issues fechadas</strong>. Eu contei <strong>24 grupos de funcionalidades novas voltadas ao usuário</strong> no <a href="https://github.com/akitaonrails/ai-memory/blob/main/CHANGELOG.md"target="_blank" rel="noopener">CHANGELOG</a>, ignorando correções, documentação e detalhes internos da mesma entrega. Se eu quebrasse a nova família <code>ai-memory run</code> em auto-seleção, adoção de sessão, suporte a Crush, <code>--yolo</code>, busca e recuperação, passava disso fácil.</p>
<p>Quinze pessoas tiveram PRs mergeados nesse período, quatorze além de mim. Preciso agradecer em especial ao <a href="https://github.com/djalmajr"target="_blank" rel="noopener">Djalma Júnior</a>, que sozinho teve 24 PRs mergeados, <a href="https://github.com/matheus-rodrigues00"target="_blank" rel="noopener">Matheus Rodrigues</a>, com cinco, <a href="https://github.com/lhzapata"target="_blank" rel="noopener">lhzapata</a>, com quatro, <a href="https://github.com/rthiago"target="_blank" rel="noopener">Thiago Silva</a> e <a href="https://github.com/cristianodewes"target="_blank" rel="noopener">Cristiano Dewes</a>, com dois cada. Mais nove contribuidores tiveram PR mergeado. Faz tempo que isso deixou de ser &ldquo;um programinha que eu fiz num fim de semana&rdquo;.</p>
<p>Não vou despejar 55 PRs aqui. Quero falar da mudança que mais afeta meu uso diário: o novo <strong><code>ai-memory run</code></strong>.</p>
<h2>A sessão também faz parte do projeto<span class="hx:absolute hx:-mt-20" id="a-sessão-também-faz-parte-do-projeto"></span>
    <a href="#a-sess%c3%a3o-tamb%c3%a9m-faz-parte-do-projeto" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Código é o resultado que sobreviveu. Ele não guarda a investigação inteira.</p>
<p>O Git mostra que você trocou Redis por SQLite. Talvez o commit explique uma parte. Mas onde ficou o experimento com Redis? Onde está o bug intermitente que só aparecia com dois workers? Quem lembrou que a primeira solução quebrava no Windows? Por que o time mudou de ideia depois de três horas? Qual workaround era temporário e qual virou decisão?</p>
<p>Boa parte disso só existe na sessão do agente.</p>
<p>Quando programo com Claude Code ou Codex, a sessão acumula o raciocínio operacional do projeto: perguntas, correções, tentativas descartadas, resultados de testes, surpresas, decisões e mudanças de direção. O código final mostra o que ficou. A sessão explica por que chegamos ali.</p>
<p>E sessão de LLM, no fim das contas, é texto. Claude Code grava JSONL. Codex também. OpenCode usa SQLite. Pi, OMP e Crush têm seus próprios formatos e diretórios. Cada harness empacota a conversa de um jeito, mas o conteúdo visível continua sendo mensagens e resultados de ferramentas.</p>
<p>Por que eu deveria deixar a parte mais cara do trabalho presa ao harness?</p>
<p>Anthropic pode mudar limite, preço, modelo ou formato amanhã. OpenAI também. Um agente pode estar excelente esta semana e insuportável na próxima. Eu quero trocar o motor sem jogar fora a viagem inteira.</p>
<p>Essa é a tese do ai-memory desde o começo: <strong>o programador tem que continuar independente das vontades dos providers</strong>. Modelo e harness são substituíveis. A memória do projeto é minha.</p>
<h2>O handoff resolvia só metade<span class="hx:absolute hx:-mt-20" id="o-handoff-resolvia-só-metade"></span>
    <a href="#o-handoff-resolvia-s%c3%b3-metade" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O ai-memory já fazia passagem de bastão. Eu encerrava Claude Code, os hooks consolidavam a sessão e o Codex seguinte recebia um resumo curto com o que foi feito, perguntas abertas e próximos passos.</p>
<p>Isso continua existindo e continua útil. Quem abre <code>claude</code>, <code>codex</code> ou <code>opencode</code> diretamente mantém o comportamento anterior. O launcher novo é opt-in.</p>
<p>Mas handoff é uma compressão deliberadamente lossy. Ele preserva o que parece mais importante naquele momento. Não pretende transportar a sessão inteira, nem retomar a sessão nativa de cada harness. Se o resumo omitiu uma tentativa antiga que voltou a ser relevante duas horas depois, você precisa procurar na wiki ou nos registros.</p>
<p>O <code>ai-memory run</code> acrescenta outra camada: uma <strong>workstream gerenciada</strong>, uma linha de trabalho que atravessa os harnesses.</p>
<h2>Claude hoje, Codex daqui a pouco<span class="hx:absolute hx:-mt-20" id="claude-hoje-codex-daqui-a-pouco"></span>
    <a href="#claude-hoje-codex-daqui-a-pouco" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O uso básico é esse:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ~/Projects/meu-projeto
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ai-memory run claude
</span></span><span class="line"><span class="cl"><span class="c1"># trabalha, encerra o Claude Code normalmente</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ai-memory run codex --yolo
</span></span><span class="line"><span class="cl"><span class="c1"># Codex continua a mesma linha de trabalho</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ai-memory run claude --model opus
</span></span><span class="line"><span class="cl"><span class="c1"># volta pra sessão nativa anterior do Claude</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ai-memory run
</span></span><span class="line"><span class="cl"><span class="c1"># ou deixa o ai-memory escolher o harness certo pra continuar</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Não precisa de <code>--</code> pra separar os argumentos. Tudo depois do nome do harness segue pra ele, com uma exceção proposital: o <code>--yolo</code> pertence ao wrapper e é traduzido pra opção perigosa nativa de Claude Code, Codex, OpenCode, Pi ou Crush.</p>
<p>Por baixo, o ai-memory não tenta converter um arquivo do Codex num arquivo do Claude. Isso seria frágil e provavelmente quebraria na próxima atualização. Cada harness mantém sua própria sessão nativa. A workstream liga essas sessões a um ledger portátil com a parte visível da conversa.</p>
<p>Pensa assim:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">sessão nativa do Claude ─┐
</span></span><span class="line"><span class="cl">sessão nativa do Codex  ─┼─ workstream ─ contexto portátil
</span></span><span class="line"><span class="cl">sessão do OpenCode      ─┤                 + busca completa
</span></span><span class="line"><span class="cl">sessão nativa do Pi     ─┘</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Na primeira vez que Claude entra naquela workstream, ele ganha uma sessão nativa. Quando você troca pra Codex, o Codex ganha a sessão nativa dele e recebe o delta portátil que ainda não viu. Ao voltar pro Claude, o launcher usa o <code>--resume</code> do próprio Claude Code e entrega apenas o que aconteceu nos outros harnesses desde a última vez.</p>
<p>Isso é bem diferente de começar um chat novo com um resumo colado no prompt. O Claude volta pra sessão real dele. O Codex volta pra sessão real dele. O ai-memory cuida da continuidade entre os dois.</p>
<p>Hoje o modo gerenciado suporta <strong>Claude Code, Codex, OpenCode, Pi, Crush e OMP</strong>. O suporte geral do ai-memory é maior, com MCP e hooks pra outros clientes, mas isso não quer dizer que todo cliente já tenha adapter de sessão nativa pro <code>run</code>. São contratos diferentes e eu prefiro deixar isso explícito.</p>
<h2>O que entra na workstream<span class="hx:absolute hx:-mt-20" id="o-que-entra-na-workstream"></span>
    <a href="#o-que-entra-na-workstream" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Quando o harness encerra, o ai-memory lê o final da sessão nativa sem modificar o store original. Entram mensagens visíveis de usuário e assistente, tool calls concluídas com seus resultados, resumos de compaction e um checkpoint não mutante do Git. Cada evento mantém a origem: veio do Claude, Codex, OpenCode, Pi, Crush ou OMP.</p>
<p>Credenciais do provider, registros criptografados, system/developer prompts e hidden reasoning ficam de fora. Formatos privados que o adapter não entende também ficam de fora e geram uma anotação de perda, em vez de o sistema fingir que importou tudo.</p>
<p>Os registros passam pelo sanitizer antes de entrar no ledger pesquisável e nos segmentos JSONL imutáveis do ai-memory. Os stores nativos são abertos read-only pelo adapter; quem continua escrevendo neles é o próprio harness.</p>
<p>Também não enfio a sessão inteira no próximo prompt. Isso recriaria o problema que o projeto tenta resolver: contexto bruto demais, caro demais e cheio de ruído. O próximo agente recebe um delta recente com tamanho limitado. Se uma decisão velha voltar a importar, o ledger completo continua pesquisável:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-memory workstream-search <span class="s2">&#34;por que desistimos do Redis&#34;</span>
</span></span><span class="line"><span class="cl">ai-memory workstream-search --limit <span class="m">50</span> --json <span class="s2">&#34;migration que falhou&#34;</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Dentro de um <code>ai-memory run</code>, o ID da workstream já entra no ambiente. O agente não precisa descobrir UUID nenhum.</p>
<p>E o ledger não substitui a wiki. Ele resolve continuidade operacional. Decisões, regras, procedimentos e gotchas que precisam sobreviver por meses continuam merecendo páginas Markdown consolidadas. Sessão bruta é evidência. Wiki é conhecimento organizado.</p>
<h2>Posso manter mais de uma linha de trabalho?<span class="hx:absolute hx:-mt-20" id="posso-manter-mais-de-uma-linha-de-trabalho"></span>
    <a href="#posso-manter-mais-de-uma-linha-de-trabalho" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Sim. A workstream padrão se chama <code>default</code>, selecionada por repositório e worktree. Se eu quiser abrir uma linha independente pra uma investigação sem contaminar o trabalho principal:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-memory run --new investigar-race claude
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># depois continuo aquela linha com outro harness</span>
</span></span><span class="line"><span class="cl">ai-memory run --workstream investigar-race codex</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Uma lease impede duas janelas de escreverem ao mesmo tempo na mesma workstream. Em encerramento normal, o launcher importa o final da sessão e libera imediatamente. Se alguém matar o processo sem cleanup, a lease expira em até 90 segundos e a próxima execução retoma do último cursor confirmado, sem duplicar os eventos já importados.</p>
<p>Uma irritação besta que eu tinha o tempo todo: voltava pra um projeto depois de alguns dias e não lembrava se a sessão mais recente estava no Claude ou no Codex. Eu chutava um, abria, percebia que o contexto estava no outro, fechava e tentava de novo.</p>
<p>Agora só rodo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-memory run
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ou com a mesma seleção automática em YOLO mode</span>
</span></span><span class="line"><span class="cl">ai-memory run --yolo</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Numa workstream vazia, o ai-memory procura sessões locais daquele checkout em Claude Code, Codex, OpenCode, Pi e Crush, descobre qual é a mais recente e abre o harness certo pra mim. Numa workstream já estabelecida, a memória do servidor vence o timestamp de arquivo: ele volta ao último harness ligado àquele trabalho, em vez de adotar por engano uma sessão velha que só recebeu uma gravação mais recente. OMP continua disponível quando escolhido explicitamente, mas ainda não participa da seleção automática.</p>
<p>Na primeira execução explícita, o launcher também pode oferecer sessões existentes do mesmo checkout pra adoção. Dá pra começar a usar sem abandonar o chat que já estava aberto antes de atualizar o ai-memory.</p>
<h2>Outras novidades que eu realmente uso<span class="hx:absolute hx:-mt-20" id="outras-novidades-que-eu-realmente-uso"></span>
    <a href="#outras-novidades-que-eu-realmente-uso" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Eu prometi não ler o changelog inteiro em voz alta, mas algumas mudanças desse mês merecem menção porque reduzem trabalho do programador.</p>
<h3>Briefing antes da primeira pergunta<span class="hx:absolute hx:-mt-20" id="briefing-antes-da-primeira-pergunta"></span>
    <a href="#briefing-antes-da-primeira-pergunta" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Um projeto pode pedir um briefing automático no início de cada sessão:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">briefing</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">inject_on_session_start</span> <span class="p">=</span> <span class="s2">&#34;true&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">max_chars</span> <span class="p">=</span> <span class="mi">4000</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>O ai-memory recompõe um pacote com páginas pinned, <code>_rules/</code>, <code>_slots/</code> e títulos recentes. O agente começa sabendo as regras e o estado básico do projeto, em vez de gastar a primeira conversa redescobrindo a arquitetura. É opt-in porque consome contexto em todo SessionStart, inclusive depois de um <code>/clear</code> do Claude.</p>
<h3>Preferências globais e busca entre projetos<span class="hx:absolute hx:-mt-20" id="preferências-globais-e-busca-entre-projetos"></span>
    <a href="#prefer%c3%aancias-globais-e-busca-entre-projetos" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Preferências que valem pra todo meu trabalho agora podem viver no escopo reservado <code>_global</code>: estilo de código, ferramentas que prefiro, regras pessoais e convenções que não pertencem a um repositório específico. Consultas normais já fazem union desse escopo com o projeto atual.</p>
<p>Pra meta-repos que precisam consultar vários projetos irmãos o tempo todo, existe outro opt-in:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">recall</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">default_global</span> <span class="p">=</span> <span class="s2">&#34;true&#34;</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Assim <code>memory_query</code> e <code>memory_recent</code> sem escopo explícito procuram em todos os projetos. Não ligo isso em qualquer repo porque busca global à toa só traz ruído.</p>
<h3>Menos instrução fixa, mais Agent Skills<span class="hx:absolute hx:-mt-20" id="menos-instrução-fixa-mais-agent-skills"></span>
    <a href="#menos-instru%c3%a7%c3%a3o-fixa-mais-agent-skills" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>O bloco de routing em <code>CLAUDE.md</code> ou <code>AGENTS.md</code> ficou pequeno. As instruções detalhadas de quando buscar memória, consolidar, guardar decisão ou criar handoff foram movidas pra Agent Skills gerenciadas. Um comando instala ou atualiza os dois sem atropelar o resto do arquivo:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-memory install-instructions</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Isso também reduz drift. Quando o protocolo muda, atualizo o pacote gerenciado em vez de caçar um prompt velho copiado em quarenta repositórios.</p>
<h3>Privacidade antes da rede<span class="hx:absolute hx:-mt-20" id="privacidade-antes-da-rede"></span>
    <a href="#privacidade-antes-da-rede" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Agora cada repo pode excluir caminhos da captura:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">capture</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">ignore_paths</span> <span class="p">=</span> <span class="p">[</span><span class="s2">&#34;private/**&#34;</span><span class="p">,</span> <span class="s2">&#34;~/personal-notes/**&#34;</span><span class="p">]</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Quando uma integração reconhece uma file tool e o caminho bate, o evento é descartado localmente antes de spool, fila, rede ou servidor. Isso tem limites claros: não é DLP mágico, não interpreta qualquer shell command e não rastreia conteúdo citado em texto livre. Mas resolve o caso verificável sem vender uma garantia falsa.</p>
<p>Também entraram integrações com Kimi Code, Grok Build CLI, Devin e Zero, um provider OpenCode Zen/Go, <code>finalize-session</code> pro Codex e melhorias na administração de workspaces. Reforço: ter MCP e hook não significa automaticamente ter <code>ai-memory run</code>. O <a href="https://github.com/akitaonrails/ai-memory#support-matrix"target="_blank" rel="noopener">README</a> separa esses níveis.</p>
<h2>Bônus: ai-jail por fora, YOLO por dentro<span class="hx:absolute hx:-mt-20" id="bônus-ai-jail-por-fora-yolo-por-dentro"></span>
    <a href="#b%c3%b4nus-ai-jail-por-fora-yolo-por-dentro" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Há pouco mais de uma semana escrevi <a href="/2026/07/11/como-me-precaver-pros-meus-agentes-nao-apagarem-minhas-coisas/">como me protejo pra agentes não apagarem minhas coisas</a>. Minha recomendação continua a mesma: YOLO mode dá a melhor experiência, desde que o sistema limite o estrago possível.</p>
<p>O <a href="https://github.com/akitaonrails/ai-jail"target="_blank" rel="noopener">ai-jail</a> chegou à versão 1.15.0 e agora entende o launcher do ai-memory. O jeito que mais estou gostando de trabalhar virou:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-jail ai-memory run codex --yolo</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Ou, se quero que o ai-memory escolha qual harness deve continuar:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-jail ai-memory run --yolo</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>A ordem importa. <code>ai-jail</code> fica por fora para manter tanto o launcher quanto o processo filho na mesma sandbox. <code>ai-memory run</code> sozinho gerencia a sessão, mas não cria sandbox.</p>
<p>O <code>--yolo</code> desliga a cerimônia de aprovação do harness. O ai-jail faz a contenção: projeto atual read-write, home substituído por tmpfs, partes necessárias do estado dos agentes montadas seletivamente e diretórios sensíveis como <code>.ssh</code>, <code>.gnupg</code> e <code>.aws</code> fora da jaula. O suporte novo também deixa o estado local do ai-memory gravável pros hooks manterem spool e cursores entre execuções.</p>
<p>ai-jail reconhece tanto a camada <code>ai-memory</code> quanto o harness selecionado. Se você tem configuração global específica pra Codex, por exemplo, ela continua sendo aplicada quando o comando real é <code>ai-memory run codex</code>. Até o ajuste de redraw da status bar entende que o filho é Codex.</p>
<p>Essa combinação resolve as duas irritações ao mesmo tempo: o agente para de pedir confirmação a cada comando e a sessão para de pertencer ao agente. Fluidez sem dar o home inteiro de presente.</p>
<h2>One more thing: ai-usagebar também cresceu<span class="hx:absolute hx:-mt-20" id="one-more-thing-ai-usagebar-também-cresceu"></span>
    <a href="#one-more-thing-ai-usagebar-tamb%c3%a9m-cresceu" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Quando publiquei o <a href="/2026/05/24/criei-widget-waybar-omarchy-monitorar-uso-llms-ai-usagebar/">ai-usagebar original</a>, ele monitorava Claude, Codex, Z.AI e OpenRouter num widget da Waybar ou numa TUI. A versão 0.14.0 já cobre <strong>onze integrações de uso, gasto ou saldo</strong>.</p>
<p>Kimi ganhou as duas informações que realmente importam pra coding: quota semanal da assinatura e janela móvel de cinco horas. Kilo, Novita, Moonshot e Grok mostram saldo restante. Uma integração separada da Anthropic Console mostra gasto de API no mês, sem confundir isso com a assinatura do Claude Code. Ela deixa explícito que o Cost API não inclui Priority Tier.</p>
<p>Também dá pra cadastrar várias contas da Anthropic, ver limites semanais específicos de modelos como Fable e enxergar um marcador de ritmo. A barra não fica vermelha só porque chegou em 40%; ela compara o percentual gasto com quanto da janela já passou. Se usei 40% em 20% da semana, estou rápido demais. Essa é a informação útil.</p>
<p>O projeto deixou de ser só Waybar. Tem app nativo de menu bar no macOS, extensão do GNOME e a TUI standalone. E a novidade mais recente é um monitor local de contexto do Claude Code: aperto <code>c</code>, escolho uma das sessões recentes e vejo quanto da janela já foi consumido. Ele lê caudas limitadas dos JSONL locais e não inventa porcentagem quando não consegue determinar o tamanho da janela.</p>
<p>No meu fluxo, o trio acaba se encontrando naturalmente. <code>ai-usagebar</code> mostra qual assinatura ainda tem espaço. <code>ai-memory run</code> troca de harness sem jogar fora o trabalho. <code>ai-jail</code> deixa o escolhido trabalhar em YOLO sem acesso irrestrito à máquina.</p>
<h2>Atualizando<span class="hx:absolute hx:-mt-20" id="atualizando"></span>
    <a href="#atualizando" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>As páginas de instalação dos três projetos têm todos os métodos, incluindo AUR, Homebrew e binários de release:</p>
<ul>
<li><a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">ai-memory</a></li>
<li><a href="https://github.com/akitaonrails/ai-jail"target="_blank" rel="noopener">ai-jail</a></li>
<li><a href="https://github.com/akitaonrails/ai-usagebar"target="_blank" rel="noopener">ai-usagebar</a></li>
</ul>
<p>Depois de atualizar o ai-memory, reinstale os hooks dos harnesses que pretende usar no modo gerenciado. Os três principais no meu caso:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-memory install-hooks --agent claude-code --apply
</span></span><span class="line"><span class="cl">ai-memory install-hooks --agent codex --apply
</span></span><span class="line"><span class="cl">ai-memory install-hooks --agent opencode --apply</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Crush não precisa de hook no modo gerenciado; ele recebe o contexto por um arquivo temporário configurado só pro processo lançado. A <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/managed-workstreams.md"target="_blank" rel="noopener">documentação de managed workstreams</a> tem os detalhes de instalação, privacidade, recuperação e os argumentos nativos de cada adapter.</p>
<h2>Conclusão<span class="hx:absolute hx:-mt-20" id="conclusão"></span>
    <a href="#conclus%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Um mês atrás, o ai-memory já conseguia transformar sessão em wiki e entregar um handoff pro próximo agente. Agora ele consegue gerenciar a própria linha de trabalho: adota uma sessão existente, mantém uma sessão nativa por harness, transporta o histórico visível, retoma cada cliente no formato dele e deixa o ledger inteiro pesquisável.</p>
<p>Pra mim, é aí que está o valor. O código contém a implementação que venceu. A sessão contém as decisões, experimentos que falharam, gotchas, bugs inesperados e mudanças de ideia que produziram aquela implementação. Jogar isso fora toda vez que muda de provider é desperdício.</p>
<p>Raw transcript também não resolve sozinho. É grande, repetitivo e caro pra enfiar em qualquer contexto. O ai-memory mantém a evidência, entrega só o delta recente e usa consolidação pra transformar o que merece sobreviver em páginas Markdown curtas.</p>
<p>Ainda há formatos novos pra suportar, arestas de plataforma e muito teste pela frente. A diferença é que agora existe uma base real, com acceptance test chamando harness de verdade, 14 contribuidores externos com PR mergeado em pouco mais de um mês e uso diário empurrando o desenho.</p>
<p>LLM e assinatura eu alugo de quem estiver entregando melhor hoje. A sessão do meu projeto fica comigo.</p>
]]></content:encoded><category>ai-memory</category><category>agentes-de-codigo</category><category>ai-jail</category><category>ai-usagebar</category></item><item><title>ai-memory: memória de longo prazo (Karpathy Wiki) e auto-aprendizado (Hermes) pros seus projetos</title><link>https://akitaonrails.github.io/2026/06/16/ai-memory-memoria-longo-prazo-karpathy-wiki-auto-aprendizado-hermes-projetos/</link><guid isPermaLink="true">https://akitaonrails.github.io/2026/06/16/ai-memory-memoria-longo-prazo-karpathy-wiki-auto-aprendizado-hermes-projetos/</guid><pubDate>Tue, 16 Jun 2026 10:00:00 -0300</pubDate><description>&lt;p&gt;Ontem eu publiquei um post sobre como o &lt;a href="https://akitaonrails.github.io/2026/06/14/ai-memory-arquitetura-emergente-e-software-maleavel/"&gt;ai-memory virou um exemplo vivo de arquitetura emergente&lt;/a&gt;. Aquele post era mais sobre processo: como um projeto pequeno, feito pra mim, foi crescendo com contribuições reais até virar um sistema multiusuário, multiplataforma, com suporte a vários agentes e um monte de aresta que só aparece quando gente de verdade começa a usar.&lt;/p&gt;
&lt;p&gt;Hoje quero falar do outro lado: &lt;strong&gt;pra que isso serve no dia a dia&lt;/strong&gt; e como o projeto incorpora uma ideia inspirada no &lt;strong&gt;&lt;a href="https://github.com/NousResearch/hermes-agent"target="_blank" rel="noopener"&gt;Hermes Agent&lt;/a&gt;&lt;/strong&gt;: um loop de auto-aprendizado com validação, trilha de auditoria e uma opção de revisão manual quando você quer mais controle.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Ontem eu publiquei um post sobre como o <a href="/2026/06/14/ai-memory-arquitetura-emergente-e-software-maleavel/">ai-memory virou um exemplo vivo de arquitetura emergente</a>. Aquele post era mais sobre processo: como um projeto pequeno, feito pra mim, foi crescendo com contribuições reais até virar um sistema multiusuário, multiplataforma, com suporte a vários agentes e um monte de aresta que só aparece quando gente de verdade começa a usar.</p>
<p>Hoje quero falar do outro lado: <strong>pra que isso serve no dia a dia</strong> e como o projeto incorpora uma ideia inspirada no <strong><a href="https://github.com/NousResearch/hermes-agent"target="_blank" rel="noopener">Hermes Agent</a></strong>: um loop de auto-aprendizado com validação, trilha de auditoria e uma opção de revisão manual quando você quer mais controle.</p>
<p>Se você caiu de paraquedas, a sequência até aqui foi:</p>
<ol>
<li>Primeiro escrevi sobre <a href="/2026/05/18/memoria-agentes-karpathy-llm-wiki-agentmemory/">memória de agentes, Karpathy LLM Wiki e agentmemory</a>. Ali eu ainda estava avaliando o <a href="https://github.com/rohitg00/agentmemory"target="_blank" rel="noopener"><code>agentmemory</code></a> original.</li>
<li>Depois eu publiquei o post principal: <a href="/2026/05/23/criei-sistema-memoria-agentes-codigo-ai-memory/">criei um sistema de memória pra agentes de código: ai-memory</a>. Esse é o texto que explica a base do projeto.</li>
<li>No <a href="/2026/05/24/dicas-e-toolkit-de-ia-do-akita-ai-jail-ai-memory-ai-usagebar/">toolkit de IA</a>, eu posicionei o ai-memory junto com <code>ai-jail</code> e <code>ai-usagebar</code>: ferramentas pequenas pra resolver dores reais de quem usa agentes todo dia.</li>
<li>E ontem veio o post de <a href="/2026/06/14/ai-memory-arquitetura-emergente-e-software-maleavel/">arquitetura emergente</a>, mostrando como o projeto evoluiu com contribuidores.</li>
</ol>
<p>Esse post é a continuação prática. A ideia do ai-memory é transformar sessões longas de desenvolvimento numa <strong>wiki de projeto</strong> que um agente consegue consultar daqui a semanas, sem você virar suporte humano de contexto.</p>
<h2>O problema real: sessão longa vira amnésia longa<span class="hx:absolute hx:-mt-20" id="o-problema-real-sessão-longa-vira-amnésia-longa"></span>
    <a href="#o-problema-real-sess%c3%a3o-longa-vira-amn%c3%a9sia-longa" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Quem usa <a href="https://docs.anthropic.com/en/docs/claude-code/overview"target="_blank" rel="noopener">Claude Code</a>, <a href="https://github.com/openai/codex"target="_blank" rel="noopener">Codex</a>, <a href="https://opencode.ai/"target="_blank" rel="noopener">OpenCode</a>, <a href="https://cursor.com/"target="_blank" rel="noopener">Cursor</a>, <a href="https://github.com/google-gemini/gemini-cli"target="_blank" rel="noopener">Gemini CLI</a> ou qualquer agente desses já conhece o ciclo. Você começa uma sessão, explica o projeto, mostra os arquivos importantes, corrige uma alucinação, descobre uma armadilha, decide uma arquitetura, roda teste, falha, corrige, roda de novo. Depois de duas horas, o agente finalmente está &ldquo;aquecido&rdquo;. Ele sabe o que não deve fazer. Sabe onde estão os buracos. Sabe que aquela função parece errada mas existe por compatibilidade legada. Sabe que o teste só passa se subir o serviço X antes.</p>
<p>Aí a sessão acaba.</p>
<p>No dia seguinte você abre outro agente, ou o mesmo agente em outra janela, ou troca de Claude Code pra Codex porque quer comparar. E começa tudo de novo. &ldquo;Não, esse projeto usa isso.&rdquo; &ldquo;Não, já tentamos esse caminho.&rdquo; &ldquo;Não, essa API não existe.&rdquo; &ldquo;Não, esse arquivo é gerado.&rdquo; Você vira o cache humano do agente.</p>
<p>Janela de contexto grande ajuda só até certo ponto. Ela pertence à sessão atual, não ao mês inteiro do projeto. E contexto bruto continua sendo contexto bruto. Jogar cem mil tokens de log dentro do prompt é diferente de ter uma página curta dizendo:</p>
<ul>
<li>decisão: usamos SQLite como índice derivado, markdown é a fonte da verdade;</li>
<li>armadilha: no Windows não confie em inode, use índice próprio;</li>
<li>regra: não editar <code>content/_index.md</code> manualmente, rodar o gerador;</li>
<li>procedimento: pra publicar post novo, escrever PT primeiro, humanizar, validar Hugo, só traduzir depois de aprovação.</li>
</ul>
<p>Isso é memória útil. Não é transcrição. É síntese.</p>
<h2>O modelo mental: Karpathy Wiki<span class="hx:absolute hx:-mt-20" id="o-modelo-mental-karpathy-wiki"></span>
    <a href="#o-modelo-mental-karpathy-wiki" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O nome que eu gosto pra esse padrão é o que o Karpathy chamou de <strong><a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f"target="_blank" rel="noopener">LLM Wiki</a></strong>: em vez de depender de histórico bruto, você mantém uma wiki em markdown, versionada, que o agente consegue consultar. Páginas pequenas, com nomes estáveis, separadas por tipo de conhecimento. O agente não precisa lembrar tudo. Ele precisa saber procurar.</p>
<figure>
  <a href="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/06/15/ai-memory-hermes/architecture-overview.svg">
    <img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/06/15/ai-memory-hermes/architecture-overview.svg" alt="Diagrama da arquitetura do ai-memory: clientes de agente enviam hooks e chamadas MCP para o servidor, que escreve em uma wiki markdown e mantém SQLite como índice derivado." />
  </a>
  <figcaption>Visão geral da arquitetura do ai-memory. A fonte do diagrama está em <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/architecture-overview.svg">docs/architecture-overview.svg</a>.</figcaption>
</figure>
<p>O ai-memory implementa isso com uma ideia simples: hooks capturam o que aconteceu, o servidor organiza o material numa wiki markdown e os agentes consultam essa wiki quando precisam continuar o trabalho.</p>
<p>Algumas páginas são resumos de sessão. Outras viram decisões, armadilhas, procedimentos ou regras do projeto. O usuário não precisa decorar a taxonomia. O ponto é que o conhecimento deixa de ficar preso na janela do chat e passa a existir como arquivo legível.</p>
<p>Repara nessa última parte: a fonte de verdade é markdown. Você pode abrir no Obsidian, fazer <code>grep</code>, versionar, fazer backup com <code>rsync</code>, ver diff no git. O banco SQLite ajuda na busca, mas é índice derivado. Se amanhã eu jogar o banco fora, o sistema consegue reconstruir o índice a partir da wiki.</p>
<p>É aqui que eu fico chato. Quero arquivo que eu consigo ler, não uma caixa-preta de embeddings que &ldquo;talvez&rdquo; lembre.</p>
<h2>A base: memória que atravessa agentes<span class="hx:absolute hx:-mt-20" id="a-base-memória-que-atravessa-agentes"></span>
    <a href="#a-base-mem%c3%b3ria-que-atravessa-agentes" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Desde cedo, o ai-memory já resolvia a dor principal: <strong>contexto que sobrevive ao agente usado naquele momento</strong>.</p>
<p>Você podia encerrar uma sessão no Claude Code, abrir Codex no mesmo diretório, e o próximo agente receber um resumo curto dizendo onde parou, quais perguntas ficaram abertas e quais próximos passos faziam sentido.</p>
<p>Além disso, o agente podia consultar a wiki antes de responder. Em vez de depender só do que ainda cabe na janela de contexto, ele podia procurar decisões antigas, armadilhas conhecidas, páginas recentes e regras permanentes do projeto.</p>
<p>Na prática, o agente para de responder arquitetura no chute. Ele pode consultar: &ldquo;o que a gente decidiu sobre autenticação?&rdquo;, &ldquo;já tentamos usar Redis aqui?&rdquo;, &ldquo;qual era a armadilha do Docker nesse projeto?&rdquo;. E o resultado não vem como mil eventos crus, vem como página de wiki.</p>
<p>Em projeto de software isso faz diferença porque &ldquo;qual arquivo existe&rdquo; é a parte fácil. Isso o agente acha com <code>grep</code>. O conhecimento caro é <strong>por que</strong> uma coisa é daquele jeito. Por que deixamos biblioteca X de lado. Por que esse teste é estranho. Por que a configuração de CI tem uma exceção. Por que aquela refatoração foi adiada.</p>
<p>É isso que uma memória de longo prazo precisa preservar.</p>
<h2>O que veio do uso real<span class="hx:absolute hx:-mt-20" id="o-que-veio-do-uso-real"></span>
    <a href="#o-que-veio-do-uso-real" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Ontem eu citei alguns números e agradeci contribuidores, mas vale reforçar as funcionalidades novas porque elas mudam o perfil do projeto. O ai-memory deixou de ser &ldquo;meu daemon local&rdquo; e virou algo que dá pra rodar num homelab ou servidor compartilhado.</p>
<p>O resumo das mudanças é:</p>
<ul>
<li><strong>Dá pra usar sozinho ou em equipe.</strong> O sistema agora entende usuários, projetos e workspaces. Isso permite rodar num homelab ou servidor compartilhado sem misturar clientes, repositórios e sessões.</li>
<li><strong>O escopo ficou previsível.</strong> Um arquivo <code>.ai-memory.toml</code> pode dizer a qual projeto aquele diretório pertence. Isso ajuda em monorepos, worktrees, consultoria e separação trabalho/pessoal.</li>
<li><strong>Mais agentes conseguem participar.</strong> Além de Claude Code, Codex e OpenCode, entraram Cursor, Gemini CLI, <a href="https://antigravity.google/docs/hooks"target="_blank" rel="noopener">Antigravity CLI</a>, <a href="https://x.ai/cli"target="_blank" rel="noopener">Grok Build CLI</a>, <a href="https://docs.openclaw.ai/"target="_blank" rel="noopener">OpenClaw</a>, <a href="https://github.com/can1357/oh-my-pi"target="_blank" rel="noopener">Oh My Pi/OMP</a>, <a href="https://code.visualstudio.com/docs/copilot/overview"target="_blank" rel="noopener">VS Code GitHub Copilot</a> e <a href="https://claude.ai/download"target="_blank" rel="noopener">Claude Desktop</a>. Alguns têm hooks completos, outros só conseguem consultar via MCP, mas todos podem se beneficiar da mesma wiki.</li>
<li><strong>Administração e recuperação ficaram menos frágeis.</strong> Renomear ou mover projetos, restaurar páginas, reconstruir índice, usar a interface web e auditar mudanças são recursos chatos de explicar, mas importantes quando a ferramenta vira parte do fluxo diário.</li>
</ul>
<p>Não vou entrar em cada detalhe aqui. Pra isso existe a <a href="https://github.com/akitaonrails/ai-memory/tree/main/docs"target="_blank" rel="noopener">documentação no GitHub</a>. O importante é entender a mudança de categoria: deixou de ser um daemon local meu e virou uma memória compartilhável de projeto.</p>
<p>Isso veio de uso real. Djalma Júnior, wlech, Pedro de Freitas Jr, Mauro Couto de Paiva, Gustavo Cateim, Lucas Oliveira, Pablo Winter, azevedo-luis, zanlucathiago e outros foram empurrando o projeto pra cenários que eu não tinha previsto. É assim que software cresce sem virar arquitetura de PowerPoint: a necessidade puxa a arquitetura, não o contrário.</p>
<h2>Auto-improve: sessão vira memória<span class="hx:absolute hx:-mt-20" id="auto-improve-sessão-vira-memória"></span>
    <a href="#auto-improve-sess%c3%a3o-vira-mem%c3%b3ria" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Hoje, o ai-memory já tem um loop de auto-aprendizado seguro: quando há um provedor de LLM configurado, um job de fundo pode revisar sessões novas, separar ruído de aprendizado real e transformar as lições úteis em páginas duráveis da wiki.</p>
<p>Esse é o ponto que importa pro usuário: você não precisa lembrar de abrir um arquivo de notas no fim do dia, nem escrever manualmente &ldquo;aprendizados da sessão&rdquo;. Se a sessão revelou uma decisão, uma armadilha reproduzível ou um procedimento que vale repetir, o sistema consegue promover isso pra memória de projeto.</p>
<p>Por baixo, ele usa a sessão consolidada, procura sinais fortes, pede pra um LLM sugerir edições pequenas, valida caminhos, evidência, tamanho e confiança, registra a proposta numa trilha de auditoria e aplica a escrita pela trilha normal da wiki.</p>
<p>Se você quiser revisão humana antes da escrita final, basta configurar <code>[auto_improve] require_approval = true</code>. Aí as propostas ficam pendentes até alguém revisar, aprovar ou rejeitar.</p>
<p>No diagrama acima ele aparece do lado de manutenção, nas tarefas que dependem de LLM configurado. Não é parte do caminho quente do hook. Isso é de propósito. Hook tem que capturar rápido, devolver 202 ou 429, e sair da frente. Revisão com LLM é outra categoria de trabalho.</p>
<p>O detalhe importante: <strong>isso não entra no caminho quente do agente</strong>.</p>
<p>O usuário continua trabalhando normalmente. Hooks capturam a sessão. A passagem de bastão continua curta e acionável. O auto-improve roda como manutenção: olha pra trás, identifica o que merece sobreviver e transforma aprendizado em memória consultável. A funcionalidade existe pra responder uma pergunta:</p>
<blockquote>
  <p>&ldquo;O que essa sessão ensinou que vale transformar em memória permanente?&rdquo;</p>

</blockquote>
<p>E a resposta vira conhecimento reaproveitável, com rastro de proposta e evidência, não um chute solto dentro do prompt.</p>
<p>Isso parece pequeno, mas é a diferença entre uma memória útil e um agente que polui seu projeto com lixo confiante. Se você deixa um LLM escrever regra automaticamente toda vez que algo dá errado, em uma semana sua wiki vira cemitério de superstição: &ldquo;nunca use ferramenta X&rdquo;, &ldquo;sempre rode comando Y&rdquo;, &ldquo;biblioteca Z está quebrada&rdquo;. Só que muitas dessas coisas eram falhas transitórias: PATH errado, token expirado, rede fora, dependência desatualizada, erro corrigido cinco minutos depois.</p>
<p>Memória ruim é pior que falta de memória. Falta de memória te obriga a perguntar. Memória ruim te dá certeza falsa.</p>
<h2>O que é Hermes Agent<span class="hx:absolute hx:-mt-20" id="o-que-é-hermes-agent"></span>
    <a href="#o-que-%c3%a9-hermes-agent" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A inspiração veio do <strong>Hermes Agent</strong>, que trata aprendizado como parte do ciclo normal do agente. Depois de trabalhar, ele pode olhar pra trás e perguntar: &ldquo;isso gerou alguma memória ou skill útil para a próxima vez?&rdquo;</p>
<p>O ponto que me interessou foi a separação. O agente faz o trabalho primeiro. Depois, em segundo plano, revisa o que aconteceu. Existe também uma manutenção mais lenta, que procura conhecimento velho, duplicado ou pouco útil. Um loop aprende com a sessão; o outro limpa o jardim.</p>
<p>Essa separação evita o erro comum de criar um daemon mágico que muda tudo o tempo todo. Parece poderoso, mas fica impossível de confiar. Se quiser detalhes do estudo, deixei isso na <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/auto-improvement-loop.md"target="_blank" rel="noopener">documentação do loop de auto-improvement</a>.</p>
<h2>Como adaptamos Hermes pro ai-memory<span class="hx:absolute hx:-mt-20" id="como-adaptamos-hermes-pro-ai-memory"></span>
    <a href="#como-adaptamos-hermes-pro-ai-memory" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O ai-memory não copia Hermes literalmente. Hermes trabalha com memórias e skills. O ai-memory trabalha com páginas de wiki. Então a adaptação é simples: quando uma sessão ensina algo útil, o sistema tenta transformar isso em uma página pequena, legível e consultável.</p>
<p>O LLM sugere, mas o produto impõe fronteiras. A sugestão precisa ter evidência, caminho válido, tamanho razoável e confiança mínima. Isso evita que uma sessão confusa contamine a wiki inteira.</p>
<p>O desenho atual é esse:</p>
<ol>
<li>A sessão termina e vira <code>sessions/&lt;id&gt;.md</code> como já acontecia.</li>
<li>Um job de fundo revisa sessões concluídas elegíveis, depois do watermark inicial e da idade mínima configurada.</li>
<li>O revisor procura decisões, armadilhas, procedimentos e regras que valem guardar.</li>
<li>O sistema valida a sugestão e registra o rastro de auditoria.</li>
<li>Por padrão, a memória entra na wiki; se você quiser, pode exigir revisão manual antes disso.</li>
</ol>
<p>Essa trilha é a peça que faltava entre &ldquo;o LLM sugeriu&rdquo; e &ldquo;isso virou verdade do projeto&rdquo;. Memória de projeto não pode ser uma caixa-preta.</p>
<h2>O tipo de coisa que deve virar memória<span class="hx:absolute hx:-mt-20" id="o-tipo-de-coisa-que-deve-virar-memória"></span>
    <a href="#o-tipo-de-coisa-que-deve-virar-mem%c3%b3ria" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Essa parte é mais importante que a ferramenta: nem tudo que acontece numa sessão merece virar memória permanente.</p>
<p>O que vale guardar é o que ajuda o próximo agente a trabalhar melhor: uma decisão que afeta o futuro, uma armadilha reproduzível, um procedimento que vai se repetir, uma preferência explícita do usuário ou um padrão importante do projeto.</p>
<p>O que não vale guardar é ruído: um comando de teste, um erro transitório, uma falha causada pelo ambiente daquele dia ou uma narrativa inteira de sessão que já está preservada em <code>sessions/</code>.</p>
<p>Esse filtro é a diferença entre uma wiki que ajuda e uma wiki que atrapalha. O auto-improve não existe pra capturar mais coisa. Existe pra <strong>promover seletivamente</strong> o que merece sair da camada episódica e entrar na memória durável do projeto.</p>
<h2>Hooks, MCP e prompts: a parte que deixa usável<span class="hx:absolute hx:-mt-20" id="hooks-mcp-e-prompts-a-parte-que-deixa-usável"></span>
    <a href="#hooks-mcp-e-prompts-a-parte-que-deixa-us%c3%a1vel" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A outra metade do sistema é menos glamourosa, mas é o que faz parecer natural. O usuário trabalha normalmente. Os hooks capturam o ciclo da sessão. O MCP dá ao agente um jeito de consultar a memória. E o bloco de instruções em <code>CLAUDE.md</code> ou <code>AGENTS.md</code> ensina quando usar tudo isso.</p>
<p>Quando a integração é completa, a experiência fica quase invisível: você encerra uma sessão, abre outra ferramenta, e o próximo agente já tem como se orientar. Quando o cliente só suporta MCP, ele ainda consegue consultar a wiki, mesmo sem capturar todo o ciclo de vida.</p>
<p>O detalhe importante não é o formato específico de hook de cada ferramenta. Isso está na <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/install.md"target="_blank" rel="noopener">documentação de instalação</a>. O importante é que o ai-memory tenta esconder essas diferenças e dar ao agente um comportamento simples: antes de decidir, consulte a memória; quando aprender algo durável, preserve.</p>
<h2>Por que isso deixa sessões de código mais inteligentes<span class="hx:absolute hx:-mt-20" id="por-que-isso-deixa-sessões-de-código-mais-inteligentes"></span>
    <a href="#por-que-isso-deixa-sess%c3%b5es-de-c%c3%b3digo-mais-inteligentes" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O fluxo que eu quero é esse.</p>
<p>Você abre o OpenCode num projeto antigo. Antes de responder qualquer coisa séria, ele sabe consultar o ai-memory. Descobre que já existe uma decisão sobre banco. Descobre uma armadilha no build. Descobre que o último agente deixou uma passagem de bastão dizendo que o teste falhava em <code>PaymentImporter</code>. Você não precisa recontar a novela.</p>
<p>Durante a sessão, hooks registram o que acontece. No final, a sessão vira uma narrativa curta. Se foi uma sessão rica, o job de auto-improve pode transformar as lições em páginas como:</p>
<ul>
<li><code>gotchas/payment-importer-timezone.md</code>;</li>
<li><code>decisions/use-ledger-table-for-reconciliation.md</code>;</li>
<li><code>procedures/run-importer-smoke-test.md</code>.</li>
</ul>
<p>No modo padrão, isso entra como memória validada e auditável. No modo manual, você olha o diff, aprova ou rejeita. Na próxima semana, outro agente consulta e não pisa no mesmo buraco.</p>
<p>Esse é o ciclo que eu quero: <strong>trabalho vira conhecimento, conhecimento melhora o próximo trabalho</strong>. Sem virar religião de prompt, sem depender de uma janela infinita, sem confiar em memória opaca.</p>
<h2>Cuidado com a palavra &ldquo;auto&rdquo;<span class="hx:absolute hx:-mt-20" id="cuidado-com-a-palavra-auto"></span>
    <a href="#cuidado-com-a-palavra-auto" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Tem uma armadilha de marketing aqui. &ldquo;Auto-aprendizado&rdquo; soa como ficção científica: o agente aprende sozinho e fica melhor pra sempre. Não é isso que eu quero vender, porque isso vira mentira rápido.</p>
<p>O que temos hoje é bem mais pé no chão: um job que revisa sessões, sugere memória, valida a sugestão, guarda evidência e aplica pela trilha normal da wiki. Se você preferir, existe modo de revisão manual antes da escrita final. E justamente por ser limitado ele é útil. O prompt ativo e a latência dos hooks ficam protegidos. O sistema observa, filtra, valida e deixa rastro.</p>
<p>Esse é o limite correto pra um sistema desses neste momento. Auto-aprovação só depois de validação estrutural e evidência. Revisão humana quando o projeto pedir. Confiança se ganha com histórico, não com entusiasmo.</p>
<h2>Fechando<span class="hx:absolute hx:-mt-20" id="fechando"></span>
    <a href="#fechando" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O ai-memory começou como uma resposta simples pra uma frustração simples: cansei de reexplicar o mesmo projeto pra agentes diferentes. Em poucas semanas virou uma wiki versionada, com hooks, MCP, passagem de bastão, multiusuário, multi-workspace, arquivo marcador, suporte a vários CLIs, interface web, recuperação e agora um loop de auto-aprendizado inspirado no Hermes Agent, com validação e auditoria em vez de fé cega no LLM.</p>
<p>A filosofia continua a mesma: memória boa organiza conhecimento em páginas pequenas, legíveis, versionadas, citáveis. É transformar sessão longa em decisão, armadilha, procedimento, regra. É deixar o próximo agente começar do ponto onde o anterior parou.</p>
<p>Se você usa agente pra projeto de software de verdade, esse é o gargalo que começa a doer primeiro. Não é só modelo melhor. É continuidade.</p>
<p>O repositório está aqui: <a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">github.com/akitaonrails/ai-memory</a>. Se você já usa com um provedor de LLM configurado, atualize e deixe o auto-improve trabalhar em segundo plano nas novas sessões concluídas.</p>
<p>Se quiser revisão manual antes de aplicar, configure:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">auto_improve</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">require_approval</span> <span class="p">=</span> <span class="kc">true</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>No modo manual, não aceite tudo. Esse é o ponto. Leia, critique, aprove só o que merece virar memória. No modo padrão, acompanhe a trilha de auditoria quando quiser entender o que foi promovido e por quê.</p>
]]></content:encoded><category>ai-memory</category><category>agentes-de-codigo</category><category>llms</category></item><item><title>ai-memory: arquitetura emergente e software maleável</title><link>https://akitaonrails.github.io/2026/06/14/ai-memory-arquitetura-emergente-e-software-maleavel/</link><guid isPermaLink="true">https://akitaonrails.github.io/2026/06/14/ai-memory-arquitetura-emergente-e-software-maleavel/</guid><pubDate>Sun, 14 Jun 2026 14:00:00 -0300</pubDate><description>&lt;p&gt;Há umas três semanas eu publiquei o &lt;a href="https://akitaonrails.github.io/2026/05/23/criei-sistema-memoria-agentes-codigo-ai-memory/"&gt;post explicando o ai-memory&lt;/a&gt;, meu sistema de memória de longo prazo pra agentes de código. A ideia central, pra quem não leu: dar pro Claude Code, Codex, OpenCode e companhia um cérebro compartilhado que persiste entre sessões, uma wiki versionada em git com busca FTS, handoff entre agentes, e consolidação opcional via LLM. Cada projeto isolado, rodando local ou self-hosted, sem mandar seu contexto pra nuvem de ninguém.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Há umas três semanas eu publiquei o <a href="/2026/05/23/criei-sistema-memoria-agentes-codigo-ai-memory/">post explicando o ai-memory</a>, meu sistema de memória de longo prazo pra agentes de código. A ideia central, pra quem não leu: dar pro Claude Code, Codex, OpenCode e companhia um cérebro compartilhado que persiste entre sessões, uma wiki versionada em git com busca FTS, handoff entre agentes, e consolidação opcional via LLM. Cada projeto isolado, rodando local ou self-hosted, sem mandar seu contexto pra nuvem de ninguém.</p>
<p>Pois é. Em três semanas esse projetinho cresceu de um jeito que merece um post só sobre o <strong>processo</strong>, porque ele virou um exemplo vivo de uma coisa que eu prego há tempos: software de verdade é cultivado, igual planta. Ninguém monta software bom peça por peça como quem monta um Lego. Vou te mostrar os números, e principalmente a história que eles contam.</p>
<h2>Os números, hoje<span class="hx:absolute hx:-mt-20" id="os-números-hoje"></span>
    <a href="#os-n%c3%bameros-hoje" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O ai-memory tem hoje, em 24 dias de vida (do primeiro commit em 21 de maio até agora):</p>
<ul>
<li><strong>482 commits</strong> no <code>main</code>, uma média de 20 por dia.</li>
<li><strong>26 pessoas</strong> commitaram no repositório.</li>
<li><strong>10 crates</strong> Rust no workspace.</li>
<li><strong>~62,7 mil linhas</strong> de Rust de produção, mais <strong>~11 mil linhas</strong> de teste em <code>tests/</code>, mais de <strong>1.000 funções de teste</strong> e 90 módulos <code>#[cfg(test)]</code> espalhados pelo código.</li>
<li><strong>~19,7 mil linhas</strong> de documentação em markdown (<code>docs/</code>).</li>
<li><strong>70 pull requests</strong>, dos quais <strong>59 mergeados</strong> (84% de aceitação).</li>
<li><strong>27 issues</strong>, <strong>100% fechadas</strong>.</li>
<li>Saímos do <code>v1.0.0</code> em 12 de junho e já estamos no <code>v1.0.6</code>.</li>
</ul>
<p>Vinte e quatro dias. Guarda esse número, porque a parte interessante não é o tamanho final, é a forma como ele chegou aqui.</p>
<h2>Como começou: um só de tudo<span class="hx:absolute hx:-mt-20" id="como-começou-um-só-de-tudo"></span>
    <a href="#como-come%c3%a7ou-um-s%c3%b3-de-tudo" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O ai-memory nasceu pequeno e burro de propósito. Nos dois primeiros dias eu cravei o esqueleto inteiro: bootstrap do workspace, servidor MCP, captura por hooks, handoff entre agentes, versionamento da wiki em git, trait de provider de LLM, embeddings. Tudo isso rodando pra <strong>um usuário, uma máquina, um workspace, uma arquitetura</strong> (Linux, basicamente). Sem multi-usuário, sem permissão, sem escopo, sem suporte a Windows ou macOS. Era o meu cérebro de agente, na minha máquina, pra mim.</p>
<p>No dia 3, quando a <a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">primeira contribuição externa chegou</a> (um fix do Lucas Oliveira pra URLs de provider OpenAI-compatível, o PR #6), o projeto tinha <strong>102 commits e cerca de 22,9 mil linhas</strong> de código-fonte. Já eram os mesmos 10 crates de hoje, mas com uma fração da funcionalidade. Era um MVP de um-só-de-tudo que funcionava pra mim e mais ninguém.</p>
<p>E aqui é onde a maioria dos projetos morre, ou pior, onde a maioria dos programadores inexperientes erra a mão.</p>
<h2>A falácia do Lego<span class="hx:absolute hx:-mt-20" id="a-falácia-do-lego"></span>
    <a href="#a-fal%c3%a1cia-do-lego" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Tem uma crença muito difundida, principalmente em quem está começando, de que dá pra desenhar tudo que um software <strong>vai ser</strong> antes de escrever a primeira linha. Você senta, planeja a arquitetura inteira, quebra em pedacinhos bem organizados, com as pastas e as camadas e as interfaces todas previstas, e aí constrói peça por peça. Quando a última peça de Lego se encaixa, o software está pronto. Lindo no papel.</p>
<p>Na prática, é o caminho mais rápido pra deteriorar código. Quanto mais cedo você cristaliza uma estrutura, mais cedo ela vira uma camisa de força. Você previu um sistema de permissões elaborado antes de ter usuários? Parabéns, agora você carrega o peso de manter abstração que ninguém usa, e que quase sempre está errada, porque você a desenhou adivinhando o futuro em vez de responder a uma necessidade real. O programador inexperiente faz engenharia em excesso no começo, e não importa o quanto ele planeje, o resultado começa a apodrecer rápido, porque ele está resolvendo problemas que ainda não existem e errando os que existem.</p>
<p>Eu não acredito em software que termina. Já escrevi sobre isso no <a href="/2026/03/01/software-nunca-esta-pronto-4-projetos-a-vida-pos-deploy-e-por-que-one-shot-prompt-e-mito/">&ldquo;Software nunca está pronto&rdquo;</a>, e ele se conecta direto com as metodologias Agile originais, as de verdade, antes de virarem ritual corporativo de post-it. Software bom é uma escultura de barro: maleável, sempre úmida, que você fica ajustando, transformando, e que nunca fica pronta. É argila que você modela enquanto ela é usada. A torre de Lego que uma hora fica pronta e acabou é fantasia.</p>
<h2>O que os contribuidores construíram<span class="hx:absolute hx:-mt-20" id="o-que-os-contribuidores-construíram"></span>
    <a href="#o-que-os-contribuidores-constru%c3%adram" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>E é aí que entra a melhor parte de ter aberto o código. Aquele MVP de um-só-de-tudo virou um sistema multiplataforma e multiusuário porque <strong>muita gente</strong> colocou a mão. Eu quero agradecer nominalmente, porque sem essas pessoas o projeto seria uma fração do que é:</p>
<p><a href="https://github.com/djalmajr"target="_blank" rel="noopener"><strong>Djalma Júnior</strong></a> tocou boa parte da arquitetura pesada (multi-usuário, admin, recall cross-project), com 25 PRs mergeados. <a href="https://github.com/wblech"target="_blank" rel="noopener"><strong>wlech</strong></a> com dezenas de commits. <a href="https://github.com/pedrofjr"target="_blank" rel="noopener"><strong>Pedro de Freitas Jr</strong></a> em embeddings e correções de web. <a href="https://github.com/mrpaiva"target="_blank" rel="noopener"><strong>Mauro Couto de Paiva</strong></a> e <a href="https://github.com/CaTeIM"target="_blank" rel="noopener"><strong>Gustavo Cateim</strong></a> tocaram boa parte do suporte a Windows. <a href="https://github.com/pablowinck"target="_blank" rel="noopener"><strong>Pablo Winter</strong></a>, <a href="https://github.com/lucasliet"target="_blank" rel="noopener"><strong>Lucas Oliveira</strong></a> (autor do primeiro PR externo) e <strong>Said Rodrigues</strong>, entre vários outros. Valeu demais, gente.</p>
<p>O que essas contribuições adicionaram, em destaque:</p>
<ul>
<li><strong>Suporte real a Windows, macOS e Linux.</strong> O que era Linux-only ganhou compatibilidade com bash 3.2 do macOS, um índice de arquivos NTFS pra rastrear inode no Windows, e comandos de hook nativos por plataforma.</li>
<li><strong>Frontend API (<code>/api/v1</code>) e UI web customizável.</strong> Deixou de ser só MCP + CLI e ganhou uma superfície HTTP de verdade, com links de wiki clicáveis e busca por caminho de arquivo.</li>
<li><strong>Multi-usuário com atribuição.</strong> Tabela de <code>users</code>, comandos de writer/reader, e atribuição de autoria na mesma transação SQL da escrita (<code>pages.author_id</code> + frontmatter).</li>
<li><strong>Multi-workspace e recall cross-project.</strong> Busca global, links entre wikis de projetos diferentes, e isolamento de projeto ativo por sessão e por ator.</li>
<li><strong>Mais providers e mais agentes.</strong> Gemini, Copilot via OAuth, OpenAI-compat strict mode; e suporte a Antigravity, Grok e VS Code Copilot além dos originais.</li>
<li><strong>Robustez operacional.</strong> Recuperação por checkpoint, <code>reindex-from-wiki</code> pra reconstruir o índice a partir do markdown, manifestos <code>_meta.md</code> auto-descritivos.</li>
</ul>
<p>Repara numa coisa: nada disso estava no plano original. Não existia plano original. Cada uma dessas features entrou porque alguém precisou dela, abriu uma issue ou um PR, e a estrutura foi cedendo espaço pra acomodar. O multi-usuário não foi previsto: ele emergiu.</p>
<h2>E só agora a gente parou pra consolidar<span class="hx:absolute hx:-mt-20" id="e-só-agora-a-gente-parou-pra-consolidar"></span>
    <a href="#e-s%c3%b3-agora-a-gente-parou-pra-consolidar" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Aqui está o ponto central do post. Durante essas três semanas, o código cresceu meio bagunçado de propósito. Quando o suporte a multi-usuário entrou, a lógica de &ldquo;qual workspace e projeto esse pedido está mirando&rdquo; foi parar <strong>embutida direto no meio</strong> de vários handlers do servidor MCP, da API web, do admin, espalhada e duplicada. Cada lugar resolvia escopo do seu jeito. Tinha duplicação. Tinha código que não era bonito. E está tudo bem, porque estava funcionando, e funcionando pra muita gente.</p>
<p>Só <strong>depois</strong> que o software já rodava na máquina de dezenas de pessoas, em três sistemas operacionais, com multi-usuário de verdade em produção, é que eu parei e falei: &ldquo;ok, agora é uma boa hora pra refatorar e repensar a fiação interna&rdquo;. O penúltimo commit grande, o <a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener"><code>refactor: centralize scope auth and wiki consistency</code></a>, fez exatamente isso, com 1.239 linhas adicionadas e 249 removidas, criando um <code>ScopeResolver</code> central de 601 linhas e um <code>ActorContext</code> consolidado.</p>
<p>Veja o &ldquo;antes&rdquo;. Esse trecho de resolução de escopo vivia duplicado, com variações, em vários métodos:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">// ANTES: lógica de escopo embutida, repetida em cada handler
</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">active</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">active_project</span><span class="p">.</span><span class="n">get_for</span><span class="p">(</span><span class="n">actor</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">name</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">explicit_project</span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="kt">str</span>::<span class="n">trim</span><span class="p">).</span><span class="n">filter</span><span class="p">(</span><span class="o">|</span><span class="n">s</span><span class="o">|</span><span class="w"> </span><span class="o">!</span><span class="n">s</span><span class="p">.</span><span class="n">is_empty</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">((</span><span class="n">active_ws</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">))</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">active</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="n">pid</span><span class="p">))</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">reader</span><span class="p">.</span><span class="n">find_project</span><span class="p">(</span><span class="n">active_ws</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="p">.</span><span class="n">to_string</span><span class="p">()).</span><span class="k">await</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nb">Ok</span><span class="p">((</span><span class="n">active_ws</span><span class="p">,</span><span class="w"> </span><span class="n">pid</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">active</span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="o">|</span><span class="p">(</span><span class="n">ws</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">)</span><span class="o">|</span><span class="w"> </span><span class="n">ws</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">workspace_id</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="n">pid</span><span class="p">))</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="n">reader</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="n">find_project</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">workspace_id</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="p">.</span><span class="n">to_string</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="k">await</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nb">Ok</span><span class="p">((</span><span class="bp">self</span><span class="p">.</span><span class="n">workspace_id</span><span class="p">,</span><span class="w"> </span><span class="n">pid</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">McpError</span>::<span class="n">internal_error</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="fm">format!</span><span class="p">(</span><span class="s">&#34;project &#39;</span><span class="si">{name}</span><span class="s">&#39; not found in the active or default workspace&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nb">None</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nb">Ok</span><span class="p">(</span><span class="n">active</span><span class="p">.</span><span class="n">unwrap_or</span><span class="p">((</span><span class="bp">self</span><span class="p">.</span><span class="n">workspace_id</span><span class="p">,</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">project_id</span><span class="p">)))</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>E o &ldquo;depois&rdquo;. A mesma resolução, agora delegada pra uma autoridade única no crate de store:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">// DEPOIS: um resolvedor central, uma chamada
</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">scope_resolver</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">ScopeResolver</span><span class="o">&lt;</span><span class="nb">&#39;_</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">ScopeResolver</span>::<span class="n">new</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">reader</span><span class="p">,</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">workspace_id</span><span class="p">,</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">project_id</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="n">with_writer</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">writer</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="n">with_active_project</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">.</span><span class="n">active_project</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// ... e cada handler vira isto:
</span></span></span><span class="line"><span class="cl"><span class="bp">self</span><span class="p">.</span><span class="n">scope_resolver</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">.</span><span class="n">resolve_current_or_project</span><span class="p">(</span><span class="n">explicit_project</span><span class="p">,</span><span class="w"> </span><span class="n">actor</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">.</span><span class="k">await</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="n">ai_memory_store</span>::<span class="n">ResolvedScope</span>::<span class="n">as_tuple</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">.</span><span class="n">map_err</span><span class="p">(</span><span class="bp">Self</span>::<span class="n">scope_error</span><span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Três métodos diferentes que antes carregavam 30 linhas de lógica embutida cada um, com <code>lookup_ids</code>, fallback de workspace e tratamento de erro próprio, colapsaram em uma chamada cada. Junto vieram os commits irmãos: <code>harden multi-user admin auth boundaries</code> e <code>prevent scoped fallback bleed</code>. Centralizar permissão, escopo de workspace e usuário, e consistência da wiki, tudo num lugar só, com regra clara.</p>
<p>O detalhe que importa: o <code>ScopeResolver</code> não foi inventado no começo do projeto adivinhando que um dia ia ter multi-usuário. Ele foi <strong>extraído</strong> de um código que já existia, já funcionava, e já tinha mostrado, na prática, quais eram os padrões que se repetiam. A abstração veio depois do uso, não antes. Eu deixei a estrutura emergir do código, e só quando ela ficou óbvia eu a consolidei.</p>
<h2>A ordem certa: make it work, make it right, make it fast<span class="hx:absolute hx:-mt-20" id="a-ordem-certa-make-it-work-make-it-right-make-it-fast"></span>
    <a href="#a-ordem-certa-make-it-work-make-it-right-make-it-fast" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Esse é o resumo de tudo. Tem um ditado antigo, atribuído ao Kent Beck, que eu carrego como mantra: <strong>&ldquo;make it work, make it right, make it fast&rdquo;</strong>. Faça funcionar, depois faça direito, depois faça rápido. Nessa ordem. A maioria dos programadores inexperientes quer fazer &ldquo;direito&rdquo; e &ldquo;rápido&rdquo; antes de fazer &ldquo;funcionar&rdquo;, e aí inventa regra sem ter código pra justificar a regra.</p>
<p>O ai-memory seguiu a ordem certa sem eu nem pensar muito nisso. Primeiro fiz funcionar pra uma pessoa, escopo simples. Depois fiz funcionar uma feature de cada vez, refatorando e endurecendo o código no caminho, mas sem nunca cair na engenharia em excesso e sem nunca reescrever do zero pra encaixar numa estrutura pré-concebida. Eu deixei as estruturas atuais emergirem do código que foi sendo adicionado. Isso significou conviver com alguma duplicação e algum código meia-boca por um tempo, até bater aquele momento de &ldquo;agora sim é hora de refatorar e repensar a fiação&rdquo;. E só agora, com o software maduro e em uso, é que eu estabeleci padrões e regras melhores pra código novo. Regras lastreadas em código de verdade, não em adivinhação.</p>
<p>KISS, &ldquo;keep it simple&rdquo;, é sobre não resolver problema que você ainda não tem. Não tem nada a ver com escrever pouco código. É deixar a arquitetura emergir do código, e não o contrário. Você não desenha a escultura e despeja o barro dentro do molde. Você pega o barro, começa a modelar, e a forma aparece conforme suas mãos trabalham. O molde, se um dia precisar de um, você constrói depois, em volta da forma que já existe.</p>
<p>Vinte e quatro dias, 482 commits, 26 pessoas, e nenhum deles seguiu um diagrama desenhado no dia 1. Porque não existia diagrama no dia 1. E é exatamente por isso que funcionou.</p>
<p>O ai-memory é open source e continua mudando toda semana: <a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">github.com/akitaonrails/ai-memory</a>. Quer ajudar a modelar o próximo pedaço? Tem issue aberta esperando.</p>
]]></content:encoded><category>ai-memory</category><category>arquitetura-de-software</category><category>agile</category></item><item><title>Dicas e Toolkit de IA do Akita: ai-jail, ai-memory, ai-usagebar</title><link>https://akitaonrails.github.io/2026/05/24/dicas-e-toolkit-de-ia-do-akita-ai-jail-ai-memory-ai-usagebar/</link><guid isPermaLink="true">https://akitaonrails.github.io/2026/05/24/dicas-e-toolkit-de-ia-do-akita-ai-jail-ai-memory-ai-usagebar/</guid><pubDate>Sun, 24 May 2026 10:30:00 -0300</pubDate><description>&lt;p&gt;No post da semana passada, &lt;a href="https://akitaonrails.github.io/2026/05/14/terminando-maratona-ia-sucesso-ou-fracasso/"&gt;&amp;ldquo;Terminando a Maratona de IA: Sucesso ou Fracasso?&amp;rdquo;&lt;/a&gt;, eu encerrei a primeira fase da minha maratona. Mais de 600 horas de uso intenso de agentes de código, dezenas de projetos, centenas de milhares de linhas de código e documentação, e uma pilha de conclusões práticas. Não de marketing. Práticas.&lt;/p&gt;
&lt;p&gt;Vou repetir uma coisa importante antes que alguém saia clonando todos os meus repositórios achando que virou produto 1.0: a maior parte dos projetos &lt;code&gt;frank-*&lt;/code&gt; no meu GitHub são provas de conceito. São experimentos. Alguns funcionam bem pra mim, no meu ambiente, no meu fluxo. Isso não quer dizer que estão prontos pra virar dependência crítica da sua empresa amanhã de manhã. Quer brincar, contribuir, estudar, ótimo. Só não confunda &amp;ldquo;publiquei no GitHub&amp;rdquo; com &amp;ldquo;está production ready&amp;rdquo;.&lt;/p&gt;</description><content:encoded><![CDATA[<p>No post da semana passada, <a href="/2026/05/14/terminando-maratona-ia-sucesso-ou-fracasso/">&ldquo;Terminando a Maratona de IA: Sucesso ou Fracasso?&rdquo;</a>, eu encerrei a primeira fase da minha maratona. Mais de 600 horas de uso intenso de agentes de código, dezenas de projetos, centenas de milhares de linhas de código e documentação, e uma pilha de conclusões práticas. Não de marketing. Práticas.</p>
<p>Vou repetir uma coisa importante antes que alguém saia clonando todos os meus repositórios achando que virou produto 1.0: a maior parte dos projetos <code>frank-*</code> no meu GitHub são provas de conceito. São experimentos. Alguns funcionam bem pra mim, no meu ambiente, no meu fluxo. Isso não quer dizer que estão prontos pra virar dependência crítica da sua empresa amanhã de manhã. Quer brincar, contribuir, estudar, ótimo. Só não confunda &ldquo;publiquei no GitHub&rdquo; com &ldquo;está production ready&rdquo;.</p>
<p>Existem exceções. O <a href="https://github.com/akitaonrails/frankmd"target="_blank" rel="noopener">FrankMD</a>, por exemplo, recebeu uma quantidade decente de contribuições, testes, lapidação, correções de bugs reais, uso real. Hoje ele já é bem mais estável do que era no primeiro post. Ainda assim, o ponto continua: esses projetos nasceram como laboratório de vibe coding, não como plano de produto de 3 anos com roadmap, suporte enterprise e SLA.</p>
<p>Este post é um apanhado do que aprendi nesse laboratório. Algumas ferramentas minhas, alguns hábitos, algumas recomendações. Nada místico. Nenhuma &ldquo;nova forma revolucionária de programar&rdquo;. É engenharia velha com ferramenta nova.</p>
<h2>Primeiro: pare de colecionar agente<span class="hx:absolute hx:-mt-20" id="primeiro-pare-de-colecionar-agente"></span>
    <a href="#primeiro-pare-de-colecionar-agente" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Se você é desenvolvedor normal, você não precisa de 12 agentes, 40 wrappers, 7 orquestradores e um diagrama de Kubernetes pra escolher quem vai escrever um <code>if</code>.</p>
<p>Na prática, foque em <strong>Claude Code</strong>, <strong>Codex</strong> ou <strong>opencode</strong>. Só isso.</p>
<p>Sim, existe Gemini CLI. Sim, existe Cursor. Sim, existe Windsurf, Crush, OpenClaw, Pi, Aider, e amanhã vai aparecer mais meia dúzia. Eu testei um monte. Leia meus posts de benchmark de LLMs, especialmente o <a href="/2026/04/24/llm-benchmarks-parte-3-deepseek-kimi-mimo/">&ldquo;LLM Benchmarks Parte 3: DeepSeek, Kimi, MiMo&rdquo;</a>. A conclusão é chata e óbvia: hoje, as melhores opções de custo-benefício pra programação pesada são <strong>Opus 4.7</strong> e <strong>GPT 5.5</strong> nos planos Pro/Plus/Max subsidiados. Nada chega perto quando o assunto é trabalhar várias horas por dia com agente de código de verdade.</p>
<p>Pagar token direto é caro. Pagar plano mensal subsidiado sai muito mais barato. É por isso que eu vivo alternando entre Claude Code e Codex: não porque eu quero &ldquo;multi-agent architecture&rdquo;, mas porque os planos têm limites e eu trabalho muitas horas seguidas.</p>
<p>DeepSeek v4 e Kimi 2.6 são mais baratos? Sim. São usáveis? Sim. Eu gosto deles pra vários casos. Mas pra <strong>Agile Vibe Coding</strong> do jeito que venho defendendo desde o post <a href="/2026/02/20/do-zero-a-pos-producao-em-1-semana-como-usar-ia-em-projetos-de-verdade-bastidores-do-the-m-akita-chronicles/">&ldquo;Do Zero à Pós-Produção em 1 Semana&rdquo;</a>, ainda falta. Eles tropeçam mais em continuidade, em refatoração longa, em testes, em entender o projeto inteiro. Dá pra usar? Dá. Mas se o objetivo é produtividade consistente, Opus e GPT ainda são a régua.</p>
<p>Rodar modelo open source local é legal. Eu mesmo brinquei bastante com isso no review do <a href="/2026/03/31/review-minisforum-ms-s1-max-amd-ai-max-395/">Minisforum MS-S1 Max com AMD AI Max+ 395</a>. Pra one-shot, pra estudar, pra brincar com inferência local, é divertido. Pra Agile Vibe Coding o dia inteiro, todo dia, ainda não é prático. Latência, contexto, qualidade, manutenção do setup, VRAM, tudo cobra imposto.</p>
<p>Também não é prático ficar rodando múltiplos LLMs em paralelo, tipo &ldquo;planner + executor + reviewer + juiz&rdquo;. Eu testei isso no post <a href="/2026/04/25/llm-benchmarks-vale-a-pena-misturar-2-modelos/">&ldquo;LLM Benchmarks: Vale a Pena Misturar 2 Modelos?&rdquo;</a>. A ideia é bonita no papel. Na prática, aumenta custo, aumenta latência, aumenta superfície de erro, e o ganho não paga a complexidade.</p>
<p>O segredo não é ter um monte de agentes. Esquece OpenClaw ou Pi pra programação do dia a dia. O segredo é processo de engenharia. XP. Testes. <a href="/2026/04/20/clean-code-para-agentes-de-ia/">Clean Code pra agentes de IA</a>. CI. Pair programming. Refatoração constante. Código pequeno. Deploy automatizado. Feedback rápido.</p>
<p>Ferramenta ajuda. Engenharia ganha.</p>
<h2>ai-jail: autonomia com cerca<span class="hx:absolute hx:-mt-20" id="ai-jail-autonomia-com-cerca"></span>
    <a href="#ai-jail-autonomia-com-cerca" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O primeiro projeto que quero destacar é o <a href="https://github.com/akitaonrails/ai-jail"target="_blank" rel="noopener">ai-jail</a>. Ele é um wrapper de sandbox pra rodar agentes de IA com acesso restrito ao sistema. No Linux usa <code>bubblewrap</code> (<code>bwrap</code>) e Landlock. No macOS usa <code>sandbox-exec</code>. A ideia é simples: o agente enxerga o ambiente que precisa pra trabalhar, mas não sai fuçando seu sistema inteiro.</p>
<p>Uso todo dia? Sim. Uso sempre? Não.</p>
<p>Quando sei que não vou fazer nada arriscado, abro <code>claude</code> ou <code>codex</code> direto. Se vou mexer num projeto simples, só rodar testes, editar markdown, refatorar coisa local, muitas vezes nem me preocupo. Em mais de 600 horas de Agile Vibe Coding intenso, mais de meio milhão de linhas de código e documentação, nunca tive um caso desses folclóricos de LLM destruindo meu sistema host de um jeito irrecuperável.</p>
<p>E olha que eu usei agentes explicitamente pra configurar meu Omarchy. ZSH, Hyprland, Waybar, configs de terminal, scripts de login, tudo. Nunca fizeram nada que eu não pedi.</p>
<p>Essas histórias de &ldquo;o agente deletou meu home inteiro sozinho&rdquo; eu leio com um pé atrás. Na minha experiência, quando você pede pra deletar algo perigoso, Claude e Codex perguntam confirmação. Você precisa dizer sim. Se você disse sim sem ler, a culpa não é mágica negra do LLM. É usuário no modo zumbi.</p>
<p>Dito isso: nada é garantido. Daí o ai-jail.</p>
<p>Meu uso preferido é combinar <code>ai-jail</code> com o modo sem freio do harness:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-jail claude --dangerously-allow-permissions
</span></span><span class="line"><span class="cl">ai-jail codex --dangerously-bypass-approvals-and-sandbox</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Parece contraditório, mas faz sentido. Eu tiro a fricção de confirmação dentro do agente, mas coloco uma cerca no nível do sistema operacional. O agente pode trabalhar rápido dentro do projeto, mas o filesystem do host fica essencialmente read-only. O diretório atual fica read-write. O que eu mapear explicitamente com <code>--rw-map</code> também fica read-write. O resto não é pra tocar.</p>
<p>O README do ai-jail resume bem: é um sandbox wrapper pra agentes como Claude Code, GPT Codex, OpenCode e Crush. No primeiro run ele cria um <code>.ai-jail</code> no projeto, que pode ser commitado. Suporta <code>--dry-run</code> pra ver os mounts antes de executar, <code>--lockdown</code> pra modo mais restritivo, <code>--private-home</code> pra esconder dotfiles reais, <code>--mask .env</code> pra esconder arquivos sensíveis dentro do próprio projeto, e perfis de navegador isolado pra Chromium/Firefox.</p>
<p>O ponto importante: não venda isso como segurança absoluta. Processo sandbox não é VM. Kernel bug existe. Side channel existe. macOS tem limitações. O próprio README é claro: se você precisa isolar workload hostil de verdade, use uma VM descartável. Eu não uso ai-jail como &ldquo;blindagem militar&rdquo;. Uso como mais uma camada, boa o suficiente pro fluxo de desenvolvimento.</p>
<p>E mesmo dentro do projeto, tudo é Git. Eu faço push frequente pro GitHub ou pro meu Gitea privado. Então o pior caso realista é o agente destruir o diretório do projeto. Chato? Sim. Catastrófico? Não. Clono de novo. Volto do remote. Refaço o que estava local. Se o <code>.git</code> corromper, apago tudo e clono de novo.</p>
<p>Secrets também têm cópia fora. <code>.env</code>, tokens, keys, tudo que importa fica no Bitwarden. <a href="/2025/09/10/omarchy-2-0-bitwarden-self-hosted-vaultwarden/">Self-hosted em Vaultwarden</a>, claro. Então se eu perder o diretório local, não perdi a chave do reino.</p>
<p>O risco mais comum não é o agente deletar tudo. É você vazar segredo no Git. Isso aconteceu comigo mais de uma vez. Você dá <code>git add .</code>, esquece um <code>.env</code>, empurra pro remote, parabéns. Acontece. Por isso tem que olhar <code>git status</code>, <code>git diff --cached</code>, e pensar antes de dar push.</p>
<p>Mesmo quando acontece, os LLMs são muito competentes pra ajudar a reescrever histórico. Peço pra limpar o segredo do Git, forçar push, revisar se sumiu, e depois eu rotaciono a key. Não é bonito, mas é administrável.</p>
<p>Então sim, recomendo usar Claude/Codex com permissões perigosas <strong>dentro</strong> do ai-jail. Existe a chance de 0,001% de acidente irrecuperável? Existe. Mas se você é bom engenheiro, isso não deveria te matar. Eu tenho camadas: snapshots automáticos em Btrfs, restic pro NAS, NAS arquivando offsite em AWS Glacier, Git remoto, Bitwarden. Ferramenta nenhuma substitui backup.</p>
<h2>ai-memory: contexto que sobrevive ao harness<span class="hx:absolute hx:-mt-20" id="ai-memory-contexto-que-sobrevive-ao-harness"></span>
    <a href="#ai-memory-contexto-que-sobrevive-ao-harness" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O segundo é o <a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">ai-memory</a>, que expliquei em detalhes no post <a href="/2026/05/23/criei-sistema-memoria-agentes-codigo-ai-memory/">&ldquo;Criei um Sistema de Memória pra Agentes de Código: ai-memory&rdquo;</a>.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/23/ai-memory/ai-memory-logo.png" alt="Logo do projeto ai-memory: pictograma circular com um chip estilizado abrindo “asas” tipo bibliotecas/páginas pra cada lado, ao lado do texto ai-memory em itálico."  loading="lazy" /></p>
<p>A motivação é simples: harnesses perdem contexto. Claude Code compacta. Codex compacta. opencode compacta. Sessão acaba. Você abre outro agente e ele não sabe o que aconteceu nas últimas 4 horas. Se você usa só um harness, talvez isso não incomode tanto. Se você alterna entre Claude e Codex como eu, incomoda rápido.</p>
<p>Eu queria um consolidador de memória de longo prazo que funcionasse atravessando harnesses diferentes. Algo que permitisse handoff entre Claude, Codex e opencode sem eu ficar escrevendo <code>HANDOFF.md</code> manual toda vez. Algo que capturasse prompts, tool calls e eventos de sessão via hooks, consolidasse em páginas markdown, indexasse com SQLite/FTS5, e expusesse tudo via MCP quando o agente precisasse consultar.</p>
<p>Outro motivador foi o que expliquei no post <a href="/2026/04/06/rag-esta-morto-contexto-longo/">&ldquo;RAG Está Morto? Contexto Longo, Grep e o Fim do Vector DB Obrigatório&rdquo;</a>. Pra projeto de código, quase sempre texto simples resolve mais do que arquitetura afetada de vector DB. Markdown, <code>grep</code>, SQLite FTS5, contexto longo e bons arquivos em <code>docs/</code> já levam você longe. O ai-memory segue essa linha: compila memória em texto, deixa no disco, indexa simples, e só chama LLM quando vale consolidar.</p>
<p>O ai-memory não foi feito pra ser uma knowledge base navegável por usuário final. Ele tem uma UI web read-only, sim, mas isso é pra auditoria e inspeção. A memória é otimizada pra LLM consumir. É um wiki interno que o harness pode consultar quando acha que precisa. É um lugar onde posso pedir explicitamente &ldquo;salva isso pra próxima sessão&rdquo; e esperar que sobreviva mais do que a compactação padrão do Claude ou do Codex.</p>
<p><img src="https://raw.githubusercontent.com/akitaonrails/ai-memory/main/docs/web-projects-home.png" alt="Homepage da UI web do ai-memory mostrando projetos detectados, contagem de páginas, última atividade e o aviso de que a memória é otimizada pra consumo por LLM, não documentação curada por humanos."  loading="lazy" /></p>
<p>O README resume bem: agentes de código perdem todo contexto quando a sessão termina; o ai-memory dá a eles um wiki persistente compartilhado. Cada prompt, tool call e decisão pode ser capturado automaticamente. No fim da sessão, páginas relevantes são reescritas como narrativa coerente. Na próxima sessão, outro agente pode receber um handoff já prepended no contexto.</p>
<p>Isso é útil quando você fecha Claude às 18h, abre Codex no dia seguinte no mesmo diretório, e quer que ele saiba que você estava testando session cookies porque rotação de JWT tinha dado problema. Ou quando você volta a um projeto seis semanas depois e não lembra por que descartou Redis.</p>
<p>Mas não confunda com documentação canônica. Se você fez uma pesquisa importante que não quer perder, peça pro agente escrever um markdown em <code>docs/</code> dentro do projeto. Decisão arquitetural, benchmark, análise de biblioteca, runbook de deploy, tudo que precisa sobreviver com garantia deve virar arquivo explícito no repo. Isso é mais simples, auditável e versionado.</p>
<p>O ai-memory cobre a faixa intermediária: informação transitória que talvez importe depois. Um bug estranho que apareceu. Um raciocínio que levou a uma decisão. Um gotcha de ambiente. Um resumo de sessão. Coisas que você não quer transformar em doc oficial ainda, mas também não quer jogar fora.</p>
<p>Ele ainda é beta. Eu uso em produção pessoal, mas precisa de muito mais gente batendo nele. Tem integração com Claude Code, Codex e opencode mais polida. Gemini CLI, OpenClaw e clientes MCP exóticos ainda precisam de mais teste. PRs são bem-vindos. Bug report também. &ldquo;Instalei e quebrou no meu setup&rdquo; é exatamente o tipo de feedback que revela suposição errada.</p>
<h2>ai-usagebar: saber quando trocar de cavalo<span class="hx:absolute hx:-mt-20" id="ai-usagebar-saber-quando-trocar-de-cavalo"></span>
    <a href="#ai-usagebar-saber-quando-trocar-de-cavalo" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Como falei acima, eu prefiro usar os planos subsidiados da Anthropic e da OpenAI. O problema é que, se você faz Agile Vibe Coding de verdade, você bate limite. Limite diário. Limite semanal. Limite de sessão. Limite que muda. Limite que não aparece direito em lugar nenhum.</p>
<p>Eu usava o <a href="https://github.com/mryll/claudebar"target="_blank" rel="noopener">claudebar</a>, que é bom, mas só cobre Claude. Eu queria ver os principais vendors num lugar só. Daí nasceu o <a href="https://github.com/akitaonrails/ai-usagebar"target="_blank" rel="noopener">ai-usagebar</a>, que apresentei no post <a href="/2026/05/24/criei-widget-waybar-omarchy-monitorar-uso-llms-ai-usagebar/">&ldquo;Criei um Widget de Waybar pra Omarchy pra Monitorar Uso de Planos de LLM: ai-usagebar&rdquo;</a>.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/24/ai-usagebar/ai-usagebar-waybar.png" alt="Widget na Waybar mostrando “cld 29% · 1h 12m” no canto superior direito, com tooltip aberto exibindo o plano Claude Max 20x: Session 29%, Weekly 47%, Sonnet only 0%, Extra usage $0.00 sobre limite de $1100, e horário da última atualização."  loading="lazy" /></p>
<p>É um widget de Waybar e uma TUI em Rust pra monitorar uso de Anthropic Claude, OpenAI Codex/ChatGPT, Z.AI GLM e OpenRouter. Pra Claude e OpenAI, ele lê as credenciais OAuth que os CLIs oficiais já gravaram. Pra Z.AI e OpenRouter, usa API key. Mostra porcentagem da sessão, reset, limites, saldo, e permite trocar o vendor principal.</p>
<p>O valor disso é banal e por isso mesmo útil: bato o olho na barra e sei se devo continuar no Claude, fazer handoff pro Codex, ou recarregar crédito no OpenRouter. Não quero descobrir que cheguei no limite semanal no meio de uma refatoração grande.</p>
<p>Também tem a TUI standalone:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/24/ai-usagebar/ai-usagebar-tui-openai.png" alt="ai-usagebar-tui na aba OpenAI rodando num terminal: gauges de Codex 5h e semanal, bloco de Credits com faixas de contagem de mensagens, abas Claude / OpenAI / GLM (Z.AI) / OpenRouter no topo, atalhos de tecla no rodapé."  loading="lazy" /></p>
<p>Se você não usa Omarchy, Hyprland ou Waybar, ainda dá pra rodar <code>ai-usagebar-tui</code> em qualquer terminal. SSH, tmux, terminal normal, tanto faz. A barra é conveniência. A TUI é a forma universal.</p>
<h2>ghpending: pendência de GitHub sem ritual<span class="hx:absolute hx:-mt-20" id="ghpending-pendência-de-github-sem-ritual"></span>
    <a href="#ghpending-pend%c3%aancia-de-github-sem-ritual" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Depois da maratona, fiquei com dezenas de <code>ai-*</code> e <code>frank-*</code> no GitHub. Isso cria um problema chato: issues e pull requests começam a aparecer. Contribuidor abre PR. Alguém reporta bug. Outro manda sugestão. Se eu tiver que abrir o navegador, entrar repo por repo, filtrar aba por aba, eu vou adiar. E se eu adiar, fico semanas sem responder.</p>
<p>Sim, eu poderia usar <code>gh</code>, a CLI oficial do GitHub. Aliás, uso. Mas eu queria uma coisa mais burra e mais rápida: um comando curto pra imprimir um digest de tudo que está pendente nos repos que eu escolhi monitorar. Nasceu o <a href="https://github.com/akitaonrails/ghpending"target="_blank" rel="noopener">ghpending</a>, que descrevi no post <a href="/2026/05/23/criei-cli-pra-checar-pendencias-github-ghpending/">&ldquo;Criei um CLI pra Checar Pendências no Meu GitHub: ghpending&rdquo;</a>.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/23/ghpending/ghpending-screenshot.png" alt="Saída do ghpending no terminal: tabela compacta listando cada repo monitorado com contagem de issues e pull requests abertos, autor da última atividade e há quanto tempo."  loading="lazy" /></p>
<p>É só isso: <code>ghpending add</code> pra escolher repos, <code>ghpending</code> pra ver o digest, <code>ghpending list</code>, <code>ghpending rm</code>. Sem autenticação funciona com limite de 60 req/h do GitHub. Com <code>GITHUB_TOKEN=$(gh auth token) ghpending</code>, sobe pra 5.000 req/h.</p>
<p>O ponto não é substituir o GitHub. É reduzir atrito. Se eu consigo rodar um comando no terminal e ver &ldquo;tem 3 PRs e 2 issues pra olhar&rdquo;, eu olho. Se depende de ritual de navegador, notificações e abas, fica pra depois.</p>
<p>E Claude/Codex são muito bons nesse tipo de trabalho. Dá pra pedir:</p>
<blockquote>
  <p>&ldquo;Checa os pull requests abertos, revisa o código, vê se compila, roda os testes, adiciona teste se faltar, faz rebase de master se precisar, mergeia e fecha.&rdquo;</p>

</blockquote>
<p>Ou:</p>
<blockquote>
  <p>&ldquo;Checa as issues abertas, avalia se tem bug real, reproduz se der, propõe correção, responde o usuário.&rdquo;</p>

</blockquote>
<p>Eles leem o PR, entendem o diff, rodam teste, fazem rebase, resolvem conflito simples, escrevem resposta pro contribuidor. Não é pra desligar o cérebro. É pra terceirizar o trabalho mecânico que você já sabe fazer.</p>
<h2>Refatoração: peça explicitamente, várias vezes<span class="hx:absolute hx:-mt-20" id="refatoração-peça-explicitamente-várias-vezes"></span>
    <a href="#refatora%c3%a7%c3%a3o-pe%c3%a7a-explicitamente-v%c3%a1rias-vezes" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Claude e Codex são muito bons em refatorar, mas não presuma que vão fazer isso automaticamente do jeito que você faria. Eu costumo começar projetos ou features com instruções explícitas:</p>
<blockquote>
  <p>&ldquo;Use as melhores práticas de Rust. Evite duplicação desnecessária. Modularize só onde fizer sentido. Adicione unit tests pra toda feature nova. Siga princípios de <a href="/2026/04/20/clean-code-para-agentes-de-ia/">Clean Code</a>. Não crie abstração antes de precisar.&rdquo;</p>

</blockquote>
<p>Depois de uma feature grande, uma correção grande, ou algumas horas de desenvolvimento, paro e peço:</p>
<blockquote>
  <p>&ldquo;Agora que mexemos bastante no código, reavalie com calma. Delete código morto. Refatore duplicações óbvias. Adicione testes faltantes. Remova magic numbers. Veja se tem módulos grandes demais. Não mude comportamento sem teste.&rdquo;</p>

</blockquote>
<p>Antes de release:</p>
<blockquote>
  <p>&ldquo;Antes de publicar essa versão, faça uma auditoria de sanidade. Procure vazamento de secrets, permissões perigosas, comandos destrutivos, path traversal, unwraps desnecessários, falta de validação, e qualquer coisa que pareça vulnerabilidade óbvia.&rdquo;</p>

</blockquote>
<p>Isso garante segurança? Claro que não. Nem perto. Mas remove muito erro besta. É mais uma camada. Eu gosto de rodar essa auditoria com Claude e depois com Codex, porque cada um acha coisas diferentes. Mesmo assim, bug passa. Segurança é processo, não ritual mágico.</p>
<h2>Experimentos descartáveis: código ficou barato<span class="hx:absolute hx:-mt-20" id="experimentos-descartáveis-código-ficou-barato"></span>
    <a href="#experimentos-descart%c3%a1veis-c%c3%b3digo-ficou-barato" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Antes de escolher biblioteca, framework, arquitetura, modelo ou serviço, eu gosto de criar <code>experiments/</code>.</p>
<p>Exemplo:</p>
<blockquote>
  <p>&ldquo;Antes de escolher entre Qwen e DeepSeek, cria um protótipo descartável em <code>experiments/</code> pra A/B test. Documenta a análise em <code>docs/</code> com resultado, custo, latência, qualidade e recomendação.&rdquo;</p>

</blockquote>
<p>Isso mudou meu jeito de decidir. Antes, muita decisão de engenharia virava opinião, feeling, fé em benchmark dos outros. Agora código é barato. Peço pro agente fazer duas ou três versões, rodar teste, medir, documentar, jogar fora o que não presta.</p>
<p>Prototipar ficou rápido de verdade. O <a href="/2026/04/05/transformando-youtube-num-app-de-karaoke-frank-karaoke/">Frank Karaoke</a> é um bom exemplo: transformar YouTube num app de karaokê era o tipo de ideia que antes eu talvez deixasse numa lista mental por meses, esperando &ldquo;um fim de semana livre&rdquo; que nunca chega. Agora dá pra abrir um <code>experiments/</code>, pedir um protótipo tosco, testar o caminho técnico, e decidir se vale virar projeto. Olha meus outros posts de 2026 sobre os projetos <code>frank-*</code> e <code>ai-*</code>: quase todos começaram assim, como código descartável que provou alguma coisa antes de merecer nome.</p>
<p>Mas protótipo barato não significa one-shot. Já escrevi em <a href="/2026/04/15/como-falar-com-o-claude-code-efetivamente/">&ldquo;Por que as LLMs não te dão o resultado esperado&rdquo;</a>: prompt bom é conversa iterativa. Você dá contexto, mostra referência, aponta restrição, lê o resultado, corrige direção, manda refazer. Se você joga uma frase vaga e espera produto pronto, o erro é seu.</p>
<p>Também aprendi isso apanhando. No post do <a href="/2026/03/05/meu-primeiro-fracasso-com-vibe-code-e-como-consertei-frank-yomik/">Frank Yomik</a> contei meu primeiro fracasso real com vibe coding: quando a direção está errada, insistir no mesmo prompt só cava o buraco. Tem hora que precisa reduzir escopo, isolar o problema, criar teste, trocar estratégia. LLM não transforma plano ruim em engenharia boa.</p>
<p>E tem domínio onde você precisa estudar junto. No post de <a href="/2026/04/23/driveclub-shadps4-e-ia-como-aprender/">Driveclub e shadPS4</a>, a IA quase me levou pra todo lado errado porque o problema exigia entender renderização, gamma, shaders, buffers. A ferramenta ajuda a explorar, mas quem decide se a explicação faz sentido ainda é você. Se você não entende o suficiente pra verificar, está só aceitando chute bonito.</p>
<p>Por isso também repito a ideia de <a href="/2026/03/01/software-nunca-esta-pronto-4-projetos-a-vida-pos-deploy-e-por-que-one-shot-prompt-e-mito/">&ldquo;Software Nunca Está Pronto&rdquo;</a>: deploy não é linha de chegada. O protótipo vira produto quando aguenta bug report, manutenção, refatoração, docs, release, rollback, usuário reclamando. LLM ajuda muito nesse ciclo chato. Mas o ciclo continua existindo.</p>
<p>Se é testável, teste. Se dá pra medir, meça. Se não dá pra medir, pelo menos escreva as premissas. O importante é não escolher só porque &ldquo;parece melhor&rdquo;.</p>
<p>Código barato também significa desapego. Faça código pra jogar fora. Faça protótipo feio. Faça benchmark descartável. Peça pro agente documentar o que aprendeu em <code>docs/decision-qwen-vs-deepseek.md</code>, depois apague <code>experiments/</code> se quiser. O documento fica. O aprendizado fica.</p>
<p>LLMs também são muito bons em documentação. Use isso. Peça pra documentar tudo. Por que escolhemos PostgreSQL em vez de SQLite nesse caso. Por que o deploy usa Docker image multi-stage. Por que o serviço roda atrás de Cloudflare Tunnel. Por que aquele sysctl existe. Mesmo que depois você delete metade, o custo de escrever caiu perto de zero.</p>
<h2>Deploy automatizado ou você vai parar de manter<span class="hx:absolute hx:-mt-20" id="deploy-automatizado-ou-você-vai-parar-de-manter"></span>
    <a href="#deploy-automatizado-ou-voc%c3%aa-vai-parar-de-manter" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Todo projeto meu que importa tem build automatizado. Muitos rodam no meu homelab, como descrevi em <a href="/2026/03/31/migrando-meu-home-server-com-claude-code/">&ldquo;Migrando meu Home Server com Claude Code&rdquo;</a>. Quase todo projeto tem um <code>bin/deploy</code> que builda imagem Docker, faz push, rotaciona no servidor, aplica migração se precisar, e valida healthcheck.</p>
<p>Claude e Codex são excelentes em deploy. Eles leem o <code>bin/deploy</code>, entendem Dockerfile, editam GitHub Actions, ajustam release workflow, corrigem assinatura de binário, atualizam Homebrew tap, geram checksum. E sim, eu peço pra Claude/Codex dar SSH no meu homelab e redeployar container Docker. Eles são muito bons nisso. O ai-jail, por exemplo, tem GitHub Actions pra buildar binários assinados pra Linux e macOS.</p>
<p>Se você tem dezenas de projetos, quanto mais automatizado melhor. Eu raramente digito comando administrativo no terminal sozinho. Peço pro LLM fazer, observo, aprovo o que for perigoso, e depois peço:</p>
<blockquote>
  <p>&ldquo;Documente o que foi feito e por que foi feito.&rdquo;</p>

</blockquote>
<p>Isso vale pro homelab e pra minha workstation. Meu Omarchy é customizado via Claude: ZSH, Hyprland, Waybar, scripts, atalhos, temas, integrações. Até meus setups de gaming/emulação entram nessa, como mostrei no post dos <a href="/2026/04/19/retrogames-de-corrida-favoritos-no-distrobox/">retrogames de corrida rodando no Distrobox</a>. Esse é um caso onde normalmente não uso ai-jail, porque justamente quero mexer no host. Então olho comandos, leio diffs, aprovo devagar. Mesmo assim, nunca tive o agente quebrando meu sistema de um jeito irrecuperável. Pelo contrário. Meu PC nunca esteve tão estável e documentado.</p>
<p>Dias depois, quando esqueço por que configurei alguma coisa daquele jeito, o contexto está em markdown, Git, ai-memory, ou no próprio histórico do projeto. Eu posso perguntar e o agente tem de onde puxar.</p>
<h2>Até este post foi escrito assim<span class="hx:absolute hx:-mt-20" id="até-este-post-foi-escrito-assim"></span>
    <a href="#at%c3%a9-este-post-foi-escrito-assim" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Inclusive, é assim que escrevo estes posts agora. Eu jogo um bloco enorme e bagunçado do meu cérebro no Claude. Peço pra ler posts recentes pra calibrar estilo. Peço pra checar os projetos diretamente e elaborar as partes técnicas. Peço pra usar as screenshots mais recentes, subir pro S3 quando precisa, linkar os posts anteriores, revisar o tom.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/24/ai-toolkit/writing-this-post.png" alt="Screenshot do terminal com o prompt bruto usado pra escrever este post: um bloco enorme de instruções, links, opiniões e detalhes técnicos jogado no agente antes da edição final."  loading="lazy" /></p>
<p>Depois eu leio e edito. Corto o que ficou genérico. Troco frase que parece release note. Coloco minhas broncas de volta. O resultado ainda é meu texto, só que agora eu gasto energia no que importa: decidir o que dizer, corrigir nuance, cortar besteira.</p>
<h2>&ldquo;Mas você testou o Pi?&rdquo;<span class="hx:absolute hx:-mt-20" id="mas-você-testou-o-pi"></span>
    <a href="#mas-voc%c3%aa-testou-o-pi" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Toda vez que falo de LLM ou ferramenta de LLM, aparece alguém nos comentários com a mesma pergunta: &ldquo;mas você testou Pi?&rdquo;, &ldquo;mas você testou DeepSeek?&rdquo;, &ldquo;mas e o Qwen?&rdquo;, &ldquo;mas e o modelo novo que saiu ontem?&rdquo;. Toda. Santa. Vez.</p>
<p>É irritante pra cacete. E quase sempre vem de três tipos de pessoa: quem não testou nada e quer terceirizar o trabalho, quem já escolheu uma ferramenta e quer que eu valide a escolha dela, ou fanboy que trata vendor de LLM como time de futebol. Todos soam iguais. NPC repetindo diálogo de tutorial.</p>
<p>Engenheiro de software não deveria decidir baseado em opinião dos outros. Nem na minha. Se você escolhe ferramenta porque &ldquo;o Akita falou&rdquo;, você entendeu errado. Eu defendo Claude Code e Codex porque usei centenas de horas, em projetos reais, publicando código e post-mortem do que funcionou e do que falhou. E mesmo assim eu não parei em opinião.</p>
<p>Eu criei meu próprio benchmark automatizado: <a href="https://github.com/akitaonrails/llm-coding-benchmark"target="_blank" rel="noopener">llm-coding-benchmark</a>. Atualizo quando vendor popular solta versão nova. Rodo cenários comparáveis. Publico resultado. Depois ajusto minha opinião baseado nos dados. É por isso que eu tenho segurança pra dizer que, no meu fluxo, Opus e GPT continuam vencendo. Não porque acordei com vontade de defender logo de empresa bilionária.</p>
<p>Se sua primeira reação foi &ldquo;mas você testou Qwen?&rdquo;, ótimo. Testa você. Roda o benchmark. Cria cenário melhor. Manda PR. Mostra número. Mostra custo. Mostra latência. Mostra onde falhou. Mostra onde ganhou. Traga dado novo.</p>
<p>Opinião solta é irrelevante. &ldquo;Pra mim funciona&rdquo; não escala. &ldquo;Eu gosto mais&rdquo; não interessa. &ldquo;No meu prompt one-shot ele foi melhor&rdquo; é anedota. Engenharia começa quando dá pra reproduzir, comparar e agir em cima.</p>
<p>Então fica simples: traga dado acionável ou fique quieto. Eu não preciso de torcida organizada de vendor nos comentários. Preciso de gente testando, medindo e contribuindo resultado novo.</p>
<h2>Checklist final<span class="hx:absolute hx:-mt-20" id="checklist-final"></span>
    <a href="#checklist-final" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Resumo curto, porque este post já ficou grande:</p>
<ul>
<li>Foque em Claude Code, Codex ou opencode. Pare de colecionar agente.</li>
<li>Use Opus 4.7 e GPT 5.5 via planos Pro/Plus/Max quando produtividade diária importa.</li>
<li>DeepSeek, Kimi e modelos locais são úteis, mas ainda não substituem o fluxo principal.</li>
<li>Agile Vibe Coding é XP com LLM: testes, <a href="/2026/04/20/clean-code-para-agentes-de-ia/">Clean Code</a>, CI, pair programming e deploy.</li>
<li>Use <code>ai-jail</code> quando quiser autonomia do agente com cerca no filesystem.</li>
<li>Combine <code>ai-jail</code> com permissões perigosas do Claude/Codex quando o projeto estiver protegido por Git.</li>
<li>Tenha backup de verdade: Btrfs snapshots, restic, NAS, offsite, Git, Bitwarden.</li>
<li>Revise <code>git add</code>, <code>git diff --cached</code> e pushes pra não vazar secrets.</li>
<li>Use <code>ai-memory</code> pra contexto transitório e handoff entre agentes.</li>
<li>Escreva documentação canônica em <code>docs/</code> quando a informação precisa sobreviver com garantia.</li>
<li>Use <code>ai-usagebar</code> pra saber quando trocar de Claude pra Codex, ou quando recarregar OpenRouter.</li>
<li>Use <code>ghpending</code> pra não abandonar issues e PRs.</li>
<li>Peça refatoração explicitamente depois de features grandes.</li>
<li>Rode auditoria de segurança antes de release, de preferência com mais de um modelo.</li>
<li>Crie protótipos descartáveis em <code>experiments/</code> antes de decidir por fé.</li>
<li>Se discordar de benchmark, rode o <a href="https://github.com/akitaonrails/llm-coding-benchmark"target="_blank" rel="noopener">llm-coding-benchmark</a> e traga dado novo.</li>
<li>Documente decisões em markdown. Código ficou barato. Documentação também.</li>
<li>Automatize deploy. Se depender de ritual manual, você vai parar de fazer.</li>
</ul>
<p>No fim, é o mesmo conselho de sempre: ferramenta muda, engenharia não. LLM aumenta a alavanca. Se você já tinha bons hábitos, vai produzir mais. Se não tinha, vai só produzir bagunça mais rápido.</p>
<p>E sim, isso muda a interface do trabalho. Já escrevi sobre isso em <a href="/2026/04/11/vs-code-e-o-novo-cartao-perfurado/">&ldquo;VS Code é o novo Cartão Perfurado&rdquo;</a>: ficar polindo pixel em editor virou nostalgia de programador velho. A parte difícil agora é escrever intenção direito, revisar execução sem preguiça, medir resultado, jogar fora código barato, e não confundir opinião com dado.</p>
]]></content:encoded><category>ai-jail</category><category>ai-memory</category><category>ai-usagebar</category><category>ghpending</category></item><item><title>Criei um Sistema de Memória pra Agentes de Código: ai-memory</title><link>https://akitaonrails.github.io/2026/05/23/criei-sistema-memoria-agentes-codigo-ai-memory/</link><guid isPermaLink="true">https://akitaonrails.github.io/2026/05/23/criei-sistema-memoria-agentes-codigo-ai-memory/</guid><pubDate>Sat, 23 May 2026 16:30:00 -0300</pubDate><description>&lt;p&gt;&lt;img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/23/ai-memory/ai-memory-logo.png" alt="Logo do projeto ai-memory: pictograma circular com um chip estilizado abrindo “asas” tipo bibliotecas/páginas pra cada lado, ao lado do texto ai-memory em itálico." loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;Há cinco dias eu &lt;a href="https://akitaonrails.github.io/2026/05/18/memoria-agentes-karpathy-llm-wiki-agentmemory/"&gt;escrevi um post longo sobre memória de agentes de código&lt;/a&gt; onde recomendei o &lt;a href="https://github.com/rohitg00/agentmemory"target="_blank" rel="noopener"&gt;agentmemory&lt;/a&gt; como solução. Depois de uma semana rodando ele em produção pessoal, voltei atrás. Esse post explica o que deu errado, e o projeto open source que comecei a construir pra resolver: o &lt;a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener"&gt;ai-memory&lt;/a&gt;.&lt;/p&gt;</description><content:encoded><![CDATA[<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/23/ai-memory/ai-memory-logo.png" alt="Logo do projeto ai-memory: pictograma circular com um chip estilizado abrindo “asas” tipo bibliotecas/páginas pra cada lado, ao lado do texto ai-memory em itálico."  loading="lazy" /></p>
<p>Há cinco dias eu <a href="/2026/05/18/memoria-agentes-karpathy-llm-wiki-agentmemory/">escrevi um post longo sobre memória de agentes de código</a> onde recomendei o <a href="https://github.com/rohitg00/agentmemory"target="_blank" rel="noopener">agentmemory</a> como solução. Depois de uma semana rodando ele em produção pessoal, voltei atrás. Esse post explica o que deu errado, e o projeto open source que comecei a construir pra resolver: o <a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">ai-memory</a>.</p>
<h2>Por que o agentmemory não rolou<span class="hx:absolute hx:-mt-20" id="por-que-o-agentmemory-não-rolou"></span>
    <a href="#por-que-o-agentmemory-n%c3%a3o-rolou" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O agentmemory tem as ideias certas (LLM Wiki do Karpathy, consolidação em tiers, hooks de captura automática, MCP) mas a implementação tem problemas estruturais que doem em uso diário. Os principais que peguei na prática:</p>
<ul>
<li><strong>Reindexação do BM25 a cada restart</strong>. O índice persiste num arquivo (<code>mem:index:bm25.bin</code>) através de um KV remoto chamado iii-engine. Com poucas observações isso voa, mas passa de 10K observações e o <code>state::set</code> começa a dar timeout, o arquivo fica em ~96 bytes vazio, e cada restart paga ~5 minutos reconstruindo do zero (<a href="https://github.com/rohitg00/agentmemory/issues/309"target="_blank" rel="noopener">issue #309</a>, aberta).</li>
<li><strong>Janela de perda de dados de 5 segundos</strong>. Toda persistência passa por um debounce de 5s do <code>IndexPersistence</code>. Quando o timeout de 30s do <code>state::set</code> estoura, o processo Node morre levando junto tudo que tava em memória (<a href="https://github.com/rohitg00/agentmemory/issues/204"target="_blank" rel="noopener">#204</a>).</li>
<li><strong>Dois caminhos de leitura de config no mesmo código</strong>. <code>process.env</code> direto num lugar, <code>getMergedEnv()</code> em outro. O famoso &ldquo;setei a variável e nada mudou&rdquo; (<a href="https://github.com/rohitg00/agentmemory/issues/456"target="_blank" rel="noopener">#456</a>).</li>
<li><strong>Hook errado em ~47% das tool calls do Claude Code</strong>. O hook leu <code>data.tool_output</code>, mas o Claude Code manda <code>tool_response</code>. Seis semanas com observações sumindo silenciosamente (<a href="https://github.com/rohitg00/agentmemory/issues/539"target="_blank" rel="noopener">#539</a>).</li>
<li><strong>Engine roda no diretório de trabalho do chamador</strong>. Usuários de Windows acharam que perderam memórias porque cada terminal abria o state store num path diferente (<a href="https://github.com/rohitg00/agentmemory/issues/303"target="_blank" rel="noopener">#303</a>, aberta).</li>
</ul>
<p>Tem mais. Documentei <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/issues-agentmemory.md"target="_blank" rel="noopener">aqui</a> no meu repo de pesquisa. O autor é responsivo, o repo tem 15.7K estrelas, e mesmo assim a arquitetura escolhida (TypeScript MCP + iii-engine Rust separado + 4 portas, 3 processos, índices em memória persistidos via KV remoto) acumula uma classe de bug que não tem como fechar sem reescrever metade do sistema. A forma do problema é estrutural, não falta de esforço do mantenedor.</p>
<p>Foi a mesma história com toda outra solução que testei: ou é incompleta, ou focada demais em alguma tecnologia específica (vector DB proprietário, knowledge graph que precisa de Neo4j, pipeline LLM elaborado), ou exige que o usuário grite <code>write_note</code> toda vez que quer salvar algo. Nenhuma &ldquo;sai do caminho&rdquo; o bastante pra eu confiar em sessões longas.</p>
<h2>O que eu queria desde o começo<span class="hx:absolute hx:-mt-20" id="o-que-eu-queria-desde-o-começo"></span>
    <a href="#o-que-eu-queria-desde-o-come%c3%a7o" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Quando comecei minha <a href="/2026/05/14/terminando-maratona-ia-sucesso-ou-fracasso/">maratona de 37 dias de vibe coding</a> lá em fevereiro, sabia que precisava de algum organizador de conhecimento. Levei mais de 500 horas de experimentação pra cristalizar o que eu queria de verdade.</p>
<p>Pra quem usa só um dos três (Claude Code, ou Codex, ou opencode) e fica nele, você provavelmente não precisa de nada extra. Os três já fazem um trabalho razoável de gerenciar memória dentro da sessão. Claude Code tem três níveis de compaction (microcompact por gap temporal, autocompact por threshold de token, sessionMemoryCompact experimental). Codex tem auto_compact_token_limit por modelo. opencode tem compaction ancorada com buffer de 20K. Cobri isso em detalhe <a href="/2026/05/18/memoria-agentes-karpathy-llm-wiki-agentmemory/">no post anterior</a>.</p>
<p>A única disciplina extra que vale a pena adotar nesse caso é manter um diretório <code>docs/</code> no projeto com arquivos markdown organizados por tópico, e pedir pro agente salvar lá quando algo importante acontece. Pesquisas que não devem ser refeitas, pegadinhas conhecidas, justificativa de por que escolheu opção A em vez de B. Funciona. Exige disciplina.</p>
<p>O problema aparece pra quem é como eu, que pula entre agentes no mesmo projeto. Eu uso Claude Code como padrão (acho o harness, o orquestrador de subagentes, e o planning de tarefas longas superior). Mas quando o Claude empaca num problema, eu disparo o Codex no mesmo diretório só pra &ldquo;agitar&rdquo;. O Codex pensa mais &ldquo;fora da caixa&rdquo; e às vezes encontra uma solução que o Claude não enxergou. Aí volto pro Claude pra implementar com mais cuidado.</p>
<p>Esse vai-e-volta entre agentes é o cenário onde a memória externa importa muito. Sem ela:</p>
<ul>
<li>Você fecha o Claude Code, abre o Codex no mesmo diretório, e o Codex não sabe nada do que foi discutido nas últimas 4 horas.</li>
<li>Você precisa pedir manualmente pro Claude escrever uma nota de handoff em <code>./HANDOFF.md</code>, depois pedir pro Codex ler. Toda vez.</li>
<li>Projetos que você deixou parados por semanas: você abre, esqueceu por que decidiu não usar Redis, esqueceu qual era o bug que tinha na biblioteca X.</li>
</ul>
<p>Karpathy resolveu o conceito da coisa no <a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f"target="_blank" rel="noopener">LLM Wiki dele</a>, que detalhei no post anterior. Mas tem uma frase específica do gist que ficou na minha cabeça:</p>
<blockquote>
  <p>O <code>index.md</code> é &ldquo;surpreendentemente bom — em ~100 fontes e algumas centenas de páginas, sem precisar de embeddings&rdquo;.</p>

</blockquote>
<p>Aquela linha resume o que eu queria. <strong>Não precisa de tecnologia complicada.</strong> Storage simples (markdown em git), índice simples (SQLite com FTS5 e links), instalação simples (um binário ou container), uso automático (hooks que disparam sozinhos), zero manutenção (memória decai sem o usuário mexer).</p>
<p>Foi por isso que comecei o ai-memory.</p>
<h2>A pesquisa antes do código<span class="hx:absolute hx:-mt-20" id="a-pesquisa-antes-do-código"></span>
    <a href="#a-pesquisa-antes-do-c%c3%b3digo" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Em vez de só sair codando, pesquisamos o código-fonte e issues dos projetos relevantes pra entender o que cada um acertou e errou. Salvei a pesquisa no <a href="https://github.com/akitaonrails/ai-memory/tree/main/docs"target="_blank" rel="noopener">próprio repo</a>:</p>
<ul>
<li><strong><a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/research-karpathy-llm-wiki.md"target="_blank" rel="noopener">research-karpathy-llm-wiki.md</a></strong> — o que Karpathy escreveu literal, separado do que a comunidade atribui (parafraseando) a ele. Três princípios fundamentais: compilação em vez de retrieval, três camadas (raw / wiki / schema), três operações (ingest / query / lint). Foi o blueprint conceitual.</li>
<li><strong><a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/research-agentmemory.md"target="_blank" rel="noopener">research-agentmemory.md</a></strong> — análise técnica do agentmemory: quatro níveis de consolidação (working → episodic → semantic → procedural), supersessão com <code>is_latest=false</code> em vez de delete, decaimento exponencial, reflexão por cluster. Mantive as ideias do agentmemory, mudei a implementação.</li>
<li><strong><a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/research-basic-memory.md"target="_blank" rel="noopener">research-basic-memory.md</a></strong> — Python, MCP-native, markdown puro no disco. O modelo é explicitamente manual: o agente chama <code>write_note</code> quando ele decide salvar. Bom modelo de storage, péssimo modelo de captura (depende do agente lembrar de chamar).</li>
<li><strong><a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/research-cognee.md"target="_blank" rel="noopener">research-cognee.md</a></strong> — pipeline de cognify (extract → chunk → graph + summarize → embed → persist) com knowledge graph + vector + relational triplo. Excelente pra agente de empresa rica que quer relação semântica entre entidades. Pesado demais pra &ldquo;memória de sessão de coding&rdquo;.</li>
</ul>
<p>A síntese que tirei: <strong>agentmemory tem as ideias certas. O resto é execução.</strong></p>
<p>A ideia que eu mais gosto do agentmemory, e que ele herdou parcialmente do LLM Wiki v2, é a <strong>consolidação tipo sono</strong>: memória curta retém detalhes brutos, memória longa vai consolidando e resumindo, e memória de longo prazo não acessada vai sendo esquecida. Não acumula lixo. Tem <code>accessCount</code>, decaimento exponencial geométrico, reforço por repetição espaçada. É similar e inspirado no que um humano faz dormindo.</p>
<p>No ai-memory eu mantive essa estrutura mas troquei a engenharia por baixo:</p>
<ul>
<li><strong>TypeScript → Rust em binário único.</strong> Sem KV remoto separado. Sem 3 processos. Um binário escrito em Rust, com um diretório de dados e um servidor Axum.</li>
<li><strong>Índice persistente em SQLite + FTS5.</strong> Nativo. Sem reindex a cada restart. WAL mode, busy_timeout 5s.</li>
<li><strong>Writer único em thread dedicada via mpsc.</strong> Sem janela de perda de 5s, sem timeout de 30s estourando.</li>
<li><strong>Markdown puro no disco como source of truth.</strong> SQLite é só índice derivado. Você pode abrir o wiki no Obsidian. Pode dar <code>grep</code>. Pode versionar com git (e ele versiona automaticamente).</li>
<li><strong>Isolamento por projeto na estrutura física do disco.</strong> <code>&lt;wiki_root&gt;/&lt;workspace_id&gt;/&lt;project_id&gt;/...</code> chaveado por UUIDs estáveis. Renomear projeto é update de uma coluna. Apagar projeto é <code>rm -rf</code> de um subdir. Mesmo nome de página em dois projetos não colide.</li>
<li><strong>Embedding e LLM são opcionais.</strong> Sem chave de provedor, o sistema ainda funciona com FTS5, expansão por links e fallback nas observações brutas. Adicione embeddings quando quiser re-ranking vetorial, e Claude Haiku ou GPT-5.4-mini quando quiser páginas consolidadas com qualidade.</li>
</ul>
<h2>Como funciona no dia a dia<span class="hx:absolute hx:-mt-20" id="como-funciona-no-dia-a-dia"></span>
    <a href="#como-funciona-no-dia-a-dia" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A interação com os agentes é por dois mecanismos: <strong>hooks/extensões</strong> (captura automática) e <strong>MCP</strong> (consulta sob demanda).</p>
<p>Claude Code e Codex usam shell hooks. OpenCode usa plugin TypeScript. OMP/Pi usa extensão TypeScript. Cursor e Gemini CLI usam configurações JSON de lifecycle. Todos mandam eventos equivalentes (<code>SessionStart</code>, <code>UserPromptSubmit</code>, <code>PreToolUse</code>, <code>PostToolUse</code>, <code>PreCompact</code>, <code>Stop</code>, <code>SessionEnd</code>) como POST fire-and-forget pro servidor HTTP do ai-memory (rodando em <code>127.0.0.1:49374</code> por padrão). O agente nunca espera. Se o ai-memory tiver fora do ar, a sessão continua normal, só sem captura. Claude Desktop e OpenClaw entram como MCP-only: consultam memória, mas não capturam ciclo de vida automaticamente.</p>
<p>Do lado do agente, o MCP server expõe ferramentas que o LLM pode chamar quando achar útil:</p>
<table>
  <thead>
      <tr>
          <th>Você diz&hellip;</th>
          <th>Agente chama&hellip;</th>
          <th>O que acontece</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>&ldquo;Já discutimos X antes?&rdquo;</td>
          <td><code>memory_query</code></td>
          <td>FTS5 + vizinhos por link/graph RRF sobre páginas compiladas, re-ranking vetorial opcional e fallback em observações brutas quando o wiki não acha nada</td>
      </tr>
      <tr>
          <td>(antes de propor arquitetura) implícito</td>
          <td><code>memory_query</code></td>
          <td>Snippet de routing instrui o agente a checar decisões anteriores antes de propor algo novo</td>
      </tr>
      <tr>
          <td>&ldquo;Me coloca a par&rdquo; / &ldquo;fiquei fora um tempo&rdquo;</td>
          <td><code>memory_explore</code></td>
          <td>Digest em prosa. Verbosidade escala com tempo desde última atividade</td>
      </tr>
      <tr>
          <td>&ldquo;Onde paramos?&rdquo;</td>
          <td>(handoff já no contexto)</td>
          <td>Hook <code>SessionStart</code> já adicionou o handoff antes do primeiro prompt</td>
      </tr>
      <tr>
          <td>&ldquo;Salva contexto pra próxima sessão&rdquo;</td>
          <td><code>memory_handoff_begin</code></td>
          <td>Escreve um handoff terso com <code>open_questions</code> + <code>next_steps</code></td>
      </tr>
      <tr>
          <td>&ldquo;Consolida essa sessão&rdquo;</td>
          <td><code>memory_consolidate</code></td>
          <td>Trigger manual do que o SessionEnd faz automaticamente</td>
      </tr>
      <tr>
          <td>&ldquo;Audita o wiki&rdquo;</td>
          <td><code>memory_lint</code></td>
          <td>Detecta páginas obsoletas, contradições, sugere regras</td>
      </tr>
      <tr>
          <td>&ldquo;Quais são os stats?&rdquo;</td>
          <td><code>memory_status</code> / <code>memory_briefing</code></td>
          <td>Conta páginas, sessões, observações e atividade recente</td>
      </tr>
  </tbody>
</table>
<p>O snippet de routing que vai no <code>CLAUDE.md</code> (ou <code>AGENTS.md</code> pra Codex/OpenCode/Cursor/Gemini/OMP) é o que faz o agente saber quando chamar qual ferramenta. Ele se instala com um comando: peça pro agente &ldquo;instala o routing do ai-memory neste projeto&rdquo; e ele invoca a tool MCP <code>memory_install_self_routing</code>, recebe o snippet canônico, e escreve no arquivo certo. Idempotente.</p>
<h2>Exemplo de handoff entre agentes<span class="hx:absolute hx:-mt-20" id="exemplo-de-handoff-entre-agentes"></span>
    <a href="#exemplo-de-handoff-entre-agentes" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Eis o cenário concreto que motivou o projeto:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>$ claude
&gt; &#34;Tô refatorando autenticação. A rotação de JWT tá quebrada, vou
   testar session cookies como alternativa.&#34;
[trabalha por uma hora]
&gt; /exit

$ codex   # mesmo diretório, horas ou dias depois
[SessionStart hook do ai-memory busca o handoff e prepende ao contexto]
&gt; &#34;Continuando: você estava investigando session cookies como
   alternativa à rotação de JWT quebrada. Posso seguir?&#34;</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Você não fez nada especial. No <code>SessionEnd</code> do Claude Code, o ai-memory consolidou as observações da sessão numa página <code>sessions/&lt;uuid&gt;.md</code>, criou um handoff tipado com <code>open_questions</code> + <code>next_steps</code>, e marcou como &ldquo;pending&rdquo;. No <code>SessionStart</code> do Codex, o servidor viu o handoff pending, recuperou e injetou no contexto inicial. O agente lê e continua.</p>
<p>Mesmo cenário se você abandona o projeto por dois meses e volta. O <code>memory_explore</code> calibra a verbosidade automaticamente: faz menos de uma hora desde a última sessão, retorna uma linha. Faz mais de 30 dias, retorna um resumo completo do que rolou.</p>
<h2>Adotando ai-memory num projeto que já existe<span class="hx:absolute hx:-mt-20" id="adotando-ai-memory-num-projeto-que-já-existe"></span>
    <a href="#adotando-ai-memory-num-projeto-que-j%c3%a1-existe" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Se você instalar o ai-memory num projeto que já tem meses de história, o wiki começa vazio e as primeiras sessões são saldo zero. Você tá populando, não recuperando. O comando <code>ai-memory bootstrap</code> resolve isso. Ele coleta seu <code>git log</code>, README, <code>docs/</code>, cabeçalhos de módulo e arquivos de regras do projeto (<code>CLAUDE.md</code> / <code>AGENTS.md</code>), e manda pro servidor que usa o LLM pra gerar páginas-semente do wiki:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ~/Projects/meu-projeto
</span></span><span class="line"><span class="cl">ai-memory bootstrap</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Custa cerca de $0.05 com Claude Haiku 4.5 (orçamento capado em 50K input tokens). Rode com <code>--dry-run</code> primeiro pra ver o que seria mandado sem pagar. A partir daí o wiki começa com contexto real, e cada sessão adiciona em cima.</p>
<h2>Instalação: três comandos<span class="hx:absolute hx:-mt-20" id="instalação-três-comandos"></span>
    <a href="#instala%c3%a7%c3%a3o-tr%c3%aas-comandos" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Eu reduzi a instalação ao essencial. O caminho recomendado é Docker, porque o servidor fica isolado e a atualização é uma linha. Não precisa de mais nada:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 1. Wrapper script (~3KB) que chama o binário dentro do container</span>
</span></span><span class="line"><span class="cl">mkdir -p ~/.local/bin
</span></span><span class="line"><span class="cl">curl -fsSL https://raw.githubusercontent.com/akitaonrails/ai-memory/main/bin/ai-memory <span class="se">\
</span></span></span><span class="line"><span class="cl">    -o ~/.local/bin/ai-memory
</span></span><span class="line"><span class="cl">chmod +x ~/.local/bin/ai-memory
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 2. Sobe o servidor (loopback-only, sem auth — single-user laptop)</span>
</span></span><span class="line"><span class="cl">docker run -d --name ai-memory <span class="se">\
</span></span></span><span class="line"><span class="cl">    --restart unless-stopped <span class="se">\
</span></span></span><span class="line"><span class="cl">    -p 127.0.0.1:49374:49374 <span class="se">\
</span></span></span><span class="line"><span class="cl">    -v ai-memory-data:/data <span class="se">\
</span></span></span><span class="line"><span class="cl">    -e <span class="nv">AI_MEMORY_LLM_PROVIDER</span><span class="o">=</span>anthropic <span class="se">\
</span></span></span><span class="line"><span class="cl">    -e <span class="nv">ANTHROPIC_API_KEY</span><span class="o">=</span>sk-ant-... <span class="se">\
</span></span></span><span class="line"><span class="cl">    akitaonrails/ai-memory:latest
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 3. Configura seu agente</span>
</span></span><span class="line"><span class="cl">ai-memory install-mcp   --client claude-code --apply
</span></span><span class="line"><span class="cl">ai-memory install-hooks --agent  claude-code --apply</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Pronto. Abra o Claude Code como sempre. Cada prompt e tool call agora aterrissam no ai-memory, e a próxima sessão que você abrir no projeto vai ver um handoff com onde você parou.</p>
<p>Repita o passo 3 com <code>--agent codex</code>, <code>--agent opencode</code>, <code>--agent omp</code>/<code>pi</code>, <code>--client cursor</code>, <code>--client gemini-cli</code>, <code>--client pi</code>/<code>omp</code>, etc. pra outros agentes. Claude Desktop e OpenClaw são MCP-only. Idempotente: re-rodar substitui só a entrada do ai-memory, preserva qualquer outro hook/MCP que você tenha. Faz backup <code>.bak-&lt;timestamp&gt;</code> antes de cada escrita.</p>
<p>O README do projeto cobre as variações (<a href="https://github.com/akitaonrails/ai-memory#quick-start"target="_blank" rel="noopener">Docker compose</a>, homelab no LAN com bearer token, <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/install.md"target="_blank" rel="noopener">instalação sem Docker</a>, build do fonte). Recomendo seguir o <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/install.md"target="_blank" rel="noopener">docs/install.md</a> se seu setup foge do caminho padrão.</p>
<h2>Comandos úteis que vale conhecer<span class="hx:absolute hx:-mt-20" id="comandos-úteis-que-vale-conhecer"></span>
    <a href="#comandos-%c3%bateis-que-vale-conhecer" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Depois de instalado, o dia a dia normal é só usar os agentes. Mas vale conhecer alguns comandos pra quando precisar:</p>
<ul>
<li><strong><code>ai-memory upgrade</code></strong> — auto-atualização do wrapper + <code>docker pull</code> da imagem nova + re-instalação dos hook scripts/plugins/extensões. Idempotente. Se você tem servidor remoto separado, refresca só o cliente local; o servidor você atualiza separadamente.</li>
<li><strong><code>ai-memory bootstrap</code></strong> — semeia o wiki a partir de git log + README + docs/ + regras do projeto. Pra projetos que já existem antes do ai-memory entrar.</li>
<li><strong><code>ai-memory purge-project --project &lt;nome&gt; --confirm</code></strong> — apaga um projeto inteiro. Atômico: linhas do SQLite, subdir do wiki, sem tocar nos vizinhos.</li>
<li><strong><code>ai-memory rename-project --from &lt;nome&gt; --to &lt;novo&gt;</code></strong> — renomeia. Uma coluna no DB, sem mover arquivo no disco. Sem efeito colateral.</li>
<li><strong><code>ai-memory backup</code></strong> — snapshot do diretório de dados (wiki + SQLite). <code>ai-memory restore</code> desfaz.</li>
<li><strong><code>ai-memory lint</code> / <code>ai-memory forget-sweep</code> / <code>ai-memory embed</code></strong> — manutenção manual. Lint e forget-sweep também rodam no agendamento do servidor por padrão; embedding backfill existe mas fica desligado por default porque pode chamar provedor pago.</li>
<li><strong><code>ai-memory generate-auth-token</code></strong> — quando você for expor o servidor além do loopback (ver <code>docs/deploy.md</code>).</li>
</ul>
<h2>Explorando o wiki no navegador<span class="hx:absolute hx:-mt-20" id="explorando-o-wiki-no-navegador"></span>
    <a href="#explorando-o-wiki-no-navegador" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O servidor também pode montar uma UI web read-only em <code>http://127.0.0.1:49374/web</code> quando sobe com <code>--enable-web</code>. Mesmo binário, mesma porta, sem processo extra. Serve pra três coisas práticas: auditar o que o agente vem salvando, conferir se as páginas consolidadas tão coerentes, e compartilhar uma página avulsa com alguém do time sem precisar dar acesso ao agente.</p>
<p>A homepage lista os projetos detectados, cada um com contagem de páginas e tempo desde a última atividade:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/23/ai-memory/ai-memory-web-projects.png" alt="Homepage do /web do ai-memory: cards de projeto (llm-coding-benchmark, nes-to-sms, ai-jail, .config, ai-memory, distrobox-gaming, scratch) cada um com contagem de páginas e “just now”, banner laranja avisando que é memória otimizada pra LLM, não documentação curada."  loading="lazy" /></p>
<p>Repare no aviso laranja no topo: o wiki é otimizado pra consumo por LLM, com páginas compiladas a partir de observações de sessão pelo LLM consolidador. Pra documentação canônica curada por humano, use o <code>docs/</code> próprio do projeto. O <code>/web</code> é pra &ldquo;spelunking&rdquo; (vasculhar o histórico).</p>
<p>Cada projeto é isolado por UUID na estrutura física do disco. Duas páginas com o mesmo path em projetos diferentes não colidem. Ao clicar num card você cai na árvore de páginas dele:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/23/ai-memory/ai-memory-web-project-view.png" alt="Página de projeto ai-memory: sidebar à esquerda com árvore agrupada por tipo (concepts/, decisions/, gotchas/), coluna direita lista atividade recente com badges de kind (fact, decision) e timestamps relativos."  loading="lazy" /></p>
<p>A sidebar mostra a árvore agrupada por tipo: <code>concepts/</code> (conhecimento durável), <code>decisions/</code> (decisões arquiteturais), <code>gotchas/</code> (pegadinhas), <code>_rules/</code> (regras de projeto sugeridas pro <code>CLAUDE.md</code>), <code>sessions/</code> (logs por sessão), e <code>bootstrap.md</code> (manifesto gerado pelo <code>ai-memory bootstrap</code>). A coluna direita mostra atividade recente.</p>
<p>Clicando em qualquer página, você cai no markdown renderizado:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/23/ai-memory/ai-memory-web-page.png" alt="Página individual “Per-project UUID-namespaced disk layout” renderizada: badges “semantic” e “fact” no topo, timestamps “updated just now” e “created 1 hour ago”, corpo em markdown com bloco de código ASCII mostrando a árvore de diretório."  loading="lazy" /></p>
<p>O rendering tem syntax highlighting, badges de tier (<code>working</code>/<code>episodic</code>/<code>semantic</code>/<code>procedural</code>) e kind (<code>decision</code>/<code>gotcha</code>/<code>rule</code>/<code>fact</code>), breadcrumbs, supersession chain visível. A busca combina FTS5, expansão por links e, se configurado, embeddings; modo claro/escuro segue a preferência do sistema via <code>prefers-color-scheme</code>.</p>
<p>Pra editar o wiki você abre os arquivos direto em qualquer editor de markdown (Obsidian funciona bem). A interface web é read-only por design: o LLM consolidador é quem escreve, humanos só leem.</p>
<h2>Por que Docker<span class="hx:absolute hx:-mt-20" id="por-que-docker"></span>
    <a href="#por-que-docker" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A escolha de Docker como caminho recomendado foi deliberada. Algumas vantagens práticas:</p>
<ul>
<li><strong>Atualização é uma linha.</strong> <code>ai-memory upgrade</code> puxa a imagem nova, refresca o wrapper, re-instala hooks/plugins/extensões. Você não compila Rust, não cuida de versão de libsqlite, não briga com mise/Node version churn como acontece com soluções baseadas em Node.</li>
<li><strong>Isolamento real.</strong> O servidor roda no container, lê só <code>/data</code> (volume nomeado), não polui seu sistema. Se quiser limpar, é <code>docker volume rm</code>.</li>
<li><strong>Mesma imagem em vários setups.</strong> Laptop, desktop, homelab. Mesma imagem amd64 ou arm64.</li>
<li><strong>Restart automático.</strong> <code>--restart unless-stopped</code> faz o servidor voltar quando você reinicia o Docker, ou quando liga a máquina (assumindo <code>systemctl enable docker</code>).</li>
<li><strong>Build de source não é necessário.</strong> Quem compila Rust toolchain 1.95+ leva uns 3 minutos em release. Pro usuário final, isso é cerimônia desnecessária. O Docker abstrai tudo.</li>
</ul>
<p>Tem caminho sem Docker no docs/install.md pra quem prefere. Mas Docker é onde a UX é melhor.</p>
<h2>Qual LLM usar pra consolidação<span class="hx:absolute hx:-mt-20" id="qual-llm-usar-pra-consolidação"></span>
    <a href="#qual-llm-usar-pra-consolida%c3%a7%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Esse é um caso onde <strong>não precisa de modelo pesado</strong>. A consolidação é texto entra, texto sai: o agente registra observações brutas durante a sessão, no <code>SessionEnd</code> o LLM compila 1-5 páginas de wiki classificadas como <code>concept</code> / <code>decision</code> / <code>gotcha</code> / <code>rule</code>. Não tem raciocínio complexo, não tem código. Opus 4.7 ou GPT-5.5 thinking são overkill, custam caro e demoram muito pra uma tarefa que aceita modelo leve.</p>
<p>Pra escolher o default rodamos A/B testing sério em 6 provedores diferentes contra 5 fixtures sintéticas, cada uma desenhada pra estressar um modo de falha específico: extração multi-página, restrição (resistir a fabricar página quando a sessão é trivial), classificação correta de <code>rule</code> vs <code>gotcha</code> vs <code>decision</code>, e separação de tópicos não relacionados. A doc completa, com tabelas de parse rate, latência e qualidade por fixture, tá em <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/llm-provider-comparison.md"target="_blank" rel="noopener"><code>docs/llm-provider-comparison.md</code></a>. Resumindo a tabela final:</p>
<table>
  <thead>
      <tr>
          <th>Modelo</th>
          <th>Custo</th>
          <th>Latência</th>
          <th>Veredicto</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>Claude Haiku 4.5</strong></td>
          <td>~$0.02/run</td>
          <td>7s</td>
          <td><strong>Default escolhido.</strong> Melhor classificação e restrição, sem alucinação.</td>
      </tr>
      <tr>
          <td>GPT-5.4-mini (OpenAI)</td>
          <td>~$0.005/run</td>
          <td>4s</td>
          <td>Alternativa mais barata e rápida. Leve over-classification em sessões triviais.</td>
      </tr>
      <tr>
          <td>qwen3:32b (Ollama local)</td>
          <td>$0</td>
          <td>92s</td>
          <td>Gratuito se você tem servidor local. Latência invisível em background.</td>
      </tr>
      <tr>
          <td>DeepSeek V4 Flash</td>
          <td>~$0.005/run</td>
          <td>22s</td>
          <td>Funciona, mas sem vantagem sobre GPT-mini ou Haiku.</td>
      </tr>
      <tr>
          <td>Sonnet 4.5</td>
          <td>~$0.06/run</td>
          <td>11s</td>
          <td>Substituído pelo Haiku. 3× o custo, mais alucinação.</td>
      </tr>
      <tr>
          <td>Kimi-K2.6</td>
          <td>n/a</td>
          <td>trava</td>
          <td>INELIGÍVEL. Modelo de raciocínio consome o budget de tokens internamente antes de emitir conteúdo.</td>
      </tr>
  </tbody>
</table>
<p>Por que Haiku ficou como default: hospedado (sempre disponível), o melhor em <strong>restrição</strong> (resiste a fabricar páginas quando a sessão é trivial, crucial pra wiki não virar coleção de páginas vazias) e o melhor em <strong>classificação</strong> (acerta <code>kind: rule</code> consistentemente, que é o que faz o roteamento automático pro <code>_rules/&lt;slug&gt;.md</code> funcionar). Custo de $0.02 por consolidação é desprezível pra uso pessoal.</p>
<p>Mas o usuário tem alternativas legítimas:</p>
<ul>
<li><strong>GPT-5.4-mini</strong> se o orçamento aperta (5× mais barato que Haiku, 2× mais rápido). O único defeito mensurável foi fabricar uma página <code>decisions/docs-spelling.md</code> numa sessão de correção de typo. Over-classification, mas leve.</li>
<li><strong>qwen3:32b no Ollama</strong> se você tem servidor local com ~20GB de RAM/VRAM disponível. Zero custo por consolidação, fidelidade compatível com os hospedados. A latência alta (~92s) não importa porque consolidação roda em background.</li>
<li><strong>DeepSeek V4 Flash</strong> funciona, mas o GPT-mini iguala em qualidade e bate em velocidade.</li>
</ul>
<p>Quem quiser testar outros modelos, o harness de avaliação tá em <a href="https://github.com/akitaonrails/ai-memory/tree/main/evals"target="_blank" rel="noopener"><code>evals/</code></a> como crate Rust separada. Adiciona um JSON de fixture, roda <code>cargo run -p ai-memory-eval --release</code>, compara dois provedores lado a lado. Os outputs ficam em <code>evals/runs/&lt;timestamp&gt;/{baseline,candidate}/</code> com o <code>.raw.txt</code> exato que o modelo respondeu mais o <code>.meta.json</code> com latência e parse rate. PRs com novos modelos testados são muito bem-vindos.</p>
<h2>Status: beta, falta usuário<span class="hx:absolute hx:-mt-20" id="status-beta-falta-usuário"></span>
    <a href="#status-beta-falta-usu%c3%a1rio" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O ai-memory tá nas tags <code>v0.2-complete</code> no GitHub. As funcionalidades principais funcionam: captura automática, MCP, web UI opcional, bootstrap, purge/rename/backup, bearer auth, browse, busca FTS5 + graph/link-neighbour RRF, embeddings opcionais, consolidação, decay, manutenção agendada e handoff entre Claude Code / Codex / OpenCode / Cursor / Gemini CLI / OMP-Pi. Eu rodo em produção pessoal há algumas semanas.</p>
<p>Mas é beta. Precisa de muito mais usuário batendo nele pra eu encontrar os bugs que ainda não aparecem na minha máquina. Claude Desktop e OpenClaw funcionam como MCP-only; alguns clientes MCP exóticos ainda precisam de teste real. A integração mais polida hoje é Claude Code, seguida de Codex, OpenCode e OMP/Pi.</p>
<p>Se você tá lendo até aqui, considera instalar e me mandar feedback. Issues no <a href="https://github.com/akitaonrails/ai-memory/issues"target="_blank" rel="noopener">github.com/akitaonrails/ai-memory/issues</a>. PRs são muito bem-vindos — o código é Rust, MIT, e a arquitetura tá documentada em <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/ARCHITECTURE.md"target="_blank" rel="noopener"><code>docs/ARCHITECTURE.md</code></a> e <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/design-decisions.md"target="_blank" rel="noopener"><code>docs/design-decisions.md</code></a>. Mesmo bug report de &ldquo;instalei, não rodou no meu setup&rdquo; ajuda — significa que tem algo que assumi sobre ambientes que não bate com o seu.</p>
<p>A motivação central continua sendo a frase do Karpathy. Memória de agente é texto. Texto fica no disco. Indexa com SQLite. Compila com LLM quando vale o trabalho. Esquece quando ninguém olha mais. Sai do caminho. E quando você troca de agente no meio do projeto, o próximo já sabe onde você parou.</p>
<p>É isso que o ai-memory tenta entregar.</p>
]]></content:encoded><category>ai-memory</category><category>agentes-de-codigo</category><category>rust</category></item><item><title>Memória de Agentes IA: Karpathy LLM Wiki e agentmemory na Prática</title><link>https://akitaonrails.github.io/2026/05/18/memoria-agentes-karpathy-llm-wiki-agentmemory/</link><guid isPermaLink="true">https://akitaonrails.github.io/2026/05/18/memoria-agentes-karpathy-llm-wiki-agentmemory/</guid><pubDate>Mon, 18 May 2026 15:00:00 -0300</pubDate><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Atualização (23 de maio de 2026)&lt;/strong&gt;: depois de uma semana rodando o agentmemory em produção pessoal, voltei atrás. A arquitetura escolhida acumula uma classe de bug que não fecha sem reescrever metade do sistema (BM25 reindex a cada restart, janela de 5s de perda de dados, hook errado em ~47% das tool calls do Claude Code, etc). Comecei um substituto em Rust chamado &lt;strong&gt;ai-memory&lt;/strong&gt; que resolve esses problemas. Veja &lt;a href="https://akitaonrails.github.io/2026/05/23/criei-sistema-memoria-agentes-codigo-ai-memory/"&gt;Criei um Sistema de Memória pra Agentes de Código: ai-memory&lt;/a&gt; com o relato completo, o ranking das alternativas e como instalar. O resto desse post continua válido como background sobre como compaction funciona nos três agentes, o padrão LLM Wiki do Karpathy, e por que memória externa importa.&lt;/p&gt;</description><content:encoded><![CDATA[<blockquote>
  <p><strong>Atualização (23 de maio de 2026)</strong>: depois de uma semana rodando o agentmemory em produção pessoal, voltei atrás. A arquitetura escolhida acumula uma classe de bug que não fecha sem reescrever metade do sistema (BM25 reindex a cada restart, janela de 5s de perda de dados, hook errado em ~47% das tool calls do Claude Code, etc). Comecei um substituto em Rust chamado <strong>ai-memory</strong> que resolve esses problemas. Veja <a href="/2026/05/23/criei-sistema-memoria-agentes-codigo-ai-memory/">Criei um Sistema de Memória pra Agentes de Código: ai-memory</a> com o relato completo, o ranking das alternativas e como instalar. O resto desse post continua válido como background sobre como compaction funciona nos três agentes, o padrão LLM Wiki do Karpathy, e por que memória externa importa.</p>

</blockquote>
<p>Todo mundo que mexe com Claude Code, Codex CLI ou opencode em sessões longas em algum momento topou com a mensagem &ldquo;context approaching limit&rdquo; ou viu o agente &ldquo;esquecer&rdquo; decisões tomadas três horas atrás. Esse post é um mergulho em como funciona a memória desses agentes hoje, onde ela quebra, e o que dá pra fazer pra ter algo mais parecido com memória de longo prazo. Olhei o código-fonte direto do Codex (Rust), do opencode (TypeScript) e do Claude Code (TypeScript, via o vazamento que circulou recentemente), e fechei testando o <a href="https://github.com/rohitg00/agentmemory"target="_blank" rel="noopener">agentmemory</a>, um servidor MCP open source que tenta resolver o problema de forma sistemática.</p>
<h2>Antes de tudo: o que é &ldquo;contexto&rdquo;<span class="hx:absolute hx:-mt-20" id="antes-de-tudo-o-que-é-contexto"></span>
    <a href="#antes-de-tudo-o-que-%c3%a9-contexto" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Um modelo de linguagem (LLM) não tem memória persistente. O que ele &ldquo;lembra&rdquo; durante uma conversa é só o conjunto de tokens que cabem na <strong>janela de contexto</strong> dele. Cada mensagem trocada, cada arquivo lido, cada saída de comando, cada chamada de ferramenta — tudo isso entra na janela. Quando você usa Claude Code, Codex ou opencode, o agente está montando uma sequência de mensagens (system prompt + histórico + ferramentas + saída delas) e mandando inteira pra API a cada turno.</p>
<p>Isso tem dois efeitos diretos. O primeiro é comportamental: o agente performa melhor quando a parte relevante da conversa está fresca no contexto, e piora à medida que informação importante fica enterrada sob páginas de output de <code>ls</code> e <code>grep</code>. O segundo é financeiro: cada token enviado é cobrado (ou descontado da sua cota), e janelas grandes têm latência maior. Opus 4.7 tem 1M de contexto, GPT 5.5 também, mas só porque a janela cabe não significa que vale a pena enchê-la. Quanto mais cheia, mais lenta a inferência e mais cara a request.</p>
<p>Por isso todos os agentes implementam algum mecanismo de <strong>compaction</strong>: quando o contexto se aproxima do limite, o agente roda uma chamada LLM extra que resume a conversa até ali em um texto bem menor, descarta o histórico bruto, e continua a sessão em cima desse resumo. O ganho é óbvio (mais espaço pra trabalhar) e o custo também (a parte resumida perde detalhe).</p>
<p>Vamos ver como cada um dos três grandes implementa isso.</p>
<h2>Codex CLI: limite por modelo + handoff explícito<span class="hx:absolute hx:-mt-20" id="codex-cli-limite-por-modelo--handoff-explícito"></span>
    <a href="#codex-cli-limite-por-modelo--handoff-expl%c3%adcito" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O Codex CLI é open source (<a href="https://github.com/openai/codex"target="_blank" rel="noopener">github.com/openai/codex</a>), então dá pra ler o código direto. A lógica de auto-compaction vive em <code>codex-rs/core/src/session/turn.rs</code> e dispara assim:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">auto_compact_limit</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">model_info</span><span class="p">.</span><span class="n">auto_compact_token_limit</span><span class="p">().</span><span class="n">unwrap_or</span><span class="p">(</span><span class="kt">i64</span>::<span class="no">MAX</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// ... a cada turno ...
</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">total_usage_tokens</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sess</span><span class="p">.</span><span class="n">get_total_token_usage</span><span class="p">().</span><span class="k">await</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">token_limit_reached</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">total_usage_tokens</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="n">auto_compact_limit</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="w"> </span><span class="n">token_limit_reached</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">needs_follow_up</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">reset_client_session</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">run_auto_compact</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="o">&amp;</span><span class="n">sess</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">turn_context</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">client_session</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">InitialContextInjection</span>::<span class="n">BeforeLastUserMessage</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">CompactionReason</span>::<span class="n">ContextLimit</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">CompactionPhase</span>::<span class="n">MidTurn</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">).</span><span class="k">await</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* ... */</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>O limite é por modelo (<code>auto_compact_token_limit</code> vem de <code>ModelProviderInfo</code>). Quando bate, o Codex chama o próprio LLM com um prompt específico de compaction (em <code>codex-rs/core/templates/compact/prompt.md</code>):</p>
<blockquote>
  <p>Você está executando um CHECKPOINT DE COMPACTAÇÃO DE CONTEXTO. Crie um resumo de handoff pra outro LLM que vai retomar a tarefa.</p>
<p>Inclua:</p>
<ul>
<li>Progresso atual e principais decisões tomadas</li>
<li>Contexto importante, restrições ou preferências do usuário</li>
<li>O que ainda falta ser feito (próximos passos claros)</li>
<li>Quaisquer dados críticos, exemplos ou referências necessárias pra continuar</li>
</ul>

</blockquote>
<p>A resposta vira o novo contexto, prefixada com um preâmbulo que diz literalmente &ldquo;another language model started to solve this problem and produced a summary of its thinking process&rdquo;. O Codex emite eventos <code>pre_compact</code> e <code>post_compact</code> que hooks podem interceptar (rodam em <a href="https://github.com/openai/codex/blob/main/codex-rs/core/src/hook_runtime.rs"target="_blank" rel="noopener"><code>codex-rs/core/src/hook_runtime.rs</code></a>). Esses hooks são o ponto onde ferramentas externas (como o agentmemory) se plugam pra salvar o estado antes da compaction destruir o histórico.</p>
<h2>opencode: buffer de 20K + summarização ancorada<span class="hx:absolute hx:-mt-20" id="opencode-buffer-de-20k--summarização-ancorada"></span>
    <a href="#opencode-buffer-de-20k--summariza%c3%a7%c3%a3o-ancorada" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O opencode (<a href="https://github.com/sst/opencode"target="_blank" rel="noopener">github.com/sst/opencode</a>) faz a mesma coisa com uma matemática diferente. Em <code>packages/opencode/src/session/overflow.ts</code>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">COMPACTION_BUFFER</span> <span class="o">=</span> <span class="mi">20</span><span class="nx">_000</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">usable</span><span class="p">(</span><span class="nx">input</span><span class="o">:</span> <span class="p">{</span> <span class="nx">cfg</span><span class="p">,</span> <span class="nx">model</span><span class="p">,</span> <span class="nx">outputTokenMax</span><span class="o">?</span> <span class="p">})</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">context</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">model</span><span class="p">.</span><span class="nx">limit</span><span class="p">.</span><span class="nx">context</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">reserved</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">cfg</span><span class="p">.</span><span class="nx">compaction</span><span class="o">?</span><span class="p">.</span><span class="nx">reserved</span>
</span></span><span class="line"><span class="cl">    <span class="o">??</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">min</span><span class="p">(</span><span class="nx">COMPACTION_BUFFER</span><span class="p">,</span> <span class="nx">ProviderTransform</span><span class="p">.</span><span class="nx">maxOutputTokens</span><span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">model</span><span class="p">,</span> <span class="nx">input</span><span class="p">.</span><span class="nx">outputTokenMax</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">input</span><span class="p">.</span><span class="nx">model</span><span class="p">.</span><span class="nx">limit</span><span class="p">.</span><span class="nx">input</span>
</span></span><span class="line"><span class="cl">    <span class="o">?</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">input</span><span class="p">.</span><span class="nx">model</span><span class="p">.</span><span class="nx">limit</span><span class="p">.</span><span class="nx">input</span> <span class="o">-</span> <span class="nx">reserved</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="o">:</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">context</span> <span class="o">-</span> <span class="nx">ProviderTransform</span><span class="p">.</span><span class="nx">maxOutputTokens</span><span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">model</span><span class="p">,</span> <span class="nx">input</span><span class="p">.</span><span class="nx">outputTokenMax</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">isOverflow</span><span class="p">(</span><span class="nx">input</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">cfg</span><span class="p">.</span><span class="nx">compaction</span><span class="o">?</span><span class="p">.</span><span class="nx">auto</span> <span class="o">===</span> <span class="kc">false</span><span class="p">)</span> <span class="k">return</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">count</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">total</span>
</span></span><span class="line"><span class="cl">    <span class="o">||</span> <span class="nx">input</span><span class="p">.</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">input</span> <span class="o">+</span> <span class="nx">input</span><span class="p">.</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">output</span> <span class="o">+</span> <span class="nx">input</span><span class="p">.</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">read</span> <span class="o">+</span> <span class="nx">input</span><span class="p">.</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">write</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">count</span> <span class="o">&gt;=</span> <span class="nx">usable</span><span class="p">(</span><span class="nx">input</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Por padrão, opencode reserva 20K tokens como buffer entre o conteúdo e o limite da janela. Quando o total de tokens passa de <code>usable()</code>, marca a sessão como <code>needsCompaction = true</code> e dispara o fluxo de compaction no próximo turno. O prompt de summarization (em <code>packages/opencode/src/agent/prompt/compaction.txt</code>) é mais cirúrgico que o do Codex:</p>
<blockquote>
  <p>Você é um assistente de sumarização de contexto ancorado pra sessões de coding.</p>
<p>Resuma apenas o histórico de conversa que recebeu. Os turnos mais recentes podem ser mantidos verbatim fora do seu resumo, então foque no contexto mais antigo que ainda importa pra continuar o trabalho.</p>
<p>Se o prompt incluir um bloco <code>&lt;previous-summary&gt;</code>, trate ele como o resumo ancorado atual. Atualize com o histórico novo preservando detalhes que continuam verdadeiros, removendo detalhes obsoletos e mesclando fatos novos.</p>

</blockquote>
<p>Repare na diferença: o opencode mantém um &ldquo;anchored summary&rdquo; que é <strong>atualizado</strong> a cada compaction, não regenerado do zero. Os turnos mais recentes ficam verbatim, e só o histórico antigo é colapsado. É um meio-termo entre o handoff completo do Codex e manter tudo cru.</p>
<h2>Claude Code: três níveis de compaction + summary detalhado<span class="hx:absolute hx:-mt-20" id="claude-code-três-níveis-de-compaction--summary-detalhado"></span>
    <a href="#claude-code-tr%c3%aas-n%c3%adveis-de-compaction--summary-detalhado" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>O Claude Code é proprietário, mas um vazamento recente expôs a fonte (TypeScript, igual o opencode mas com arquitetura bem diferente). O código mostra que a Anthropic foi mais longe que os concorrentes: o Claude Code tem <strong>três níveis de compaction</strong> rodando em paralelo, não um.</p>
<p>O primeiro é o <code>microcompact</code> time-based, em <code>src/services/compact/microCompact.ts</code> e <code>timeBasedMCConfig.ts</code>. Quando o gap desde a última mensagem do assistente passa de 60 minutos, o cache de prompt do servidor (TTL de 1h) está garantidamente expirado, então o prefixo inteiro vai ser reescrito de qualquer jeito na próxima request. Antes de mandar, o Claude Code limpa o conteúdo de resultados antigos de ferramentas (<code>Read</code>, <code>Grep</code>, <code>Glob</code>, <code>WebFetch</code>, <code>Bash</code>, etc.) e substitui por <code>[Old tool result content cleared]</code>. Reduz o tamanho da request sem entrar no fluxo caro de summarization. Comentário no código:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="cm">/** Trigger when (now − last assistant timestamp) exceeds this many minutes.
</span></span></span><span class="line"><span class="cl"><span class="cm"> *  60 is the safe choice: the server&#39;s 1h cache TTL is guaranteed expired
</span></span></span><span class="line"><span class="cl"><span class="cm"> *  for all users, so we never force a miss that wouldn&#39;t have happened. */</span>
</span></span><span class="line"><span class="cl"><span class="nx">gapThresholdMinutes</span>: <span class="kt">number</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>O segundo nível é o <code>autoCompact</code>, em <code>src/services/compact/autoCompact.ts</code>. Análogo ao do opencode, mas com mais cuidado:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">MAX_OUTPUT_TOKENS_FOR_SUMMARY</span> <span class="o">=</span> <span class="mi">20</span><span class="nx">_000</span>
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">AUTOCOMPACT_BUFFER_TOKENS</span> <span class="o">=</span> <span class="mi">13</span><span class="nx">_000</span>
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">WARNING_THRESHOLD_BUFFER_TOKENS</span> <span class="o">=</span> <span class="mi">20</span><span class="nx">_000</span>
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">ERROR_THRESHOLD_BUFFER_TOKENS</span> <span class="o">=</span> <span class="mi">20</span><span class="nx">_000</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">getAutoCompactThreshold</span><span class="p">(</span><span class="nx">model</span>: <span class="kt">string</span><span class="p">)</span><span class="o">:</span> <span class="kt">number</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">effectiveContextWindow</span> <span class="o">=</span> <span class="nx">getEffectiveContextWindowSize</span><span class="p">(</span><span class="nx">model</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">effectiveContextWindow</span> <span class="o">-</span> <span class="nx">AUTOCOMPACT_BUFFER_TOKENS</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Reserva 20K tokens pra saída da summarization, 13K de buffer pra disparar a compaction, e tem warning + error thresholds 20K abaixo desse limite (a barra de status do TUI fica amarela quando passa do warning, vermelha no error). Tem também um circuit breaker: depois de 3 falhas consecutivas de auto-compact, para de tentar — um comentário interno revela que sem isso &ldquo;1,279 sessions had 50+ consecutive failures (up to 3,272), wasting ~250K API calls/day globally&rdquo;.</p>
<p>O terceiro nível é o <code>sessionMemoryCompact</code> em <code>sessionMemoryCompact.ts</code>, marcado como experimental, que cruza com o sistema de memória persistente entre sessões.</p>
<p>A diferença mais visível em comparação com Codex e opencode está no prompt de summarization. Onde o Codex pede 4 bullets curtos e o opencode pede um update do &ldquo;anchored summary&rdquo;, o Claude Code pede uma estrutura de 9 seções explícitas (<code>src/services/compact/prompt.ts</code>):</p>
<blockquote>
  <ol>
<li>Pedido e Intenção Primária: Capture todos os pedidos e intenções explícitas do usuário em detalhe</li>
<li>Conceitos Técnicos-Chave: Liste todos os conceitos técnicos, tecnologias e frameworks discutidos.</li>
<li>Arquivos e Trechos de Código: Enumere arquivos e trechos específicos que foram examinados, modificados ou criados&hellip;</li>
<li>Erros e correções: Liste todos os erros que apareceram e como foram corrigidos&hellip;</li>
<li>Resolução de Problemas: Documente problemas resolvidos e investigações em andamento.</li>
<li>Todas as mensagens do usuário: Liste TODAS as mensagens do usuário que não são resultados de ferramentas. São críticas&hellip;</li>
<li>Tarefas Pendentes: Liste tarefas pendentes que foram explicitamente solicitadas.</li>
<li>Trabalho Atual: Descreva em detalhe precisamente o que estava sendo feito imediatamente antes desse pedido de resumo&hellip;</li>
<li>Próximo Passo Opcional: Liste o próximo passo que você vai tomar&hellip;</li>
</ol>

</blockquote>
<p>A seção 6 (&ldquo;All user messages&rdquo;) é a mais incomum: o resumo precisa conter a lista verbatim de cada mensagem do usuário que não seja resultado de ferramenta. Ou seja, mesmo depois da compaction, o Claude Code preserva o que você pediu, literal. Isso explica por que sessões compactadas no Claude Code parecem manter o tom da conversa melhor que as do Codex (onde o handoff é mais executivo e menos narrativo).</p>
<p>Existe também uma variante <code>PARTIAL_COMPACT_PROMPT</code> que summariza só o trecho mais recente quando há um summary anterior preservado, e uma <code>PARTIAL_COMPACT_UP_TO_PROMPT</code> pra preservar cache hit ao colocar o resumo no início. O comando <code>/compact</code> continua disponível como força manual, e os hooks <code>PreCompact</code> / <code>PostCompact</code> rodam como nos outros agentes.</p>
<h2>Comparando os três lado a lado<span class="hx:absolute hx:-mt-20" id="comparando-os-três-lado-a-lado"></span>
    <a href="#comparando-os-tr%c3%aas-lado-a-lado" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><table>
  <thead>
      <tr>
          <th></th>
          <th>Claude Code</th>
          <th>Codex</th>
          <th>opencode</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Buffer pré-compaction</td>
          <td>13K (autocompact) + 20K (saída)</td>
          <td>por modelo via <code>auto_compact_token_limit</code></td>
          <td>20K (config <code>compaction.reserved</code>)</td>
      </tr>
      <tr>
          <td>Tipos de compaction</td>
          <td>3 (microcompact, autocompact, sessionMemoryCompact)</td>
          <td>1 (mais variantes remote v1/v2)</td>
          <td>1 (anchored, com summary atualizável)</td>
      </tr>
      <tr>
          <td>Estrutura do summary</td>
          <td>9 seções fixas + bloco <code>&lt;analysis&gt;</code> de scratchpad</td>
          <td>4 bullets livres (progress, decisions, next, refs)</td>
          <td>Atualização do &ldquo;anchored summary&rdquo; previamente existente</td>
      </tr>
      <tr>
          <td>Preservação verbatim</td>
          <td>Lista todas mensagens do usuário</td>
          <td>Não</td>
          <td>Turnos mais recentes ficam intactos fora do summary</td>
      </tr>
      <tr>
          <td>Circuit breaker</td>
          <td>Sim, 3 falhas consecutivas param o ciclo</td>
          <td>Não documentado</td>
          <td>Não</td>
      </tr>
      <tr>
          <td>Hooks</td>
          <td>PreCompact / PostCompact</td>
          <td>pre_compact / post_compact (Rust)</td>
          <td>sem hooks de compaction explícitos</td>
      </tr>
      <tr>
          <td>Microcompact por gap temporal</td>
          <td>Sim (60min, sincronizado com TTL de cache)</td>
          <td>Não</td>
          <td>Não</td>
      </tr>
  </tbody>
</table>
<p>A escolha de design conta uma história. O Claude Code investe em <strong>preservar narrativa do usuário</strong> (as 9 seções, especialmente a 6) e <strong>otimizar custo de cache</strong> (microcompact por gap, separação clara entre 3 caminhos). O Codex prioriza <strong>handoff entre modelos</strong> (a frase &ldquo;summary produced by the other language model&rdquo; no prefixo do resumo mostra a expectativa de que o próximo turno pode ser executado por outro LLM). O opencode escolheu <strong>summarização incremental</strong>: o anchored summary é atualizado a cada ciclo, em vez de regenerado. Cada estratégia tem trade-offs, mas é a primeira vez que dá pra olhar lado a lado o código real dos três.</p>
<h2>&ldquo;Vendor lock&rdquo;? Não existe pra esse tipo de memória<span class="hx:absolute hx:-mt-20" id="vendor-lock-não-existe-pra-esse-tipo-de-memória"></span>
    <a href="#vendor-lock-n%c3%a3o-existe-pra-esse-tipo-de-mem%c3%b3ria" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Uma preocupação que aparece muito é que ao começar com Claude Code você fica &ldquo;preso&rdquo; a ele, e não dá pra migrar pra opencode ou Codex depois. Isso é mito. Memória de agente, como vimos, é só <strong>texto</strong>. Não tem formato proprietário binário, não tem schema fechado, não tem state que só o vendor sabe ler. Tudo que o agente carrega é prompt + histórico de mensagens + arquivos de contexto.</p>
<p>Na prática você pode fazer handoff manual entre agentes. Pede pro Claude Code: &ldquo;escreva um documento markdown em <code>./HANDOFF.md</code> com o estado atual do projeto, decisões tomadas, próximos passos, e qualquer contexto importante pra um agente diferente continuar.&rdquo; Sai uma sessão bem feita, fecha o Claude Code, abre o opencode, pede &ldquo;leia <code>./HANDOFF.md</code> e continue de onde parou.&rdquo; E o opencode pega de onde o Claude parou, sem perda significativa (a perda é exatamente a mesma que uma compaction interna teria provocado).</p>
<p>Esse padrão de exportar contexto explicitamente é, inclusive, melhor do que confiar na compaction automática. Você decide quando e o que preservar, ao invés de deixar o agente decidir baseado em pressão de tokens.</p>
<h2>O problema: long-term memory desaparece junto<span class="hx:absolute hx:-mt-20" id="o-problema-long-term-memory-desaparece-junto"></span>
    <a href="#o-problema-long-term-memory-desaparece-junto" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Compaction resolve o problema imediato (espaço no contexto) mas cria um problema mais sutil: <strong>informação do início da sessão é eliminada primeiro</strong>. Se você passou 30 minutos no turno 5 explorando uma arquitetura, decidiu três trade-offs e descartou duas abordagens, no turno 50 essa exploração inteira pode ter virado uma linha de bullet point. Se você precisar voltar pra um daqueles trade-offs descartados (&ldquo;por que decidimos não usar Redis aqui?&rdquo;), o agente não sabe mais.</p>
<p>A solução que venho usando há meses é forçar o agente a escrever em arquivos manualmente. Em projetos importantes mantenho um diretório <code>./.docs/</code> ou <code>./docs/</code> com arquivos markdown organizados por tópico: arquitetura, decisões, pegadinhas conhecidas, configurações esquisitas, links pra issues relevantes. Quando alguma coisa importante acontece numa sessão, peço: &ldquo;salva isso em <code>./.docs/&lt;topico&gt;.md</code>&rdquo;. Aí na próxima sessão, ou depois de uma compaction, o agente pode reler o arquivo se precisar.</p>
<p>O custo dessa abordagem é disciplina. Eu tenho que lembrar de pedir pra salvar. O agente não vai fazer isso sozinho. E eu tenho que organizar os arquivos pra que ele consiga achar o que precisa depois (o que normalmente significa um arquivo MEMORY.md ou CLAUDE.md no root listando os tópicos).</p>
<p>Existe uma forma mais sistemática de fazer isso. O nome dela é <strong>LLM Wiki</strong>, popularizada pelo <a href="https://venturebeat.com/data/karpathy-shares-llm-knowledge-base-architecture-that-bypasses-rag-with-an"target="_blank" rel="noopener">Andrej Karpathy em abril de 2026</a> num gist no GitHub.</p>
<h2>O padrão LLM Wiki do Karpathy<span class="hx:absolute hx:-mt-20" id="o-padrão-llm-wiki-do-karpathy"></span>
    <a href="#o-padr%c3%a3o-llm-wiki-do-karpathy" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/18/memoria-agentes/karpathy_wiki_diagram.jpg" alt="Diagrama do padrão LLM Wiki: três camadas (Raw Sources, The Wiki, Schema) na arquitetura; três operações (Ingest, Query, Lint); dois atores (Human e LLM Agent). Visualização do Yuchen Jin sobre o tweet original do Karpathy."  loading="lazy" /></p>
<p>A ideia é simples e poderosa: em vez de tratar conhecimento como algo a <strong>recuperar</strong> sob demanda (RAG), trata como algo a <strong>compilar</strong> ao longo do tempo, igual código. A arquitetura tem três camadas:</p>
<ol>
<li><strong>Raw Sources</strong> — documentos imutáveis (papers, artigos, transcrições, notas) que servem como source of truth.</li>
<li><strong>Wiki Layer</strong> — arquivos markdown gerados e mantidos pelo LLM. Cada conceito vira uma página. Páginas referenciam outras páginas. O LLM atualiza, faz cross-reference, marca contradições.</li>
<li><strong>Schema</strong> — um arquivo (estilo <code>CLAUDE.md</code> ou <code>SCHEMA.md</code>) que define convenções: como nomear páginas, taxonomia de tags, estrutura mínima de cada entrada.</li>
</ol>
<p>O workflow tem três operações. <strong>Ingest</strong>: quando uma fonte nova chega, o LLM lê, extrai o que importa, atualiza 10-15 páginas existentes, cria as que faltam, conserta cross-references. <strong>Query</strong>: perguntas ganham resposta sintetizada com citações; insights valiosos viram páginas novas. <strong>Lint</strong>: passes periódicos detectam contradições, claims desatualizadas, conexões faltando.</p>
<p>A vantagem central sobre RAG é que <strong>conhecimento compõe</strong>. RAG re-derive resposta a cada query, partindo dos mesmos documentos brutos. A wiki sintetiza uma vez, e a próxima query parte da síntese, não dos brutos. Pra programação isso vale ouro: a primeira vez que você descobre que uma biblioteca tem uma pegadinha esquisita com timezone, vira página da wiki. Da segunda vez que o assunto aparece, o agente lê a página, não re-descobre o problema.</p>
<p>O trabalho manual de manter uma wiki sempre matou wikis humanas. Por isso elas morrem. Mas LLMs são bons em escrita e manutenção repetitiva. A aposta do Karpathy é que finalmente temos uma máquina que faz o trabalho chato de manter a wiki viva.</p>
<h2>agentmemory: implementação prática do padrão<span class="hx:absolute hx:-mt-20" id="agentmemory-implementação-prática-do-padrão"></span>
    <a href="#agentmemory-implementa%c3%a7%c3%a3o-pr%c3%a1tica-do-padr%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/18/memoria-agentes/agentmemory-banner.png" alt="Banner do projeto agentmemory: “Persistent memory for AI coding agents” com selo de R@5 95.2% retrieval, 92% fewer tokens, 53 MCP tools, 12 auto hooks, 0 external DBs, 950&#43; tests passing."  loading="lazy" /></p>
<p>Eu vinha fazendo essa wiki manualmente em <code>./.docs/</code> há meses. Essa semana migrei pra uma ferramenta que automatiza a maior parte do processo: o <a href="https://github.com/rohitg00/agentmemory"target="_blank" rel="noopener">agentmemory</a> do Rohit Ghumare. É open source (Apache-2.0), e é literalmente uma implementação do padrão LLM Wiki com algumas extensões (confidence scoring, lifecycle de memórias, knowledge graph, hybrid search).</p>
<p>O que ele é, na prática:</p>
<ul>
<li>Um <strong>daemon Node</strong> rodando localmente em <code>127.0.0.1:3111</code> (REST) e <code>:3113</code> (viewer web com timeline e replay de sessão). Storage em SQLite + index vetorial em memória, zero dependência externa.</li>
<li>Um <strong>servidor MCP</strong> (<code>@agentmemory/mcp</code>) que qualquer agente compatível com MCP (Claude Code, Codex, opencode, Cursor, Gemini CLI, etc.) carrega como stdio server. Expõe 51 tools de memória (<code>memory_smart_search</code>, <code>memory_save</code>, <code>memory_sessions</code>, <code>memory_consolidate</code>, etc.).</li>
<li><strong>Plugins de hooks</strong> pra Claude Code (12 hooks) e Codex (6 hooks) que capturam observações automaticamente em cada tool call, prompt e evento de compaction.</li>
<li>Retrieval híbrida: <strong>BM25 + vetor + knowledge graph</strong>, fundidos com Reciprocal Rank Fusion (RRF, k=60), com diversificação por sessão.</li>
<li><strong>4-tier memory consolidation</strong> inspirada em como o cérebro humano processa memória durante o sono: Working (raw observations) → Episodic (resumos de sessão) → Semantic (fatos e padrões extraídos) → Procedural (workflows e padrões de decisão).</li>
</ul>
<p>A última parte é o que torna isso interessante. Não é só um log de tudo que aconteceu. Tem decay (Ebbinghaus curve — memórias que não são acessadas decaem), reforço (memórias acessadas frequentemente fortalecem), eviction de stale, detecção e resolução de contradições. É exatamente o que falta no padrão &ldquo;escrever em <code>./.docs/</code> manualmente&rdquo;.</p>
<h2>Instalação rápida<span class="hx:absolute hx:-mt-20" id="instalação-rápida"></span>
    <a href="#instala%c3%a7%c3%a3o-r%c3%a1pida" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Tem três jeitos: npm global, npx, ou (o que eu fiz) um prefixo dedicado pra fugir do mise/Node version churn. A versão one-liner do README do projeto:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">npm install -g @agentmemory/agentmemory     <span class="c1"># uma vez — `agentmemory` no PATH</span>
</span></span><span class="line"><span class="cl">agentmemory                                  <span class="c1"># sobe o daemon em :3111</span>
</span></span><span class="line"><span class="cl">agentmemory demo                             <span class="c1"># popula sessões de exemplo + valida recall</span>
</span></span><span class="line"><span class="cl">agentmemory connect claude-code              <span class="c1"># configura seu agente (também: codex, cursor, gemini-cli, ...)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Pra detalhes completos, o <a href="https://github.com/rohitg00/agentmemory#install"target="_blank" rel="noopener">README do agentmemory</a> cobre todas as variações (Docker, source build, Windows, embedding providers). Pra quem usa mise pra gerenciar Node, vale instalar num prefixo dedicado (algo como <code>~/.local/share/agentmemory-npm/</code>) e subir o daemon via systemd user unit pra fugir do problema de pacotes globais sumirem quando o mise troca de versão de Node. Mas o caminho do README serve a maioria dos casos.</p>
<p>Depois de subir o daemon, o passo principal é registrar o servidor MCP no agente que você usa.</p>
<p>Pro <strong>Claude Code</strong>, edite <code>~/.mcp.json</code>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;mcpServers&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;agentmemory&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="s2">&#34;/path/to/agentmemory-mcp&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;env&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;AGENTMEMORY_URL&#34;</span><span class="p">:</span> <span class="s2">&#34;http://localhost:3111&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Verifique com <code>claude mcp list</code>. Deve aparecer <code>agentmemory: ✓ Connected</code>.</p>
<p>Pro <strong>Codex CLI</strong>, edite <code>~/.codex/config.toml</code>:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">mcp_servers</span><span class="p">.</span><span class="nx">agentmemory</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">command</span> <span class="p">=</span> <span class="s2">&#34;/path/to/agentmemory-mcp&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="nx">mcp_servers</span><span class="p">.</span><span class="nx">agentmemory</span><span class="p">.</span><span class="nx">env</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">AGENTMEMORY_URL</span> <span class="p">=</span> <span class="s2">&#34;http://localhost:3111&#34;</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Pro <strong>opencode</strong>, edite <code>~/.config/opencode/opencode.json</code> e adicione na raiz do objeto:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;mcp&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;agentmemory&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;local&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;command&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;/path/to/agentmemory-mcp&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;enabled&#34;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;environment&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;AGENTMEMORY_URL&#34;</span><span class="p">:</span> <span class="s2">&#34;http://localhost:3111&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Depois disso, os três agentes compartilham o mesmo servidor de memória. Salvou uma decisão no Claude Code, faz <code>memory_smart_search</code> no Codex e ela aparece.</p>
<p>Pra forçar o agente a consultar memória no início de tarefas não-triviais, vale adicionar uma linha no <code>CLAUDE.md</code> (ou equivalente):</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>At the start of non-trivial tasks, call `memory_smart_search` with the task
keywords. Use `memory_save` or `memory_lesson_save` when capturing decisions,
patterns, or preferences worth keeping.</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Caso contrário o agente usa as tools quando achar que faz sentido, mas vai esquecer em sessões puramente exploratórias.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/05/18/memoria-agentes/agentmemory-traces.png" alt="Console iii do agentmemory mostrando waterfall de traces de uma sessão: cada operação (smart-search, save, recall, consolidate) ao longo do tempo, com latências e relações entre chamadas."  loading="lazy" /></p>
<h2>Vantagem prática: handoff sem fricção<span class="hx:absolute hx:-mt-20" id="vantagem-prática-handoff-sem-fricção"></span>
    <a href="#vantagem-pr%c3%a1tica-handoff-sem-fric%c3%a7%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Aqui mora a coisa que mais me convenceu. Lembra do padrão de export-pra-markdown que descrevi antes, pra migrar entre agentes? Com agentmemory, isso fica automático. Salvou uma decisão arquitetural numa sessão de Claude Code (<code>memory_save type=architecture content=&quot;usamos cookie store em vez de session store porque X&quot;</code>). Abre o opencode no mesmo projeto. Pergunta sobre persistência de sessão. O opencode chama <code>memory_smart_search</code>, recupera a entrada, e parte daí.</p>
<p>Esquece o &ldquo;exportar pra markdown, abrir o outro agente, mandar ler&rdquo;. Os dois agentes lêem do mesmo lugar. Vendor lock perde o sentido nesse setup, porque a fonte da memória é externa a ambos.</p>
<h2>Os trade-offs que ficam<span class="hx:absolute hx:-mt-20" id="os-trade-offs-que-ficam"></span>
    <a href="#os-trade-offs-que-ficam" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Não é mágica. Algumas coisas pra ter na cabeça:</p>
<p>A camada de embedding ideal é uma API paga (Voyage, OpenAI, Cohere). Sem isso o agentmemory usa MiniLM local via <code>@xenova/transformers</code>, que funciona mas é mais lento na primeira ingest e menos acurado em buscas semânticas complexas. Pra quem aceita rodar um modelo local, é solução real. Pra quem quer máxima qualidade de recall, vale a chave de API.</p>
<p>O daemon roda como processo permanente. Precisa de um systemd unit (eu rodo em user mode) ou launchd no macOS. Não é &ldquo;rode o servidor quando lembrar&rdquo; — tem que estar sempre up, senão os hooks do plugin perdem eventos.</p>
<p>A consolidação de 4 tiers usa um LLM pra processar. Sem chave de provider configurada, o agentmemory roda em &ldquo;no-op mode&rdquo; — ainda indexa observações e busca, mas não comprime nem consolida. Você ainda tem o equivalente da wiki, só que sem o &ldquo;lint periódico&rdquo; do Karpathy.</p>
<p>E como toda ferramenta nova, a documentação tem buracos. Algumas coisas pra ficar de olho que não estão no README upstream: o state path real depende de como o daemon é iniciado (relativo ao cwd), a porta <code>49134</code> do iii engine bindeia em <code>0.0.0.0</code> por default (passa pelo firewall, vale conferir), o <code>import-jsonl</code> não respeita o flag <code>--dry-run</code> apesar de o help global dizer que sim. Vale ler o README do projeto antes, e estar disposto a debugar quando a docs falhar.</p>
<h2>Memória é texto. Texto precisa de gestão.<span class="hx:absolute hx:-mt-20" id="memória-é-texto-texto-precisa-de-gestão"></span>
    <a href="#mem%c3%b3ria-%c3%a9-texto-texto-precisa-de-gest%c3%a3o" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A síntese que eu tiro disso tudo é simples. Memória de agente, no fundo, é texto. Não tem schema proprietário, não tem formato binário, não tem state secreto. Isso é libertador: você não fica preso a um vendor, pode mover entre Claude Code, Codex e opencode na hora que quiser, manualmente ou via uma camada externa como o agentmemory.</p>
<p>Mas texto solto vira lixo rápido. Sem compaction, a janela de contexto enche e o agente fica lento e caro. Com compaction, perde-se memória de longo prazo. Sem disciplina de salvar em arquivos, decisões importantes evaporam na próxima compaction. Sem estrutura nos arquivos, eles viram um amontoado que o agente nem consegue ler eficientemente.</p>
<p>A solução é uma combinação de quatro camadas:</p>
<ul>
<li><strong>Compaction</strong> resolve o problema de janela de contexto cheia. Os três grandes (Claude Code, Codex, opencode) fazem isso sozinhos.</li>
<li><strong>Markdown manual em <code>./.docs/</code> ou <code>./docs/</code></strong> é o fallback de base que sempre funciona, com a desvantagem de exigir disciplina do programador.</li>
<li><strong>Padrão LLM Wiki</strong> (Karpathy) eleva o markdown manual a um workflow estruturado: source / wiki / schema, com ingest / query / lint.</li>
<li><strong>agentmemory</strong> (ou ferramentas similares via MCP) automatiza a wiki, adiciona consolidação em tiers, retrieval híbrida, lifecycle de memória, e como bônus serve os três agentes do mesmo daemon.</li>
</ul>
<p>A parte mais subestimada disso tudo é o efeito composto. Uma decisão arquitetural salva hoje fica disponível pra todas as sessões futuras, em qualquer agente. Uma pegadinha de biblioteca descoberta na terça-feira não precisa ser re-descoberta no domingo. É o tipo de produtividade que demora algumas semanas pra aparecer (porque você precisa de massa crítica de memórias salvas), mas que muda o jogo quando engata.</p>
<p>Vale testar. Se você usa Claude Code, Codex ou opencode todo dia e nunca configurou nada de memória de longo prazo, comece pelo simples (um <code>./.docs/</code> no repo atual). Quando bater a frustração da terceira &ldquo;explicação que eu já dei&rdquo;, aí instala o agentmemory.</p>
]]></content:encoded><category>ai-memory</category><category>agentes-de-codigo</category><category>llms</category></item></channel></rss>