obsidian:~/vault$ search --hybrid obsidian

Localização do vault de exemplo

# Obsidian como infraestrutura de IA: a referência técnica definitiva

words: 14331 read_time: 55m updated: 2026-04-16 20:47
$ retriever search --hybrid obsidian

Principais conclusões

Engenharia de contexto, não anotações. O valor de um vault do Obsidian para IA não são as notas em si, mas a camada de recuperação que as torna consultáveis. Um vault com 16.000 arquivos sem recuperação é um banco de dados somente escrita. Um vault com 200 arquivos com busca híbrida e integração MCP é uma base de conhecimento para IA. A infraestrutura de recuperação é o produto. As notas são a matéria-prima.

Recuperação híbrida supera busca puramente por palavras-chave ou puramente semântica. BM25 captura identificadores exatos e nomes de funções. Busca vetorial captura sinônimos e correspondências conceituais entre terminologias diferentes. Reciprocal Rank Fusion (RRF) combina ambos sem exigir calibração de pontuação. Nenhum método isolado cobre ambos os modos de falha. Pesquisas sobre MS MARCO passage ranking confirmam o padrão: recuperação híbrida consistentemente supera qualquer método isolado.3 O aprofundamento sobre o recuperador híbrido cobre a matemática do RRF, exemplos práticos com números reais, análise de modos de falha e uma calculadora interativa de fusão.

MCP dá às ferramentas de IA acesso direto ao vault. Servidores Model Context Protocol (MCP) expõem o recuperador como uma ferramenta que Claude Code, Codex CLI, Cursor e outras ferramentas de IA podem chamar diretamente. O agente consulta o vault, recebe resultados ranqueados com atribuição de fonte e usa o contexto sem carregar arquivos inteiros. O servidor MCP é um wrapper fino sobre o motor de recuperação.

Local-first significa zero custos de API e privacidade total. Toda a stack roda em uma única máquina: SQLite para armazenamento, Model2Vec para embeddings, FTS5 para busca por palavras-chave, sqlite-vec para KNN vetorial. Sem serviços em nuvem, sem chamadas de API, sem dependência de rede. Notas pessoais nunca saem da máquina. O re-embedding completo de 49.746 chunks custaria aproximadamente US$ 0,30 nos preços de API da OpenAI, mas os custos reais são latência, exposição de privacidade e a dependência de rede para um sistema que deveria funcionar offline.4

Indexação incremental mantém o sistema atualizado em menos de 10 segundos. A comparação do tempo de modificação dos arquivos detecta mudanças. Apenas arquivos modificados são re-fragmentados e re-embedded. Uma reindexação completa leva cerca de quatro minutos em hardware Apple M-series. Atualizações incrementais das edições de um dia típico rodam em menos de dez segundos. O sistema se mantém atualizado sem intervenção manual.

A arquitetura escala de 200 a mais de 20.000 notas. O mesmo design de três camadas (ingestão, recuperação, integração) funciona em qualquer tamanho de vault. Comece com busca apenas BM25 em um vault pequeno. Adicione busca vetorial quando colisões de palavras-chave se tornarem um problema. Adicione fusão RRF quando precisar de correspondências exatas e semânticas. Cada camada é independentemente útil e independentemente removível.


Como usar este guia

Este guia cobre o sistema completo. Seu ponto de partida depende de onde você está:

Você é… Comece aqui Depois explore
Novo no Obsidian + IA Por que Obsidian para infraestrutura de IA, Início rápido Arquitetura do vault, Arquitetura do servidor MCP
Vault existente, quer acesso por IA Arquitetura do servidor MCP, Integração com Claude Code Modelos de embedding, Busca full-text com FTS5
Construindo um sistema de recuperação O pipeline completo de recuperação, Reciprocal Rank Fusion Ajuste de desempenho, Solução de problemas
Contexto de equipe ou empresarial Framework de decisão, Padrões de grafo de conhecimento Receitas de workflow para desenvolvedores, Guia de migração

Seções marcadas como Contrato incluem detalhes de implementação, blocos de configuração e modos de falha. Seções marcadas como Narrativa focam em conceitos, decisões de arquitetura e o raciocínio por trás das escolhas de design. Seções marcadas como Receita fornecem workflows passo a passo.


Por que Obsidian para infraestrutura de IA

A tese deste guia: Vaults do Obsidian são o melhor substrato para bases de conhecimento pessoais de IA porque são local-first, em texto puro, estruturados em grafo, e o usuário controla cada camada da stack.

O que o Obsidian oferece à IA que alternativas não oferecem

Arquivos markdown em texto puro. Cada nota é um arquivo .md no seu sistema de arquivos. Sem formato proprietário, sem exportação de banco de dados, sem API necessária para ler o conteúdo. Qualquer ferramenta que lê arquivos pode ler seu vault. grep, ripgrep, pathlib do Python, SQLite FTS5 — todos funcionam diretamente nos arquivos fonte. Quando você constrói um sistema de recuperação, está indexando arquivos, não respostas de API. O índice é sempre consistente com a fonte porque a fonte é o sistema de arquivos.

Arquitetura local-first. O vault reside na sua máquina. Sem servidor, sem dependência de sincronização em nuvem, sem limites de taxa de API, sem termos de serviço governando como você processa seu próprio conteúdo. Você pode gerar embeddings, indexar, fragmentar e buscar suas notas sem nenhum serviço externo. Isso importa para infraestrutura de IA porque o pipeline de recuperação roda tão rápido quanto seu disco permite, não tão rápido quanto um endpoint de API responde. Também importa para privacidade: notas pessoais contendo credenciais, dados de saúde, informações financeiras e reflexões privadas nunca saem da sua máquina.

Estrutura de grafo através de wiki-links. A sintaxe [[wiki-link]] do Obsidian cria um grafo direcionado entre notas. Uma nota sobre implementação de OAuth linka para notas sobre rotação de tokens, gerenciamento de sessões e segurança de API. A estrutura de grafo codifica relacionamentos curados por humanos entre conceitos. Embeddings vetoriais capturam similaridade semântica, mas wiki-links capturam conexões intencionais que o autor fez enquanto pensava sobre o tema. O grafo é um sinal que embeddings não conseguem replicar.

Ecossistema de plugins. O Obsidian tem mais de 2.500 plugins da comunidade (em março de 2026, contra mais de 1.800 em meados de 2025). Dataview consulta seu vault como um banco de dados. Templater gera notas a partir de templates com lógica JavaScript. Integração com Git sincroniza seu vault com um repositório. Linter garante consistência de formatação. O plugin core Bases (introduzido na v1.9.10) adiciona visualizações tipo banco de dados — tabelas, galerias, calendários e quadros kanban — sobre arquivos do vault usando propriedades do frontmatter como campos, salvos como arquivos .base.27 Esses plugins adicionam estrutura ao vault sem alterar o formato texto puro subjacente. O sistema de recuperação indexa a saída desses plugins, não os plugins em si.

Mais de 5 milhões de usuários. O Obsidian tem uma grande comunidade ativa produzindo templates, workflows, plugins e documentação. Quando você encontra um problema com organização do vault ou configuração de plugins, alguém provavelmente já documentou uma solução. A comunidade também produz ferramentas adjacentes ao Obsidian: servidores MCP, scripts de indexação, pipelines de publicação e wrappers de API.

O que um sistema de arquivos sozinho não oferece

Um diretório de arquivos markdown tem a vantagem do texto puro, mas carece de três coisas que o Obsidian adiciona:

  1. Links bidirecionais. O Obsidian rastreia backlinks automaticamente. Quando você linka da Nota A para a Nota B, a Nota B mostra que a Nota A a referencia. O painel de grafo visualiza clusters de conexão. Essa consciência bidirecional é metadado que um sistema de arquivos puro não fornece.

  2. Pré-visualização ao vivo com renderização de plugins. Consultas Dataview, diagramas Mermaid e blocos de destaque renderizam em tempo real. A experiência de escrita é mais rica que um editor de texto enquanto o formato de armazenamento permanece texto puro. Você escreve e organiza em um ambiente rico; o sistema de recuperação indexa o markdown bruto.

  3. Infraestrutura da comunidade. Descoberta de plugins, marketplace de temas, serviço de sincronização (opcional), serviço de publicação (opcional) e um ecossistema de documentação. Você pode replicar qualquer recurso individual com ferramentas independentes, mas o Obsidian os empacota em um workflow coerente.

O que o Obsidian NÃO faz (e o que você constrói)

O Obsidian não inclui infraestrutura de recuperação. Ele tem busca básica (full-text, nome de arquivo, tag), mas nenhum pipeline de embedding, nenhuma busca vetorial, nenhum ranking por fusão, nenhum servidor MCP, nenhuma filtragem de credenciais, nenhuma estratégia de chunking e nenhum hook de integração para ferramentas de IA externas. Este guia cobre a infraestrutura que você constrói sobre o Obsidian. O vault é o substrato. O pipeline de recuperação, o servidor MCP e os hooks de integração são a infraestrutura.

A arquitetura descrita aqui é markdown-first, não exclusiva do Obsidian. Se você usa Logseq, Foam, Dendron ou um diretório simples de arquivos markdown, o pipeline de recuperação funciona de forma idêntica. O fragmentador lê arquivos .md. O gerador de embeddings processa strings de texto. O indexador escreve no SQLite. Nenhum desses componentes depende de recursos específicos do Obsidian. A contribuição do Obsidian é o ambiente de escrita e organização que produz os arquivos markdown que o recuperador indexa.


Início rápido: Primeiro vault conectado a IA

Esta seção conecta um vault a uma ferramenta de IA em cinco minutos. Você vai instalar o Obsidian, criar um vault, instalar um servidor MCP e executar sua primeira consulta. O início rápido usa um servidor MCP da comunidade para resultados imediatos. As seções posteriores cobrem a construção de um pipeline de recuperação personalizado para uso em produção.

Pré-requisitos

  • macOS, Linux ou Windows
  • Node.js 18+ (para o servidor MCP)
  • Obsidian 1.12+ (para integração com CLI; versões anteriores funcionam para configurações apenas com MCP)
  • Claude Code, Codex CLI ou Cursor instalado

Passo 1: Crie um vault

Baixe o Obsidian em obsidian.md e crie um novo vault. Escolha um local que você vai lembrar — o servidor MCP precisa do caminho absoluto.

# Example vault location
~/Documents/knowledge-base/

Adicione algumas notas para dar ao recuperador algo com que trabalhar. Mesmo 10-20 notas são suficientes para ver resultados. Cada nota deve ser um arquivo .md com um título significativo e pelo menos um parágrafo de conteúdo.

Passo 2: Instale um servidor MCP

Vários servidores MCP da comunidade fornecem acesso imediato ao vault. O ecossistema cresceu significativamente ao longo de 2025-2026. Atualizações recentes notáveis incluem o MCPVault v0.11.0 (março de 2026) que adicionou list_all_tags para escanear frontmatter e hashtags com contagens, melhorou o tratamento de pastas com pontos e adicionou suporte para arquivos .base e .canvas.25 O pacote também foi renomeado para @bitbonsai/mcpvault no npm.

Servidor Autor Transporte Requer Plugin Recurso principal
obsidian-mcp-server StevenStavrakis STDIO Não Leve, baseado em arquivos
mcp-obsidian MarkusPfundstein STDIO REST API local CRUD completo do vault via REST
obsidian-mcp-tools jacksteamdev STDIO Sim (plugin) Busca semântica + Templater
obsidian-claude-code-mcp iansinnott WebSocket Sim (plugin) Auto-descoberta para Claude Code
obsidian-mcp-server cyanheads STDIO REST API local Tags, gerenciamento de frontmatter

Para o início rápido, a opção mais simples é um servidor baseado em arquivos que lê arquivos .md diretamente:

npm install -g obsidian-mcp-server

Passo 3: Configure sua ferramenta de IA

Claude Code — adicione em ~/.claude/settings.json:

{
  "mcpServers": {
    "obsidian": {
      "command": "obsidian-mcp-server",
      "args": ["--vault", "/absolute/path/to/your/vault"]
    }
  }
}

Codex CLI — adicione em .codex/config.toml:

[mcp_servers.obsidian]
command = "obsidian-mcp-server"
args = ["--vault", "/absolute/path/to/your/vault"]

Cursor — adicione em .cursor/mcp.json:

{
  "mcpServers": {
    "obsidian": {
      "command": "obsidian-mcp-server",
      "args": ["--vault", "/absolute/path/to/your/vault"]
    }
  }
}

Passo 4: Execute sua primeira consulta

Abra sua ferramenta de IA e faça uma pergunta que as notas do seu vault possam responder:

Search my Obsidian vault for notes about [topic you wrote about]

A ferramenta de IA chama o servidor MCP, que pesquisa seu vault e retorna conteúdo correspondente. Você deve ver resultados com caminhos de arquivos e trechos relevantes.

O que você acabou de construir

Você conectou uma base de conhecimento local a uma ferramenta de IA através de um protocolo padrão. O servidor MCP lê os arquivos do seu vault, realiza busca básica e retorna resultados. Esta é a versão mínima viável.

O que este início rápido NÃO oferece: - Recuperação híbrida (BM25 + busca vetorial + fusão RRF) - Busca semântica baseada em embeddings - Filtragem de credenciais - Indexação incremental - Injeção automática de contexto baseada em hooks

O restante deste guia cobre a construção de cada uma dessas capacidades. O início rápido comprova o conceito. O pipeline completo entrega recuperação com qualidade de produção.


CLI do Obsidian para fluxos de trabalho com IA

O Obsidian 1.12 (fevereiro de 2026) introduziu uma interface de linha de comando integrada que abre uma nova superfície de integração para fluxos de trabalho com IA.28 O CLI funciona como um controle remoto para a GUI do Obsidian — o Obsidian precisa estar em execução (ou será iniciado automaticamente no primeiro comando). Habilite-o em Configurações > Geral > Interface de linha de comando.

Por que o CLI importa para infraestrutura de IA

O CLI fornece acesso programático a operações nativas do Obsidian que antes exigiam a GUI ou APIs de plugins. Para fluxos de trabalho com IA, as principais capacidades são:

  • Busca a partir de scripts e hooks. obsidian search "query" e obsidian search:context "query" executam buscas no vault a partir de qualquer shell script, hook ou pipeline de automação. A variante search:context retorna linhas correspondentes com contexto ao redor, útil para alimentar resultados em prompts de IA.
  • Automação de notas diárias. obsidian daily abre ou cria a nota diária de hoje. Combinado com shell scripting, isso permite fluxos de trabalho automatizados de briefing diário — um hook pode adicionar resumos gerados por IA à nota diária.
  • Criação de notas baseada em templates. obsidian template list e obsidian template create geram notas a partir de templates do Templater ou do core, permitindo que agentes de IA criem entradas estruturadas no vault sem escrever arquivos markdown diretamente.
  • Gerenciamento de propriedades. obsidian property set e obsidian property get leem e escrevem propriedades do frontmatter, permitindo atualizações de metadados a partir de scripts sem parsear YAML.
  • Controle de plugins. obsidian plugin enable/disable/list gerencia plugins programaticamente, útil para alternar plugins de indexação durante operações em lote.
  • Gerenciamento de tarefas. obsidian task list/add/complete fornece acesso estruturado a tarefas, útil para agentes de IA que gerenciam itens de trabalho no vault.

CLI vs MCP para acesso de IA

O CLI e os servidores MCP desempenham papéis diferentes e são complementares, não concorrentes:

Aspecto CLI do Obsidian Servidor MCP
Chamador Shell scripts, hooks, cron jobs Agentes de IA (Claude Code, Codex, Cursor)
Protocolo Processo POSIX (stdin/stdout/stderr) MCP (JSON-RPC sobre STDIO ou HTTP)
Ponto forte Operações nativas do Obsidian (templates, plugins, propriedades) Recuperação personalizada (embeddings, BM25, fusão RRF)
Limitação Sem busca vetorial, sem pipeline de embeddings Sem acesso a operações internas do Obsidian
Melhor para Scripts de automação, pipelines de ingestão, ações de hooks Consultas de agentes de IA em tempo real durante sessões

Recomendação: Use o CLI para automação de ingestão (criar notas, gerenciar propriedades, executar busca nativa do Obsidian) e MCP para recuperação (busca híbrida com embeddings). Um hook PreToolUse pode chamar obsidian search:context como uma pré-verificação rápida antes de recorrer ao recuperador MCP completo para resultados ranqueados.

Exemplo: hook de ingestão com CLI

#!/bin/bash
# Hook: append today's signals to daily note via CLI
DATE=$(date +%Y-%m-%d)
SUMMARY="$1"
obsidian daily  # ensure daily note exists
obsidian file append "Daily Notes/${DATE}.md" "## AI Summary\n${SUMMARY}"

Plugins de agentes para Obsidian

Uma categoria crescente de plugins do Obsidian incorpora agentes de codificação com IA diretamente na interface do vault, fornecendo uma alternativa à configuração de servidores MCP externos. Esses plugins executam o agente de IA dentro da barra lateral do Obsidian em vez de conectar a partir de uma ferramenta externa.

Claudian

Claudian incorpora o Claude Code como um colaborador de IA no vault. O diretório do vault se torna o diretório de trabalho do Claude, dando a ele capacidades agênticas completas: leitura/escrita de arquivos, busca, comandos bash e fluxos de trabalho com múltiplas etapas.29

Recursos principais para infraestrutura de IA: - Prompts com reconhecimento de contexto. Anexa automaticamente a nota em foco, suporta menções de arquivos com @notename, exclusão baseada em tags e seleção do editor como contexto. - Suporte a visão. Analise imagens via arrastar e soltar, colar ou caminho de arquivo — útil para processar capturas de tela e diagramas capturados no vault. - Comandos slash. Crie templates de prompts reutilizáveis acionados por /command, permitindo operações padronizadas no vault. - Modos de permissão. Modos YOLO (aprovação automática), Safe (aprovar cada ação) e Plan (apenas planejamento) com lista de bloqueio de segurança e confinamento ao vault.

Agent Client

Agent Client traz Claude Code, Codex CLI e Gemini CLI para uma barra lateral unificada do Obsidian via Agent Client Protocol (ACP).30

Recursos principais: - Alternância entre múltiplos agentes. Converse com Claude Code, Codex ou Gemini CLI no mesmo painel, alternando entre agentes conforme necessário. - Menções de notas. Use @notename para incluir conteúdos de notas nos prompts, similar ao Claudian porém agnóstico em relação ao agente. - Execução de shell. Execute comandos de terminal inline no chat — scripts de build, comandos git ou qualquer operação de terminal sem sair da conversa. - Aprovação de ações. Controle granular sobre leituras de arquivos, edições e execuções de comandos.

Quando usar plugins de agentes vs MCP externo

Cenário Plugin de agente MCP externo
Escrever e editar notas do vault com assistência de IA Melhor — o agente vê o contexto do editor Funciona, mas sem reconhecimento do editor
Desenvolvimento de código em múltiplos repositórios Limitado — escopo restrito ao vault Melhor — escopo do projeto com acesso completo ao sistema de arquivos
Recuperação de um grande corpus indexado Apenas busca básica Pipeline completo de recuperação híbrida
Perguntas rápidas ao vault durante sessões de anotação Ideal — sem troca de contexto Requer alternar para o terminal

Recomendação: Use plugins de agentes para fluxos de trabalho centrados no vault (escrever, organizar, resumir notas). Use servidores MCP externos para fluxos de trabalho de desenvolvimento onde o agente de IA precisa do pipeline completo de recuperação e acesso a repositórios fora do vault. As duas abordagens podem coexistir — execute o Claudian dentro do Obsidian para trabalho com notas e Claude Code com MCP externamente para desenvolvimento.


Framework de decisão: Obsidian vs alternativas

Nem todo caso de uso precisa do Obsidian. Esta seção mapeia quando o Obsidian é o substrato certo, quando é exagero e quando outra ferramenta se encaixa melhor.

Árvore de decisão

START: What is your primary content type?

├─ Structured data (tables, records, schemas)
   Use a database. SQLite, PostgreSQL, or a spreadsheet.
   Obsidian is for prose, not tabular data.

├─ Ephemeral context (current project, temporary notes)
   Use CLAUDE.md / AGENTS.md in the project repo.
   These travel with the code and reset per project.

├─ Team wiki (shared documentation, onboarding)
   Evaluate Notion, Confluence, or a shared git repo.
   Obsidian vaults are personal-first. Team sync is possible
    but not native.

└─ Growing personal knowledge corpus
   
   ├─ < 50 notes
      A folder of markdown files + grep is sufficient.
      Obsidian adds value mainly through the link graph,
       which needs density to be useful.
   
   ├─ 50 - 500 notes
      Obsidian adds value. Wiki-links create a navigable graph.
      BM25-only search (FTS5) is sufficient at this scale.
      Skip vector search and RRF until keyword collisions appear.
   
   ├─ 500 - 5,000 notes
      Full hybrid retrieval becomes valuable. Keyword collisions
       increase. Semantic search catches queries that BM25 misses.
      Add vector search + RRF fusion at this scale.
   
   └─ 5,000+ notes
       Full pipeline is essential. BM25-only returns too much noise.
       Credential filtering becomes critical (more notes = more
        accidentally pasted secrets).
       Incremental indexing matters (full reindex takes minutes).
       MCP integration pays dividends on every AI interaction.

Matriz de comparação

Critério Obsidian Notion Apple Notes Sistema de arquivos CLAUDE.md
Local-first Sim Não (nuvem) Parcial (iCloud) Sim Sim
Texto puro Sim (markdown) Não (blocos) Não (proprietário) Sim Sim
Estrutura em grafo Sim (wiki-links) Parcial (menções) Não Não Não
Indexável por IA Acesso direto aos arquivos API necessária Exportação necessária Acesso direto aos arquivos Já está no contexto
Ecossistema de plugins 2.500+ plugins Integrações Nenhum N/A N/A
Funciona offline Completo Somente leitura em cache Parcial Completo Completo
Escala para 10K+ notas Sim Sim (com API) Degrada Sim Não (arquivo único)
Custo Gratuito (core) $10/mês+ Gratuito Gratuito Gratuito

Quando o Obsidian é exagero

  • Contexto de projeto único. Se a IA precisa apenas de contexto sobre o codebase atual, coloque-o no CLAUDE.md, AGENTS.md ou na documentação do projeto. Esses arquivos acompanham o repositório e são carregados automaticamente.
  • Dados estruturados. Se o conteúdo consiste em tabelas, registros ou schemas, use um banco de dados. Notas do Obsidian são voltadas para prosa. O Dataview consegue consultar campos do frontmatter, mas um banco de dados real lida melhor com consultas estruturadas.
  • Pesquisa temporária. Se as notas serão descartadas após o fim do projeto, um diretório temporário com arquivos markdown é mais simples. Não construa infraestrutura de recuperação para conteúdo efêmero.

Quando o Obsidian é a escolha certa

  • Acúmulo de conhecimento ao longo de meses ou anos. O valor se acumula conforme o corpus cresce. Um vault de 200 notas consultado diariamente por seis meses gera mais valor do que um vault de 5.000 notas consultado uma única vez.
  • Múltiplos domínios em um único corpus. Um vault contendo notas sobre programação, arquitetura, segurança, design e projetos pessoais se beneficia da recuperação cross-domain que um CLAUDE.md específico de projeto não consegue oferecer.
  • Conteúdo sensível em termos de privacidade. Local-first significa que o pipeline de recuperação nunca envia conteúdo para serviços externos. O vault contém o que você colocar nele, incluindo conteúdo que você não faria upload para um serviço em nuvem.

Modelo mental: três camadas

O sistema possui três camadas que operam de forma independente, mas se potencializam quando combinadas. Cada camada tem uma preocupação diferente e um modo de falha diferente.

┌─────────────────────────────────────────────────────┐
                 INTEGRATION LAYER                     
  MCP servers, hooks, skills, context injection        
  Concern: delivering context to AI tools              
  Failure: wrong context, too much context, stale      
└──────────────────────┬──────────────────────────────┘
                        query + ranked results
┌──────────────────────┴──────────────────────────────┐
                  RETRIEVAL LAYER                      
  BM25, vector KNN, RRF fusion, token budget           
  Concern: finding the right content for any query     
  Failure: wrong ranking, missed results, slow queries 
└──────────────────────┬──────────────────────────────┘
                        chunked, embedded, indexed
┌──────────────────────┴──────────────────────────────┐
                   INTAKE LAYER                        
  Note creation, signal triage, vault organization     
  Concern: what enters the vault and how it's stored   │
  Failure: noise, duplicates, missing structure        
└─────────────────────────────────────────────────────┘

Intake determina o que entra no vault. Sem curadoria, o vault acumula ruído: capturas de tela de tweets, artigos copiados e colados sem anotação, pensamentos pela metade sem contexto. A camada de intake é responsável pelo controle de qualidade no ponto de entrada. Um pipeline de pontuação, convenção de tags ou processo de revisão manual — qualquer mecanismo que garanta que o vault contenha conteúdo que vale a pena recuperar.

Retrieval torna o vault consultável. Este é o motor: dividir notas em unidades de busca (chunking), converter chunks em espaço vetorial (embeddings), indexar para busca por palavras-chave e semântica, e fundir resultados com RRF. A camada de retrieval transforma um diretório de arquivos em uma base de conhecimento consultável. Sem essa camada, o vault é navegável através de busca manual e pesquisa básica, mas não é acessível programaticamente para ferramentas de IA.

Integration conecta a camada de retrieval às ferramentas de IA. Um servidor MCP expõe a recuperação como uma ferramenta invocável. Hooks injetam contexto automaticamente. Skills capturam novo conhecimento de volta no vault. A camada de integration é a interface entre a base de conhecimento e os agentes de IA que a consomem.

As camadas são desacopladas por design. O pipeline de pontuação do intake não sabe nada sobre embeddings. O retriever não sabe nada sobre regras de roteamento de sinais. O servidor MCP não sabe nada sobre como as notas foram criadas. Esse desacoplamento significa que você pode melhorar qualquer camada de forma independente. Substitua o modelo de embeddings sem alterar o pipeline de intake. Adicione uma nova capacidade MCP sem modificar o retriever. Mude as heurísticas de pontuação de sinais sem tocar no índice.


Arquitetura do vault para consumo por IA

Um vault otimizado para recuperação por IA segue convenções diferentes de um vault otimizado para navegação pessoal. Esta seção aborda estrutura de pastas, esquema de notas, convenções de frontmatter e os padrões específicos que melhoram a qualidade da recuperação.

Estrutura de pastas

Use prefixos numéricos para pastas de nível superior para criar uma hierarquia organizacional previsível. Os números não indicam prioridade — eles agrupam domínios relacionados e tornam a estrutura facilmente escaneável.

vault/
├── 00-inbox/              # Capturas não classificadas, pendentes de triagem
├── 01-projects/           # Notas de projetos ativos
├── 02-areas/              # Áreas de responsabilidade contínuas
├── 03-resources/          # Material de referência por tópico
   ├── programming/
   ├── security/
   ├── ai-engineering/
   ├── design/
   └── devops/
├── 04-archive/            # Projetos concluídos, referências antigas
├── 05-signals/            # Intake de sinais com pontuação
   ├── ai-tooling/
   ├── security/
   ├── systems/
   └── ...12 domain folders
├── 06-daily/              # Notas diárias (se utilizadas)
├── 07-templates/          # Templates de notas (excluídos do índice)
├── 08-attachments/        # Imagens, PDFs (excluídos do índice)
├── .obsidian/             # Configuração do Obsidian (excluída do índice)
└── .indexignore            # Caminhos a excluir do índice de recuperação

Pastas que devem ser indexadas: Tudo que contém prosa em markdown — projetos, áreas, recursos, sinais, notas diárias.

Pastas que devem ser excluídas da indexação: Templates (contêm variáveis de placeholder, não conteúdo), anexos (arquivos binários), configuração do Obsidian e qualquer pasta com conteúdo sensível que você não quer no índice de recuperação.

O arquivo .indexignore

Crie um arquivo .indexignore na raiz do vault para excluir explicitamente caminhos do índice de recuperação. A sintaxe segue o padrão do .gitignore:

# Obsidian internal
.obsidian/

# Templates contain placeholders, not content
07-templates/

# Binary attachments
08-attachments/

# Personal health/medical notes
02-areas/health/

# Financial records
02-areas/finance/personal/

# Career documents (resumes, salary data)
02-areas/career/private/

O indexador lê este arquivo antes de escanear e pula completamente os caminhos correspondentes. Arquivos em caminhos excluídos nunca passam por chunking, nunca recebem embeddings e nunca aparecem nos resultados de busca.

Esquema de notas

Toda nota deve ter frontmatter YAML. O retriever usa campos de frontmatter para filtragem e enriquecimento de contexto:

---
title: "OAuth Token Rotation Patterns"
type: note           # note | signal | project | moc | daily
domain: security     # primary domain for routing
tags:
  - authentication
  - oauth
  - token-management
created: 2026-01-15
updated: 2026-02-28
source: ""           # URL if captured from external source
status: active       # active | archived | draft
---

Campos obrigatórios para recuperação:

  • title — Usado na exibição dos resultados de busca e no contexto de cabeçalhos para BM25
  • type — Permite consultas filtradas por tipo (“mostrar apenas MOCs” ou “apenas sinais”)
  • tags — Indexadas no contexto de cabeçalhos do FTS5 com peso 0.3, fornecendo correspondências por palavras-chave mesmo quando o corpo do texto usa terminologia diferente

Campos opcionais, porém valiosos:

  • domain — Permite consultas com escopo por domínio (“buscar apenas em notas de segurança”)
  • source — Atribuição para conteúdo capturado; o retriever pode incluir URLs de origem nos resultados
  • status — Permite excluir notas arquivadas ou em rascunho da busca ativa

Convenções de chunking

O retriever divide o conteúdo nos limites de cabeçalhos H2 (##). Isso significa que a estrutura da sua nota afeta diretamente a granularidade da recuperação:

Bom para recuperação:

## Token Rotation Strategy

The rotation interval depends on the threat model...

## Implementation with refresh_token

The OAuth 2.0 refresh token flow requires...

## Error Handling: Expired Tokens

When a token expires mid-request...

Três seções H2 produzem três chunks pesquisáveis de forma independente. Cada chunk tem contexto suficiente para que o embedding capture seu significado. Uma consulta sobre “tratamento de token expirado” corresponde especificamente ao terceiro chunk.

Ruim para recuperação:

# OAuth Notes

Token rotation depends on threat model. The OAuth 2.0 refresh
token flow requires storing the refresh token securely. When a
token expires mid-request, the client should retry after refresh.
The rotation interval is typically 15-30 minutes for access tokens
and 7-30 days for refresh tokens...

Uma seção longa sem cabeçalhos H2 produz um único chunk grande. O embedding calcula a média entre todos os tópicos da seção. Uma consulta sobre qualquer subtópico corresponde à nota inteira de forma igual.

Regra prática: Se uma seção abrange mais de um conceito, divida-a em subseções H2. O chunker cuida do resto.

O que não colocar nas notas

Conteúdo que degrada a qualidade da recuperação:

  • Cópias brutas de artigos inteiros sem anotação. O retriever indexa as palavras-chave do artigo original, diluindo seu vault com conteúdo que você não escreveu. Em vez disso, adicione um resumo, extraia os pontos-chave ou insira um link para a URL de origem.
  • Capturas de tela sem descrição textual. O retriever indexa texto em markdown. Uma imagem sem texto alternativo ou descrição ao redor é invisível tanto para BM25 quanto para busca vetorial.
  • Strings de credenciais. Chaves de API, tokens, senhas, strings de conexão. Mesmo com filtragem de credenciais, a abordagem mais segura é nunca colar segredos nas notas. Referencie-os pelo nome (“o token API do Cloudflare em ~/.env”).
  • Conteúdo gerado automaticamente sem curadoria. Se uma ferramenta gera uma nota (transcrição de reunião, destaques do Readwise, importação de RSS), revise e anote antes de incorporá-la ao vault permanente. Importações automáticas sem curadoria adicionam volume sem agregar valor recuperável.

Ecossistema de plugins para fluxos de trabalho com IA

Plugins do Obsidian que melhoram a qualidade do vault para recuperação por IA se dividem em três categorias: estruturais (garantem consistência), de consulta (expõem metadados) e de sincronização (mantêm o vault atualizado).

Plugins essenciais

Dataview. Consulta seu vault como um banco de dados usando campos de frontmatter. Crie índices dinâmicos: “todas as notas com tag security atualizadas nos últimos 30 dias” ou “todas as notas de projeto com status active.” O Dataview não ajuda diretamente na recuperação, mas ajuda a identificar lacunas na cobertura do seu vault e encontrar notas que precisam de atualização.

TABLE type, domain, updated
FROM "03-resources"
WHERE status = "active"
SORT updated DESC
LIMIT 20

Templater. Cria notas a partir de templates com campos dinâmicos. Garanta que toda nova nota comece com frontmatter correto usando um template que preenche automaticamente os campos created, type e domain. Frontmatter consistente melhora a filtragem na recuperação.

<%* /* New Resource Note Template */ %>
---
title: "<% tp.file.cursor() %>"
type: note
domain: <% tp.system.suggester(["programming", "security", "ai-engineering", "design", "devops"], ["programming", "security", "ai-engineering", "design", "devops"]) %>
tags: []
created: <% tp.date.now("YYYY-MM-DD") %>
updated: <% tp.date.now("YYYY-MM-DD") %>
source: ""
status: active
---

## Key Points

## Details

## Referências

Linter. Aplica regras de formatação em todo o vault. Uma hierarquia de cabeçalhos consistente (H1 para título, H2 para seções, H3 para subseções) garante que o chunker produza resultados previsíveis. Regras do Linter que importam para a recuperação:

  • Incremento de cabeçalhos: forçar níveis sequenciais (sem pular de H1 para H3)
  • YAML title: corresponder ao nome do arquivo
  • Espaços à direita: remover (evita artefatos de tokenização do FTS5)
  • Linhas em branco consecutivas: limitar a 1 (chunks mais limpos)

Integração com Git. Controle de versão para o seu vault. Acompanhe mudanças ao longo do tempo, sincronize entre máquinas e recupere-se de exclusões acidentais. O Git também fornece dados de mtime que o indexador usa para detecção incremental de alterações.

Plugins que ajudam a indexação

Smart Connections. Um plugin para Obsidian que oferece busca semântica com IA dentro do próprio Obsidian. O Smart Connections v4 cria embeddings locais por padrão — uma vez que seu vault esteja indexado, as conexões semânticas e a busca funcionam inteiramente offline, sem chamadas de API.23 Embora o sistema de recuperação neste guia seja externo ao Obsidian (roda como um pipeline Python), o Smart Connections é útil para explorar relações semânticas enquanto você escreve. Os dois sistemas indexam o mesmo conteúdo, mas atendem a casos de uso diferentes: Smart Connections para descoberta dentro do editor, o recuperador externo para integração de ferramentas de IA via MCP.

Metadata Menu. Oferece edição estruturada de frontmatter com autocompletar para valores de campos. Reduz erros de digitação nos campos type, domain e tags. Metadados consistentes melhoram a precisão da filtragem na recuperação.

Plugins que prejudicam a indexação

Excalidraw. Armazena desenhos como JSON embutido em arquivos markdown. O JSON é markdown sintaticamente válido, mas produz lixo quando dividido em chunks e convertido em embeddings. Exclua arquivos do Excalidraw do índice via .indexignore ou filtre por extensão de arquivo.

Kanban. Armazena o estado do quadro como markdown com formatação especial. O formato é projetado para renderização Kanban, não para recuperação de prosa. O chunker produz fragmentos de títulos de cartões e metadados que não geram bons embeddings. Exclua quadros Kanban do índice.

Calendar. Cria notas diárias com conteúdo mínimo (geralmente apenas um cabeçalho com a data). Notas vazias ou quase vazias produzem chunks de baixa qualidade. Se você usa notas diárias, escreva conteúdo substancial nelas ou exclua a pasta de notas diárias do índice.

Configurações de plugins que importam

File recovery → Ativado. Protege contra exclusão acidental de notas. Não está diretamente relacionado à recuperação, mas é essencial para uma base de conhecimento da qual você depende.

Strict line breaks → Desativado. Quebras de linha padrão do markdown (duplo newline para parágrafo) produzem chunks mais limpos do que o modo estrito do Obsidian (newline simples para <br>).

Default new file location → Pasta designada. Direcione novos arquivos para 00-inbox/ para que notas não categorizadas não poluam as pastas de domínio. A inbox é uma área de triagem; os arquivos são movidos para pastas de domínio após a classificação.

Wiki-link format → Caminho mais curto quando possível. Alvos de link mais curtos são mais fáceis para o recuperador resolver ao indexar a estrutura de links.


Modelos de embedding: escolha e configuração

O modelo de embedding converte trechos de texto em vetores numéricos para busca semântica. A escolha do modelo determina a qualidade da recuperação, o tamanho do índice, a velocidade de embedding e as dependências de runtime. Esta seção explica por que o potion-base-8M do Model2Vec é a escolha padrão e quando optar por alternativas.

Por que o Model2Vec potion-base-8M

Modelo: minishlab/potion-base-8M Parâmetros: 7,6 milhões Dimensões: 256 Tamanho: ~30 MB Dependências: model2vec (apenas numpy, sem PyTorch) Inferência: apenas CPU, embeddings de palavras estáticos (sem camadas de atenção)

O Model2Vec destila o conhecimento de um sentence transformer em embeddings de tokens estáticos. Em vez de executar camadas de atenção sobre a entrada (como fazem BERT, MiniLM e outros modelos transformer), o Model2Vec produz vetores por meio de média ponderada de embeddings de tokens pré-computados.5 A consequência prática: a velocidade de embedding é 50-500x mais rápida do que modelos baseados em transformer, porque não há computação sequencial.

No benchmark suite MTEB, o potion-base-8M alcança 89% do desempenho do all-MiniLM-L6-v2 (50,03 vs 56,09 de média).6 A diferença de 11% na qualidade é o trade-off pelas vantagens de velocidade e simplicidade. Para trechos curtos de markdown (média de 200-400 palavras em um vault típico), a diferença de qualidade é menos pronunciada do que em documentos mais longos, porque ambos os modelos convergem para representações similares em textos curtos e focados.

Configuração

# embedder.py
DEFAULT_MODEL = "minishlab/potion-base-8M"
EMBEDDING_DIM = 256

class Model2VecEmbedder:
    def __init__(self, model_name=DEFAULT_MODEL):
        self._model_name = model_name
        self._model = None

    def _ensure_model(self):
        if self._model is not None:
            return
        _activate_venv()  # Add isolated venv to sys.path
        from model2vec import StaticModel
        self._model = StaticModel.from_pretrained(self._model_name)

    def embed_batch(self, texts):
        self._ensure_model()
        vecs = self._model.encode(texts)
        return [v.tolist() for v in vecs]

Carregamento sob demanda. O modelo é carregado no primeiro uso, não no momento da importação. Importar o módulo do embedder não custa nada quando o retriever opera em modo fallback apenas com BM25 (por exemplo, quando o venv de embedding não está instalado).

Ambiente virtual isolado. O modelo roda em um venv dedicado (por exemplo, ~/.claude/venvs/memory/) para evitar conflitos de dependência com o restante do toolchain. A função _activate_venv() adiciona o site-packages do venv ao sys.path em tempo de execução.

# Create isolated venv
python3 -m venv ~/.claude/venvs/memory
~/.claude/venvs/memory/bin/pip install model2vec

Processamento em lote. O embedder processa textos em lotes de 64 para amortizar o overhead do Model2Vec. O indexador alimenta os trechos no embed_batch() em vez de fazer embedding de um trecho por vez.

Quando escolher alternativas

Modelo Dim Tamanho Velocidade Qualidade (MTEB) Melhor para
potion-base-8M 256 30 MB 500x 50,03 Padrão: local, rápido, sem GPU
potion-base-32M 256 120 MB 400x 52,46 Maior qualidade, ainda estático
potion-retrieval-32M 256 120 MB 400x 36,35 (recuperação) Estático otimizado para recuperação
potion-multilingual-128M 256 ~500 MB 300x Vaults multilíngues (101 idiomas)
all-MiniLM-L6-v2 384 80 MB 1x 56,09 Maior qualidade, ainda local
nomic-embed-text-v1.5 768 270 MB 0,5x 62,28 Melhor qualidade local
text-embedding-3-small 1536 API N/A 62,30 Baseado em API, maior qualidade

Escolha potion-base-32M quando quiser melhor qualidade do que o potion-base-8M sem sair da família de embeddings estáticos. Lançado em janeiro de 2025, ele usa um vocabulário maior destilado do baai/bge-base-en-v1.5, alcançando 52,46 de média no MTEB (5% de melhoria sobre o potion-base-8M) mantendo a mesma saída de 256 dimensões e dependência apenas de numpy.20 O arquivo do modelo 4x maior aumenta o uso de memória, mas a velocidade de embedding permanece ordens de magnitude mais rápida que modelos transformer.

Escolha potion-retrieval-32M quando seu caso de uso principal é recuperação (que é exatamente o que a busca no vault faz). Essa variante é fine-tuned a partir do potion-base-32M especificamente para tarefas de recuperação, atingindo 36,35 nos benchmarks de recuperação do MTEB contra 33,52 do modelo base.20 A média geral do MTEB cai para 49,73 porque o fine-tuning troca desempenho de uso geral por ganhos específicos de recuperação.

Escolha potion-multilingual-128M quando seu vault contém notas em múltiplos idiomas. Lançado em maio de 2025, este modelo de 101 idiomas é o modelo de embedding estático com melhor desempenho para tarefas multilíngues, gerando embeddings para qualquer texto em qualquer idioma mantendo a mesma dependência apenas de numpy dos outros modelos potion.24 O arquivo de modelo maior (~500 MB) é o trade-off pela capacidade cross-lingual. Use quando você tiver notas em japonês, chinês, alemão ou outros idiomas não ingleses junto com conteúdo em inglês.

Escolha all-MiniLM-L6-v2 quando a qualidade de recuperação importa mais do que velocidade e você tem o PyTorch instalado. Os vetores de 384 dimensões aumentam o tamanho do banco de dados SQLite em ~50% comparado com vetores de 256 dimensões. A velocidade de embedding cai de <1 minuto para ~10 minutos para um reindex completo de 15.000 arquivos em hardware da série M.

Escolha nomic-embed-text-v1.5 quando você precisa da melhor qualidade de recuperação local possível e aceita indexação mais lenta. Os vetores de 768 dimensões praticamente triplicam o tamanho do banco de dados. Requer PyTorch e uma CPU moderna ou GPU.

Escolha text-embedding-3-small quando latência de rede e privacidade são trade-offs aceitáveis. A API produz os embeddings de maior qualidade, mas introduz uma dependência de nuvem, custo por token ($0,02/milhão de tokens) e envia seu conteúdo para os servidores da OpenAI.

Continue com potion-base-8M em todos os outros casos. A vantagem de velocidade é crítica para indexação iterativa (reindex durante o desenvolvimento), a dependência apenas de numpy evita a complexidade de instalação do PyTorch, e os vetores de 256 dimensões mantêm o banco de dados compacto.

Quantização e redução de dimensionalidade

O Model2Vec v0.5.0+ suporta carregamento de modelos com precisão e dimensões reduzidas.20 Isso é útil para deploy em hardware com recursos limitados ou para reduzir o tamanho do banco de dados sem trocar de modelo:

from model2vec import StaticModel

# Load with int8 quantization (25% of original size)
model = StaticModel.from_pretrained("minishlab/potion-base-8M", quantize=True)

# Load with reduced dimensions (e.g., 128 instead of 256)
model = StaticModel.from_pretrained("minishlab/potion-base-8M", dimensionality=128)

Modelos quantizados mantêm qualidade de recuperação quase idêntica com uma fração do footprint de memória. A redução de dimensionalidade segue truncamento no estilo Matryoshka — as primeiras N dimensões carregam a maior parte da informação. Reduzir de 256 para 128 dimensões corta pela metade o armazenamento de vetores com perda mínima de qualidade para recuperação de textos curtos.

Desde maio de 2025, o Model2Vec também suporta tokenizadores BPE e Unigram (além do WordPiece), o que expande o conjunto de sentence transformers que podem ser destilados em modelos estáticos.22

Fine-tuning para embeddings específicos do vault

O Model2Vec v0.4.0+ suporta treinamento de modelos de classificação customizados sobre embeddings estáticos, e a v0.7.0 adiciona quantização de vocabulário e pooling configurável para destilação.22 Isso é relevante para vaults com vocabulário especializado (notas médicas, referências jurídicas, jargão específico de domínio) onde os modelos potion padrão podem não capturar nuances semânticas:

from model2vec import StaticModel
from model2vec.train import train_model

# Fine-tune on vault-specific data
model = StaticModel.from_pretrained("minishlab/potion-base-8M")
trained_model = train_model(model, train_texts, train_labels)
trained_model.save_pretrained("./vault-embeddings")

Para a maioria dos vaults, o potion-base-8M padrão produz qualidade de recuperação suficiente. O fine-tuning vale a pena apenas quando a recuperação consistentemente perde conexões específicas do domínio que um modelo de uso geral não consegue capturar.

Rastreamento de hash do modelo

O indexador armazena um hash derivado do nome do modelo e do tamanho do vocabulário. Se você trocar o modelo de embedding, o indexador detecta a incompatibilidade na próxima execução incremental e dispara um reindex completo automaticamente.

def _compute_model_hash(self):
    """Hash model name + vocab size for compatibility tracking."""
    key = f"{self._model_name}:{self._model.vocab_size}"
    return hashlib.sha256(key.encode()).hexdigest()[:16]

Isso evita misturar vetores de modelos diferentes no mesmo banco de dados, o que produziria scores de cosine similarity sem sentido.

Modos de falha

Falha no download do modelo. A primeira execução baixa o modelo do Hugging Face. Se o download falhar (problema de rede, firewall corporativo), o retriever volta ao modo apenas BM25. O modelo é armazenado em cache localmente após o primeiro download.

Incompatibilidade de dimensões. Se você trocar de modelo sem limpar o banco de dados, os vetores armazenados terão dimensão diferente dos novos embeddings. O indexador detecta isso pelo hash do modelo e dispara um reindex completo. Se a verificação do hash falhar (modelo customizado sem hash adequado), o sqlite-vec retornará erro em queries KNN com dimensões incompatíveis.

Pressão de memória em vaults grandes. Fazer embedding de 50.000+ trechos em um único lote pode consumir memória significativa. O indexador processa em lotes de 64 para limitar o pico de uso de memória. Se a memória ainda for um problema, reduza o tamanho do lote.


Busca de texto completo com FTS5

A extensão FTS5 do SQLite oferece busca de texto completo com ranking BM25. O FTS5 é o componente de busca por palavras-chave do pipeline de hybrid retrieval. Esta seção aborda a configuração do FTS5, quando o BM25 se destaca e seus modos de falha específicos.

Tabela virtual FTS5

CREATE VIRTUAL TABLE chunks_fts USING fts5(
    chunk_text,
    section,
    heading_context,
    content=chunks,
    content_rowid=id
);

Modo de sincronização de conteúdo. O parâmetro content=chunks instrui o FTS5 a referenciar a tabela chunks diretamente em vez de armazenar uma cópia duplicada do texto. Isso reduz o armazenamento pela metade, mas significa que o FTS5 precisa ser sincronizado manualmente quando chunks são inseridos, atualizados ou removidos.

Colunas. Três colunas são indexadas: - chunk_text — O conteúdo principal de cada chunk (peso BM25: 1.0) - section — O texto do cabeçalho H2 (peso BM25: 0.5) - heading_context — Título da nota, tags e metadados (peso BM25: 0.3)

Ranking BM25

O BM25 classifica documentos por frequência de termos, frequência inversa de documentos e normalização pelo tamanho do documento. A função auxiliar bm25() no FTS5 aceita pesos por coluna:

SELECT
    c.id, c.file_path, c.section, c.chunk_text,
    bm25(chunks_fts, 1.0, 0.5, 0.3) AS score
FROM chunks_fts
JOIN chunks c ON chunks_fts.rowid = c.id
WHERE chunks_fts MATCH ?
ORDER BY score
LIMIT 30;

Os pesos das colunas (1.0, 0.5, 0.3) significam: - Uma correspondência de palavra-chave em chunk_text contribui mais para a pontuação - Uma correspondência em section (cabeçalho) contribui com metade - Uma correspondência em heading_context (título, tags) contribui com 30%

Esses pesos são ajustáveis. Se o seu vault tem cabeçalhos descritivos que preveem bem a qualidade do conteúdo, aumente o peso de section. Se suas tags são abrangentes e precisas, aumente o peso de heading_context.

Quando o BM25 vence

O BM25 se destaca em consultas que contêm identificadores exatos:

  • Nomes de funções: _rrf_fuse, embed_batch, get_stale_files
  • Flags de CLI: --incremental, --vault, --model
  • Chaves de configuração: bm25_weight, max_tokens, batch_size
  • Mensagens de erro: SQLITE_LOCKED, ConnectionRefusedError
  • Termos técnicos específicos: PostToolUse, PreToolUse, AGENTS.md

Para essas consultas, o BM25 encontra a correspondência exata imediatamente. A busca vetorial retornaria conteúdo semanticamente relacionado, mas poderia classificar a correspondência exata abaixo de uma discussão conceitual.

Quando o BM25 falha

O BM25 falha em consultas que usam terminologia diferente do conteúdo armazenado:

  • Consulta: “how to handle authentication failures” → O vault contém notas sobre “login error recovery” e “session expiration handling.” O BM25 não encontra correspondência porque as palavras-chave são diferentes.
  • Consulta: “what is the best way to manage state” → O vault contém notas sobre “Redux store patterns” e “context providers.” O BM25 não encontra porque “state management” é expresso através de nomes de tecnologias específicas.

O BM25 também falha com colisão de palavras-chave em escala. Em um vault com 15.000 arquivos, uma busca por “configuration” corresponde a centenas de notas porque praticamente toda nota de projeto menciona configuração. Os resultados são tecnicamente corretos, porém praticamente inúteis — o ranking não consegue determinar qual nota sobre “configuration” é relevante para a consulta atual.

Tokenizador FTS5

O FTS5 usa o tokenizador unicode61 por padrão, que lida com texto ASCII e Unicode. Para vaults com conteúdo significativo em CJK (chinês, japonês, coreano), considere o tokenizador trigram:

-- For CJK-heavy vaults
CREATE VIRTUAL TABLE chunks_fts USING fts5(
    chunk_text, section, heading_context,
    content=chunks, content_rowid=id,
    tokenize='trigram'
);

O tokenizador padrão unicode61 divide o texto nos limites de palavras, o que funciona mal para idiomas sem espaços entre as palavras. O tokenizador trigram divide a cada três caracteres, permitindo correspondência de substrings ao custo do tamanho do índice (aproximadamente 3x maior).

Manutenção

O FTS5 requer sincronização explícita quando a tabela chunks subjacente é alterada:

# After inserting chunks
cursor.execute("""
    INSERT INTO chunks_fts(chunks_fts)
    VALUES('rebuild')
""")

O comando rebuild reconstrói o índice FTS5 a partir da tabela de conteúdo. Execute-o após inserções em massa (reindexação completa), mas não após atualizações incrementais individuais — para essas, use INSERT INTO chunks_fts(rowid, chunk_text, section, heading_context) para sincronizar linhas individuais.


Busca vetorial com sqlite-vec

A extensão sqlite-vec traz busca vetorial KNN (K-Nearest Neighbors) para o SQLite. Esta seção aborda a configuração do sqlite-vec, o pipeline de embeddings desde a nota até o vetor pesquisável, e os padrões específicos de consulta.

Tabela virtual sqlite-vec

CREATE VIRTUAL TABLE chunk_vecs USING vec0(
    id INTEGER PRIMARY KEY,
    embedding float[256]
);

O módulo vec0 armazena vetores float de 256 dimensões como dados binários compactados. A coluna id mapeia 1:1 para a tabela chunks, permitindo joins entre resultados vetoriais e metadados dos chunks.

Pipeline de embeddings

O pipeline flui da nota até o vetor pesquisável:

Note (.md file)
   Chunker: split at H2 boundaries
     Chunks (30-2000 chars each)
       Credential filter: scrub secrets
         Embedder: Model2Vec encode
           Vectors (256-dim float arrays)
             sqlite-vec: store as packed binary
               Ready for KNN queries

Serialização de vetores

O módulo struct do Python serializa vetores float para armazenamento no sqlite-vec:

import struct

def _serialize_vector(vec):
    """Pack float list into binary for sqlite-vec."""
    return struct.pack(f"{len(vec)}f", *vec)

def _deserialize_vector(blob, dim=256):
    """Unpack binary blob to float list."""
    return list(struct.unpack(f"{dim}f", blob))

Consulta KNN

Uma consulta de busca vetorial converte a query de entrada em embedding e então encontra os K chunks mais próximos por distância cosseno:

def _vector_search(self, query_text, limit=30):
    query_vec = self.embedder.embed_batch([query_text])[0]
    packed = _serialize_vector(query_vec)

    results = self.db.execute("""
        SELECT
            cv.id,
            cv.distance,
            c.file_path,
            c.section,
            c.chunk_text
        FROM chunk_vecs cv
        JOIN chunks c ON cv.id = c.id
        WHERE embedding MATCH ?
            AND k = ?
        ORDER BY distance
    """, [packed, limit]).fetchall()

    return results

O operador MATCH no sqlite-vec realiza busca aproximada de vizinhos mais próximos. O parâmetro k controla quantos resultados retornar. A coluna distance contém a distância cosseno (0 = idêntico, 2 = oposto).

Paginação KNN com restrições de distância

A partir do sqlite-vec v0.1.7, consultas KNN suportam restrições WHERE distance < ?, permitindo paginação baseada em cursor através de grandes conjuntos de resultados sem re-escanear páginas anteriores.26

def _paginated_vector_search(self, query_vec, page_size=20, max_distance=None):
    """Paginate through KNN results using distance constraints."""
    packed = _serialize_vector(query_vec)
    constraint = f"AND distance < {max_distance}" if max_distance else ""

    results = self.db.execute(f"""
        SELECT cv.id, cv.distance, c.file_path, c.chunk_text
        FROM chunk_vecs cv
        JOIN chunks c ON cv.id = c.id
        WHERE embedding MATCH ?
            AND k = ?
            {constraint}
        ORDER BY distance
    """, [packed, page_size]).fetchall()

    # Use last result's distance as cursor for next page
    next_cursor = results[-1][1] if results else None
    return results, next_cursor

Isso substitui o padrão anterior de buscar um k grande e fatiar no Python, reduzindo o uso de memória para consultas exploratórias em vaults grandes.

Suporte a DELETE em tabelas vec0

O sqlite-vec v0.1.7 adicionou suporte nativo a DELETE para tabelas virtuais vec0.26 Anteriormente, remover vetores exigia descartar e recriar a tabela. Agora o caminho de remoção de arquivos do indexador pode deletar vetores diretamente:

# Before v0.1.7: required workaround (drop + recreate, or mark as inactive)
# After v0.1.7: direct DELETE works
db.execute("DELETE FROM chunk_vecs WHERE id = ?", [chunk_id])

Isso simplifica a reindexação incremental quando notas são deletadas ou movidas. O indexador não precisa mais manter uma tabela auxiliar de “IDs ativos” ou reconstruções em lote.

Quando a busca vetorial se destaca

A busca vetorial se destaca em consultas onde o conceito importa mais do que as palavras específicas:

  • Consulta: “how to handle authentication failures” → Encontra notas sobre “login error recovery” (mesmo espaço semântico, palavras-chave diferentes)
  • Consulta: “what patterns exist for caching” → Encontra notas sobre “memoization,” “Redis TTL strategies,” e “HTTP cache headers” (conceitos relacionados, terminologia diversa)
  • Consulta: “approaches to testing asynchronous code” → Encontra notas sobre “pytest-asyncio fixtures,” “mock event loops,” e “async test patterns” (mesmo conceito expresso através de detalhes de implementação)

Quando a busca vetorial falha

A busca vetorial tem dificuldade com identificadores exatos:

  • Consulta: _rrf_fuse → Retorna notas sobre “fusion algorithms” e “rank merging”, mas pode classificar a definição real da função abaixo de discussões conceituais
  • Consulta: PostToolUse → Retorna notas sobre “tool lifecycle hooks” e “post-execution handlers” em vez do nome específico do hook

A busca vetorial também tem dificuldade com dados estruturados. Arquivos de configuração JSON, blocos YAML e trechos de código produzem embeddings que capturam padrões estruturais em vez de significado semântico. Um arquivo JSON com "review": true gera um embedding diferente de uma discussão em prosa sobre revisão de código.

Degradação graciosa

Se o sqlite-vec não conseguir carregar (extensão ausente, plataforma incompatível, biblioteca corrompida), o retriever recorre à busca apenas com BM25:

class VectorIndex:
    def __init__(self, db_path):
        self.db = sqlite3.connect(db_path)
        self._vec_available = False
        try:
            self.db.enable_load_extension(True)
            self.db.load_extension("vec0")
            self._vec_available = True
        except Exception:
            pass  # BM25-only mode

    @property
    def vec_available(self):
        return self._vec_available

O retriever verifica vec_available antes de tentar consultas vetoriais. Quando desabilitado, todas as buscas usam apenas BM25, e a etapa de fusão RRF é ignorada.


Reciprocal Rank Fusion (RRF)

RRF mescla duas listas ranqueadas sem exigir calibração de pontuação. Esta seção cobre o algoritmo, um rastreamento detalhado de consulta, ajuste do parâmetro k e por que RRF é escolhido em vez de alternativas. Para uma calculadora interativa com ranks editáveis, presets de cenários e um explorador visual de arquitetura, veja o aprofundamento sobre hybrid retriever.

O algoritmo

RRF atribui a cada documento uma pontuação baseada apenas em sua posição de rank em cada lista:

score(d) = Σ (weight_i / (k + rank_i))

Onde: - k é uma constante de suavização (60, seguindo Cormack et al.3) - rank_i é o rank do documento (base 1) na lista de resultados i - weight_i é um multiplicador opcional por lista (padrão 1.0)

Documentos que se posicionam bem em múltiplas listas recebem pontuações fundidas mais altas. Documentos que aparecem em apenas uma lista recebem uma pontuação dessa única fonte.

Por que RRF em vez de alternativas

Combinação linear ponderada exige calibrar pontuações BM25 contra distâncias de cosseno. Pontuações BM25 são ilimitadas e escalam com o tamanho do corpus. Distâncias de cosseno são limitadas [0, 2]. Combiná-las exige normalização, e os parâmetros de normalização dependem do dataset. RRF usa apenas posições de rank, que são sempre inteiros começando em 1, independentemente do método de pontuação.

Modelos de fusão treinados exigem dados de treinamento rotulados — pares de relevância consulta-documento. Para uma base de conhecimento pessoal, esses dados de treinamento não existem. Você precisaria avaliar manualmente centenas de pares consulta-documento para treinar um modelo útil. RRF funciona sem nenhum dado de treinamento.

Métodos de votação Condorcet (contagem de Borda, método Schulze) são teoricamente elegantes, porém mais complexos de implementar e ajustar. O artigo original de RRF demonstrou que RRF supera métodos Condorcet em dados de avaliação TREC.3

Fusão na prática

Consulta: “how does the review aggregator handle disagreements”

BM25 ranqueia review-aggregator.py na posição 3 (correspondências exatas de palavras-chave em “review,” “aggregator,” “disagreements”), mas coloca dois arquivos de configuração acima (eles correspondem “review” de forma mais proeminente). A busca vetorial ranqueia o mesmo chunk na posição 1 (correspondência semântica sobre resolução de conflitos). Após a fusão RRF:

Chunk BM25 Vec Pontuação fundida
review-aggregator.py “Disagreement Resolution” #3 #1 0,0323
code-review-patterns.md “Multi-Reviewer” #4 #2 0,0317
deliberation-config.json “Review Weights” #1 0,0164

Chunks que se posicionam bem em ambas as listas emergem para o topo. Chunks que aparecem em apenas uma lista recebem uma pontuação de fonte única e ficam abaixo dos resultados com ranqueamento duplo. A lógica real de resolução de desacordos vence porque ambos os métodos a encontraram — BM25 através de palavras-chave, busca vetorial através de semântica.

Para o rastreamento completo passo a passo com a matemática RRF por rank, experimente diferentes valores de k na calculadora interativa de RRF.

Implementação

RRF_K = 60

def _rrf_fuse(self, bm25_results, vec_results,
              bm25_weight=1.0, vec_weight=1.0):
    """Fuse BM25 and vector results using Reciprocal Rank Fusion."""
    scores = {}

    for rank, r in enumerate(bm25_results, start=1):
        cid = r["id"]
        if cid not in scores:
            scores[cid] = {
                "rrf_score": 0.0,
                "file_path": r["file_path"],
                "section": r["section"],
                "chunk_text": r["chunk_text"],
                "bm25_rank": None,
                "vec_rank": None,
            }
        scores[cid]["rrf_score"] += bm25_weight / (self._rrf_k + rank)
        scores[cid]["bm25_rank"] = rank

    for rank, r in enumerate(vec_results, start=1):
        cid = r["id"]
        if cid not in scores:
            scores[cid] = {
                "rrf_score": 0.0,
                "file_path": r["file_path"],
                "section": r["section"],
                "chunk_text": r["chunk_text"],
                "bm25_rank": None,
                "vec_rank": None,
            }
        scores[cid]["rrf_score"] += vec_weight / (self._rrf_k + rank)
        scores[cid]["vec_rank"] = rank

    fused = sorted(
        scores.values(),
        key=lambda x: x["rrf_score"],
        reverse=True,
    )
    return fused

Ajustando k

A constante k controla quanta importância é dada aos resultados mais bem ranqueados em comparação com os menos bem ranqueados:

  • k mais baixo (ex.: 10): Resultados no topo dominam. Rank 1 pontua 1/11 = 0,091, rank 10 pontua 1/20 = 0,050 (diferença de 1,8x). Bom quando você confia que os ranqueadores individuais acertam o resultado do topo.
  • k padrão (60): Equilibrado. Rank 1 pontua 1/61 = 0,0164, rank 10 pontua 1/70 = 0,0143 (diferença de 1,15x). Diferenças de rank são comprimidas, dando mais peso ao fato de aparecer em múltiplas listas.
  • k mais alto (ex.: 200): Aparecer em ambas as listas importa muito mais do que a posição de rank. Rank 1 pontua 1/201, rank 10 pontua 1/210 — quase idênticos. Use quando os ranqueadores individuais produzem rankings ruidosos, mas a concordância entre listas é confiável.

Comece com k=60. O artigo original de RRF considerou esse valor robusto em diversos datasets TREC. Ajuste apenas após medir casos de falha na sua própria distribuição de consultas.

Desempate

Quando dois chunks têm pontuações RRF idênticas (raro, mas possível com o mesmo rank em uma lista e nenhuma aparição na outra), desempate por:

  1. Prefira chunks que aparecem em ambas as listas em vez de chunks que aparecem em apenas uma
  2. Entre chunks em ambas as listas, prefira o que tem o menor rank combinado
  3. Entre chunks em apenas uma lista, prefira o que tem o menor rank nessa lista

O pipeline completo de recuperação

Esta seção acompanha uma consulta desde a entrada até a saída através de todo o pipeline: busca BM25, busca vetorial, fusão RRF, truncamento por orçamento de tokens e montagem de contexto.

Fluxo de ponta a ponta

User query: "PostToolUse hook for context compression"
  │
  ├─ BM25 Search (FTS5)
  │    → MATCH "PostToolUse hook context compression"
  │    → Top 30 results ranked by BM25 score
  │    → 12ms
  │
  ├─ Vector Search (sqlite-vec)
  │    → Embed query with Model2Vec
  │    → KNN k=30 on chunk_vecs
  │    → Top 30 results ranked by cosine distance
  │    → 8ms
  │
  └─ RRF Fusion
       → Merge 60 candidates (may overlap)
       → Score by rank position
       → Top 10 results
       → 3ms
       │
       └─ Token Budget
            → Truncate to max_tokens (default 4000)
            → Estimate at 4 chars per token
            → Return results with metadata
            → <1ms

Latência total: ~23ms para um banco de dados de 49.746 chunks em hardware Apple M3 Pro.

O API de busca

class HybridRetriever:
    def search(self, query, limit=10, max_tokens=4000,
               bm25_weight=1.0, vec_weight=1.0):
        """
        Search the vault using hybrid BM25 + vector retrieval.

        Args:
            query: Search query text
            limit: Maximum results to return
            max_tokens: Token budget for total result text
            bm25_weight: Weight for BM25 results in RRF
            vec_weight: Weight for vector results in RRF

        Returns:
            List of SearchResult with file_path, section,
            chunk_text, rrf_score, bm25_rank, vec_rank
        """
        # BM25 search
        bm25_results = self._bm25_search(query, limit=30)

        # Vector search (if available)
        if self.index.vec_available:
            vec_results = self._vector_search(query, limit=30)
            fused = self._rrf_fuse(
                bm25_results, vec_results,
                bm25_weight, vec_weight,
            )
        else:
            fused = bm25_results  # BM25-only fallback

        # Token budget truncation
        results = []
        token_count = 0
        for r in fused[:limit]:
            chunk_tokens = len(r["chunk_text"]) // 4
            if token_count + chunk_tokens > max_tokens:
                break
            results.append(r)
            token_count += chunk_tokens

        return results

Truncamento por orçamento de tokens

O parâmetro max_tokens impede que o recuperador retorne mais contexto do que a ferramenta de IA consegue utilizar. A estimativa usa 4 caracteres por token (uma aproximação razoável para texto em inglês). Os resultados são truncados de forma gulosa: adiciona resultados na ordem do ranking até que o orçamento se esgote.

Essa é uma estratégia conservadora. Uma abordagem mais sofisticada consideraria pontuações de qualidade por resultado e priorizaria resultados mais curtos e de maior qualidade em vez de resultados mais longos e de menor qualidade. A abordagem gulosa é mais simples e funciona bem na prática porque o ranking RRF já ordena os resultados por relevância.

Schema do banco de dados (completo)

-- Chunk content and metadata
CREATE TABLE chunks (
    id INTEGER PRIMARY KEY,
    file_path TEXT NOT NULL,
    section TEXT NOT NULL,
    chunk_text TEXT NOT NULL,
    heading_context TEXT DEFAULT '',
    mtime_ns INTEGER NOT NULL,
    embedded_at REAL NOT NULL
);

CREATE INDEX idx_chunks_file ON chunks(file_path);
CREATE INDEX idx_chunks_mtime ON chunks(mtime_ns);

-- FTS5 for BM25 search (content-synced to chunks table)
CREATE VIRTUAL TABLE chunks_fts USING fts5(
    chunk_text, section, heading_context,
    content=chunks, content_rowid=id
);

-- sqlite-vec for vector KNN search
CREATE VIRTUAL TABLE chunk_vecs USING vec0(
    id INTEGER PRIMARY KEY,
    embedding float[256]
);

-- Model metadata for compatibility tracking
CREATE TABLE model_meta (
    key TEXT PRIMARY KEY,
    value TEXT
);

Caminho de degradação gradual

Full pipeline:     BM25 + Vector + RRF    Best results
No sqlite-vec:     BM25 only              Good results (no semantic)
No model download:  BM25 only              Good results (no semantic)
No FTS5:           Vector only             Decent results (no keyword)
No database:       Error                   Prompt user to run indexer

O recuperador verifica as capacidades disponíveis durante a inicialização e adapta sua estratégia de consulta. Um componente ausente degrada a qualidade, mas não causa erros. A única falha crítica é a ausência do arquivo de banco de dados.

Estatísticas de produção

Medido em um vault de 16.894 arquivos, 49.746 chunks, banco de dados SQLite de 83 MB, Apple M3 Pro:

Métrica Valor
Total de arquivos 16.894
Total de chunks 49.746
Tamanho do banco de dados 83 MB
Latência de consulta BM25 (p50) 12ms
Latência de consulta vetorial (p50) 8ms
Latência da fusão RRF 3ms
Latência de busca ponta a ponta (p50) 23ms
Tempo de reindexação completa ~4 minutos
Tempo de reindexação incremental <10 segundos
Modelo de embeddings potion-base-8M (256-dim)
Pool de candidatos BM25 30
Pool de candidatos vetoriais 30
Limite padrão de resultados 10
Orçamento padrão de tokens 4.000 tokens

Hashing de conteúdo e detecção de alterações

O indexador precisa saber quais arquivos foram modificados desde a última execução de indexação. Esta seção aborda o mecanismo de detecção de alterações e a estratégia de hashing.

Comparação por tempo de modificação do arquivo

O indexador armazena mtime_ns (tempo de modificação do arquivo em nanossegundos) para cada chunk na tabela chunks. Em uma execução incremental, o indexador:

  1. Varre o vault em busca de todos os arquivos .md nas pastas permitidas
  2. Lê o mtime_ns de cada arquivo a partir do sistema de arquivos
  3. Compara com o mtime_ns armazenado no banco de dados
  4. Identifica três categorias:
  5. Arquivos novos: o caminho existe no sistema de arquivos, mas não no banco de dados
  6. Arquivos alterados: o caminho existe em ambos, mas o mtime_ns difere
  7. Arquivos excluídos: o caminho existe no banco de dados, mas não no sistema de arquivos
def get_stale_files(self, vault_mtimes):
    """Find files whose mtime changed or are new."""
    stored = dict(self.db.execute(
        "SELECT DISTINCT file_path, mtime_ns FROM chunks"
    ).fetchall())

    stale = []
    for path, mtime in vault_mtimes.items():
        if path not in stored or stored[path] != mtime:
            stale.append(path)
    return stale

def get_deleted_files(self, vault_paths):
    """Find files in database that no longer exist in vault."""
    stored_paths = set(r[0] for r in self.db.execute(
        "SELECT DISTINCT file_path FROM chunks"
    ).fetchall())
    return stored_paths - set(vault_paths)

Por que mtime e não hash de conteúdo

O hashing de conteúdo (SHA-256 do conteúdo do arquivo) seria mais confiável do que a comparação por mtime — detectaria casos em que um arquivo foi tocado sem ser alterado (por exemplo, um git checkout restaurando o mtime original). Porém, o hashing exige a leitura de cada arquivo em toda execução incremental. Para 16.894 arquivos, ler o conteúdo leva de 2 a 3 segundos. Ler os mtimes do sistema de arquivos leva menos de 100ms.

O trade-off: a comparação por mtime ocasionalmente dispara reindexações desnecessárias de arquivos inalterados (falsos positivos), mas nunca deixa de detectar alterações reais. Falsos positivos custam algumas chamadas extras de embedding por execução. A diferença de velocidade (100ms contra 3 segundos) torna o mtime a escolha pragmática para um sistema que roda a cada interação com IA.

Tratamento de exclusões

Quando um arquivo é excluído do vault, o indexador remove todos os seus chunks do banco de dados:

def remove_file(self, file_path):
    """Remove all chunks and vectors for a file."""
    chunk_ids = [r[0] for r in self.db.execute(
        "SELECT id FROM chunks WHERE file_path = ?",
        [file_path],
    ).fetchall()]

    for cid in chunk_ids:
        self.db.execute(
            "DELETE FROM chunk_vecs WHERE id = ?", [cid]
        )
    self.db.execute(
        "DELETE FROM chunks WHERE file_path = ?",
        [file_path],
    )

O comando DELETE FROM chunk_vecs funciona nativamente a partir do sqlite-vec v0.1.7.26 Versões anteriores exigiam contornos (excluir e recriar a tabela virtual, ou manter um conjunto externo de “IDs ativos”). Se você está usando uma versão anterior à 0.1.7, atualize antes de depender de exclusões diretas.

Tabelas FTS5 com sincronização de conteúdo exigem exclusão explícita via INSERT INTO chunks_fts(chunks_fts, rowid, ...) VALUES('delete', ?, ...) para cada linha removida. O indexador lida com isso como parte do processo de remoção de arquivo.


Reindexação incremental vs completa

O indexador suporta dois modos: incremental (rápido, uso diário) e completo (lento, ocasional). Esta seção aborda quando usar cada um, as garantias de idempotência e a recuperação de corrupção.

Reindexação incremental

Quando usar: Indexação diária após editar notas. É o modo padrão.

O que faz: 1. Escaneia o vault em busca de alterações nos arquivos (comparação de mtime) 2. Exclui chunks de arquivos deletados 3. Refaz o chunking e os embeddings de arquivos modificados 4. Insere novos chunks para arquivos novos 5. Sincroniza o índice FTS5

Duração típica: <10 segundos para as edições de um dia em um vault de 16.000 arquivos.

python index_vault.py --incremental

Reindexação completa

Quando usar: - Após trocar o modelo de embedding (incompatibilidade de hash do modelo detectada) - Após migração de schema (novas colunas, índices alterados) - Após corrupção do banco de dados (verificação de integridade falha) - Quando a indexação incremental produz resultados inesperados

O que faz: 1. Remove todos os dados existentes (chunks, vetores, entradas FTS5) 2. Escaneia o vault inteiro 3. Faz o chunking de todos os arquivos 4. Gera embeddings de todos os chunks 5. Reconstrói o índice FTS5 do zero

Duração típica: ~4 minutos para 16.894 arquivos em um Apple M3 Pro.

python index_vault.py --full

Idempotência

Ambos os modos são idempotentes: executar o mesmo comando duas vezes produz o mesmo resultado. O indexador exclui os chunks existentes de um arquivo antes de inserir os novos, então reexecutar a indexação incremental em um banco de dados já atualizado produz zero alterações. Reexecutar a indexação completa produz um banco de dados idêntico.

Recuperação de corrupção

Se o banco de dados SQLite for corrompido (queda de energia durante a escrita, erro de disco, processo encerrado no meio de uma transação):

# Check integrity
sqlite3 vectors.db "PRAGMA integrity_check;"

# If corruption detected, full reindex rebuilds from source files
python index_vault.py --full

A fonte da verdade são sempre os arquivos do vault, não o banco de dados. O banco de dados é um artefato derivado que pode ser reconstruído a qualquer momento. Essa é uma propriedade de design fundamental: você nunca precisa fazer backup do banco de dados.

O flag --incremental

Quando o indexador é executado com --incremental:

  1. Verificação do hash do modelo. Compara o hash do modelo armazenado com o modelo atual. Se forem diferentes, muda automaticamente para o modo de reindexação completa e alerta o usuário.
  2. Escaneamento de arquivos. Percorre as pastas permitidas, coletando caminhos de arquivo e mtimes.
  3. Detecção de alterações. Compara com os dados armazenados.
  4. Processamento em lotes. Refaz o chunking e os embeddings dos arquivos modificados em lotes de 64.
  5. Relatório de progresso. Exibe a contagem de arquivos processados e o tempo decorrido.
  6. Encerramento gracioso. Trata SIGINT finalizando o arquivo atual antes de parar.

Filtragem de credenciais e limites de dados

Notas pessoais contêm segredos: chaves de API, bearer tokens, strings de conexão com banco de dados, chaves privadas coladas durante sessões de debugging. O filtro de credenciais impede que esses dados entrem no índice de busca.

O problema

Uma nota sobre debugging de uma integração OAuth pode conter:

The token was: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
I used this curl command:
  curl -H "Authorization: Bearer sk-ant-api03-abc123..."

Sem filtragem, tanto o JWT quanto a chave API seriam divididos em chunks, convertidos em embeddings e armazenados no banco de dados. Uma busca por “autenticação” retornaria o chunk contendo segredos reais. Pior ainda, se o retriever alimentar resultados para uma ferramenta de IA através de MCP, os segredos aparecem na janela de contexto da IA e potencialmente nos logs da ferramenta.

Filtragem baseada em padrões

O filtro de credenciais é executado em cada chunk antes do armazenamento, identificando 25 padrões específicos de vendors além de padrões genéricos:

Padrões específicos de vendors:

Padrão Exemplo Regex
Chave API OpenAI sk-... sk-[a-zA-Z0-9_-]{20,}
Chave API Anthropic sk-ant-api03-... sk-ant-api\d{2}-[a-zA-Z0-9_-]{20,}
PAT GitHub ghp_... gh[ps]_[a-zA-Z0-9]{36,}
Chave de acesso AWS AKIA... AKIA[0-9A-Z]{16}
Chave Stripe sk_live_... [sr]k_(live\|test)_[a-zA-Z0-9]{24,}
Token Cloudflare ... Padrões variados

Padrões genéricos:

Padrão Detecção
Tokens JWT eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+
Bearer tokens Bearer\s+[a-zA-Z0-9_\-\.]+
Chaves privadas -----BEGIN (RSA\|EC\|OPENSSH) PRIVATE KEY-----
base64 de alta entropia Strings com >4,5 bits/caractere de entropia, 40+ caracteres
Atribuições de senha password\s*[:=]\s*["'][^"']+["']

Implementação do filtro

def clean_content(text):
    """Scrub credentials from text before indexing."""
    result = ScanResult(is_clean=True, match_count=0, patterns=[])

    for pattern in CREDENTIAL_PATTERNS:
        matches = pattern.regex.findall(text)
        if matches:
            text = pattern.regex.sub(
                f"[REDACTED:{pattern.name}]", text
            )
            result.is_clean = False
            result.match_count += len(matches)
            result.patterns.append(pattern.name)

    return text, result

Decisões de design importantes:

  1. Filtrar antes de gerar embeddings. O texto limpo é o que recebe o embedding. A representação vetorial nunca codifica padrões de credenciais. Uma consulta por “chave API” retorna notas que discutem gerenciamento de chaves de API, não notas que contêm chaves reais.

  2. Substituir, não remover. O token [REDACTED:pattern-name] preserva o contexto semântico do texto ao redor. O embedding captura que “algo parecido com uma credencial estava aqui” sem codificar a credencial em si.

  3. Registrar padrões, não valores. O filtro registra quais padrões foram encontrados (ex.: “Scrubbed 2 credential(s) from oauth-debug.md [jwt, bearer-token]”), mas nunca registra o valor da credencial.

Exclusão baseada em caminhos

O arquivo .indexignore fornece exclusão de granularidade grossa por caminho. O filtro de credenciais fornece limpeza de granularidade fina dentro dos arquivos indexados. Ambos são necessários:

  • .indexignore para pastas inteiras que você sabe que contêm conteúdo sensível (notas de saúde, registros financeiros, documentos de carreira)
  • Filtro de credenciais para segredos acidentalmente incorporados em conteúdo que, de outra forma, seria indexável

Classificação de dados

Para vaults com conteúdo diverso, considere classificar as notas por sensibilidade:

Nível Exemplos Indexar? Filtrar?
Público Rascunhos de blog, notas técnicas Sim Sim
Interno Planos de projeto, decisões de arquitetura Sim Sim
Sensível Dados salariais, registros de saúde Não (.indexignore) N/A
Restrito Credenciais, chaves privadas Não (.indexignore) N/A

Arquitetura do servidor MCP

Servidores Model Context Protocol (MCP) expõem o retriever como uma ferramenta que agentes de IA podem chamar. Esta seção cobre o design do servidor, a superfície de capacidades e os limites de permissão.

Escolha de protocolo: STDIO vs HTTP

MCP suporta dois modos de transporte:

STDIO — A ferramenta de IA inicia o servidor MCP como um processo filho e se comunica via stdin/stdout. Este é o modo padrão para ferramentas locais. Claude Code, Codex CLI e Cursor suportam servidores MCP via STDIO.

{
  "mcpServers": {
    "obsidian": {
      "command": "python",
      "args": ["/path/to/obsidian_mcp.py"],
      "env": {
        "VAULT_PATH": "/path/to/vault",
        "DB_PATH": "/path/to/vectors.db"
      }
    }
  }
}

HTTP — O servidor MCP roda como um serviço HTTP independente. Útil para acesso remoto, configurações com múltiplos clientes ou equipes onde o vault está em um servidor compartilhado.

{
  "mcpServers": {
    "obsidian": {
      "url": "http://localhost:3333/mcp"
    }
  }
}

Recomendação: Use STDIO para vaults pessoais. É mais simples, mais seguro (sem exposição de rede), e o ciclo de vida do servidor é gerenciado pela ferramenta de IA. Use HTTP apenas quando múltiplas ferramentas ou múltiplas máquinas precisam de acesso simultâneo ao mesmo vault.

Evolução da especificação MCP. A especificação MCP de junho de 2025 adicionou autorização OAuth 2.1, saídas estruturadas de ferramentas (schemas de retorno tipados) e elicitação (prompts iniciados pelo servidor para o usuário). O lançamento de novembro de 2025 trouxe Streamable HTTP como modo de transporte de primeira classe, descoberta via URL .well-known para navegação automática de capacidades do servidor, anotações estruturadas de ferramentas que declaram se uma ferramenta é somente leitura ou mutável, e um sistema de padronização de camadas SDK.1821 O próximo lançamento da especificação (provisoriamente meados de 2026) propõe operações assíncronas para tarefas de longa duração, extensões de protocolo específicas por domínio para indústrias como saúde e finanças, e padrões de comunicação agente-para-agente para fluxos de trabalho multi-agente.21 Para servidores de vault pessoal, STDIO continua sendo o caminho mais simples. O transporte Streamable HTTP e a descoberta .well-known beneficiam principalmente implantações HTTP empresariais com roteamento multi-tenant e balanceamento de carga. Acompanhe o roadmap do MCP para atualizações que afetem sua escolha de transporte.

Design de capacidades

O servidor MCP deve expor um conjunto mínimo de ferramentas:

search — A ferramenta principal. Executa recuperação híbrida e retorna resultados ranqueados.

{
  "name": "obsidian_search",
  "description": "Search the Obsidian vault using hybrid BM25 + vector retrieval",
  "parameters": {
    "query": { "type": "string", "description": "Search query" },
    "limit": { "type": "integer", "default": 5 },
    "max_tokens": { "type": "integer", "default": 2000 }
  }
}

read_note — Lê o conteúdo completo de uma nota específica pelo caminho. Útil quando o agente quer ver o contexto completo de um resultado de busca.

{
  "name": "obsidian_read_note",
  "description": "Read the full content of a note by file path",
  "parameters": {
    "file_path": { "type": "string", "description": "Relative path within vault" }
  }
}

list_notes — Lista notas que correspondem a um filtro (por pasta, tag, tipo ou intervalo de datas). Útil para exploração quando o agente não tem uma consulta específica.

{
  "name": "obsidian_list_notes",
  "description": "List notes matching filters",
  "parameters": {
    "folder": { "type": "string", "description": "Folder path within vault" },
    "tag": { "type": "string", "description": "Tag to filter by" },
    "limit": { "type": "integer", "default": 20 }
  }
}

get_context — Uma ferramenta de conveniência que executa uma busca e formata os resultados como um bloco de contexto adequado para injeção em uma conversa.

{
  "name": "obsidian_get_context",
  "description": "Get formatted context from vault for a topic",
  "parameters": {
    "topic": { "type": "string", "description": "Topic to get context for" },
    "max_tokens": { "type": "integer", "default": 2000 }
  }
}

Limites de permissão

O servidor MCP deve impor limites rigorosos:

  1. Somente leitura. O servidor lê o vault e o banco de dados de índice. Ele não cria, modifica ou exclui notas. Operações de escrita (capturar novas notas) são tratadas por hooks ou skills separados, não pelo servidor MCP.

  2. Escopo limitado ao vault. O servidor só lê arquivos dentro do caminho configurado do vault. Tentativas de travessia de caminho (../../etc/passwd) devem ser rejeitadas.

  3. Saída com filtragem de credenciais. Mesmo que o banco de dados contenha conteúdo pré-filtrado, aplique filtragem de credenciais na saída como medida de defesa em profundidade.

  4. Respostas com limite de tokens. Imponha max_tokens em todas as respostas de ferramentas para evitar que a ferramenta de IA receba blocos de contexto excessivamente grandes.

Tratamento de erros

Ferramentas MCP devem retornar mensagens de erro estruturadas que ajudem a ferramenta de IA a se recuperar:

def search(self, query, limit=5, max_tokens=2000):
    if not self.db_path.exists():
        return {
            "error": "Index database not found. Run the indexer first.",
            "suggestion": "python index_vault.py --full"
        }

    results = self.retriever.search(query, limit, max_tokens)

    if not results:
        return {
            "results": [],
            "message": f"No results found for '{query}'. Try broader terms."
        }

    return {
        "results": [
            {
                "file_path": r["file_path"],
                "section": r["section"],
                "text": r["chunk_text"],
                "score": round(r["rrf_score"], 4),
            }
            for r in results
        ],
        "count": len(results),
        "query": query,
    }

Integração com Claude Code

Claude Code é o principal consumidor do sistema de recuperação do Obsidian. Esta seção aborda a configuração de MCP, integração com hooks e o padrão obsidian_bridge.py.

Configuração de MCP

Adicione o servidor MCP do Obsidian ao ~/.claude/settings.json:

{
  "mcpServers": {
    "obsidian": {
      "command": "python",
      "args": ["/path/to/obsidian_mcp.py"],
      "env": {
        "VAULT_PATH": "/absolute/path/to/vault",
        "DB_PATH": "/absolute/path/to/vectors.db"
      }
    }
  }
}

Após adicionar a configuração, reinicie o Claude Code. O servidor MCP será iniciado como um processo filho. Verifique se está em execução:

> What tools do you have from the obsidian MCP server?

O Claude Code deve listar as ferramentas disponíveis (obsidian_search, obsidian_read_note, etc.).

Integração com hooks

Hooks estendem o comportamento do Claude Code em pontos definidos do ciclo de vida. Dois hooks são relevantes para a integração com o Obsidian:

Hook PreToolUse — Consulta o vault antes que o agente processe uma chamada de ferramenta. Injeta contexto relevante automaticamente.

#!/bin/bash
# ~/.claude/hooks/pre-tool-use/obsidian-context.sh
# Automatically inject vault context before tool execution

TOOL_NAME="$1"
PROMPT="$2"

# Only inject context for code-related tools
case "$TOOL_NAME" in
    Edit|Write|Bash)
        # Query the vault
        CONTEXT=$(python /path/to/retriever.py search "$PROMPT" --limit 3 --max-tokens 1500)
        if [ -n "$CONTEXT" ]; then
            echo "---"
            echo "Relevant vault context:"
            echo "$CONTEXT"
            echo "---"
        fi
        ;;
esac

Hook PostToolUse — Captura saídas significativas de ferramentas de volta para o vault para recuperação futura.

#!/bin/bash
# ~/.claude/hooks/post-tool-use/capture-insight.sh
# Capture significant outputs to vault (selective)

TOOL_NAME="$1"
OUTPUT="$2"

# Only capture substantial outputs
if [ ${#OUTPUT} -gt 500 ]; then
    python /path/to/capture.py --text "$OUTPUT" --source "claude-code-$TOOL_NAME"
fi

O padrão obsidian_bridge.py

Um módulo bridge fornece uma Python API que hooks e skills podem chamar:

# obsidian_bridge.py
from retriever import HybridRetriever

_retriever = None

def get_retriever():
    global _retriever
    if _retriever is None:
        _retriever = HybridRetriever(
            db_path="/path/to/vectors.db",
            vault_path="/path/to/vault",
        )
    return _retriever

def search_vault(query, limit=5, max_tokens=2000):
    """Search vault and return formatted context."""
    retriever = get_retriever()
    results = retriever.search(query, limit, max_tokens)

    if not results:
        return ""

    lines = ["## Vault Context\n"]
    for r in results:
        lines.append(f"**{r['file_path']}** — {r['section']}")
        lines.append(f"> {r['chunk_text'][:500]}")
        lines.append("")

    return "\n".join(lines)

A skill /capture

Uma skill do Claude Code para capturar insights de volta para o vault:

/capture "OAuth token rotation requires both access and refresh token invalidation"
  --domain security
  --tags oauth,tokens

A skill cria uma nova nota em 00-inbox/ com frontmatter adequado e dispara uma reindexação incremental para que a nova nota seja imediatamente pesquisável.

Padrões de comandos personalizados

Skills do Claude Code podem encapsular operações do vault em comandos nomeados. Praticantes construíram bibliotecas de comandos específicos para o Obsidian que tratam o vault tanto como fonte de leitura quanto como destino de escrita.

Varredura de sinais. Um comando /scan-intel consulta fontes externas, pontua descobertas com base em interesses de pesquisa pessoais e escreve sinais qualificados como notas do vault com frontmatter:

/scan-intel --topics "agent infrastructure, security" --lookback 7d

O comando busca em fontes configuradas (arXiv, HN, RSS), aplica um modelo de pontuação (relevância, acionabilidade, profundidade, autoridade) e escreve sinais aprovados em pastas temáticas do vault. O vault se torna o consumidor downstream de um pipeline automatizado de inteligência.

Diário de bordo. Um comando /captains-log agrega a atividade diária do git em todos os repositórios, escreve uma entrada de diário estruturada no vault e inclui decisões tomadas, percepções e questões em aberto:

/captains-log

O comando puxa o histórico de commits do GitHub, agrupa por repositório e formata como uma entrada narrativa de diário. Com o tempo, os registros diários criam um histórico pesquisável do que foi entregue e por quê.

Captura para o Obsidian. Um comando /obsidian-capture pega um insight da sessão atual do Claude Code e o escreve diretamente no vault com metadados adequados:

/obsidian-capture "SAST gates in agent loops increase security degradation"
  --folder AI-Tools --tags security,agents

O padrão se estende a qualquer operação do vault: criar MOCs, atualizar notas de status de projeto, vincular sinais relacionados ou gerar resumos semanais a partir dos registros diários acumulados.

Exemplos da comunidade. Praticantes estão publicando suas bibliotecas de comandos. Um desenvolvedor compartilhou 22 comandos personalizados de Obsidian + Claude Code cobrindo revisões diárias, planejamento de projetos, captura de pesquisas e workflows de conteúdo.1 Outro construiu uma skill “Visual Explainer” que gera notas de diagramas no vault a partir de análise de código.2 Os comandos variam, mas a arquitetura é consistente: skills do Claude Code como interface, notas do vault como camada de armazenamento e infraestrutura de recuperação como motor de consulta.

Gerenciamento da janela de contexto

A integração deve ser consciente da janela de contexto do Claude Code:

  • Limite o contexto injetado a 1.500-2.000 tokens por consulta. Mais do que isso compete com a memória de trabalho do agente.
  • Inclua atribuição de fonte. Sempre inclua o caminho do arquivo e o título da seção para que o agente possa referenciar a origem.
  • Trunque o texto dos chunks. Chunks longos devem ser truncados com ... em vez de omitidos completamente. Os primeiros 300-500 caracteres geralmente contêm a informação principal.
  • Não injete em toda chamada de ferramenta. O hook PreToolUse deve injetar contexto seletivamente com base na ferramenta sendo chamada. Operações de leitura não precisam de contexto do vault. Operações de escrita e edição se beneficiam dele.

Integração com Codex CLI

O Codex CLI se conecta a servidores MCP através do config.toml. O padrão de integração difere do Claude Code na sintaxe de configuração e na entrega de instruções.

Configuração de MCP

Adicione ao .codex/config.toml ou ~/.codex/config.toml:

[mcp_servers.obsidian]
command = "python"
args = ["/path/to/obsidian_mcp.py"]

[mcp_servers.obsidian.env]
VAULT_PATH = "/absolute/path/to/vault"
DB_PATH = "/absolute/path/to/vectors.db"

Padrões do AGENTS.md

O Codex CLI lê o AGENTS.md para instruções em nível de projeto. Inclua orientações de busca no vault:

## Available Tools

### Obsidian Vault (MCP: obsidian)
Use the `obsidian_search` tool to find relevant context from the knowledge base.
Search the vault when you need:
- Background on a concept or pattern
- Prior decisions or rationale
- Reference material for implementation

Example queries:
- "authentication patterns in FastAPI"
- "how does the review aggregator work"
- "sqlite-vec configuration"

Diferenças em relação ao Claude Code

Recurso Claude Code Codex CLI
Configuração MCP settings.json config.toml
Hooks ~/.claude/hooks/ Não suportado
Skills ~/.claude/skills/ Não suportado
Arquivo de instruções CLAUDE.md AGENTS.md
Modos de aprovação --dangerously-skip-permissions suggest / auto-edit / full-auto

Diferença principal: O Codex CLI não suporta hooks. O padrão de injeção automática de contexto (hook PreToolUse) não está disponível. Em vez disso, inclua instruções explícitas no AGENTS.md orientando o agente a pesquisar o vault antes de iniciar o trabalho.


Cursor e outras ferramentas

Cursor e outras ferramentas de IA que suportam MCP podem se conectar ao mesmo servidor MCP do Obsidian. Esta seção cobre a configuração para ferramentas comuns.

Cursor

Adicione ao .cursor/mcp.json na raiz do seu projeto:

{
  "mcpServers": {
    "obsidian": {
      "command": "python",
      "args": ["/path/to/obsidian_mcp.py"],
      "env": {
        "VAULT_PATH": "/absolute/path/to/vault",
        "DB_PATH": "/absolute/path/to/vectors.db"
      }
    }
  }
}

O arquivo .cursorrules do Cursor pode incluir instruções para usar o vault:

When working on implementation tasks, search the Obsidian vault
for relevant context before writing code. Use the obsidian_search
tool with descriptive queries about the concept you're implementing.

Matriz de compatibilidade

Ferramenta Suporte a MCP Transporte Local de configuração
Claude Code Completo STDIO ~/.claude/settings.json
Codex CLI Completo STDIO .codex/config.toml
Cursor Completo STDIO .cursor/mcp.json
Windsurf Completo STDIO .windsurf/mcp.json
Continue.dev Parcial HTTP ~/.continue/config.json
Zed Em andamento STDIO Interface de configurações
Claudian (plugin do Obsidian) N/A (embutido) Claude Code CLI Configurações do plugin do Obsidian
Agent Client (plugin do Obsidian) N/A (embutido) ACP Configurações do plugin do Obsidian

Alternativa para ferramentas sem suporte a MCP

Para ferramentas que não suportam MCP, o retriever pode ser encapsulado como uma CLI:

# Search from command line
python retriever_cli.py search "query text" --limit 5

# Output formatted for copy-paste into any tool
python retriever_cli.py context "query text" --format markdown

A CLI gera texto estruturado que pode ser colado manualmente na entrada de qualquer ferramenta de IA. É menos elegante que a integração via MCP, mas funciona universalmente.


Prompt caching a partir de notas estruturadas

Notas estruturadas no vault podem servir como blocos de contexto reutilizáveis que reduzem o consumo de tokens nas interações com IA. Esta seção cobre o design de chaves de cache e o gerenciamento do orçamento de tokens.

O padrão

Em vez de buscar contexto a cada interação, pré-construa blocos de contexto a partir de notas bem estruturadas do vault e armazene-os em cache:

# cache_keys.py
CONTEXT_BLOCKS = {
    "auth-patterns": {
        "vault_query": "authentication patterns implementation",
        "max_tokens": 1500,
        "ttl_hours": 24,  # Rebuild daily
    },
    "api-conventions": {
        "vault_query": "API design conventions REST patterns",
        "max_tokens": 1000,
        "ttl_hours": 168,  # Rebuild weekly
    },
    "project-architecture": {
        "vault_query": "current project architecture decisions",
        "max_tokens": 2000,
        "ttl_hours": 12,  # Rebuild twice daily
    },
}

Invalidação de cache

A invalidação de cache é baseada em dois sinais:

  1. Expiração do TTL. Cada bloco de contexto tem um tempo de vida (time-to-live). Quando o TTL expira, o bloco é reconstruído consultando o vault novamente.
  2. Detecção de alterações no vault. Quando o indexador detecta alterações em arquivos que contribuíram para um bloco de contexto em cache, o bloco é invalidado imediatamente.

Gerenciamento do orçamento de tokens

Uma sessão começa com um orçamento total de contexto. Os blocos em cache consomem parte desse orçamento:

Total context budget:    8,000 tokens
├─ System prompt:        1,500 tokens
├─ Cached blocks:        3,000 tokens (pre-loaded)
├─ Dynamic search:       2,000 tokens (on-demand)
└─ Conversation:         1,500 tokens (remaining)

Os blocos em cache são carregados no início da sessão. Os resultados de busca dinâmica preenchem o orçamento restante por consulta. Essa abordagem híbrida dá ao agente uma base de contexto frequentemente necessário, preservando orçamento para consultas específicas.

Antes/depois do uso de tokens

Sem cache: cada consulta relevante aciona uma busca no vault, retornando 1.500-2.000 tokens de contexto. Ao longo de 10 consultas em uma sessão, o agente consome 15.000-20.000 tokens de contexto do vault.

Com cache: três blocos de contexto pré-construídos consomem 4.500 tokens no total. Buscas adicionais acrescentam 1.500-2.000 tokens por consulta única. Ao longo de 10 consultas, onde 6 são cobertas pelos blocos em cache, o agente consome 4.500 + (4 × 1.500) = 10.500 tokens — aproximadamente metade do consumo sem cache.


Hooks PostToolUse para compressão de contexto

As saídas de ferramentas podem ser verbosas: stack traces, listagens de arquivos, resultados de testes. Um hook PostToolUse pode comprimir essas saídas antes que elas consumam espaço na janela de contexto.

O problema

Uma chamada da ferramenta Bash que executa testes pode retornar:

PASSED tests/test_auth.py::test_login_success
PASSED tests/test_auth.py::test_login_failure
PASSED tests/test_auth.py::test_token_refresh
PASSED tests/test_auth.py::test_session_expiry
... (200 more lines)
FAILED tests/test_api.py::test_rate_limit_exceeded

A saída completa tem 5.000 tokens, mas o sinal está em 2 linhas: 200 passaram, 1 falhou.

Implementação do hook

#!/bin/bash
# ~/.claude/hooks/post-tool-use/compress-output.sh
# Compress verbose tool outputs to preserve context window

TOOL_NAME="$1"
OUTPUT="$2"
OUTPUT_LEN=${#OUTPUT}

# Only compress large outputs
if [ "$OUTPUT_LEN" -lt 2000 ]; then
    exit 0  # Pass through unchanged
fi

case "$TOOL_NAME" in
    Bash)
        # Compress test output
        if echo "$OUTPUT" | grep -q "PASSED\|FAILED"; then
            PASSED=$(echo "$OUTPUT" | grep -c "PASSED")
            FAILED=$(echo "$OUTPUT" | grep -c "FAILED")
            FAILURES=$(echo "$OUTPUT" | grep "FAILED")
            echo "Tests: $PASSED passed, $FAILED failed"
            if [ "$FAILED" -gt 0 ]; then
                echo "Failures:"
                echo "$FAILURES"
            fi
        fi
        ;;
esac

Prevenção de disparo recursivo

Um hook de compressão que emite saída pode disparar a si mesmo se não houver uma proteção:

# Guard against recursive invocation
if [ -n "$COMPRESS_HOOK_ACTIVE" ]; then
    exit 0
fi
export COMPRESS_HOOK_ACTIVE=1

Heurísticas de compressão

Tipo de saída Detecção Estratégia de compressão
Resultados de teste Palavras-chave PASSED / FAILED Contar aprovações/falhas, mostrar apenas falhas
Listagem de arquivos ls ou find no comando Truncar nas primeiras 20 entradas + contagem
Stack traces Palavra-chave Traceback Manter primeiro e último frame + mensagem de erro
Git status modified: / new file: Resumir contagens por status
Saída de build warning: / error: Remover linhas informativas, manter warnings/errors

Pipeline de intake e triagem de sinais

A camada de intake determina o que entra no vault. Sem curadoria, o vault acumula ruído. Esta seção cobre o pipeline de pontuação que roteia sinais para pastas de domínio.

Fontes

Os sinais vêm de múltiplos canais:

  • Feeds RSS: blogs técnicos, alertas de segurança, notas de lançamento
  • Bookmarks: favoritos do navegador salvos via Obsidian Web Clipper ou bookmarklet
  • Newsletters: trechos-chave de newsletters por email
  • Captura manual: notas escritas durante leitura, conversas ou pesquisa
  • Saída de ferramentas: saídas significativas de ferramentas de IA capturadas via hooks
  • iOS Share Extension: o app iOS do Obsidian (atualizado no início de 2026) inclui uma Share Extension que salva conteúdo do Safari, redes sociais e outros apps diretamente no vault sem abrir o Obsidian.31 Isso cria um caminho de intake mobile com baixa fricção — compartilhe um artigo do Safari e ele chega como uma nota no vault pronta para pontuação.
  • Obsidian CLI: scripts de shell e hooks podem criar notas via obsidian file create ou adicionar conteúdo a notas existentes via obsidian file append, habilitando pipelines de intake automatizados no desktop.

Dimensões de pontuação

Cada sinal é pontuado em quatro dimensões (0,0 a 1,0 cada):

Dimensão Pergunta Pontuação baixa (0,0-0,3) Pontuação alta (0,7-1,0)
Relevância Isso se relaciona com meus domínios ativos? Tangencial, fora do escopo Diretamente relevante para o trabalho em andamento
Acionabilidade Posso usar essa informação? Teoria pura, sem aplicação Técnica ou padrão específico que posso aplicar
Profundidade Quão substancial é o conteúdo? Manchetes, resumo superficial Análise detalhada com exemplos
Autoridade Quão confiável é a fonte? Blog anônimo, não verificado Fonte primária, revisada por pares, especialista reconhecido

Pontuação composta e roteamento

composite = (relevance * 0.35) + (actionability * 0.25) +
            (depth * 0.25) + (authority * 0.15)
Faixa de pontuação Ação
0,55+ Roteamento automático para pasta de domínio
0,40 - 0,55 Enfileirar para revisão manual
< 0,40 Descartar (não armazenar)

Roteamento por domínio

Sinais com pontuação acima de 0,55 são roteados para uma das 12 pastas de domínio com base em correspondência de palavras-chave e classificação de tópicos:

05-signals/
├── ai-tooling/        # Claude, LLMs, AI development tools
├── security/          # Vulnerabilities, auth, cryptography
├── systems/           # Architecture, distributed systems
├── programming/       # Languages, patterns, algorithms
├── web/               # Frontend, backends, APIs
├── data/              # Databases, data engineering
├── devops/            # CI/CD, containers, infrastructure
├── design/            # UI/UX, product design
├── mobile/            # iOS, Android, cross-platform
├── career/            # Industry trends, hiring, growth
├── research/          # Academic papers, whitepapers
└── other/             # Signals that don't fit a domain

Estatísticas de produção

Ao longo de 14 meses de operação:

Métrica Valor
Total de sinais processados 7.771
Roteados automaticamente (>0,55) 4.832 (62%)
Enfileirados para revisão (0,40-0,55) 1.543 (20%)
Descartados (<0,40) 1.396 (18%)
Pastas de domínio ativas 12
Média de sinais por dia ~18

Padrões de grafo de conhecimento

O grafo de wiki-link do Obsidian codifica relacionamentos entre notas. Esta seção aborda semântica de links, travessia de grafo para expansão de contexto e anti-padrões que degradam a qualidade do grafo.

Cada wiki-link cria uma aresta direcionada no grafo. O Obsidian rastreia tanto links diretos quanto backlinks:

  • Link direto: A Nota A contém [[Nota B]] → A aponta para B
  • Backlink: A Nota B mostra que a Nota A a referencia

O grafo codifica diferentes tipos de relacionamentos dependendo do contexto:

Padrão de link Semântica Exemplo
Link inline “Está relacionado a” “Veja [[OAuth Token Rotation]] para detalhes”
Link de cabeçalho “Tem subtópico” ”## Relacionados\n- [[Token Rotation]]\n- [[Session Management]]”
Link tipo tag “É categorizado como” ”[[type/reference]]”
Link MOC “Faz parte de” Uma nota Map of Content listando notas relacionadas

Maps of Content (MOCs)

MOCs são notas de índice que organizam notas relacionadas em uma estrutura navegável:

---
title: "Authentication & Security MOC"
type: moc
domain: security
---

## Core Concepts
- [[OAuth 2.0 Overview]]
- [[JWT Token Anatomy]]
- [[Session Management Patterns]]

## Implementation Patterns
- [[OAuth Token Rotation]]
- [[Refresh Token Security]]
- [[PKCE Flow Implementation]]

## Failure Modes
- [[Token Expiry Handling]]
- [[Session Fixation Prevention]]
- [[CSRF Defense Strategies]]

MOCs beneficiam a recuperação de duas formas:

  1. Correspondência direta. Uma busca por “visão geral de autenticação” encontra o próprio MOC, fornecendo ao agente uma lista curada de notas relacionadas.
  2. Expansão de contexto. Após encontrar uma nota específica, o retriever pode verificar se a nota aparece em algum MOC e incluir a estrutura do MOC nos resultados, dando ao agente um mapa do tópico mais amplo.

Travessia de grafo para expansão de contexto

Uma melhoria futura para o retriever: após encontrar os melhores resultados, expandir o contexto seguindo os links:

def expand_context(results, depth=1):
    """Follow wiki-links from top results to find related context."""
    expanded = set()
    for result in results:
        # Parse wiki-links from chunk text
        links = extract_wiki_links(result["chunk_text"])
        for link_target in links:
            # Resolve link to file path
            target_path = resolve_wiki_link(link_target)
            if target_path and target_path not in expanded:
                expanded.add(target_path)
                # Include target's most relevant chunk
                target_chunks = get_chunks_for_file(target_path)
                # ... rank and include best chunk
    return results + list(expanded_results)

Isso não está implementado no retriever atual, mas representa uma extensão natural da estrutura de grafo.

Anti-padrões

Clusters órfãos. Grupos de notas que se linkam entre si, mas não possuem conexões com o restante do vault. O painel de grafo do Obsidian torna esses grupos visíveis como ilhas desconectadas. Clusters órfãos indicam MOCs ausentes ou links entre domínios faltando.

Proliferação de tags. Usar tags de forma inconsistente ou criar tags excessivamente granulares. Um vault com 500 tags únicas em 5.000 notas tem em média 1 nota a cada 10 tags — as tags não são úteis para filtragem. Consolide para 20-50 tags de alto nível que mapeiem suas pastas de domínio.

Notas com muitos links e pouco conteúdo. Notas que consistem inteiramente de wiki-links sem texto. Essas notas são mal indexadas porque o chunker não tem texto para gerar embeddings. Adicione pelo menos um parágrafo de contexto explicando por que as notas linkadas estão relacionadas.

Links bidirecionais para tudo. Nem toda referência precisa ser um wiki-link. Mencionar “OAuth” de passagem não requer [[OAuth 2.0 Overview]]. Reserve wiki-links para relacionamentos intencionais e navegáveis, onde clicar no link forneceria contexto útil.


Receitas de workflow para desenvolvedores

Workflows práticos que combinam recuperação do vault com tarefas diárias de desenvolvimento.

Carregamento de contexto matinal

Comece o dia carregando o contexto relevante:

Search my vault for notes about [current project] updated in the last week

O retriever retorna notas recentes sobre seu projeto ativo, oferecendo uma recapitulação rápida de onde você parou. Mais eficaz do que reler as mensagens de commit do dia anterior.

Captura de pesquisa durante a codificação

Ao implementar uma funcionalidade, capture insights sem sair do editor:

/capture "FastAPI dependency injection with async generators requires yield,
not return. The generator is the dependency lifecycle."
  --domain programming
  --tags fastapi,dependency-injection

O insight capturado é indexado imediatamente e fica disponível para recuperação futura. Ao longo dos meses, essas micro-capturas constroem um corpus de conhecimento específico de implementação.

Início de projeto

Ao começar um novo projeto ou funcionalidade:

  1. Busque no vault: “O que eu sei sobre [tecnologia/padrão]?”
  2. Revise os 5 melhores resultados em busca de decisões anteriores e armadilhas
  3. Verifique se existe um MOC para o domínio; se não, crie um
  4. Busque por modos de falha: “problemas com [tecnologia]”

Debugging com busca no vault

Ao encontrar um erro ou comportamento inesperado:

Search my vault for [error message or symptom]

Notas de debugging anteriores frequentemente contêm a causa raiz e a correção. Isso é particularmente valioso para problemas recorrentes entre projetos — o vault lembra o que você esquece.

Preparação para code review

Antes de revisar um PR:

Search my vault for patterns and conventions about [module being changed]

O vault retorna decisões anteriores, restrições arquiteturais e padrões de codificação relevantes para o código em revisão. A review é informada por conhecimento institucional, não apenas pelo diff.


Otimização de desempenho

Esta seção aborda estratégias de otimização para diferentes tamanhos de vault e padrões de uso.

Gerenciamento do tamanho do índice

Tamanho do vault Chunks Tamanho do DB Reindexação completa Incremental
500 notas ~1.500 3 MB 15 segundos <1 segundo
2.000 notas ~6.000 12 MB 45 segundos 2 segundos
5.000 notas ~15.000 30 MB 2 minutos 4 segundos
15.000 notas ~50.000 83 MB 4 minutos <10 segundos
50.000 notas ~150.000 250 MB 15 minutos 30 segundos

Com 50.000+ notas, considere: - Aumentar o batch size de 64 para 128 para gerar embeddings mais rápido - Usar modo WAL (padrão) para acesso concorrente - Executar reindexação completa fora do horário de pico

Otimização de consultas

Modo WAL. O modo Write-Ahead Logging do SQLite permite leituras concorrentes enquanto o indexador escreve:

db.execute("PRAGMA journal_mode=WAL")

Isso é essencial quando o servidor MCP atende consultas enquanto o indexador executa uma atualização incremental.

Pool de conexões. O servidor MCP deve reutilizar conexões com o banco de dados em vez de abrir uma nova conexão por consulta. Uma única conexão persistente com modo WAL suporta leituras concorrentes.

# MCP server initialization
db = sqlite3.connect(DB_PATH, check_same_thread=False)
db.execute("PRAGMA journal_mode=WAL")
db.execute("PRAGMA mmap_size=268435456")  # 256 MB mmap

I/O com mapeamento de memória. O pragma mmap_size instrui o SQLite a usar I/O com mapeamento de memória para o arquivo do banco de dados. Para um banco de 83 MB, mapear o arquivo inteiro na memória elimina a maioria das leituras de disco.

Otimização do FTS5. Após uma reindexação completa, execute:

INSERT INTO chunks_fts(chunks_fts) VALUES('optimize');

Isso mescla os segmentos internos de b-tree do FTS5, reduzindo a latência de consultas nas buscas subsequentes.

Benchmarks de escalabilidade

Medido em Apple M3 Pro, 36 GB de RAM, SSD NVMe:

Operação 500 notas 5K notas 15K notas 50K notas
Consulta BM25 2ms 5ms 12ms 25ms
Consulta vetorial 1ms 3ms 8ms 20ms
Fusão RRF <1ms <1ms 3ms 5ms
Busca completa 3ms 8ms 23ms 50ms

Todos os benchmarks incluem acesso ao banco de dados, execução de consulta e formatação de resultados. A latência de rede para comunicação MCP STDIO adiciona 1-2ms.

Solução de problemas

Desatualização do índice

Sintoma: A busca retorna resultados desatualizados ou não encontra notas adicionadas recentemente.

Causa: O indexador incremental não foi executado após a adição de notas, ou o mtime de um arquivo não foi atualizado (por exemplo, sincronizado de outra máquina com timestamps preservados).

Correção: Execute uma reindexação completa: python index_vault.py --full

Troca do modelo de embedding

Sintoma: Após trocar o modelo de embedding, a busca vetorial retorna resultados sem sentido.

Causa: Vetores antigos (do modelo anterior) estão sendo comparados com vetores de consulta novos. As dimensões ou a semântica do espaço vetorial são incompatíveis.

Correção: O indexador deve detectar a incompatibilidade de hash do modelo e acionar uma reindexação completa automaticamente. Caso isso não aconteça, limpe o banco de dados manualmente e reindexe:

rm vectors.db
python index_vault.py --full

Manutenção do FTS5

Sintoma: Consultas FTS5 retornam resultados incorretos ou incompletos após muitas atualizações incrementais.

Causa: Os segmentos internos do FTS5 podem ficar fragmentados após muitas atualizações pequenas.

Correção: Reconstrua e otimize:

INSERT INTO chunks_fts(chunks_fts) VALUES('rebuild');
INSERT INTO chunks_fts(chunks_fts) VALUES('optimize');

Timeout do MCP

Sintoma: A ferramenta de IA reporta que o servidor MCP expirou o tempo limite.

Causa: A primeira consulta aciona o carregamento do modelo (inicialização lazy), que leva de 2 a 5 segundos. O timeout padrão do MCP da ferramenta de IA pode ser mais curto.

Correção: Pré-aqueça o modelo na inicialização do servidor:

# In MCP server initialization
retriever = HybridRetriever(db_path, vault_path)
retriever.search("warmup", limit=1)  # Trigger model load

Bloqueios de arquivo SQLite

Sintoma: Erros SQLITE_BUSY ou SQLITE_LOCKED.

Causa: Múltiplos processos escrevendo no banco de dados simultaneamente. O modo WAL permite leituras concorrentes, mas apenas um escritor.

Correção: Garanta que apenas um processo (o indexador) escreva no banco de dados. O servidor MCP e os hooks devem apenas ler. Se você precisar de escritas concorrentes, use o modo WAL e defina um busy timeout:

db.execute("PRAGMA busy_timeout=5000")  # Wait up to 5 seconds

sqlite-vec não carrega

Sintoma: A busca vetorial está desativada; o retriever opera apenas no modo BM25.

Causa: A extensão sqlite-vec não está instalada, não foi encontrada no caminho da biblioteca ou é incompatível com a versão do SQLite.

Correção:

# Install via pip
pip install sqlite-vec

# Or compile from source
git clone https://github.com/asg017/sqlite-vec
cd sqlite-vec && make

Verifique se a extensão carrega corretamente:

import sqlite3
db = sqlite3.connect(":memory:")
db.enable_load_extension(True)
db.load_extension("vec0")
print("sqlite-vec loaded successfully")

Problemas de memória em vaults grandes

Sintoma: Erros de falta de memória durante a reindexação completa de um vault grande (mais de 50.000 notas).

Causa: O tamanho do lote de embeddings é muito grande, ou todo o conteúdo dos arquivos está sendo carregado na memória simultaneamente.

Correção: Reduza o tamanho do lote e processe os arquivos de forma incremental:

BATCH_SIZE = 32  # Reduce from 64

Garanta também que o indexador processe os arquivos um de cada vez (lendo, dividindo em chunks e gerando embeddings de cada arquivo antes de passar para o próximo) em vez de carregar todos os arquivos na memória.


Guia de migração

Do Apple Notes

  1. Exporte o Apple Notes pela opção “Export All” (macOS) ou use uma ferramenta de migração como apple-notes-liberator
  2. Converta as exportações HTML para markdown usando markdownify ou pandoc
  3. Mova os arquivos convertidos para a pasta 00-inbox/ do seu vault
  4. Revise e adicione frontmatter a cada nota
  5. Mova as notas para as pastas de domínio apropriadas

Do Notion

  1. Exporte do Notion: Settings → Export → Markdown & CSV
  2. Descompacte a exportação na pasta 00-inbox/ do seu vault
  3. Corrija artefatos de markdown específicos do Notion:
  4. O Notion usa - [ ] para checklists — isso é markdown padrão
  5. O Notion inclui tabelas de propriedades como HTML — converta para frontmatter YAML
  6. O Notion incorpora imagens como caminhos relativos — copie as imagens para sua pasta de anexos
  7. Adicione frontmatter padrão (type, domain, tags)
  8. Substitua os links de página do Notion por wiki-links do Obsidian

Do Google Docs

  1. Use o Google Takeout para exportar todos os documentos
  2. Converta arquivos .docx para markdown: pandoc -f docx -t markdown input.docx -o output.md
  3. Conversão em lote: for f in *.docx; do pandoc -f docx -t markdown "$f" -o "${f%.docx}.md"; done
  4. Mova para o vault, adicione frontmatter e organize em pastas

De markdown puro (sem Obsidian)

Se você já possui um diretório com arquivos markdown:

  1. Abra o diretório como um vault do Obsidian (Obsidian → Open Vault → Open folder)
  2. Adicione .obsidian/ ao .gitignore se o diretório estiver sob controle de versão
  3. Crie templates de frontmatter e aplique aos arquivos existentes
  4. Comece a vincular notas com [[wiki-links]] conforme lê e organiza
  5. Execute o indexador imediatamente — o sistema de recuperação funciona desde o primeiro dia

De outro sistema de recuperação

Se você está migrando de um sistema de embedding/busca diferente:

  1. Não tente migrar vetores. Modelos diferentes produzem espaços vetoriais incompatíveis. Execute uma reindexação completa com o novo modelo.
  2. Migre o conteúdo, não o índice. Os arquivos do vault são a fonte da verdade. O índice é um artefato derivado.
  3. Verifique após a migração. Execute de 10 a 20 consultas cujas respostas você conhece e confirme se os resultados correspondem às suas expectativas.

Registro de alterações

Data Alteração
01/04/2026 Adição da seção Obsidian CLI (comandos v1.12 para fluxos de trabalho com IA). Adição da seção de plugins de agente (Claudian, Agent Client). Documentação do plugin core Bases para organização do vault. Atualização da contagem de plugins para mais de 2.500. Adição do iOS Share Extension como fonte de entrada. Atualização da matriz de compatibilidade com plugins de agente embutidos.
30/03/2026 MCPVault v0.11.0: ferramenta list_all_tags, suporte a .base/.canvas, renomeado para @bitbonsai/mcpvault. Obsidian Desktop v1.12.7 inclui binário CLI para interações mais rápidas no terminal.
23/03/2026 Documentação do sqlite-vec v0.1.7 estável: suporte a DELETE para tabelas vec0, restrições de distância KNN para paginação. Índice DiskANN de vizinho mais próximo aproximado anunciado para lançamento futuro.
07/03/2026 Adição do potion-multilingual-128M (101 idiomas, maio de 2025) à comparação de modelos de embedding. sqlite-vec na versão v0.1.7-alpha.10 (correções de CI/CD, sem mudanças de funcionalidade). Especificação MCP e técnicas de recuperação confirmadas como atuais.
03/03/2026 Atualização da evolução da especificação MCP (novembro de 2025 lançado: Streamable HTTP, .well-known, anotações de ferramentas). Adição de fine-tuning do Model2Vec e suporte a tokenizador BPE/Unigram. Adição de tabela comparativa de servidores MCP da comunidade. Atualização do Smart Connections para v4.
02/03/2026 Adição do potion-base-32M e potion-retrieval-32M à comparação de modelos. Adição da seção de quantização/redução de dimensionalidade. Adição de nota sobre a evolução da especificação MCP.
01/03/2026 Lançamento inicial

Referências


  1. Internet Vin, “22 commands I use with Obsidian and Claude Code,” March 2026, x.com/internetvin/status/2026461256677245131

  2. Nicopreme, “Visual Explainer” agent skill with slash commands, x.com/nicopreme/status/2023495040258261460

  3. Cormack, G.V., Clarke, C.L.A., and Buettcher, S. Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods. SIGIR, 2009. Apresenta o RRF com k=60 como método livre de parâmetros para combinar listas ranqueadas. 

  4. OpenAI Embeddings Pricing. text-embedding-3-small: $0,02 por milhão de tokens. Custo estimado do vault por reindexação completa: ~$0,30. 

  5. van Dongen, T. et al. Model2Vec: Turn any Sentence Transformer into a Small Fast Model. arXiv, 2025. Descreve a abordagem de destilação que produz embeddings estáticos a partir de sentence transformers. 

  6. MTEB: Massive Text Embedding Benchmark. potion-base-8M obtém 50,03 de média vs 56,09 do all-MiniLM-L6-v2 (89% de retenção). 

  7. SQLite FTS5 Extension. O FTS5 oferece busca de texto completo com ranqueamento BM25 e pesos de coluna configuráveis. 

  8. sqlite-vec: A vector search SQLite extension. Fornece tabelas virtuais vec0 para busca vetorial KNN dentro do SQLite. 

  9. Robertson, S. and Zaragoza, H. The Probabilistic Relevance Framework: BM25 and Beyond. Foundations and Trends in Information Retrieval, 2009. 

  10. Karpukhin, V. et al. Dense Passage Retrieval for Open-Domain Question Answering. EMNLP, 2020. Representações densas superam o BM25 em 9-19% em QA de domínio aberto. 

  11. Reimers, N. and Gurevych, I. Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. EMNLP, 2019. Trabalho fundamental sobre similaridade semântica densa. 

  12. Luan, Y. et al. Sparse, Dense, and Attentional Representations for Text Retrieval. TACL, 2021. A recuperação híbrida supera consistentemente abordagens de modalidade única no MS MARCO. 

  13. SQLite Write-Ahead Logging. Modo WAL para leituras concorrentes com um único escritor. 

  14. Gao, Y. et al. Retrieval-Augmented Generation for Large Language Models: A Survey. arXiv, 2024. Levantamento de arquiteturas RAG e estratégias de chunking. 

  15. Thakur, N. et al. BEIR: A Heterogeneous Benchmark for Zero-shot Evaluation of Information Retrieval Models. NeurIPS, 2021. 

  16. Model2Vec: Distill a Small Fast Model from any Sentence Transformer. Minish Lab, 2024. 

  17. Obsidian Documentation. Documentação oficial do Obsidian. 

  18. Model Context Protocol Specification. O padrão MCP para conectar ferramentas de IA a fontes de dados. 

  19. Dados de produção do autor. 16.894 arquivos, 49.746 chunks, banco de dados SQLite de 83,56 MB, 7.771 sinais processados ao longo de 14 meses. Latência de consulta medida via time.perf_counter()

  20. Model2Vec Potion Models. Minish Lab, 2025. Potion-base-32M (MTEB 52,46), potion-retrieval-32M (MTEB retrieval 36,35) e recursos de quantização/redução de dimensionalidade na v0.5.0+. 

  21. Update on the Next MCP Protocol Release. O lançamento de novembro de 2025 trouxe transporte Streamable HTTP, descoberta de URL .well-known, anotações estruturadas de ferramentas e padronização de camadas SDK. O próximo lançamento está previsto provisoriamente para meados de 2026 com operações assíncronas, extensões específicas de domínio e comunicação entre agentes. 

  22. Model2Vec Releases. v0.4.0 (fev 2025): suporte a treinamento/fine-tuning. v0.5.0 (abr 2025): reescrita do backend, quantização, redução de dimensionalidade. v0.7.0 (out 2025): quantização de vocabulário, suporte a tokenizador BPE/Unigram. 

  23. Smart Connections for Obsidian. Smart Connections v4: embeddings de IA local-first, busca semântica funciona offline após a indexação inicial. 

  24. potion-multilingual-128M. Minish Lab, maio de 2025. Modelo de embeddings estáticos para 101 idiomas, melhor desempenho entre embeddings estáticos multilíngues. Mesma dependência exclusiva de numpy dos outros modelos potion. 

  25. MCPVault v0.11.0. Março de 2026. Nova ferramenta list_all_tags para escanear frontmatter e hashtags com contagens. Melhorias no tratamento de pastas com ponto, suporte a arquivos .base e .canvas. Pacote renomeado para @bitbonsai/mcpvault no npm. 

  26. sqlite-vec v0.1.7 Release. 17 de março de 2026. Versão estável: suporte a DELETE para tabelas virtuais vec0, restrições de distância KNN para paginação, melhorias em testes de fuzzing. Indexação DiskANN de vizinho mais próximo aproximado anunciada para lançamento futuro. 

  27. Introduction to Bases. Plugin core do Obsidian introduzido na v1.9.10. Visualizações tipo banco de dados (tabelas, galerias, calendários, quadros kanban) sobre arquivos do vault usando propriedades de frontmatter como campos. Arquivos salvos no formato .base

  28. Obsidian 1.12 Desktop Changelog. 27 de fevereiro de 2026. Apresenta o CLI do Obsidian para automação do vault via terminal. Os comandos incluem busca, notas diárias, templates, propriedades, plugins, tarefas e ferramentas de desenvolvimento. Documentação do CLI

  29. Claudian. Plugin do Obsidian que incorpora o Claude Code como colaborador de IA no vault. Oferece chat na barra lateral, prompts contextuais, suporte a visão, comandos slash e modos de permissão. 

  30. Agent Client. Plugin do Obsidian que fornece uma interface unificada para Claude Code, Codex CLI e Gemini CLI via Agent Client Protocol (ACP). Suporta menções a notas, execução de shell e aprovação de ações. 

  31. Obsidian iOS Changelog. As atualizações do início de 2026 incluem a Share Extension para salvar conteúdo de outros apps diretamente no vault, correções nos widgets de Nota Diária e Favoritos, e melhorias na atualização do widget Visualizar Nota. 

VAULT obsidian.md INDEXED