Claude Code com memória: como automatizei meu segundo cérebro no Obsidian
Todo segundo cérebro morre do mesmo jeito. Vira um lugar onde você escreve e nunca mais volta.
Costumam dizer que isso é falta de disciplina. Não é. O problema está no desenho. Escrever a nota custa no pior momento possível, logo depois que você resolveu o problema e só quer seguir em frente. E o retorno vem meses depois, num dia que você não tem como prever.
Duas mudanças resolveram isso pra mim. Nenhuma das duas foi organizar melhor as pastas.
A primeira: eu deixei de ser o leitor do cofre. Quem lê agora é o agente, no começo de cada sessão e de novo a cada pedido, sem eu mandar.
A segunda é a que segura o resto. O agente não consegue fechar a sessão sem escrever no cofre. Se a sessão mexeu em src/ e não registrou nada, o encerramento trava.
O que eu descrevo aqui é o cofre do front-end de onde nascem os outros sistemas. São 55 notas, duas camadas, três hooks e umas 1.700 linhas de script sem nenhuma dependência externa. Vou mostrar as decisões que não são óbvias.
1. Duas camadas e uma pergunta só
O cofre tem duas pastas na raiz. A divisão não é para organizar. É para sobreviver a uma cópia.
As duas camadas, vistas no copia-e-cola
55 notaso cofre onde ele nasceu
Em cima, o guia de desenvolvimento. Embaixo, o sistema inteiro descrito: o que o produto faz, como está construído, as regras que atravessam telas, o comportamento de cada tela e o porquê de cada decisão. Cada pasta é fonte de verdade de uma coisa só, para a mesma regra não acabar escrita em dois lugares.
- Nucleo/o guia de desenvolvimento
- Projeto/tudo sobre este sistema
Nucleo/ é o guia de desenvolvimento. Como as coisas devem ser feitas e por quê: princípios, arquitetura, qualidade, segurança, acessibilidade, plataforma web, metodologia, trabalho com IA, padrões de tela. Mais os adaptadores, que traduzem as regras para a stack concreta, e os templates. O Núcleo não fala do seu sistema. Ele fala de como construir qualquer sistema.
Projeto/ é o seu sistema. Tudo o que é verdade sobre aquele repositório e não sobrevive à cópia. O que o produto faz e para quem, como ele está construído, as regras de negócio que atravessam telas, o comportamento de cada tela, e o porquê de cada decisão estrutural. Não é um anexo de documentação, é a descrição do sistema inteiro.
Cada pasta ali é fonte de verdade de uma coisa só, e isso é de propósito. Uma regra escrita em dois lugares diverge, é questão de tempo, e aí ninguém sabe qual das duas o código seguiu. Na prática a separação que mais importa é essa: regra que vale só naquela tela (paginação, ordem dos campos, texto do estado vazio) fica em Especificações/. Regra que continua verdadeira fora da tela (estoque baixo, unicidade, elegibilidade, preço) fica em Domínio/, e as telas apontam para lá. Em sistema complexo a maior parte das regras que importam é do segundo tipo. Sem essa separação, a mesma regra acaba escrita em quatro especificações.
Tem também uma fronteira do lado de fora, que vale dizer. O cofre registra o que é verdade sobre o produto e por quê. O que ainda não é, como backlog, prioridade e estimativa, fica no rastreador de trabalho do time. É informação de validade curta, que envelhece rápido e cujo dono é outro.
Para saber em qual das duas camadas uma nota mora, eu faço uma pergunta só. Isso continuaria verdadeiro em outro projeto?
Vai para Nucleo/ | Vai para Projeto/ |
|---|---|
| "Token de sessão fora do alcance de JS" | "Nosso login usa o SSO do cliente" |
| "Lista CRUD precisa de estado vazio" | "A tela de Produtos filtra por categoria e status" |
| "Dependência entra por decisão" | "Escolhemos Pinia; o ADR-002 explica" |
Na dúvida, começa em Projeto/. Promover depois é barato. O caminho contrário é caro: para tirar do Núcleo alguma coisa que era específica de um projeto, você precisa descobrir quantos projetos já copiaram aquilo.
E a divisão existe por causa da cópia. Quando um projeto novo nasce, o Nucleo/ vai junto inteiro e o Projeto/ chega vazio, para ser preenchido do zero. Sem essa fronteira você não sabe o que preservar, e o cofre acaba preso ao repositório onde nasceu.
2. Quando duas fontes discordam, quem manda
Essa é a nota mais importante do cofre, e eu nunca vi ela em tutorial de segundo cérebro. Ela responde uma pergunta que aparece toda semana.
A ordem é essa:
- Restrição legal ou contratual. LGPD, contrato de cliente, exigência de auditoria.
- O repositório real.
package.json, lockfile, configuração, o código que já está escrito. Projeto/. As decisões deste projeto, os ADRs, as especificações de tela.Nucleo/. A base geral.
Veja que o cofre ficou em último. Um cofre que se acha mais verdadeiro que o package.json gera o pior tipo de erro, aquele que vem com jeito de documentação oficial.
Junto com a ordem vem a regra que faz ela funcionar:
Divergência entre níveis é para ser exposta, nunca resolvida por suposição.
Se o Núcleo assume Vue 3 e o repositório está em Vue 2, a resposta certa é "o cofre assume Vue 3, o repositório está em Vue 2, como você quer seguir?". Não é aplicar a regra às cegas, e também não é escolher sozinho.
Isso vale até quando o pedido é bom e quem está errado é uma regra velha. Nesse caso o que muda é a regra, e a mudança fica registrada. O que não pode é a regra ser contrariada em silêncio.
Quando a mesma divergência aparece várias vezes, significa uma coisa só. O cofre está desatualizado. Aí conserta o cofre.
3. O cofre se consulta sozinho
Aqui está a parte que transforma pasta de notas em sistema. São três hooks, guardados em Cofre/_bin/, que fazem a consulta acontecer sem ninguém precisar lembrar dela.
Os três hooks, na linha do tempo de uma sessão
Cofre/_bin/Regenera o INDICE.md e injeta o protocolo mais o mapa do cofre, com os títulos agrupados por área. Não é o índice inteiro. Roda uma vez só por sessão, porque o mapa quase não muda e pagar por ele a cada pedido seria desperdício.
Eles moram dentro do cofre, e não em .claude/hooks/. Isso é de propósito. Se morassem fora, o cofre chegaria mudo no projeto novo. Tudo em CommonJS sem dependência externa, para rodar no destino sem npm install e sem depender do type do package.json de lá.
Para ligar num projeto:
{
"hooks": {
"SessionStart": [{ "hooks": [{ "type": "command", "command": "node", "args": ["${CLAUDE_PROJECT_DIR}/Cofre/_bin/hook-sessao.cjs"], "timeout": 15 }] }],
"UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "node", "args": ["${CLAUDE_PROJECT_DIR}/Cofre/_bin/hook-prompt.cjs"], "timeout": 15 }] }],
"Stop": [{ "hooks": [{ "type": "command", "command": "node", "args": ["${CLAUDE_PROJECT_DIR}/Cofre/_bin/hook-registro.cjs"], "timeout": 15 }] }]
}
}
O que me custou uma reescrita foi o orçamento de contexto. A tentação é jogar o índice inteiro no começo da sessão, afinal é só texto. Mas o índice completo custa uns 42 tokens por nota, e cresce em linha reta.
| Notas | Índice completo | Mapa por área |
|---|---|---|
| 100 | ~4.600 tokens | ~1.400 |
| 250 | ~10.900 | ~2.900 |
| 400 | ~17.100 | ~4.400 |
Com 250 notas seriam quase 11 mil tokens gastos antes de qualquer trabalho começar. Ou seja, o cofre ficaria caro justo quando ficasse útil. Por isso a sessão recebe só o mapa agrupado por área, a uns 10 tokens por nota. A busca fina fica com o hook de prompt.
4. O campo quando: é a busca da nota
Toda nota tem frontmatter, e ele não é enfeite.
---
title: "Autenticação e Sessão no Cliente"
tipo: regra
status: ativo
quando: "Ao implementar login, logout, renovação de sessão, guarda de rota
autenticada, integração OAuth/OIDC, ou ao decidir onde guardar token."
tags: [segurança, sessão, autenticação, REG-SEC-003]
atualizado: 2026-09-08
---
O campo quando: é o que diz para a máquina se aquela nota serve para o pedido. Nota sem tag própria é nota que a máquina não acha. Ela existe, está bonita, e nunca entra no contexto.
A cada pedido o hook procura evidência de que alguma nota é relevante. Achando, injeta a nota inteira, no máximo duas.
| Evidência | Peso | Exemplo |
|---|---|---|
| Código de regra citado, declarado nas tags da nota | 100 | "aplicar REG-SEC-003" |
| Título da nota citado no pedido | 80 | "sobre Armazenamento no Navegador" |
| Tag citada como palavra inteira | 40+ | "trato xss como?" |
Sem evidência, não entra nada. E isso é o certo, não uma limitação. O agente já recebeu o mapa no começo da sessão e decide sozinho o que abrir com Read.
O que entra no contexto, e o que não entra
hook-prompt.cjsaplicar REG-SEC-003 no interceptador do axios
Autenticação e Sessão no Cliente tags: [segurança, sessão, autenticação, REG-SEC-003] → nota inteira
match forte
É a evidência mais forte que existe. O código de regra só conta quando está nas tags da nota, nunca no corpo. Se procurasse no corpo, ia casar qualquer nota que cita o código como exemplo no meio do texto, e você receberia a nota que fala da regra em vez da que define a regra.
Duas decisões dessa máquina cortaram o ruído que derrubou a versão anterior dela. As duas parecem erradas na primeira leitura.
Código de regra só vale nas tags, nunca no corpo. Se procurasse no corpo, ia casar qualquer nota que cita o código como exemplo no meio do texto. Você acabaria injetando a nota que fala da regra em vez da que define a regra.
Tag que aparece em mais de um quinto das notas é jogada fora. A tag segurança está em 14 das 55 notas. Casar por ela traria uma nota qualquer da área 04 no lugar da certa. Tag que aparece em tudo não ajuda a escolher nada.
Tem também um verificar.cjs que sai com código 1 no CI. Ele separa o que é problema do que é só chatice. Nota isolada, que ninguém alcança navegando, é problema, porque ela só vai ser lida por acidente. O caso mais comum é a nota de contrato de área, justo a que precisa ser lida primeiro por quem for preencher aquela área. Nota sem quando: é problema grave. Já nota que não aponta para ninguém não é problema nenhum. Template é folha por natureza, e grafo cheio de linha não é grafo saudável.
5. O hook que trava o encerramento
Essa é a parte que faz o cofre aprender em vez de só guardar.
Na hora de encerrar, o hook-registro lê o transcript da sessão. Se teve escrita em src/ ou cypress/ e nenhuma em Cofre/Projeto/, ele devolve decision: "block" mandando registrar antes de sair. E ainda diz onde escrever, dependendo do que mudou:
- Comportamento de tela novo ou alterado → Cofre/Projeto/Especificações/<Tela>.md
- Decisão técnica estrutural ou não óbvia → Cofre/Projeto/Decisões/ADR-NNN — <título>.md
- Regra de negócio que vale em mais de uma tela → Cofre/Projeto/Domínio/
O motivo de isso funcionar é simples. Quem escreve é o modelo que ainda tem o contexto. Não é uma segunda passada de IA lendo diff frio. É o mesmo agente, na mesma sessão, com a conversa toda ainda carregada. É o único momento em que escrever a nota sai barato.
Três limites deixam essa escrita automática reversível, e eu não ligaria o hook sem os três.
Bloco delimitado. Em nota que já existe, a automação só escreve entre os marcadores. Texto fora do bloco ela não toca.
<!-- cofre:auto:inicio -->
...conteúdo mantido automaticamente...
<!-- cofre:auto:fim -->
Teto de 400 linhas por nota de Projeto/, conferido a cada parada. Passou disso, o hook manda consolidar antes de acrescentar. Sem esse teto, escrita automática vira pilha de nota, que é a mesma doença do vault abandonado, só que mais rápida.
Tudo em Git. Toda escrita automática vira um diff que eu reviso ou reverto. Sem isso não é memória, é alucinação acumulada.
Tem ainda uma trava de loop. Com stop_hook_active, o hook não bloqueia duas vezes na mesma parada.
E tem uma escolha que vale contar, porque o custo dela não aparece. Todos os hooks são fail-open. Qualquer erro é engolido e o trabalho segue, porque hook que quebra e trava o usuário é pior que hook nenhum. A consequência é que, se um hook parar de funcionar, ele falha calado. O cofre simplesmente deixa de ser consultado e ninguém percebe. Por isso existe um diagnóstico manual:
echo '{}' | node Cofre/_bin/hook-sessao.cjs
echo '{"prompt":"como trato xss?"}' | node Cofre/_bin/hook-prompt.cjs
node Cofre/_bin/verificar.cjs
6. Como o cofre aprende enquanto o projeto muda
O ciclo tem quatro tempos, e só o segundo é automático.
O ciclo, passo a passo
passo 1 de 4A sessão mexe no código
Uma tela ganhou regra nova. Até aqui esse conhecimento existe num lugar só, que é a conversa prestes a ser fechada.
- src/o que roda
- Projeto/tudo sobre este sistema
- Nucleo/o guia de desenvolvimento
O terceiro tempo é onde o sistema para de acumular e começa a aprender. Promover de Projeto/ para Nucleo/ faz um conhecimento sair do fim do processo e voltar para a base que todo projeto novo recebe.
Antes disso tem uma peça que cuida do envelhecimento. O deriva.cjs compara a data em atualizado: com o histórico do Git dos arquivos que a nota diz cobrir. Se o código mudou depois da nota, ela provavelmente está velha. E nota que mente é pior que nota que não existe, porque parece autoridade.
O importante é o que a ferramenta afirma:
Não é prova de erro. É prova de que ninguém verificou.
Pode ter sido refatoração sem mudança de comportamento. A deriva não acusa a nota de estar errada. Acusa de não ter sido conferida, que é uma afirmação que a máquina consegue fazer com honestidade. Ela só aponta erro de verdade quando um arquivo que a nota declara não existe mais. Aí a tela sumiu ou foi renomeada, e a nota ficou para trás.
O que eu levo daqui
- Segundo cérebro não é onde você escreve. É o que é lido antes de decidir e escrito antes de encerrar.
- O cofre é a última autoridade, não a primeira. Antes dele vêm a lei, o repositório real e as decisões do projeto.
- Divergência é para expor, não para resolver no chute. E divergência repetida quer dizer cofre desatualizado.
quando:etags:são a busca da nota. Sem elas, a nota existe e nunca é encontrada.- Injetar sem evidência é ruído. E ruído com cara de fonte é pior que silêncio.
- Automatize a cobrança do registro. A curadoria, não.
Se você for montar algo assim, não comece pelas 55 notas. Comece pelo hook de Stop e uma pasta só. É a obrigação de registrar antes de encerrar que gera as notas. A estrutura aparece depois, com o formato que o seu trabalho pediu, e não com o que um tutorial adivinhou.
No post sobre agentes autônomos eu separei memória de curto prazo, semântica e episódica. O cofre é as duas últimas morando fora do agente, em arquivo de texto versionado que eu leio, revejo e corrijo. Se eu trocar de ferramenta amanhã, a memória continua minha.
Uma pergunta que me interessa de verdade. Você deixaria um hook travar o encerramento da sua sessão? Eu deixei, e desconfio que a resposta muda conforme o tamanho do time. Me escreve, o contato está no rodapé.
