obsidian:~/vault$ search --hybrid obsidian

Obsidian MCP + recuperación híbrida: referencia de 2026

# Conecta Obsidian con Claude y otros agentes mediante MCP: configuración del servidor, recuperación híbrida con BM25 + vectores e indexación de una bóveda de 16.894 archivos, con configuraciones funcionales.

author: words: 20641 read_time: 95m updated: 2026-08-16 11:28
$ retriever search --hybrid obsidian

Obsidian no es una app para tomar notas. Es un corpus Markdown local-first, de texto plano y estructurado como grafo, que se convierte en un reservorio de contexto para IA cuando agregas infraestructura de recuperación. 16.894 archivos. 49.746 chunks. Consultas de 23 ms. Cero llamadas a API. Un archivo SQLite de 83 MB. Esta guía cubre el sistema completo: desde la arquitectura del vault hasta la recuperación hybrid, la integración con MCP y los flujos de trabajo operativos.


Ideas clave

Ingeniería de contexto, no toma de notas. El valor de un vault de Obsidian para la IA no reside en las notas en sí, sino en la capa de recuperación que permite consultarlas. Un vault de 16.000 archivos sin recuperación es una base de datos de solo escritura. Un vault de 200 archivos con búsqueda hybrid e integración de MCP es una base de conocimientos para IA. La infraestructura de recuperación es el producto. Las notas son la materia prima.

La recuperación hybrid supera a la búsqueda puramente por palabras clave o puramente semántica. BM25 detecta identificadores exactos y nombres de funciones. La búsqueda vectorial detecta sinónimos y coincidencias conceptuales entre terminologías diferentes. Reciprocal Rank Fusion (RRF) combina ambos métodos sin requerir calibración de puntuaciones. Ningún método por sí solo cubre ambos modos de fallo. La investigación sobre el ranking de pasajes de MS MARCO confirma este patrón: la recuperación hybrid supera sistemáticamente a cualquiera de los métodos de forma aislada.3 El análisis detallado del recuperador hybrid explica las matemáticas de RRF, ejemplos resueltos con números reales, análisis de modos de fallo y una calculadora interactiva de fusión.

MCP da a las herramientas de IA acceso directo al vault. Los servidores Model Context Protocol (MCP) exponen el recuperador como una herramienta que Claude Code, Codex CLI, Cursor y otras herramientas de IA pueden invocar directamente. El agente consulta el vault, recibe resultados ordenados con atribución de fuente y utiliza el contexto sin cargar archivos completos. El servidor MCP es una capa ligera sobre el motor de recuperación.

Local-first significa cero costos de API y privacidad total. Toda la pila se ejecuta en una sola máquina: SQLite para almacenamiento, Model2Vec para embeddings, FTS5 para búsqueda por palabras clave, sqlite-vec para KNN vectorial. Sin servicios en la nube, sin llamadas a API, sin dependencia de red. Las notas personales nunca salen de la máquina. La reindexación completa de 49.746 fragmentos costaría aproximadamente $0,30 a los precios de API de OpenAI, pero los costos reales son la latencia, la exposición de privacidad y la dependencia de red de un sistema que debería funcionar sin conexión.4

La indexación incremental mantiene el sistema actualizado en menos de 10 segundos. La comparación de la hora de modificación de los archivos detecta los cambios. Solo se vuelven a fragmentar y generar embeddings para los archivos modificados. Una reindexación completa tarda unos cuatro minutos en hardware Apple de la serie M. Las actualizaciones incrementales de las ediciones de un día típico se ejecutan en menos de diez segundos. El sistema se mantiene actualizado sin intervención manual.

La arquitectura escala de 200 a más de 20.000 notas. El mismo diseño de tres capas (ingesta, recuperación, integración) funciona con cualquier tamaño de vault. Empieza con búsqueda solo con BM25 en un vault pequeño. Agrega búsqueda vectorial cuando las colisiones de palabras clave se conviertan en un problema. Agrega fusión RRF cuando necesites coincidencias exactas y semánticas. Cada capa es útil de forma independiente y también se puede eliminar de forma independiente.


Cómo usar esta guía

Esta guía cubre el sistema completo. Tu punto de partida depende de dónde te encuentres:

Tú eres… Empieza aquí Luego explora
Nuevo en Obsidian + IA Por qué Obsidian para infraestructura de IA, Configuración de Obsidian MCP Arquitectura del vault, Arquitectura del servidor MCP
Tienes un vault y quieres acceso de IA Arquitectura del servidor MCP, Integración de Claude Code Modelos de embeddings, Búsqueda de texto completo
Estás creando un sistema de recuperación El pipeline de recuperación completo, Reciprocal Rank Fusion Ajuste de rendimiento, Solución de problemas
Contexto de equipo o empresa Marco de decisión, Patrones de grafo de conocimiento Recetas de flujo de trabajo para desarrolladores, Guía de migración

Las secciones marcadas como Contrato incluyen detalles de implementación, bloques de configuración y modos de fallo. Las secciones marcadas como Narrativa se enfocan en conceptos, decisiones de arquitectura y el razonamiento detrás de las elecciones de diseño. Las secciones marcadas como Receta proporcionan flujos de trabajo paso a paso.


Por qué Obsidian para infraestructura de IA

La tesis de esta guía: los vaults de Obsidian son el mejor sustrato para las bases de conocimientos personales de IA porque son local-first, de texto plano, estructurados como grafos y el usuario controla cada capa de la pila.

Lo que Obsidian ofrece a la IA y las alternativas no

Archivos Markdown de texto plano. Cada nota es un archivo .md en tu sistema de archivos. Sin formato propietario, sin exportación de base de datos, sin requerir API para leer el contenido. Cualquier herramienta que lea archivos puede leer tu vault. grep, ripgrep, pathlib de Python, SQLite FTS5: todos funcionan directamente sobre los archivos fuente. Cuando creas un sistema de recuperación, indexas archivos, no respuestas de API. El índice siempre es coherente con la fuente porque la fuente es el sistema de archivos.

Arquitectura local-first. El vault reside en tu máquina. Sin servidor, sin dependencia de sincronización en la nube, sin límites de tasa de API, sin términos de servicio que regulen cómo procesas tu propio contenido. Puedes generar embeddings, indexar, fragmentar y buscar en tus notas sin ningún servicio externo. Esto importa para la infraestructura de IA porque el pipeline de recuperación se ejecuta tan rápido como lo permita tu disco, no tan rápido como responda un endpoint de API. También importa para la privacidad: las notas personales que contienen credenciales, datos de salud, información financiera y reflexiones privadas nunca salen de tu máquina.

Estructura de grafo mediante wiki-links. La sintaxis [[wiki-link]] de Obsidian crea un grafo dirigido entre las notas. Una nota sobre la implementación de OAuth enlaza a notas sobre rotación de tokens, gestión de sesiones y seguridad de API. La estructura de grafo codifica relaciones entre conceptos seleccionadas por una persona. Los embeddings vectoriales capturan similitud semántica, pero los wiki-links capturan conexiones intencionales que el autor creó mientras reflexionaba sobre el tema. El grafo es una señal que los embeddings no pueden replicar.

Ecosistema de plugins. Obsidian tiene más de 2.500 plugins de la comunidad (la cifra superó los 2.500 en marzo de 2026, frente a más de 1.800 a mediados de 2025). Dataview consulta tu vault como una base de datos. Templater genera notas a partir de plantillas con lógica de JavaScript. La integración con Git sincroniza tu vault con un repositorio. Linter aplica coherencia de formato. El plugin principal Bases (introducido en la v1.9.10) agrega vistas similares a una base de datos —tablas, galerías, calendarios y tableros kanban— sobre los archivos del vault mediante propiedades de frontmatter como campos, guardadas como archivos .base.15 Estos plugins agregan estructura al vault sin cambiar el formato subyacente de texto plano. El sistema de recuperación indexa la salida de estos plugins, no los plugins en sí.

Más de 5 millones de usuarios. Obsidian tiene una gran comunidad activa que produce plantillas, flujos de trabajo, plugins y documentación. Cuando encuentres un problema con la organización del vault o la configuración de plugins, probablemente alguien ya habrá documentado una solución. La comunidad también produce herramientas adyacentes a Obsidian: servidores MCP, scripts de indexación, pipelines de publicación y wrappers de API.

Lo que un sistema de archivos por sí solo no te ofrece

Un directorio de archivos Markdown tiene la ventaja del texto plano, pero carece de tres cosas que Obsidian agrega:

  1. Enlaces bidireccionales. Obsidian rastrea backlinks automáticamente. Cuando enlazas desde la Nota A a la Nota B, la Nota B muestra que la Nota A la referencia. El panel de grafo visualiza grupos de conexiones. Esta conciencia bidireccional es metadato que un sistema de archivos sin procesar no proporciona.

  2. Vista previa en vivo con renderizado de plugins. Las consultas de Dataview, los diagramas Mermaid y los bloques de llamada se renderizan en tiempo real. La experiencia de escritura es más rica que la de un editor de texto, mientras el formato de almacenamiento sigue siendo texto plano. Escribes y organizas en un entorno enriquecido; el sistema de recuperación indexa el Markdown sin procesar.

  3. Infraestructura de la comunidad. Descubrimiento de plugins, mercado de temas, servicio de sincronización (opcional), servicio de publicación (opcional) y un ecosistema de documentación. Puedes replicar cualquier función individual con herramientas independientes, pero Obsidian las integra en un flujo de trabajo coherente.

Lo que Obsidian NO hace (y lo que tú construyes)

Obsidian no incluye infraestructura de recuperación. Tiene búsqueda básica (texto completo, nombre de archivo, etiqueta), pero no pipeline de embeddings, búsqueda vectorial, ranking por fusión, servidor MCP, filtrado de credenciales, estrategia de fragmentación ni hooks de integración para herramientas externas de IA. Esta guía cubre la infraestructura que construyes sobre Obsidian. El vault es el sustrato. El pipeline de recuperación, el servidor MCP y los hooks de integración son la infraestructura.

La arquitectura descrita aquí es Markdown-first, no exclusiva de Obsidian. Si usas Logseq, Foam, Dendron o un directorio simple de archivos Markdown, el pipeline de recuperación funciona de forma idéntica. El fragmentador lee archivos .md. El generador de embeddings procesa cadenas de texto. El indexador escribe en SQLite. Ninguno de estos componentes depende de funciones específicas de Obsidian. La contribución de Obsidian es el entorno de escritura y organización que produce los archivos Markdown que indexa el recuperador.

Configuración de Obsidian MCP

Model Context Protocol (MCP) es la interfaz estándar que proporciona a Claude Code, Codex CLI, Cursor y otras herramientas de IA acceso directo a un vault de Obsidian. Esta sección conecta un vault con una herramienta de IA en cinco minutos. Instalarás Obsidian, crearás un vault, instalarás un servidor MCP y ejecutarás tu primera consulta. La guía rápida utiliza un servidor MCP de la comunidad para obtener resultados inmediatos. Las secciones posteriores explican cómo crear un pipeline de recuperación personalizado para uso en producción.

Requisitos previos

  • macOS, Linux o Windows
  • Node.js 18+ (para el servidor MCP)
  • Obsidian 1.12+ (para la integración de CLI; 1.13.7 es la versión pública actual de escritorio – las versiones estable y beta convergieron, la línea 1.13 salió de Catalyst el 30 de julio de 2026; las versiones anteriores funcionan en configuraciones solo con MCP)
  • Claude Code, Codex CLI o Cursor instalados

Paso 1: Crea un vault

Descarga Obsidian desde obsidian.md y crea un vault nuevo. Elige una ubicación que recuerdes — el servidor MCP necesita la ruta absoluta.

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

Agrega algunas notas para darle algo con qué trabajar al recuperador. Incluso 10-20 notas bastan para ver resultados. Cada nota debe ser un archivo .md con un título significativo y al menos un párrafo de contenido.

Paso 2: Instala un servidor MCP

Varios servidores MCP de la comunidad proporcionan acceso inmediato al vault. El ecosistema creció significativamente entre 2025 y 2026. Uno destacado es MCPVault (npm @bitbonsai/mcpvault, repositorio bitbonsai/mcpvault), actualmente en la v0.15.0 (verificado en npm el 14 de agosto de 2026) — un proyecto independiente de MarkusPfundstein/mcp-obsidian mencionado más adelante, no un cambio de nombre. La v0.11.0 (marzo de 2026) agregó list_all_tags para analizar frontmatter y hashtags con recuentos, mejoró el manejo de carpetas con puntos y añadió compatibilidad con .base/.canvas. Conviene adoptar las tres correcciones publicadas el 23 de julio de 2026: la v0.12.3 agrega una herramienta wiki_link que resuelve las formas [[Document Name]], [[Name|Display]], [[Name\|Display]] con escape en tablas y #fragment, devolviendo el contenido de la nota junto con la ruta resuelta y las alternativas ambiguas — la primitiva de recuperación que permite a un agente seguir el propio grafo de enlaces de un vault en vez de volver a buscarlo — y excluye .trash/ de todas las herramientas mediante el filtro de rutas predeterminado; la v0.12.4 extiende wiki_link a enlaces con ruta calificada como [[folder/Note]]; la v0.12.2 evita que patch_note corrompa inserciones que contengan patrones de reemplazo $ y normaliza rutas que por accidente incluyan el prefijo del vault. Se revelaron dos avisos de gravedad media (GHSA-9c83-rr99-vfwj y GHSA-j99q-93c9-h869) contra su lista de denegación de directorios restringidos del filtro de rutas; ambos se corrigieron mucho antes de la línea 0.12, en las versiones 0.11.4 y 0.11.5, por lo que cualquier versión 0.12.x está libre de ellos.13

Cambio de abril de 2026 — Obsidian CLI como puente preferido: Obsidian 1.12.0 introdujo el CLI de primera clase, y el instalador público 1.12.7 (23 de marzo de 2026) incorporó el binario independiente + TUI + mejoras en el archivo de socket que facilitaron la instalación y ejecución de flujos de trabajo en terminal.16 La línea 1.13 llegó al canal público como 1.13.4 el 30 de julio de 2026 — una versión de configuración, imágenes y seguridad de URI sin nuevas capacidades de IA o automatización más allá de la superficie de CLI de la versión 1.12.x (consulta la fila del registro de cambios para ver qué sí modifica).2526 Las herramientas de la comunidad están migrando activamente del plugin Local REST API (que impulsaba mcp-obsidian) a la integración basada en CLI porque es más rápida y estable. El repositorio MarkusPfundstein/mcp-obsidian sigue mantenido — los commits hasta mayo de 2026 agregaron herramientas como search_by_tag y get_frontmatter — aunque no publica versiones etiquetadas (instala desde un commit fijado). Sigue basado en Local-REST-API; para configuraciones nuevas, el puente CLI suele ser más rápido y estable, así que es preferible usarlo o las alternativas más recientes de la comunidad que se enumeran a continuación.20 Consulta la sección «Obsidian CLI para flujos de trabajo de IA» más adelante en esta guía para ver la configuración recomendada.

Servidor Autor Transporte Requiere plugin Función principal
obsidian-mcp (npm obsidian-mcp) StevenStavrakis STDIO No Ligero, basado en archivos
mcp-obsidian MarkusPfundstein STDIO Local REST API CRUD completo del vault mediante REST, además de search_by_tag/get_frontmattermantenido activamente (commits hasta mayo de 2026); sin versiones etiquetadas, fija un commit20
obsidian-mcp-tools jacksteamdev STDIO Sí (plugin) Búsqueda semántica + Templater
obsidian-claude-code-mcp iansinnott WebSocket Sí (plugin) Detección automática para Claude Code
obsidian-mcp-server (npm obsidian-mcp-server) cyanheads STDIO Local REST API Etiquetas, gestión de frontmatter — se configura mediante OBSIDIAN_API_KEY/OBSIDIAN_BASE_URL, no mediante flags de CLI
Búsqueda híbrida MCP comunidad STDIO No Servidor MCP de búsqueda BM25 + semántica + CLI. Mantenido por la comunidad; verifica los commits recientes antes de adoptarlo.

Para la guía rápida, la opción más sencilla es un servidor basado en archivos que lee directamente los archivos .md. Cuidado con la colisión de nombres en npm: el servidor basado en archivos es npm obsidian-mcp (StevenStavrakis); npm obsidian-mcp-server es el servidor de cyanheads respaldado por REST-API, que necesita el plugin Local REST API y una clave API — una confusión habitual que deja a quienes leen la guía con un servidor que no puede iniciarse:

npm install -g obsidian-mcp

Paso 3: Configura tu herramienta de IA

Claude Code — registra el servidor con claude mcp add (Claude Code almacena los servidores MCP en ~/.claude.json para el ámbito de usuario o en .mcp.json de un proyecto — no en ~/.claude/settings.json, que ignora silenciosamente un bloque mcpServers):

# User scope (all your projects)
claude mcp add obsidian -s user -- npx -y obsidian-mcp@2 serve --vault notes=/absolute/path/to/your/vault

# Or project scope, shared with the repo (writes .mcp.json)
claude mcp add obsidian -s project -- npx -y obsidian-mcp@2 serve --vault notes=/absolute/path/to/your/vault

Codex CLI — agrega lo siguiente a ~/.codex/config.toml:

[mcp_servers.obsidian]
command = "npx"
args = ["-y", "obsidian-mcp@2", "serve", "--vault", "notes=/absolute/path/to/your/vault"]

Cursor — agrega lo siguiente a .cursor/mcp.json:

{
  "mcpServers": {
    "obsidian": {
      "command": "npx",
      "args": ["-y", "obsidian-mcp@2", "serve", "--vault", "notes=/absolute/path/to/your/vault"]
    }
  }
}

Paso 4: Ejecuta tu primera consulta

Abre tu herramienta de IA y haz una pregunta que las notas de tu vault puedan responder:

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

La herramienta de IA llama al servidor MCP, que busca en tu vault y devuelve contenido coincidente. Deberías ver resultados con rutas de archivo y fragmentos relevantes.

Lo que Claude puede hacer una vez conectado

Los nombres exactos de las herramientas varían según el servidor, pero la superficie de capacidades principal es coherente entre implementaciones:

Capacidad Herramienta habitual Qué hace el agente con ella
Buscar en el vault obsidian_search / search Encuentra notas que coinciden con una consulta y devuelve fragmentos clasificados con rutas de archivo y atribución de fuente
Leer una nota completa obsidian_read_note / read_note Obtiene el contenido completo de una nota cuando un fragmento de búsqueda no basta
Listar y explorar obsidian_list_notes / list_notes Explora notas por carpeta, etiqueta o intervalo de fechas cuando no hay una consulta específica
Obtener contexto formateado obsidian_get_context Devuelve un bloque de contexto orientado a un tema, ajustado a un presupuesto de tokens y listo para insertarse en la conversación

En la práctica, Claude responde preguntas a partir de tus notas con atribución de fuente, incorpora decisiones previas y material de referencia en sesiones de programación, y explora la estructura del vault sin cargar archivos completos en el contexto. Algunos servidores de la comunidad también exponen operaciones de escritura (crear, anexar, gestionar etiquetas y frontmatter); el servidor personalizado que se crea más adelante en esta guía es deliberadamente de solo lectura, y la creación de notas se gestiona mediante hooks.

Análisis detallados: Arquitectura del servidor MCP para el diseño de herramientas y permisos, Integración de Claude Code para hooks y el patrón de puente, Integración de Codex CLI y Cursor y otras herramientas para otros agentes.

Lo que acabas de crear

Conectaste una base de conocimientos local a una herramienta de IA mediante un protocolo estándar. El servidor MCP lee los archivos de tu vault, realiza una búsqueda básica y devuelve resultados. Esta es la versión mínima viable.

Lo que esta guía rápida NO te ofrece: - Recuperación híbrida (búsqueda BM25 + vectorial + fusión RRF) - Búsqueda semántica basada en embeddings - Filtrado de credenciales - Indexación incremental - Inyección automática de contexto basada en hooks

El resto de esta guía explica cómo crear cada una de estas capacidades. La guía rápida demuestra el concepto. El pipeline completo ofrece recuperación con calidad de producción.


Obsidian CLI para flujos de trabajo de AI

Obsidian 1.12 (febrero de 2026) introdujo una interfaz de línea de comandos integrada que abre una nueva superficie de integración para flujos de trabajo de AI; sigue vigente hasta la versión 1.13.7 (la línea 1.13 llegó al canal público el 30 de julio de 2026; desde entonces no hay nuevas capacidades de CLI).162526 El CLI actúa como un control remoto para la GUI de Obsidian: Obsidian debe estar en ejecución (o se iniciará automáticamente con el primer comando). Actívalo en Settings > General > Command line interface.

Por qué el CLI es importante para la infraestructura de AI

El CLI proporciona acceso programático a operaciones nativas de Obsidian que antes requerían la GUI o los APIs de plugins. Para los flujos de trabajo de AI, estas son las capacidades clave:

  • Búsqueda desde scripts y hooks. obsidian search "query" y obsidian search:context "query" ejecutan búsquedas en el vault desde cualquier script de shell, hook o canalización de automatización. La variante search:context devuelve las líneas coincidentes con el contexto circundante, lo que resulta útil para incorporar resultados en prompts de AI.
  • Automatización de notas diarias. obsidian daily abre o crea la nota diaria de hoy. Combinado con scripts de shell, permite flujos de trabajo de informes diarios automatizados: un hook puede añadir resúmenes generados por AI a la nota diaria.
  • Creación de notas basada en plantillas. obsidian template list y obsidian template create generan notas a partir de plantillas de Templater o del núcleo, lo que permite a los agentes de AI crear entradas estructuradas en el vault sin escribir directamente archivos Markdown.
  • Gestión de propiedades. obsidian property set y obsidian property get leen y escriben propiedades de frontmatter, lo que permite actualizar metadatos desde scripts sin analizar YAML.
  • Control de plugins. obsidian plugin enable/disable/list administra plugins de forma programática, útil para activar o desactivar plugins de indexación durante operaciones por lotes.
  • Gestión de tareas. obsidian task list/add/complete proporciona acceso estructurado a las tareas, útil para agentes de AI que administran elementos de trabajo en el vault.

CLI frente a MCP para acceso de AI

Los servidores CLI y MCP cumplen funciones distintas y son complementarios, no competidores:

Aspecto Obsidian CLI Servidor MCP
Quien lo llama Scripts de shell, hooks, trabajos cron Agentes de AI (Claude Code, Codex, Cursor)
Protocolo Proceso POSIX (stdin/stdout/stderr) MCP (JSON-RPC sobre STDIO o HTTP)
Fortaleza Operaciones nativas de Obsidian (plantillas, plugins, propiedades) Recuperación personalizada (embeddings, BM25, fusión RRF)
Limitación Sin búsqueda vectorial ni canalización de embeddings Sin acceso a operaciones internas de Obsidian
Mejor para Scripts de automatización, canalizaciones de incorporación, acciones de hooks Consultas de agentes de AI en tiempo real durante las sesiones

Recomendación: Usa el CLI para la automatización de incorporación (crear notas, gestionar propiedades y ejecutar búsquedas nativas de Obsidian) y MCP para la recuperación (búsqueda hybrid con embeddings). Un hook UserPromptSubmit puede llamar a obsidian search:context como una comprobación previa rápida antes de ejecutar la recuperación hybrid más pesada (los eventos de hooks con alcance de herramienta no pueden inyectar contenido: su stdout nunca llega al modelo).

Ejemplo: hook de incorporación impulsado por 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

Una categoría creciente de plugins de Obsidian incorpora agentes de programación con AI directamente en la UI del vault, lo que ofrece una alternativa a la configuración de servidores MCP externos. Estos plugins ejecutan el agente de AI en la barra lateral de Obsidian, en lugar de conectarse desde una herramienta externa.

Claudian

Claudian incorpora Claude Code como colaborador de AI en el vault. El directorio del vault se convierte en el directorio de trabajo de Claude, lo que le da capacidades agénticas completas: lectura y escritura de archivos, búsqueda, comandos Bash y flujos de trabajo de varios pasos.17

Funciones clave para la infraestructura de AI: - Prompts conscientes del contexto. Adjunta automáticamente la nota enfocada, admite menciones de archivos con @notename, exclusión basada en etiquetas y la selección del editor como contexto. - Compatibilidad con visión. Analiza imágenes mediante arrastrar y soltar, pegado o ruta de archivo, útil para procesar capturas de pantalla y diagramas incluidos en el vault. - Comandos de barra. Crea plantillas de prompts reutilizables que se activan con /command, lo que permite operaciones estandarizadas en el vault. - Modos de permisos. Modos YOLO (aprobación automática), Safe (aprobar cada acción) y Plan (solo planificación), con una lista de bloqueo de seguridad y confinamiento al vault.

Agent Client

Agent Client integra Claude Code, Codex CLI y Gemini CLI en una barra lateral unificada de Obsidian mediante el Agent Client Protocol (ACP).18

Funciones clave: - Cambio entre múltiples agentes. Chatea con Claude Code, Codex o Gemini CLI desde el mismo panel y alterna entre agentes según sea necesario. - Menciones de notas. Usa @notename para incluir el contenido de las notas en los prompts, de forma similar a Claudian, pero sin depender de un agente específico. - Ejecución de shell. Ejecuta comandos de terminal en línea en el chat: scripts de compilación, comandos git o cualquier operación de terminal, sin salir de la conversación. - Aprobación de acciones. Control detallado sobre lecturas de archivos, ediciones y ejecuciones de comandos.

Cuándo usar plugins de agentes frente a MCP externo

Escenario Plugin de agente MCP externo
Escribir y editar notas del vault con ayuda de AI Mejor: el agente ve el contexto del editor Funciona, pero sin conocimiento del editor
Desarrollo de código en varios repositorios Limitado: restringido al vault Mejor: centrado en el proyecto y con acceso completo al sistema de archivos
Recuperación desde un corpus indexado grande Solo búsqueda básica Canalización completa de recuperación hybrid
Preguntas y respuestas rápidas sobre el vault durante sesiones de toma de notas Ideal: sin cambio de contexto Requiere cambiar a la terminal

Recomendación: Usa plugins de agentes para flujos de trabajo centrados en el vault (escritura, organización y resumen de notas). Usa servidores MCP externos para flujos de desarrollo en los que el agente de AI necesite la canalización completa de recuperación y acceso a bases de código fuera del vault. Ambos enfoques pueden coexistir: ejecuta Claudian dentro de Obsidian para trabajar con notas y Claude Code con MCP externamente para desarrollo.


Marco de decisión: Obsidian vs alternativas

No todos los casos de uso necesitan Obsidian. Esta sección muestra cuándo Obsidian es la base adecuada, cuándo es excesivo y cuándo otra opción encaja mejor.

Árbol de decisión

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 comparativa

Criterio Obsidian Notion Apple Notes Sistema de archivos plano CLAUDE.md
Local-first No (nube) Parcial (iCloud)
Texto plano Sí (markdown) No (bloques) No (propietario)
Estructura de grafo Sí (wiki-links) Parcial (menciones) No No No
Indexable por AI Acceso directo a archivos API requerido Requiere exportación Acceso directo a archivos Ya está en contexto
Ecosistema de plugins Más de 2.500 plugins Integraciones Ninguno N/A N/A
Funciona sin conexión Completo Caché de solo lectura Parcial Completo Completo
Escala a más de 10K notas Sí (con API) Se degrada No (archivo único)
Costo Gratis (núcleo) USD 10/mes+ Gratis Gratis Gratis

Cuándo Obsidian es excesivo

  • Contexto de un solo proyecto. Si la AI solo necesita contexto sobre el codebase actual, colócalo en CLAUDE.md, AGENTS.md o documentación a nivel de proyecto. Estos archivos viajan con el repo y se cargan automáticamente.
  • Datos estructurados. Si el contenido son tablas, registros o esquemas, usa una base de datos. Las notas de Obsidian priorizan la prosa. Dataview puede consultar campos de frontmatter, pero una base de datos real maneja mejor las consultas estructuradas.
  • Investigación temporal. Si las notas se descartarán cuando termine el proyecto, una carpeta temporal con archivos markdown es más simple. No construyas infraestructura de recuperación para contenido efímero.

Cuándo Obsidian es la opción correcta

  • Conocimiento acumulado durante meses o años. El valor se compone a medida que crece el corpus. Una bóveda de 200 notas consultada a diario durante seis meses aporta más valor que una bóveda de 5.000 notas consultada una sola vez.
  • Múltiples dominios en un solo corpus. Una bóveda con notas sobre programación, arquitectura, seguridad, diseño y proyectos personales se beneficia de la recuperación entre dominios, algo que un CLAUDE.md específico de proyecto no puede ofrecer.
  • Contenido sensible en términos de privacidad. Local-first significa que el pipeline de recuperación nunca envía contenido a servicios externos. La bóveda contiene lo que pongas en ella, incluido contenido que no subirías a un servicio en la nube.

Modelo mental: tres capas

El sistema tiene tres capas que operan de forma independiente, pero que se potencian cuando se combinan. Cada capa tiene una responsabilidad distinta y un modo de falla 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 qué entra en la bóveda. Sin curación, la bóveda acumula ruido: capturas de pantalla de tweets, artículos copiados y pegados sin anotaciones, ideas a medio terminar sin contexto. La capa de intake es responsable del control de calidad en el punto de entrada. Un pipeline de puntuación, una convención de etiquetas o un proceso de revisión manual: cualquier mecanismo que asegure que la bóveda contenga contenido que valga la pena recuperar.

Retrieval vuelve consultable la bóveda. Este es el motor: dividir notas en unidades de búsqueda mediante chunking, convertir chunks en embeddings dentro de un espacio vectorial, indexar para búsqueda por palabras clave y búsqueda semántica, y fusionar resultados con RRF. La capa de retrieval transforma una carpeta de archivos en una base de conocimiento consultable. Sin esta capa, se puede navegar la bóveda mediante exploración manual y búsqueda básica, pero no queda accesible programáticamente para herramientas de AI.

Integration conecta la capa de retrieval con herramientas de AI. Un servidor MCP expone la recuperación como una herramienta invocable. Los hooks inyectan contexto automáticamente. Las skills capturan nuevo conocimiento de vuelta en la bóveda. La capa de integration es la interfaz entre la base de conocimiento y los agentes de AI que la consumen.

Las capas están desacopladas por diseño. El pipeline de puntuación de intake no sabe nada sobre embeddings. El retriever no sabe nada sobre reglas de enrutamiento de señales. El servidor MCP no sabe nada sobre cómo se crearon las notas. Este desacoplamiento significa que puedes mejorar cualquier capa de forma independiente. Reemplaza el modelo de embeddings sin cambiar el pipeline de intake. Agrega una nueva capacidad de MCP sin modificar el retriever. Cambia las heurísticas de puntuación de señales sin tocar el índice.


Arquitectura de la bóveda para consumo de IA

Una bóveda optimizada para la recuperación con IA sigue convenciones distintas a las de una bóveda optimizada para navegación personal. Esta sección cubre la estructura de carpetas, el esquema de notas, las convenciones de frontmatter y los patrones específicos que mejoran la calidad de recuperación.

Estructura de carpetas

Usa prefijos numerados para las carpetas de nivel superior y así crear una jerarquía organizativa predecible. Los números no implican prioridad: agrupan dominios relacionados y hacen que la estructura sea fácil de escanear.

vault/
├── 00-inbox/              # Unsorted captures, pending triage
├── 01-projects/           # Active project notes
├── 02-areas/              # Ongoing areas of responsibility
├── 03-resources/          # Reference material by topic
   ├── programming/
   ├── security/
   ├── ai-engineering/
   ├── design/
   └── devops/
├── 04-archive/            # Completed projects, old references
├── 05-signals/            # Scored signal intake
   ├── ai-tooling/
   ├── security/
   ├── systems/
   └── ...12 domain folders
├── 06-daily/              # Daily notes (if used)
├── 07-templates/          # Note templates (excluded from index)
├── 08-attachments/        # Images, PDFs (excluded from index)
├── .obsidian/             # Obsidian config (excluded from index)
└── .indexignore            # Paths to exclude from retrieval index

Carpetas que deben indexarse: Todo lo que contenga prosa en markdown: proyectos, áreas, recursos, señales, notas diarias.

Carpetas que deben excluirse de la indexación: Templates (contienen variables de marcador de posición, no contenido), archivos adjuntos (archivos binarios), configuración de Obsidian y cualquier carpeta con contenido sensible que no quieras incluir en el índice de recuperación.

El archivo .indexignore

Crea un archivo .indexignore en la raíz de la bóveda para excluir rutas explícitamente del índice de recuperación. La sintaxis coincide con .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/

El indexador lee este archivo antes de escanear y omite por completo las rutas que coincidan. Los archivos en rutas excluidas nunca se dividen en chunks, nunca se convierten en embeddings y nunca aparecen en los resultados de búsqueda.

Esquema de notas

Cada nota debe tener frontmatter YAML. El sistema de recuperación usa los campos de frontmatter para filtrar y enriquecer el 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 obligatorios para la recuperación:

  • title — Se usa en la visualización de resultados de búsqueda y como contexto de encabezado para BM25
  • type — Permite consultas filtradas por tipo (“muéstrame solo MOCs” o “solo señales”)
  • tags — Se indexan en el contexto de encabezado de FTS5 con un peso de 0,3, lo que aporta coincidencias de palabras clave incluso cuando el cuerpo usa otra terminología

Campos opcionales pero valiosos:

  • domain — Permite consultas acotadas por dominio (“busca solo notas de seguridad”)
  • source — Atribución para contenido capturado; el sistema de recuperación puede incluir URL de origen en los resultados
  • status — Permite excluir notas archivadas o en borrador de la búsqueda activa

Convenciones de chunking

El sistema de recuperación divide en chunks en los límites de encabezados H2 (##). Esto significa que la estructura de tus notas afecta directamente la granularidad de la recuperación:

Bueno para la recuperación:

## 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...

Tres secciones H2 producen tres chunks que pueden buscarse de forma independiente. Cada chunk tiene suficiente contexto para que el embedding capture su significado. Una consulta sobre “manejo de tokens vencidos” coincide específicamente con el tercer chunk.

Deficiente para la recuperación:

# 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...

Una sección larga sin encabezados H2 produce un único chunk grande. El embedding promedia todos los temas de la sección. Una consulta sobre cualquier subtema coincide por igual con toda la nota.

Regla práctica: Si una sección cubre más de un concepto, divídela en subsecciones H2. El chunker se encarga del resto.

Qué no poner en las notas

Contenido que degrada la calidad de recuperación:

  • Copias y pegados sin procesar de artículos completos y sin anotación. El sistema de recuperación indexa las palabras clave del artículo original, lo que diluye tu bóveda con contenido que no escribiste. En su lugar, agrega un resumen, extrae los puntos clave o enlaza la URL de origen.
  • Capturas de pantalla sin descripción textual. El sistema de recuperación indexa texto markdown. Una imagen sin texto alternativo ni descripción alrededor es invisible tanto para BM25 como para la búsqueda vectorial.
  • Cadenas de credenciales. Claves API, tokens, contraseñas, cadenas de conexión. Incluso con filtrado de credenciales, el enfoque más seguro es nunca pegar secretos en las notas. En su lugar, haz referencia a ellos por nombre (“el token API de Cloudflare en ~/.env”).
  • Contenido generado automáticamente sin curación. Si una herramienta genera una nota (transcripción de reunión, destacados de Readwise, importación RSS), revísala y anótala antes de que entre en la bóveda permanente. Las importaciones automáticas sin curación agregan volumen sin sumar valor recuperable.

Ecosistema de plugins para flujos de trabajo de AI

Los plugins de Obsidian que mejoran la calidad de la bóveda para la recuperación con AI se dividen en tres categorías: estructurales (imponen consistencia), de consulta (exponen metadata) y de sincronización (mantienen la bóveda actualizada).

Plugins esenciales

Dataview. Consulta tu bóveda como una base de datos usando campos de frontmatter. Crea índices dinámicos: “todas las notas etiquetadas con security actualizadas en los últimos 30 días” o “todas las notas de proyecto con estado active.” Dataview no ayuda directamente a la recuperación, pero te ayuda a identificar vacíos en la cobertura de tu bóveda y a encontrar notas que necesitan actualización.

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

Templater. Crea notas a partir de plantillas con campos dinámicos. Asegúrate de que cada nota nueva comience con el frontmatter correcto usando una plantilla que complete previamente los campos created, type y domain. Un frontmatter consistente mejora el filtrado de recuperación.

<%* /* 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

## References

Linter. Impone reglas de formato en toda la bóveda. Una jerarquía de encabezados consistente (H1 para el título, H2 para secciones, H3 para subsecciones) garantiza que el chunker produzca resultados predecibles. Reglas de Linter que importan para la recuperación:

  • Incremento de encabezados: exige niveles de encabezado secuenciales (sin saltar de H1 a H3)
  • Título YAML: debe coincidir con el nombre del archivo
  • Espacios finales: eliminar (evita artefactos de tokenización de FTS5)
  • Líneas en blanco consecutivas: limitar a 1 (chunks más limpios)

Integración con Git. Control de versiones para tu bóveda. Registra cambios a lo largo del tiempo, sincroniza entre máquinas y permite recuperarte de eliminaciones accidentales. Git también proporciona datos de mtime que el indexador usa para la detección incremental de cambios.

Plugins que ayudan a la indexación

Smart Connections. Un plugin de Obsidian que ofrece búsqueda semántica impulsada por AI dentro de Obsidian. Smart Connections v4 crea embeddings locales de forma predeterminada: una vez que tu bóveda está indexada, las conexiones semánticas y la búsqueda funcionan completamente sin conexión, sin llamadas a API.11 v4.5.0 (5 de mayo de 2026) incorpora las conexiones del pie de página a Smart Connections Core, por lo que cualquier instalación puede mostrar conexiones con notas relacionadas en el pie de página sin abrir un panel lateral. Las versiones recientes de v4 también agregaron vistas de grafo para listas de conexiones, ubicaciones de dock configurables, mejor recuperación de block-embedding después de ejecuciones de indexación interrumpidas y “Substrate”, un entorno entre plugins que permite que Smart Connections, Smart Chat y Smart Composer compartan estado.21 Aunque el sistema de recuperación de esta guía es externo a Obsidian (se ejecuta como una pipeline Python), Smart Connections es útil para explorar relaciones semánticas mientras escribes. Los dos sistemas indexan el mismo contenido, pero sirven casos de uso distintos: Smart Connections para descubrimiento dentro del editor, el recuperador externo para integración con herramientas de AI mediante MCP.

Plugins AI-native lanzados en abril de 2026. Una ola de nuevos plugins comunitarios apunta directamente al flujo de trabajo de Claude Code / Codex / Gemini-CLI:

Plugin Lanzamiento Qué hace
Cortex 4 de abril Agente de bóveda impulsado por Claude Code: trata la bóveda como un espacio de trabajo de agente, no solo como un almacén de notas
VaultSearch 7 de abril Búsqueda hybrid local-first: BM25 + semántica + fuzzy (se superpone directamente con la pila de recuperación de esta guía)
LLM Wiki 9 de abril Convierte tu bóveda en una base de conocimiento consultable de forma privada
Drift 11 de abril Visor de diff al estilo VS Code para edición de Obsidian impulsada por AI; orientado a flujos de trabajo con Claude Code
EngramQuest 11 de abril Genera desafíos de memoria a partir de notas; incluye “AI Skills” para Claude Code / Gemini CLI / Cursor
Hybrid Search MCP Marzo (aún reciente) Servidor MCP + CLI con BM25 + búsqueda semántica, creado específicamente para asistentes de AI

Trata esto como una superficie emergente: es probable que varios de estos plugins se consoliden o sean absorbidos por Smart Connections / el núcleo de Obsidian en los próximos trimestres. Si hoy tienes que elegir uno, VaultSearch y Hybrid Search MCP son los más cercanos en filosofía al recuperador externo de esta guía.

Nota sobre Dataview: Dataview (el plugin de consultas de Obsidian de larga trayectoria) lanzó por última vez la versión 0.5.70 en abril de 2025 y, desde entonces, ha estado prácticamente inactivo. Para trabajos nuevos, la función integrada Bases de Obsidian (1.9+) es el sucesor implícito y la ruta recomendada.

Metadata Menu. Ofrece edición estructurada de frontmatter con autocompletado para valores de campos. Reduce errores tipográficos en los campos type, domain y tags. La metadata consistente mejora la precisión del filtrado de recuperación.

Plugins que perjudican la indexación

Excalidraw. Almacena dibujos como JSON incrustado en archivos markdown. El JSON es markdown sintácticamente válido, pero produce basura cuando se divide en chunks y se convierte en embeddings. Excluye los archivos de Excalidraw del índice mediante .indexignore o filtra por extensión de archivo.

Kanban. Almacena el estado del tablero como markdown con formato especial. El formato está diseñado para renderizar Kanban, no para recuperación de prosa. El chunker produce fragmentos de títulos de tarjetas y metadata que no se convierten bien en embeddings. Excluye los tableros Kanban del índice.

Calendar. Crea notas diarias con contenido mínimo (a menudo solo un encabezado de fecha). Las notas vacías o casi vacías producen chunks de baja calidad. Si usas notas diarias, escribe contenido sustantivo en ellas o excluye la carpeta de notas diarias del índice.

Configuración de plugins que importa

Recuperación de archivos → Activada. Protege contra la eliminación accidental de notas. No está directamente relacionada con la recuperación, pero es crítica para una base de conocimiento de la que dependes.

Saltos de línea estrictos → Desactivados. Los saltos de línea estándar de Markdown (doble salto de línea para párrafo) producen chunks más limpios que el modo estricto de Obsidian (un solo salto de línea para <br>).

Ubicación predeterminada de archivos nuevos → Carpeta designada. Envía los archivos nuevos a 00-inbox/ para que las notas sin categorizar no contaminen las carpetas de dominio. La bandeja de entrada es un área de preparación; los archivos se mueven a carpetas de dominio después de la revisión.

Formato de wiki-link → Ruta más corta cuando sea posible. Los destinos de enlace más cortos son más fáciles de resolver para el recuperador al indexar la estructura de enlaces.


Modelos de embeddings: elección y configuración

El modelo de embeddings convierte fragmentos de texto en vectores numéricos para la búsqueda semántica. La elección del modelo determina la calidad de recuperación, el tamaño del índice, la velocidad de generación de embeddings y las dependencias en tiempo de ejecución. En esta sección se explica por qué Model2Vec potion-base-8M es la opción predeterminada y cuándo conviene elegir alternativas.

Por qué Model2Vec potion-base-8M

Modelo: minishlab/potion-base-8M Parámetros: 7,6 millones Dimensiones: 256 Tamaño: ~30 MB Dependencias: model2vec (solo numpy, sin PyTorch) Inferencia: solo CPU, embeddings estáticos de palabras (sin capas de atención)

Model2Vec destila el conocimiento de un sentence transformer en embeddings estáticos de tokens. En lugar de ejecutar capas de atención sobre la entrada (como hacen BERT, MiniLM y otros modelos transformer), Model2Vec produce vectores mediante un promedio ponderado de embeddings de tokens precalculados.5 La consecuencia práctica: la velocidad de generación de embeddings es entre 50 y 500 veces mayor que la de los modelos basados en transformers porque no hay cómputo secuencial.

En la página actual de resultados de Model2Vec, potion-base-8M alcanza alrededor del 92% de la puntuación global de all-MiniLM-L6-v2 en todas las tareas (51,32 frente a 55,80), mientras se mantiene varios órdenes de magnitud más rápido.6 La brecha de calidad restante es el costo de las ventajas en velocidad y simplicidad. Para fragmentos cortos de markdown (un promedio de 200 a 400 palabras en un vault típico), la diferencia de calidad es menos marcada que en documentos más largos, porque ambos modelos convergen en representaciones similares para texto breve y enfocado.

Configuración

# 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]

Carga diferida. El modelo se carga en el primer uso, no al momento de importar. Importar el módulo embedder no tiene costo cuando el retriever opera en modo de respaldo solo con BM25 (por ejemplo, cuando el venv de embeddings no está instalado).

Entorno virtual aislado. El modelo se ejecuta en un venv dedicado (por ejemplo, ~/.claude/venvs/memory/) para evitar conflictos de dependencias con el resto de la cadena de herramientas. La función _activate_venv() agrega el site-packages del venv a sys.path en tiempo de ejecución.

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

Procesamiento por lotes. El embedder procesa textos en lotes de 64 para amortizar la sobrecarga de Model2Vec. El indexer envía fragmentos a embed_batch() en lugar de generar el embedding de un fragmento a la vez.

Cuándo elegir alternativas

Modelo Dim Tamaño Velocidad Calidad (MTEB) Ideal para
potion-base-8M 256 30 MB 500x 51,32 Predeterminado: local, rápido, sin GPU
potion-base-32M 256 120 MB 400x 52,83 Mayor calidad, todavía estático
potion-retrieval-32M 256 120 MB 400x 35,06 (retrieval) Estático optimizado para retrieval
potion-multilingual-128M 256 ~500 MB 300x Vaults multilingües (101 idiomas)
all-MiniLM-L6-v2 384 80 MB 1x 55,80 Mayor calidad, todavía local
nomic-embed-text-v1.5 768 270 MB 0,5x 62,28 Mejor calidad local
text-embedding-3-small 1536 API N/A 62,30 Basado en API, máxima calidad

Elige potion-base-32M cuando quieras mejor calidad que potion-base-8M sin salir de la familia de embeddings estáticos. Usa un vocabulario más grande destilado de baai/bge-base-en-v1.5, con una puntuación global de 52,83 en todas las tareas (alrededor de un 3% más que potion-base-8M), mientras conserva la misma salida de 256 dimensiones y la dependencia solo de numpy.8 El archivo del modelo, 4 veces más grande, aumenta el uso de memoria, pero la velocidad de generación de embeddings sigue siendo varios órdenes de magnitud superior a la de los modelos transformer.

Elige potion-retrieval-32M cuando tu caso de uso principal sea retrieval (como lo es la búsqueda en el vault). Esta variante está ajustada a partir de potion-base-32M específicamente para tareas de retrieval, con una puntuación de 35,06 en la tabla de benchmarks de retrieval de Model2Vec, frente a 32,67 para potion-base-32M.8 La concesión es que está optimizada para retrieval en lugar de calidad de embeddings de propósito general.

Elige potion-multilingual-128M cuando tu vault contenga notas en varios idiomas. Lanzado en mayo de 2025, este modelo de 101 idiomas es el modelo de embeddings estáticos con mejor rendimiento para tareas multilingües; genera embeddings para cualquier texto en cualquier idioma y mantiene la misma dependencia solo de numpy que los demás modelos potion.12 El archivo de modelo más grande (~500 MB) es el costo de la capacidad interlingüística. Úsalo cuando tengas notas en japonés, chino, alemán u otros idiomas distintos del inglés junto con contenido en inglés.

Elige all-MiniLM-L6-v2 cuando la calidad de retrieval importe más que la velocidad y tengas PyTorch instalado. Los vectores de 384 dimensiones aumentan el tamaño de la base de datos SQLite en ~50% frente a los vectores de 256 dimensiones. La velocidad de generación de embeddings pasa de <1 minuto a ~10 minutos para una reindexación completa de 15.000 archivos en hardware M-series.

Elige nomic-embed-text-v1.5 cuando necesites la mejor calidad local posible de retrieval y aceptes una indexación más lenta. Los vectores de 768 dimensiones aproximadamente triplican el tamaño de la base de datos. Requiere PyTorch y una CPU moderna o GPU.

Elige text-embedding-3-small cuando la latencia de red y la privacidad sean concesiones aceptables. API produce embeddings de la mayor calidad, pero introduce una dependencia de la nube, costo por token ($0,02/millón de tokens) y envía tu contenido a los servidores de OpenAI.

Quédate con potion-base-8M en todos los demás casos. La ventaja de velocidad es crítica para la indexación iterativa (reindexar durante el desarrollo), la dependencia solo de numpy evita la complejidad de instalar PyTorch y los vectores de 256 dimensiones mantienen compacta la base de datos.

Cuantización y reducción de dimensionalidad

Model2Vec v0.5.0+ admite cargar modelos con precisión y dimensiones reducidas.8 Esto es útil para desplegar en hardware limitado o reducir el tamaño de la base de datos sin cambiar 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)

Los modelos cuantizados conservan una calidad de retrieval casi idéntica con una fracción de la huella de memoria. La reducción de dimensionalidad sigue una truncación al estilo Matryoshka: las primeras N dimensiones contienen la mayor parte de la información. Reducir de 256 a 128 dimensiones reduce a la mitad el almacenamiento de vectores con una pérdida mínima de calidad para retrieval de textos cortos.

Model2Vec v0.8.x actualiza los componentes internos de tokenización/persistencia, depreca la compatibilidad con Python 3.9 y actualiza los resultados publicados a las tablas MTEB más recientes. Fija o prueba model2vec antes de actualizar un indexer de producción, porque las actualizaciones de la biblioteca pueden cambiar las rutas de carga de modelos incluso cuando el nombre del modelo de embeddings se mantiene igual.10

Ajuste fino para embeddings específicos del vault

Model2Vec v0.4.0+ admite entrenar modelos de clasificación personalizados sobre embeddings estáticos, v0.7.0 agrega cuantización de vocabulario y pooling configurable para destilación, y v0.8.x refactoriza el comportamiento de tokenización y persistencia.10 Esto es relevante para vaults con vocabulario especializado (notas médicas, referencias legales, jerga específica de un dominio) donde los modelos potion predeterminados quizá no capturen los matices semánticos:

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 la mayoría de los vaults, potion-base-8M predeterminado produce una calidad de retrieval suficiente. El ajuste fino solo vale la pena cuando el retrieval omite de forma constante conexiones específicas del dominio que un modelo de propósito general no puede capturar.

Seguimiento del hash del modelo

El indexer almacena un hash derivado del nombre del modelo y del tamaño del vocabulario. Si cambias el modelo de embeddings, el indexer detecta la discrepancia en la siguiente ejecución incremental y activa automáticamente una reindexación completa.

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]

Esto evita mezclar vectores de distintos modelos en la misma base de datos, lo que produciría puntuaciones de cosine similarity sin sentido.

Modos de falla

Falla en la descarga del modelo. La primera ejecución descarga el modelo desde Hugging Face. Si la descarga falla (problema de red, firewall corporativo), el retriever vuelve al modo solo con BM25. El modelo queda almacenado localmente en caché después de la primera descarga.

Incompatibilidad de dimensiones. Si cambias de modelo sin limpiar la base de datos, los vectores almacenados tienen una dimensión distinta de los nuevos embeddings. El indexer detecta esto mediante el hash del modelo y activa una reindexación completa. Si la verificación del hash falla (modelo personalizado sin hash adecuado), sqlite-vec generará un error en las consultas KNN con dimensiones incompatibles.

Presión de memoria en vaults grandes. Generar embeddings para más de 50.000 fragmentos en un solo lote puede consumir mucha memoria. El indexer procesa en lotes de 64 para limitar el pico de uso de memoria. Si la memoria sigue siendo un problema, reduce el tamaño del lote.


Búsqueda de texto completo con FTS5

La extensión FTS5 de SQLite proporciona búsqueda de texto completo con ranking BM25. FTS5 es el componente de búsqueda por palabras clave del pipeline de recuperación hybrid. Esta sección cubre la configuración de FTS5, cuándo destaca BM25 y sus modos de falla específicos.

Tabla virtual FTS5

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

Modo de sincronización de contenido. El parámetro content=chunks le indica a FTS5 que referencie directamente la tabla chunks en lugar de almacenar una copia duplicada del texto. Esto reduce a la mitad el requisito de almacenamiento, pero significa que FTS5 debe sincronizarse manualmente cuando se insertan, actualizan o eliminan chunks.

Columnas. Se indexan 3 columnas: - chunk_text — El contenido principal de cada chunk (peso BM25: 1.0) - section — El texto del encabezado H2 (peso BM25: 0.5) - heading_context — Título de la nota, etiquetas y metadatos (peso BM25: 0.3)

Ranking BM25

BM25 clasifica documentos por frecuencia de términos, frecuencia inversa de documentos y normalización de longitud del documento. La función auxiliar bm25() en FTS5 acepta pesos por columna:

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;

Los pesos de columna (1.0, 0.5, 0.3) significan: - Una coincidencia de palabra clave en chunk_text aporta más al puntaje - Una coincidencia en section (encabezado) aporta la mitad - Una coincidencia en heading_context (título, etiquetas) aporta el 30%

Estos pesos se pueden ajustar. Si tu vault tiene encabezados descriptivos que predicen con fuerza la calidad del contenido, aumenta el peso de section. Si tus etiquetas son completas y precisas, aumenta el peso de heading_context.

Cuándo gana BM25

BM25 destaca en consultas que contienen identificadores exactos:

  • Nombres de funciones: _rrf_fuse, embed_batch, get_stale_files
  • Flags de CLI: --incremental, --vault, --model
  • Claves de configuración: bm25_weight, max_tokens, batch_size
  • Mensajes de error: SQLITE_LOCKED, ConnectionRefusedError
  • Términos técnicos específicos: PostToolUse, PreToolUse, AGENTS.md

Para estas consultas, BM25 encuentra la coincidencia exacta de inmediato. La búsqueda vectorial devolvería contenido relacionado semánticamente, pero podría clasificar la coincidencia exacta por debajo de una discusión conceptual.

Cuándo falla BM25

BM25 falla en consultas que usan una terminología distinta de la del contenido almacenado:

  • Consulta: “cómo manejar fallas de autenticación” → El vault contiene notas sobre “recuperación de errores de inicio de sesión” y “manejo de expiración de sesiones”. BM25 no encuentra coincidencias porque las palabras clave son distintas.
  • Consulta: “cuál es la mejor forma de gestionar estado” → El vault contiene notas sobre “patrones de Redux store” y “context providers”. BM25 no acierta porque “gestión de estado” está expresado mediante nombres de tecnologías específicas.

BM25 también falla con colisión de palabras clave a escala. En un vault de 15.000 archivos, una búsqueda de “configuración” coincide con cientos de notas porque casi todas las notas de proyecto mencionan configuración. Los resultados son técnicamente correctos, pero prácticamente inútiles: el ranking no puede determinar qué nota de “configuración” es relevante para la consulta actual.

Tokenizer FTS5

FTS5 usa el tokenizer unicode61 de forma predeterminada, que maneja texto ASCII y Unicode. Para vaults con una cantidad significativa de contenido CJK (chino, japonés, coreano), considera el tokenizer trigram:

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

El tokenizer predeterminado unicode61 divide por límites de palabras, lo que funciona mal para idiomas sin espacios entre palabras. El tokenizer trigram divide cada 3 caracteres, lo que permite coincidencias de subcadenas a costa del tamaño del índice (aproximadamente 3 veces más grande).

Mantenimiento

FTS5 requiere sincronización explícita cuando cambia la tabla chunks subyacente:

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

El comando rebuild reconstruye el índice FTS5 a partir de la tabla de contenido. Ejecútalo después de inserciones masivas (reindexación completa), pero no después de actualizaciones incrementales individuales; para esas, usa INSERT INTO chunks_fts(rowid, chunk_text, section, heading_context) para sincronizar filas individuales.


Búsqueda vectorial con sqlite-vec

La extensión sqlite-vec incorpora la búsqueda vectorial KNN (K-Nearest Neighbors) en SQLite. Esta sección cubre la configuración de sqlite-vec, el pipeline de embeddings desde una nota hasta un vector buscable, y los patrones de consulta específicos.

Tabla virtual sqlite-vec

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

El módulo vec0 almacena vectores float de 256 dimensiones como datos binarios empaquetados. La columna id se mapea 1:1 con la tabla chunks, lo que permite hacer joins entre los resultados vectoriales y los metadatos de los fragmentos.

Pipeline de embeddings

El pipeline va desde la nota hasta el vector buscable:

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

Serialización vectorial

El módulo struct de Python serializa vectores float para almacenarlos en 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

Una consulta de búsqueda vectorial genera el embedding de la consulta de entrada y luego encuentra los K fragmentos más cercanos por distancia coseno:

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

El operador MATCH en sqlite-vec realiza búsqueda aproximada de vecinos más cercanos. El parámetro k controla cuántos resultados se devuelven. La columna distance contiene la distancia coseno (0 = idéntico, 2 = opuesto).

Paginación KNN con restricciones de distancia

A partir de sqlite-vec v0.1.7, las consultas KNN admiten restricciones WHERE distance < ?, lo que permite paginación basada en cursor a través de conjuntos de resultados grandes sin volver a escanear las páginas anteriores.14 Las versiones estables posteriores v0.1.8 y v0.1.9 son releases de empaquetado y corrección de bugs de DELETE, no releases con un nuevo modelo de consulta, por lo que v0.1.7 sigue siendo el límite de función para este patrón de paginación.23

En el horizonte, la línea v0.1.10-alpha (31 de marzo al 18 de mayo de 2026) es la primera en llevar sqlite-vec más allá del KNN de fuerza bruta: introduce tipos de índice de vecino más cercano aproximado — rescore, un índice experimental ivf (inverted-file) que no está habilitado de forma predeterminada, y un índice DiskANN basado en disco para bóvedas demasiado grandes como para mantener los vectores residentes en memoria.23 Esto cambiaría la historia de escalamiento para bóvedas muy grandes, pero la línea 0.1.10 todavía está en pre-release (alpha): trata la indexación ANN como experimental y sigue construyendo sobre la ruta estable de KNN de fuerza bruta de v0.1.9 para bóvedas de producción hasta que se publique una versión estable 0.1.10.

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

Esto reemplaza el patrón anterior de obtener un k grande y recortarlo en Python, lo que reduce el uso de memoria en consultas exploratorias sobre bóvedas grandes.

Compatibilidad con DELETE en tablas vec0

sqlite-vec v0.1.7 agregó compatibilidad nativa con DELETE para tablas virtuales vec0, y v0.1.9 corrigió una ruta de error de DELETE relacionada con columnas de texto de metadatos de más de 12 caracteres.1423 Antes, eliminar vectores requería descartar y recrear la tabla. Ahora la ruta de eliminación de archivos del indexador puede borrar vectores directamente:

# 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])

Esto simplifica la reindexación incremental cuando se eliminan o se mueven notas. El indexador ya no necesita mantener una tabla paralela de “IDs activos” ni reconstrucciones por lotes.

Cuándo gana la búsqueda vectorial

La búsqueda vectorial destaca en consultas donde el concepto importa más que las palabras específicas:

  • Consulta: “cómo manejar fallos de autenticación” → Encuentra notas sobre “recuperación de errores de inicio de sesión” (mismo espacio semántico, distintas palabras clave)
  • Consulta: “qué patrones existen para caching” → Encuentra notas sobre “memoization”, “estrategias de TTL de Redis” y “encabezados de caché HTTP” (conceptos relacionados, terminología diversa)
  • Consulta: “enfoques para probar código asíncrono” → Encuentra notas sobre “fixtures de pytest-asyncio”, “bucles de eventos simulados” y “patrones de pruebas async” (el mismo concepto expresado mediante detalles de implementación)

Cuándo falla la búsqueda vectorial

La búsqueda vectorial tiene dificultades con identificadores exactos:

  • Consulta: _rrf_fuse → Devuelve notas sobre “algoritmos de fusión” y “combinación de rankings”, pero puede posicionar la definición real de la función por debajo de discusiones conceptuales
  • Consulta: PostToolUse → Devuelve notas sobre “hooks de ciclo de vida de herramientas” y “manejadores posteriores a la ejecución”, en lugar del nombre específico del hook

La búsqueda vectorial también tiene dificultades con datos estructurados. Los archivos de configuración JSON, los bloques YAML y los fragmentos de código producen embeddings que capturan patrones estructurales en lugar de significado semántico. Un archivo JSON con "review": true genera un embedding distinto al de una discusión en prosa sobre revisión de código.

Degradación gradual

Si sqlite-vec no se puede cargar (extensión faltante, plataforma incompatible, biblioteca corrupta), el retriever vuelve a búsqueda solo con 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

El retriever revisa vec_available antes de intentar consultas vectoriales. Cuando está deshabilitado, todas las búsquedas usan solo BM25, y el paso de fusión RRF se omite.


Reciprocal Rank Fusion (RRF)

RRF fusiona dos listas clasificadas sin requerir calibración de puntajes. Esta sección cubre el algoritmo, un seguimiento paso a paso de una consulta, el ajuste del parámetro k y por qué se elige RRF frente a otras alternativas. Para ver una calculadora interactiva con rangos editables, escenarios preconfigurados y un explorador visual de arquitectura, consulta el análisis profundo del hybrid retriever.

El algoritmo

RRF asigna a cada documento un puntaje basado únicamente en su posición de rango dentro de cada lista:

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

Donde: - k es una constante de suavizado (60, siguiendo a Cormack et al.3) - rank_i es el rango del documento con base 1 en la lista de resultados i - weight_i es un multiplicador opcional por lista (predeterminado 1.0)

Los documentos que tienen buen rango en varias listas reciben puntajes fusionados más altos. Los documentos que aparecen en una sola lista reciben un puntaje de esa única fuente.

Por qué RRF en lugar de otras alternativas

La combinación lineal ponderada requiere calibrar los puntajes de BM25 contra las distancias de coseno. Los puntajes de BM25 no tienen límite superior y escalan con el tamaño del corpus. Las distancias de coseno están acotadas en [0, 2]. Combinarlas requiere normalización, y los parámetros de normalización dependen del conjunto de datos. RRF usa solo posiciones de rango, que siempre son enteros que empiezan en 1 sin importar el método de puntuación.

Los modelos de fusión aprendidos requieren datos de entrenamiento etiquetados: pares consulta-documento con relevancia. Para una base de conocimiento personal, esos datos de entrenamiento no existen. Tendrías que evaluar manualmente cientos de pares consulta-documento para entrenar un modelo útil. RRF funciona sin datos de entrenamiento.

Los métodos de votación Condorcet (Borda count, Schulze method) son teóricamente elegantes, pero más complejos de implementar y ajustar. El artículo original de RRF demostró que RRF supera a los métodos Condorcet en datos de evaluación TREC.3

Fusión en la práctica

Consulta: “how does the review aggregator handle disagreements”

BM25 clasifica review-aggregator.py en la posición 3 (coincidencias exactas de palabras clave en “review”, “aggregator”, “disagreements”), pero coloca dos archivos de configuración más arriba (coinciden con “review” de forma más prominente). La búsqueda vectorial clasifica el mismo fragmento en la posición 1 (coincidencia semántica sobre resolución de conflictos). Después de la fusión con RRF:

Fragmento BM25 Vec Puntaje fusionado
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

Los fragmentos que tienen buen rango en ambas listas suben a los primeros lugares. Los fragmentos que solo aparecen en una lista obtienen un puntaje de una sola fuente y quedan por debajo de los resultados clasificados en dos listas. La lógica real de resolución de desacuerdos gana porque ambos métodos la encontraron: BM25 mediante palabras clave, la búsqueda vectorial mediante semántica.

Para ver el seguimiento completo paso a paso con los cálculos de RRF por rango, prueba distintos valores de k en la calculadora interactiva de RRF.

Implementación

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

Ajuste de k

La constante k controla cuánto peso se da a los resultados mejor clasificados frente a los resultados con rangos más bajos:

  • k más bajo (por ejemplo, 10): Los resultados mejor clasificados dominan. El rango 1 puntúa 1/11 = 0,091; el rango 10 puntúa 1/20 = 0,050 (diferencia de 1,8x). Es útil cuando confías en que los rankers individuales acierten con el primer resultado.
  • k predeterminado (60): Equilibrado. El rango 1 puntúa 1/61 = 0,0164; el rango 10 puntúa 1/70 = 0,0143 (diferencia de 1,15x). Las diferencias de rango se comprimen, lo que da más peso a aparecer en varias listas.
  • k más alto (por ejemplo, 200): Aparecer en ambas listas importa mucho más que la posición de rango. El rango 1 puntúa 1/201; el rango 10 puntúa 1/210: casi idénticos. Úsalo cuando los rankers individuales produzcan rankings ruidosos, pero la coincidencia entre listas sea confiable.

Empieza con k=60. El artículo original de RRF encontró que este valor era robusto en diversos conjuntos de datos TREC. Ajústalo solo después de medir casos de fallo en tu propia distribución de consultas.

Desempate

Cuando dos fragmentos tienen puntajes RRF idénticos (raro, pero posible con el mismo rango en una lista y sin aparición en la otra), rompe los empates así:

  1. Prefiere los fragmentos que aparecen en ambas listas sobre los que aparecen en una sola
  2. Entre fragmentos que aparecen en ambas listas, prefiere el que tenga el rango combinado más bajo
  3. Entre fragmentos que aparecen en una sola lista, prefiere el que tenga el rango más bajo en esa lista

El pipeline completo de retrieval

Esta sección sigue una consulta desde la entrada hasta la salida a través de todo el pipeline: búsqueda BM25, búsqueda vectorial, fusión RRF, truncamiento del presupuesto de tokens y ensamblaje de contexto.

Flujo de principio a fin

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

Latencia total: ~23ms para una base de datos de 49.746 chunks en hardware Apple M3 Pro.

El API de búsqueda

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

Truncamiento del presupuesto de tokens

El parámetro max_tokens evita que el retriever devuelva más contexto del que la herramienta de AI puede usar. La estimación usa 4 caracteres por token (una aproximación razonable para prosa en inglés). Los resultados se truncan de forma codiciosa: se agregan resultados en orden de ranking hasta agotar el presupuesto.

Esta es una estrategia conservadora. Un enfoque más sofisticado consideraría las puntuaciones de calidad de cada resultado y preferiría resultados más cortos y de mayor calidad por encima de resultados más largos y de menor calidad. El enfoque codicioso es más simple y funciona bien en la práctica porque el ranking RRF ya ordena los resultados por relevancia.

Esquema de base de datos (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
);

Ruta de degradación elegante

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

El retriever verifica las capacidades durante la inicialización y adapta su estrategia de consulta. Un componente faltante degrada la calidad, pero no provoca errores. La única falla crítica es que falte el archivo de base de datos.

Estadísticas de producción

Medido en una bóveda de 16.894 archivos, 49.746 chunks, una base de datos SQLite de 83 MB, Apple M3 Pro:

Métrica Valor
Archivos totales 16.894
Chunks totales 49.746
Tamaño de la base de datos 83 MB
Latencia de consulta BM25 (p50) 12ms
Latencia de consulta vectorial (p50) 8ms
Latencia de fusión RRF 3ms
Latencia de búsqueda de principio a fin (p50) 23ms
Tiempo de reindexación completa ~4 minutos
Tiempo de reindexación incremental <10 segundos
Modelo de embedding potion-base-8M (256-dim)
Pool de candidatos BM25 30
Pool de candidatos vectoriales 30
Límite de resultados predeterminado 10
Presupuesto de tokens predeterminado 4.000 tokens

Hashing de contenido y detección de cambios

El indexador necesita saber qué archivos cambiaron desde la última ejecución del índice. Esta sección cubre el mecanismo de detección de cambios y la estrategia de hashing.

Comparación de hora de modificación de archivos

El indexador almacena mtime_ns (hora de modificación del archivo en nanosegundos) para cada chunk en la tabla chunks. En una ejecución incremental, el indexador:

  1. Escanea la bóveda en busca de todos los archivos .md en las carpetas permitidas
  2. Lee el mtime_ns de cada archivo desde el filesystem
  3. Lo compara con el mtime_ns almacenado en la base de datos
  4. Identifica tres categorías:
  5. Archivos nuevos: la ruta existe en el filesystem, pero no en la base de datos
  6. Archivos modificados: la ruta existe en ambos, pero mtime_ns difiere
  7. Archivos eliminados: la ruta existe en la base de datos, pero no en el filesystem
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 qué mtime y no hash de contenido

El hashing de contenido (SHA-256 del contenido de los archivos) sería más confiable que la comparación de mtime: detectaría casos en los que un archivo se tocó sin cambiar (por ejemplo, un git checkout que restaura el mtime original). Sin embargo, hacer hash requiere leer todos los archivos en cada ejecución incremental. Para 16.894 archivos, leer el contenido de los archivos toma 2-3 segundos. Leer mtimes desde el filesystem toma <100ms.

El compromiso: la comparación de mtime ocasionalmente activa una reindexación innecesaria de archivos sin cambios (falsos positivos), pero nunca pierde cambios reales. Los falsos positivos cuestan unas pocas llamadas extra de embedding por ejecución. La diferencia de velocidad (100ms frente a 3 segundos) hace que mtime sea la opción pragmática para un sistema que se ejecuta en cada interacción con AI.

Manejo de eliminaciones

Cuando se elimina un archivo de la bóveda, el indexador elimina todos sus chunks de la base de datos:

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],
    )

La instrucción DELETE FROM chunk_vecs funciona de forma nativa desde sqlite-vec v0.1.7, con una corrección de error en v0.1.9 para operaciones DELETE contra tablas vec0 con columnas de texto de metadatos más largas.1423 Las versiones anteriores requerían soluciones alternativas (eliminar y recrear la tabla virtual, o mantener un conjunto externo de “IDs activos”). Si estás ejecutando una versión anterior a 0.1.9, actualiza antes de depender de eliminaciones directas en esquemas con muchos metadatos.

Las tablas de sincronización de contenido FTS5 requieren eliminación explícita mediante INSERT INTO chunks_fts(chunks_fts, rowid, ...) VALUES('delete', ?, ...) para cada fila eliminada. El indexador maneja esto como parte del proceso de eliminación de archivos.


Reindexación incremental vs completa

El indexador admite dos modos: incremental (rápido, para uso diario) y completo (lento, ocasional). Esta sección cubre cuándo usar cada uno, las garantías de idempotencia y la recuperación ante corrupción.

Reindexación incremental

Cuándo usarla: Indexación diaria después de editar notas. Es el modo predeterminado.

Qué hace: 1. Escanea el vault para detectar cambios en archivos (comparación de mtime) 2. Elimina chunks de archivos borrados 3. Vuelve a dividir en chunks y a generar embeddings de los archivos modificados 4. Inserta nuevos chunks para archivos nuevos 5. Sincroniza el índice FTS5

Duración típica: <10 segundos para las ediciones de un día en un vault de 16.000 archivos.

python index_vault.py --incremental

Reindexación completa

Cuándo usarla: - Después de cambiar el modelo de embeddings (se detecta una discrepancia en el hash del modelo) - Después de una migración de esquema (nuevas columnas, índices modificados) - Después de corrupción en la base de datos (falla la comprobación de integridad) - Cuando la indexación incremental produce resultados inesperados

Qué hace: 1. Elimina todos los datos existentes (chunks, vectores, entradas FTS5) 2. Escanea todo el vault 3. Divide todos los archivos en chunks 4. Genera embeddings de todos los chunks 5. Construye el índice FTS5 desde cero

Duración típica: ~4 minutos para 16.894 archivos en Apple M3 Pro.

python index_vault.py --full

Idempotencia

Ambos modos son idempotentes: ejecutar el mismo comando dos veces produce el mismo resultado. El indexador elimina los chunks existentes de un archivo antes de insertar los nuevos, así que volver a ejecutar la indexación incremental sobre una base de datos ya actualizada produce cero cambios. Volver a ejecutar la indexación completa produce una base de datos idéntica.

Recuperación ante corrupción

Si la base de datos SQLite se corrompe (pérdida de energía durante una escritura, error de disco, proceso terminado a mitad de transacción):

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

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

La fuente de verdad siempre son los archivos del vault, no la base de datos. La base de datos es un artefacto derivado que puede reconstruirse en cualquier momento. Esta es una propiedad de diseño crítica: nunca necesitas hacer copias de seguridad de la base de datos.

La flag --incremental

Cuando el indexador se ejecuta con --incremental:

  1. Comprobación del hash del modelo. Compara el hash del modelo almacenado con el modelo actual. Si es diferente, cambia automáticamente al modo de reindexación completa y advierte al usuario.
  2. Escaneo de archivos. Recorre las carpetas permitidas y recopila rutas de archivo y mtimes.
  3. Detección de cambios. Compara contra los datos almacenados.
  4. Procesamiento por lotes. Vuelve a dividir en chunks y a generar embeddings de los archivos modificados en lotes de 64.
  5. Reporte de progreso. Imprime la cantidad de archivos procesados y el tiempo transcurrido.
  6. Apagado ordenado. Maneja SIGINT terminando el archivo actual antes de detenerse.

Filtrado de credenciales y límites de datos

Las notas personales contienen secretos: claves de API, bearer tokens, cadenas de conexión a bases de datos, claves privadas pegadas durante sesiones de depuración. El filtro de credenciales evita que entren al índice de recuperación.

El problema

Una nota sobre la depuración de una integración de OAuth podría contener:

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

Sin filtrado, tanto el JWT como la clave de API se dividirían en chunks, se convertirían en embeddings y se almacenarían en la base de datos. Una búsqueda de “authentication” devolvería el chunk que contiene secretos reales. Peor aún, si el recuperador envía resultados a una herramienta de AI mediante MCP, los secretos aparecen en la ventana de contexto de la AI y potencialmente en los logs de la herramienta.

Filtrado basado en patrones

El filtro de credenciales se ejecuta en cada chunk antes del almacenamiento, comparando 25 patrones específicos de proveedores más patrones genéricos:

Patrones específicos de proveedores:

Patrón Ejemplo Regex
Clave de API de OpenAI sk-... sk-[a-zA-Z0-9_-]{20,}
Clave de API de Anthropic sk-ant-api03-... sk-ant-api\d{2}-[a-zA-Z0-9_-]{20,}
PAT de GitHub ghp_... gh[ps]_[a-zA-Z0-9]{36,}
AWS Access Key AKIA... AKIA[0-9A-Z]{16}
Clave de Stripe sk_live_... [sr]k_(live\|test)_[a-zA-Z0-9]{24,}
Token de Cloudflare ... Varios patrones

Patrones genéricos:

Patrón Detección
Tokens JWT eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+
Bearer tokens Bearer\s+[a-zA-Z0-9_\-\.]+
Claves privadas -----BEGIN (RSA\|EC\|OPENSSH) PRIVATE KEY-----
base64 de alta entropía Cadenas con >4,5 bits/carácter de entropía, 40+ caracteres
Asignaciones de contraseña password\s*[:=]\s*["'][^"']+["']

Implementación del 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

Decisiones clave de diseño:

  1. Filtrar antes de generar embeddings. El texto limpio es el que se convierte en embeddings. La representación vectorial nunca codifica patrones de credenciales. Una consulta de “clave de API” devuelve notas que hablan sobre la gestión de claves de API, no notas que contienen claves reales.

  2. Reemplazar, no eliminar. El token [REDACTED:pattern-name] conserva el contexto semántico del texto circundante. El embedding captura que “había algo parecido a una credencial aquí” sin codificar la credencial en sí.

  3. Registrar patrones, no valores. El filtro registra qué patrones coincidieron (por ejemplo, “Scrubbed 2 credential(s) from oauth-debug.md [jwt, bearer-token]”), pero nunca registra el valor de la credencial.

Exclusión basada en rutas

El archivo .indexignore proporciona exclusión general por ruta. El filtro de credenciales ofrece limpieza detallada dentro de archivos indexados. Ambos son necesarios:

  • .indexignore para carpetas completas que sabes que contienen contenido sensible (notas de salud, registros financieros, documentos profesionales)
  • Filtro de credenciales para secretos incrustados accidentalmente en contenido que, por lo demás, sí se puede indexar

Clasificación de datos

Para vaults que contienen contenido diverso, considera clasificar las notas por sensibilidad:

Nivel Ejemplos ¿Indexar? ¿Filtrar?
Público Borradores de blog, notas técnicas
Interno Planes de proyecto, decisiones de arquitectura
Sensible Datos salariales, registros de salud No (.indexignore) N/A
Restringido Credenciales, claves privadas No (.indexignore) N/A

MCP Arquitectura del servidor

Los servidores de Model Context Protocol (MCP) exponen el recuperador como una herramienta que los agentes de IA pueden invocar. Esta sección abarca el diseño del servidor, la superficie de capacidades y los límites de permisos.

Elección del protocolo: STDIO vs HTTP

MCP admite dos modos de transporte:

STDIO — La herramienta de IA inicia el servidor MCP como un proceso secundario y se comunica mediante stdin/stdout. Este es el modo estándar para herramientas locales. Claude Code, Codex CLI y Cursor admiten servidores MCP con STDIO.

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

HTTP — El servidor MCP se ejecuta como un servicio HTTP independiente. Es útil para acceso remoto, configuraciones con varios clientes o configuraciones de equipo en las que el vault se encuentra en un servidor compartido.

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

Recomendación: Usa STDIO para vaults personales. Es más simple, más seguro (sin exposición a la red) y la herramienta de IA administra el ciclo de vida del servidor. Usa HTTP solo cuando varias herramientas o varias máquinas necesiten acceso simultáneo al mismo vault.

Evolución de la especificación de MCP. La especificación de MCP de junio de 2025 añadió autorización OAuth 2.1, salidas estructuradas de herramientas (esquemas de retorno tipados) y elicitación (solicitudes al usuario iniciadas por el servidor). La versión de noviembre de 2025 incorporó Streamable HTTP como modo de transporte de primera clase, descubrimiento de URL .well-known para explorar automáticamente las capacidades del servidor, anotaciones estructuradas de herramientas que declaran si una herramienta es de solo lectura o realiza modificaciones, y un sistema de estandarización de niveles SDK.79 La siguiente revisión ya es concreta: la especificación 2026-07-28 entró en Release Candidate el 21 de mayo de 2026, la mayor revisión de MCP desde su lanzamiento. Sus cambios principales son un núcleo de protocolo sin estado (se eliminan el handshake initialize y el encabezado Mcp-Session-Id, por lo que los servidores ya no rastrean el estado de sesión por conexión), las Apps de MCP (los servidores pueden devolver HTML renderizados por el servidor, mostrados en iframes de cliente aislados), las Tasks que pasan del núcleo experimental a ser una extensión oficial (tasks/get, tasks/update, tasks/cancel para operaciones de larga duración), una autorización reforzada de OAuth 2.0 / OIDC y una política de ciclo de vida de 12 meses para la descontinuación de funciones. Se lanzó según lo previsto como la revisión del 28 de julio de 2026, ahora la especificación Current (verificada el 14 de agosto de 2026).24 Para servidores de vaults personales, STDIO sigue siendo la opción más simple, y el núcleo sin estado hace que los servidores STDIO para un solo usuario sean aún más ligeros. El transporte Streamable HTTP, el descubrimiento .well-known y las Apps de MCP benefician principalmente a implementaciones HTTP empresariales con enrutamiento multitenant y balanceo de carga. Supervisa la hoja de ruta de MCP para conocer actualizaciones que afecten tu elección de transporte.

Diseño de capacidades

El servidor MCP debe exponer un conjunto mínimo de herramientas:

search — La herramienta principal. Ejecuta recuperación hybrid y devuelve resultados clasificados.

{
  "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 — Lee el contenido completo de una nota específica mediante su ruta. Es útil cuando el agente quiere ver el contexto completo de un resultado de búsqueda.

{
  "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 — Enumera las notas que coinciden con un filtro (por carpeta, etiqueta, tipo o intervalo de fechas). Es útil para explorar cuando el agente no tiene una 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 — Una herramienta práctica que ejecuta una búsqueda y da formato a los resultados como un bloque de contexto adecuado para insertarlo en una conversación.

{
  "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 }
  }
}

Límites de permisos

El servidor MCP debe aplicar límites estrictos:

  1. Solo lectura. El servidor lee el vault y la base de datos del índice. No crea, modifica ni elimina notas. Las operaciones de escritura (capturar notas nuevas) se manejan mediante hooks o skills independientes, no mediante el servidor MCP.

  2. Limitado al vault. El servidor solo lee archivos dentro de la ruta configurada del vault. Los intentos de recorrido de rutas (../../etc/passwd) deben rechazarse.

  3. Salida con filtrado de credenciales. Aunque la base de datos contenga contenido filtrado previamente, aplica filtrado de credenciales en la salida como medida de defensa en profundidad.

  4. Respuestas limitadas por tokens. Aplica max_tokens en todas las respuestas de herramientas para evitar que la herramienta de IA reciba bloques de contexto excesivamente grandes.

Manejo de errores

Las herramientas de MCP deben devolver mensajes de error estructurados que ayuden a la herramienta de IA a recuperarse:

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,
    }

Integración de Claude Code

Claude Code es el principal consumidor del sistema de recuperación de Obsidian. Esta sección abarca la configuración de MCP, la integración de hooks y el patrón obsidian_bridge.py.

Configuración de MCP

Registra el servidor personalizado con claude mcp add (el ámbito de usuario escribe en ~/.claude.json; -s project escribe un .mcp.json compartible — ~/.claude/settings.json no es una superficie de configuración de MCP):

claude mcp add obsidian -s user \
  -e VAULT_PATH=/absolute/path/to/vault \
  -e DB_PATH=/absolute/path/to/vectors.db \
  -- python /path/to/obsidian_mcp.py

La entrada equivalente en .mcp.json, si prefieres escribirla a mano:

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

Después de añadir la configuración, reinicia Claude Code. El servidor MCP se iniciará como un proceso hijo. Verifica que esté ejecutándose:

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

Claude Code debería mostrar las herramientas disponibles (obsidian_search, obsidian_read_note, etc.).

Integración de hooks

Los hooks amplían el comportamiento de Claude Code en puntos definidos de su ciclo de vida. Hay dos hooks relevantes para la integración con Obsidian:

Los hooks se registran en la configuración (~/.claude/settings.json, bajo la clave hooks, con un nombre de evento y un matcher) y reciben una carga útil de JSON por stdin; no existe un directorio de hooks que Claude Code descubra automáticamente, y los detalles de las herramientas nunca llegan como argumentos $1/$2.

Hook UserPromptSubmit — consulta el vault cuando envías un prompt e inyecta contexto relevante (stdout de este evento se añade a la conversación):

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [{ "type": "command", "command": "/path/to/obsidian-context.sh" }]
      }
    ]
  }
}
#!/bin/bash
# obsidian-context.sh — read the JSON payload from stdin
PROMPT=$(jq -r '.prompt // empty')
[ -z "$PROMPT" ] && exit 0
CONTEXT=$(python /path/to/retriever.py search "$PROMPT" --limit 3 --max-tokens 1500)
if [ -n "$CONTEXT" ]; then
    printf 'Relevant vault context:\n%s\n' "$CONTEXT"   # stdout -> added as context
fi

Hook PostToolUse — captura resultados significativos de herramientas en el vault para recuperarlos en el futuro (se registra con un matcher para que solo se active con las herramientas que te interesan):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write|Bash",
        "hooks": [{ "type": "command", "command": "/path/to/capture-insight.sh" }]
      }
    ]
  }
}
#!/bin/bash
# capture-insight.sh — tool name and response arrive as stdin JSON
PAYLOAD=$(cat)
TOOL_NAME=$(printf '%s' "$PAYLOAD" | jq -r '.tool_name')
OUTPUT=$(printf '%s' "$PAYLOAD" | jq -r '.tool_response // "" | tostring')
if [ ${#OUTPUT} -gt 500 ]; then
    python /path/to/capture.py --text "$OUTPUT" --source "claude-code-$TOOL_NAME"
fi

El patrón obsidian_bridge.py

Un módulo puente proporciona una Python API que los hooks y las skills pueden llamar:

# 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)

La skill /capture

Una skill de Claude Code para capturar insights en el vault:

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

La skill crea una nota nueva en 00-inbox/ con el frontmatter adecuado y activa una reindexación incremental para que la nueva nota pueda buscarse de inmediato.

Patrones de comandos personalizados

Las skills de Claude Code pueden encapsular operaciones del vault en comandos con nombre. Los profesionales han creado bibliotecas de comandos específicos de Obsidian que tratan el vault tanto como fuente de lectura como destino de escritura.

Escaneo de señales. Un comando /scan-intel consulta fuentes externas, puntúa los hallazgos según intereses de investigación personales y escribe las señales que califican como notas del vault con frontmatter:

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

El comando obtiene información de fuentes configuradas (arXiv, HN, RSS), aplica un modelo de puntuación (relevancia, capacidad de acción, profundidad, autoridad) y escribe las señales aprobadas en carpetas del vault específicas por tema. El vault se convierte en el consumidor final de un pipeline automatizado de inteligencia.

Bitácora del capitán. Un comando /captains-log agrega la actividad diaria de git de todos los repositorios, escribe una entrada de diario estructurada en el vault e incluye las decisiones tomadas, las conclusiones y los temas abiertos:

/captains-log

El comando obtiene el historial de commits de GitHub, agrupa por repositorio y lo da formato como una entrada narrativa de diario. Con el tiempo, los registros diarios crean un historial consultable de lo que se entregó y por qué.

Captura de Obsidian. Un comando /obsidian-capture toma un insight de la sesión actual de Claude Code y lo escribe directamente en el vault con los metadatos adecuados:

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

El patrón se extiende a cualquier operación del vault: crear MOCs, actualizar notas de estado de proyectos, vincular señales relacionadas o generar resúmenes semanales a partir de registros diarios acumulados.

Ejemplos de la comunidad. Los profesionales están publicando sus bibliotecas de comandos. Un desarrollador compartió 22 comandos personalizados de Obsidian + Claude Code que abarcan revisiones diarias, planificación de proyectos, captura de investigación y flujos de trabajo de contenido.1 Otro creó una skill de “Visual Explainer” que genera notas de diagramas en el vault a partir del análisis de código.2 Los comandos varían, pero la arquitectura es coherente: las skills de Claude Code como interfaz, las notas del vault como capa de almacenamiento y la infraestructura de recuperación como motor de consultas.

Gestión de la ventana de contexto

La integración debe tener en cuenta la ventana de contexto de Claude Code:

  • Limita el contexto inyectado a 1.500-2.000 tokens por consulta. Más que eso compite con la memoria de trabajo del agente.
  • Incluye atribución de la fuente. Incluye siempre la ruta del archivo y el encabezado de la sección para que el agente pueda hacer referencia a la fuente.
  • Trunca el texto de los chunks. Los chunks largos deben truncarse con ... en lugar de omitirse por completo. Los primeros 300-500 caracteres suelen contener la información clave.
  • No inyectes en cada prompt. La inyección se ejecuta mediante UserPromptSubmit (el evento cuyo stdout llega al modelo), así que administra el presupuesto allí: omite los prompts conversacionales cortos, inyecta solo cuando el prompt mencione código, archivos o decisiones pasadas, y limita el bloque inyectado. Los eventos con ámbito de herramienta, como PreToolUse, pueden controlar o registrar, pero su stdout nunca llega al modelo.

Integración de Codex CLI

Codex CLI se conecta a servidores MCP mediante config.toml. El patrón de integración difiere de Claude Code en la sintaxis de configuración y la entrega de instrucciones.

Configuración de MCP

Añade lo siguiente a ~/.codex/config.toml (Codex lee $CODEX_HOME/config.toml; las instrucciones de nivel de proyecto pertenecen a AGENTS.md, no a un archivo de configuración del proyecto):

[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"

Patrones de AGENTS.md

Codex CLI lee AGENTS.md para las instrucciones de nivel de proyecto. Incluye orientación para buscar en el 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"

Diferencias con Claude Code

Función Claude Code Codex CLI
Configuración de MCP claude mcp add~/.claude.json / .mcp.json de proyecto ~/.codex/config.toml
Hooks Registrados en la configuración, 31 eventos de ciclo de vida, JSON por stdin Compatibles (superficie estable; su propio conjunto de eventos)
Skills ~/.claude/skills/ ~/.codex/skills/ (estable)
Archivo de instrucciones CLAUDE.md AGENTS.md
Superficie de permisos Modos: Manual / acceptEdits / auto (predeterminado en Pro/Max/Team desde el 14 de agosto de 2026) / plan / bypassPermissions Política de aprobación untrusted / on-request / never × sandbox read-only / workspace-write / danger-full-access (--full-auto se eliminó en v0.147.0)

Diferencia clave: ambas herramientas ahora admiten hooks y skills; lo que difiere es la forma. Codex combina una política de aprobación con un modo sandbox a nivel del sistema operativo en lugar de los modos de permisos de Claude Code, y sus eventos de hook son distintos: adapta el patrón (consulta el vault antes de trabajar, captura después), no la configuración. AGENTS.md sigue siendo el lugar adecuado para instrucciones permanentes de buscar primero en el vault en Codex.

Cursor y otras herramientas

Cursor y otras herramientas de IA compatibles con MCP pueden conectarse al mismo servidor MCP de Obsidian. Esta sección explica la configuración de herramientas habituales.

Cursor

Añade lo siguiente a .cursor/mcp.json en la raíz de tu proyecto:

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

El archivo .cursorrules de Cursor puede incluir instrucciones para usar el 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 compatibilidad

Herramienta Compatibilidad con MCP Transporte Ubicación de configuración
Claude Code Completa STDIO claude mcp add~/.claude.json / .mcp.json del proyecto
Codex CLI Completa STDIO ~/.codex/config.toml
Cursor Completa STDIO .cursor/mcp.json
Windsurf Completa STDIO ~/.codeium/windsurf/mcp_config.json
Continue.dev Completa STDIO + HTTP ~/.continue/config.yaml (mcpServers)
Zed Completa (servidores de contexto) STDIO settings.json (context_servers)
Claudian (plugin de Obsidian) No aplica (integrado) Claude Code CLI Configuración del plugin de Obsidian
Agent Client (plugin de Obsidian) No aplica (integrado) ACP Configuración del plugin de Obsidian

Alternativa para herramientas sin MCP

Para las herramientas que no admiten MCP, el recuperador puede envolverse como un 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

El CLI genera texto estructurado que puedes pegar manualmente en la entrada de cualquier herramienta de IA. Es menos elegante que la integración con MCP, pero funciona en todas partes.


Caché de prompts a partir de notas estructuradas

Las notas estructuradas del vault pueden servir como bloques de contexto reutilizables que reducen el uso de tokens en las interacciones con IA. Esta sección cubre el diseño de claves de caché y la gestión del presupuesto de tokens.

El patrón

En lugar de buscar contexto en cada interacción, crea con anticipación bloques de contexto a partir de notas bien estructuradas del vault y guárdalos en caché:

# 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
    },
}

Invalidación de caché

La invalidación de caché se basa en dos señales:

  1. Vencimiento del TTL. Cada bloque de contexto tiene un tiempo de vida. Cuando vence el TTL, el bloque se reconstruye al volver a consultar el vault.
  2. Detección de cambios en el vault. Cuando el indexador detecta cambios en archivos que contribuyeron a un bloque de contexto almacenado en caché, el bloque se invalida de inmediato.

Gestión del presupuesto de tokens

Una sesión comienza con un presupuesto total de contexto. Los bloques almacenados en caché consumen una parte de ese presupuesto:

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)

Los bloques almacenados en caché se cargan al iniciar la sesión. Los resultados de búsqueda dinámicos ocupan el presupuesto restante según cada consulta. Este enfoque híbrido proporciona al agente una base de contexto que se necesita con frecuencia, a la vez que conserva presupuesto para consultas específicas.

Uso de tokens antes y después

Sin caché: Cada consulta relevante activa una búsqueda en el vault, que devuelve entre 1.500 y 2.000 tokens de contexto. A lo largo de 10 consultas en una sesión, el agente consume entre 15.000 y 20.000 tokens de contexto del vault.

Con caché: Tres bloques de contexto creados previamente consumen 4.500 tokens en total. Las búsquedas adicionales agregan entre 1.500 y 2.000 tokens por cada consulta única. En 10 consultas, de las cuales 6 están cubiertas por bloques almacenados en caché, el agente consume 4.500 + (4 * 1.500) = 10.500 tokens, aproximadamente la mitad del uso sin caché.


Captura de resúmenes comprimidos de resultados extensos

Los resultados de herramientas pueden ser extensos: trazas de pila, listados de archivos y resultados de pruebas. Un hook no puede reducir lo que ve el modelo: cuando se activa PostToolUse, el resultado completo ya está en la ventana de contexto, y nada de lo que imprima un hook lo reemplaza. Lo que un hook sí puede hacer es escribir un resumen comprimido en el vault, para que las sesiones futuras recuperen el veredicto de dos líneas en lugar de volver a ejecutar o leer el original de 5.000 tokens. Considera esto un patrón de captura para la memoria entre sesiones, no un mecanismo de ahorro de contexto dentro de la sesión (dentro de la sesión, las palancas reales son /compact, los prompts acotados y pedir resultados menos extensos).

El problema

Una llamada a la herramienta Bash que ejecuta pruebas podría devolver:

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

El resultado completo tiene 5.000 tokens, pero la señal está en 2 líneas: 200 aprobadas, 1 fallida.

Implementación del hook

Registrado en PostToolUse con un matcher de Bash (registrado en la configuración, stdin JSON; consulta la sección anterior sobre integración de hooks):

#!/bin/bash
# summarize-and-capture.sh — write a compressed summary to the vault
PAYLOAD=$(cat)
OUTPUT=$(printf '%s' "$PAYLOAD" | jq -r '.tool_response // "" | tostring')

# Only summarize large outputs
[ ${#OUTPUT} -lt 2000 ] && exit 0

if printf '%s' "$OUTPUT" | grep -q "PASSED\|FAILED"; then
    PASSED=$(printf '%s' "$OUTPUT" | grep -c "PASSED")
    FAILED=$(printf '%s' "$OUTPUT" | grep -c "FAILED")
    SUMMARY="Tests: $PASSED passed, $FAILED failed"
    [ "$FAILED" -gt 0 ] && SUMMARY="$SUMMARY
$(printf '%s' "$OUTPUT" | grep 'FAILED')"
    python /path/to/capture.py --text "$SUMMARY" --source "test-run-summary"
fi
exit 0

Cada invocación del hook es un proceso nuevo, por lo que no se necesita una protección contra recursión: las propias escrituras de un hook no lo vuelven a activar y las variables exportadas nunca persisten hasta la siguiente invocación.

Heurísticas de compresión

Tipo de resultado Detección Estrategia de compresión
Resultados de pruebas Palabras clave PASSED / FAILED Contar aprobadas/fallidas; mostrar solo los fallos
Listados de archivos ls o find en el comando Truncar a las primeras 20 entradas + cantidad
Trazas de pila Palabra clave Traceback Conservar el primer y último frame + el mensaje de error
Estado de Git modified: / new file: Resumir las cantidades por estado
Resultado de compilación warning: / error: Eliminar líneas informativas; conservar advertencias/errores

Canalización de recepción y triaje de señales

La capa de recepción determina qué entra en el vault. Sin curaduría, el vault acumula ruido. Esta sección cubre la canalización de puntuación que dirige las señales a las carpetas de dominio.

Fuentes

Las señales provienen de varios canales:

  • Feeds RSS: Blogs técnicos, avisos de seguridad, notas de lanzamiento
  • Marcadores mediante Web Clipper: La extensión oficial Obsidian Web Clipper (Chrome, Firefox, Safari) es la ruta de recepción de mayor fidelidad para la captura desde el navegador. El ciclo de lanzamientos de abril de 2026 la volvió considerablemente más útil para los flujos de trabajo de IA:22
    • 1.4.0 (9 de abr): Interfaz interactiva de transcripciones de YouTube — fija el video, desplázate por la transcripción, activa el desplazamiento automático y resalta la posición actual. Además, incluye la opción predeterminada “Open in Reader”, que envía una captura de un clic directamente al modo Reader.
    • 1.5.0–1.5.1 (15 de abr): Visor de resaltados — explora y busca los resaltados capturados en todo el vault. Transición de aparición hacia Reader. Reproducción/pausa de YouTube más fluida. La versión 1.5.1 corrigió una regresión de compilación de webpack.
    • 1.6.0–1.6.2 (21–23 de abr): Renovación de la UX del resaltador con compatibilidad móvil. Defuddle 0.18 incorpora extractores específicos por fuente para LinkedIn, Threads, Bluesky, Discourse y Medium. La versión 1.6.2 corrige una regresión del portapapeles en el modo integrado de Safari. Configura plantillas por dominio de origen para que las transcripciones de YouTube, los README de GitHub y los artículos extensos lleguen cada uno a una nota con un nombre razonable y el frontmatter adecuado para la canalización de puntuación que aparece más abajo.
  • Boletines: Extractos clave de boletines por correo electrónico
  • Captura manual: Notas escritas durante lecturas, conversaciones o investigaciones
  • Salida de herramientas: Salidas relevantes de herramientas de IA capturadas mediante hooks
  • Extensión Share de iOS: La app de iOS de Obsidian (actualizada a principios de 2026) incluye una extensión Share que guarda contenido de Safari, redes sociales y otras apps directamente en el vault sin abrir Obsidian; la línea 1.13 incorpora destinos configurables de Share Sheet con variables de plantilla —incluida url—, de modo que una página capturada registra automáticamente su enlace de origen en el frontmatter.19 Esto crea una ruta de recepción móvil de baja fricción: comparte un artículo desde Safari y llegará como una nota del vault lista para puntuarse.
  • Obsidian CLI: Los scripts de shell y hooks pueden crear notas mediante obsidian file create o agregar contenido a notas existentes mediante obsidian file append, lo que permite canalizaciones de recepción automatizadas en equipos de escritorio.

Dimensiones de puntuación

Cada señal se puntúa en cuatro dimensiones (de 0,0 a 1,0 cada una):

Dimensión Pregunta Puntuación baja (0,0-0,3) Puntuación alta (0,7-1,0)
Relevancia ¿Se relaciona con mis dominios activos? Tangencial, fuera de alcance Directamente relevante para el trabajo activo
Aplicabilidad ¿Puedo usar esta información? Teoría pura, sin aplicación Técnica o patrón específico que puedo aplicar
Profundidad ¿Qué tan sustancial es el contenido? Titulares, resumen superficial Análisis detallado con ejemplos
Autoridad ¿Qué tan creíble es la fuente? Blog anónimo, sin verificar Fuente primaria, revisión por pares, experto reconocido

Puntuación compuesta y enrutamiento

composite = (relevance * 0.35) + (actionability * 0.25) +
            (depth * 0.25) + (authority * 0.15)
Rango de puntuación Acción
0.55+ Enrutar automáticamente a la carpeta de dominio
0.40 - 0.55 Poner en cola para revisión manual
< 0.40 Descartar (no almacenar)

Enrutamiento por dominio

Las señales con una puntuación superior a 0.55 se dirigen a una de 12 carpetas de dominio según la coincidencia de palabras clave y la clasificación de temas:

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

Estadísticas de producción

Durante 14 meses de operación:

Métrica Valor
Total de señales procesadas 7,771
Enrutadas automáticamente (>0.55) 4,832 (62%)
En cola para revisión (0.40-0.55) 1,543 (20%)
Descartadas (<0.40) 1,396 (18%)
Carpetas de dominio activas 12
Promedio de señales por día ~18

Patrones de grafos de conocimiento

El grafo de wiki-links de Obsidian codifica las relaciones entre notas. Esta sección cubre la semántica de los enlaces, el recorrido del grafo para ampliar el contexto y los anti-patrones que degradan la calidad del grafo.

Cada wiki-link crea una arista dirigida en el grafo. Obsidian registra tanto los enlaces hacia adelante como los backlinks:

  • Enlace hacia adelante: La nota A contiene [[Note B]] → A enlaza a B
  • Backlink: La nota B muestra que la nota A hace referencia a ella

El grafo codifica distintos tipos de relaciones según el contexto:

Patrón de enlace Semántica Ejemplo
Enlace en línea “Se relaciona con” “Consulta [[OAuth Token Rotation]] para más detalles”
Enlace de encabezado “Tiene un subtema” ”## Related\n- [[Token Rotation]]\n- [[Session Management]]”
Enlace similar a una etiqueta “Se clasifica como” ”[[type/reference]]”
Enlace MOC “Forma parte de” Una nota Map of Content que enumera notas relacionadas

Maps of Content (MOCs)

Los MOCs son notas índice que organizan notas relacionadas en una estructura navegable:

---
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]]

Los MOCs mejoran la recuperación de dos maneras:

  1. Coincidencia directa. Una búsqueda de “authentication overview” encuentra el propio MOC, proporcionando al agente una lista curada de notas relacionadas.
  2. Ampliación de contexto. Después de encontrar una nota específica, el recuperador puede comprobar si la nota aparece en algún MOC e incluir la estructura del MOC en los resultados, dando al agente un mapa del tema más amplio.

Recorrido del grafo para ampliar el contexto

Una mejora futura para el recuperador: después de encontrar los resultados principales, ampliar el contexto siguiendo enlaces:

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)

Esto no está implementado en el recuperador actual, pero representa una extensión natural de la estructura del grafo.

Anti-patrones

Clústeres huérfanos. Grupos de notas que se enlazan entre sí, pero no tienen conexiones con el resto del vault. El panel de grafos de Obsidian los muestra como islas desconectadas. Los clústeres huérfanos indican MOCs faltantes o enlaces entre dominios ausentes.

Proliferación de etiquetas. Usar etiquetas de forma inconsistente o crear demasiadas etiquetas muy específicas. Un vault con 500 etiquetas únicas en 5.000 notas promedia 1 nota por cada 10 etiquetas: las etiquetas no resultan útiles para filtrar. Consolídalas en 20-50 etiquetas de alto nivel que se correspondan con tus carpetas de dominio.

Notas con muchos enlaces y poco contenido. Notas que consisten por completo en wiki-links sin prosa. Estas notas se indexan mal porque el chunker no tiene texto que incrustar. Agrega al menos un párrafo de contexto que explique por qué las notas enlazadas se relacionan.

Enlaces bidireccionales para todo. No toda referencia necesita ser un wiki-link. Mencionar “OAuth” de pasada no requiere [[OAuth 2.0 Overview]]. Reserva los wiki-links para relaciones intencionales y navegables, donde hacer clic en el enlace proporcione contexto útil.


Recetas de flujo de trabajo para desarrolladores

Flujos de trabajo prácticos que combinan la recuperación del vault con tareas diarias de desarrollo.

Carga de contexto matutina

Empieza el día cargando contexto relevante:

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

El retriever devuelve notas recientes sobre tu proyecto activo y te da un repaso rápido de dónde te quedaste. Es más efectivo que releer los mensajes de commit de ayer.

Captura de investigación mientras programas

Mientras implementas una función, captura hallazgos sin salir del editor:

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

El hallazgo capturado se indexa de inmediato y queda disponible para recuperarlo en el futuro. Con el paso de los meses, estas microcapturas construyen un corpus de conocimiento específico de implementación.

Inicio de proyecto

Al empezar un proyecto o una función nueva:

  1. Busca en el vault: “What do I know about [technology/pattern]?”
  2. Revisa los 5 resultados principales para encontrar decisiones previas y problemas conocidos
  3. Verifica si existe un MOC para el dominio; si no, crea uno
  4. Busca modos de falla: “problems with [technology]”

Debugging con búsqueda en el vault

Cuando encuentres un error o un comportamiento inesperado:

Search my vault for [error message or symptom]

Las notas previas de debugging suelen contener la causa raíz y la solución. Esto es especialmente valioso para problemas recurrentes entre proyectos: el vault recuerda lo que tú olvidas.

Preparación para revisión de código

Antes de revisar un PR:

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

El vault devuelve decisiones previas, restricciones arquitectónicas y estándares de código relevantes para el código en revisión. La revisión se informa con conocimiento institucional, no solo con el diff.


Ajuste de rendimiento

Esta sección cubre estrategias de optimización para distintos tamaños de vault y patrones de uso.

Gestión del tamaño del índice

Tamaño del vault Chunks Tamaño de DB Reindexado completo 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

Con 50,000+ notas, considera: - Aumentar el tamaño de batch de 64 a 128 para acelerar los embeddings - Usar WAL mode (predeterminado) para acceso concurrente - Ejecutar el reindexado completo fuera del horario de mayor uso

Optimización de consultas

WAL mode. El modo Write-Ahead Logging de SQLite permite lecturas concurrentes mientras el indexer escribe:

db.execute("PRAGMA journal_mode=WAL")

Esto es crítico cuando el servidor MCP gestiona consultas mientras el indexer ejecuta una actualización incremental.

Connection pooling. El servidor MCP debería reutilizar conexiones a la base de datos en lugar de abrir una conexión nueva por consulta. Una sola conexión de larga duración con WAL mode admite lecturas concurrentes.

# 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 con mapeo de memoria. El pragma mmap_size le indica a SQLite que use I/O con mapeo de memoria para el archivo de base de datos. En una base de datos de 83 MB, mapear todo el archivo en memoria elimina la mayoría de las lecturas de disco.

Optimización de FTS5. Después de un reindexado completo, ejecuta:

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

Esto fusiona los segmentos b-tree internos de FTS5 y reduce la latencia de las consultas en búsquedas posteriores.

Benchmarks de escalado

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

Operación 500 notas 5K notas 15K notas 50K notas
Consulta BM25 2ms 5ms 12ms 25ms
Consulta vectorial 1ms 3ms 8ms 20ms
Fusión RRF <1ms <1ms 3ms 5ms
Búsqueda completa 3ms 8ms 23ms 50ms

Todos los benchmarks incluyen acceso a la base de datos, ejecución de consultas y formato de resultados. La latencia de red para la comunicación MCP por STDIO agrega 1-2ms.


Solución de problemas

Desfase del índice

Síntoma: La búsqueda devuelve resultados obsoletos o no encuentra notas agregadas recientemente.

Causa: El indexer incremental no se ejecutó después de agregar notas, o no se actualizó el mtime de un archivo (por ejemplo, se sincronizó desde otra máquina conservando timestamps).

Solución: Ejecuta un reindexado completo: python index_vault.py --full

Cambio de modelo de embeddings

Síntoma: Después de cambiar el modelo de embeddings, la búsqueda vectorial devuelve resultados sin sentido.

Causa: Se están comparando vectores antiguos (del modelo anterior) contra nuevos vectores de consulta. Las dimensiones o la semántica del espacio vectorial son incompatibles.

Solución: El indexer debería detectar la discrepancia del hash del modelo y activar automáticamente un reindexado completo. Si no lo hace, borra manualmente la base de datos y vuelve a indexar:

rm vectors.db
python index_vault.py --full

Mantenimiento de FTS5

Síntoma: Las consultas FTS5 devuelven resultados incorrectos o incompletos después de muchas actualizaciones incrementales.

Causa: Los segmentos internos de FTS5 pueden fragmentarse después de muchas actualizaciones pequeñas.

Solución: Reconstruye y optimiza:

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

Timeout de MCP

Síntoma: La herramienta de AI informa que el servidor MCP agotó el tiempo de espera.

Causa: La primera consulta activa la carga del modelo (inicialización diferida), lo que tarda de 2 a 5 segundos. El timeout predeterminado de MCP de la herramienta de AI puede ser más corto.

Solución: Precarga el modelo al iniciar el servidor:

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

Bloqueos de archivo en SQLite

Síntoma: Errores SQLITE_BUSY o SQLITE_LOCKED.

Causa: Varios procesos escriben en la base de datos al mismo tiempo. WAL mode permite lecturas concurrentes, pero solo un escritor.

Solución: Asegúrate de que solo un proceso (el indexer) escriba en la base de datos. El servidor MCP y los hooks solo deberían leer. Si necesitas escrituras concurrentes, usa WAL mode y configura un busy timeout:

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

sqlite-vec no carga

Síntoma: La búsqueda vectorial está deshabilitada; el retriever se ejecuta solo en modo BM25.

Causa: La extensión sqlite-vec no está instalada, no se encuentra en la ruta de bibliotecas o es incompatible con la versión de SQLite.

Solución:

# Install via pip
pip install sqlite-vec

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

Verifica que la extensión cargue:

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

Problemas de memoria en vaults grandes

Síntoma: Errores de falta de memoria durante el reindexado completo de un vault grande (50,000+ notas).

Causa: El tamaño de batch de embeddings es demasiado grande, o todo el contenido de los archivos se carga en memoria al mismo tiempo.

Solución: Reduce el tamaño de batch y procesa los archivos de forma incremental:

BATCH_SIZE = 32  # Reduce from 64

También asegúrate de que el indexer procese los archivos de uno en uno (leyendo, haciendo chunking y generando embeddings para cada archivo antes de pasar al siguiente) en lugar de cargar todos los archivos en memoria.


Guía de migración

Desde Apple Notes

  1. Exporta Apple Notes con la opción “Export All” (macOS) o usa una herramienta de migración como apple-notes-liberator
  2. Convierte las exportaciones HTML a markdown con markdownify o pandoc
  3. Mueve los archivos convertidos a la carpeta 00-inbox/ de tu vault
  4. Revisa y agrega frontmatter a cada nota
  5. Mueve las notas a las carpetas de dominio correspondientes

Desde Notion

  1. Exporta desde Notion: Settings → Export → Markdown & CSV
  2. Descomprime la exportación en la carpeta 00-inbox/ de tu vault
  3. Corrige los artefactos markdown específicos de Notion:
  4. Notion usa - [ ] para listas de verificación; son markdown estándar
  5. Notion incluye tablas de propiedades como HTML; conviértelas a frontmatter YAML
  6. Notion incrusta imágenes como rutas relativas; copia las imágenes a tu carpeta de adjuntos
  7. Agrega frontmatter estándar (type, domain, tags)
  8. Reemplaza los enlaces de páginas de Notion con wiki-links de Obsidian

Desde Google Docs

  1. Usa Google Takeout para exportar todos los documentos
  2. Convierte archivos .docx a markdown: pandoc -f docx -t markdown input.docx -o output.md
  3. Conversión por lotes: for f in *.docx; do pandoc -f docx -t markdown "$f" -o "${f%.docx}.md"; done
  4. Mueve al vault, agrega frontmatter y organiza en carpetas

Desde markdown plano (sin Obsidian)

Si ya tienes un directorio de archivos markdown:

  1. Abre el directorio como un vault de Obsidian (Obsidian → Open Vault → Open folder)
  2. Agrega .obsidian/ a .gitignore si el directorio está bajo control de versiones
  3. Crea plantillas de frontmatter y aplícalas a los archivos existentes
  4. Empieza a enlazar notas con [[wiki-links]] mientras lees y organizas
  5. Ejecuta el indexer de inmediato: el sistema de recuperación funciona desde el primer día

Desde otro sistema de recuperación

Si estás migrando desde otro sistema de embeddings/búsqueda:

  1. No intentes migrar vectores. Distintos modelos producen espacios vectoriales incompatibles. Ejecuta un reindexado completo con el nuevo modelo.
  2. Migra el contenido, no el índice. Los archivos del vault son la fuente de verdad. El índice es un artefacto derivado.
  3. Verifica después de migrar. Ejecuta 10-20 consultas cuyas respuestas conozcas y comprueba que los resultados coincidan con tus expectativas.

Registro de cambios

Fecha Cambio Fuente
2026-08-14 Primera auditoría integral de compuerta — lectura del evaluador de la guía completa; R1 obtuvo 8,29 con tres hallazgos CRITICAL y cinco MAJOR, todos corregidos en esta fila. Los CRITICAL perjudicaban al lector: el inicio rápido instalaba npm obsidian-mcp-server como «la opción basada en archivos más sencilla» — ese paquete es el servidor de cyanheads respaldado por REST-API (necesita el plugin Local REST API + OBSIDIAN_API_KEY; no tiene la opción --vault), mientras que el servidor basado en archivos es npm obsidian-mcp (StevenStavrakis) — la tabla de servidores contenía la misma colisión de nombres y ambos se corrigieron con nombres explícitos de npm; ambos bloques de configuración de Claude Code MCP indicaban mcpServers en ~/.claude/settings.json, que Claude Code ignora silenciosamente — se reescribieron para usar claude mcp add (ámbito de usuario → ~/.claude.json) con una variante de ámbito de proyecto en .mcp.json, y se corrigió la celda de la matriz de compatibilidad; los ejemplos de hooks usaban argumentos posicionales $1/$2 y un directorio de detección automática ~/.claude/hooks/pre-tool-use/ — una interfaz que Claude Code nunca ha tenido — se reescribieron como hooks registrados en la configuración que leen stdin JSON mediante jq (la inyección de contexto se trasladó a UserPromptSubmit, cuya salida stdout realmente se añade al contexto), y la premisa de la sección «Compresión de contexto PostToolUse» (un hook que reduce lo que ve el modelo) es imposible — se reformuló como capturar un resumen comprimido en el vault para reutilizarlo entre sesiones, y se eliminó la protección contra recursión innecesaria (cada invocación de hook es un proceso nuevo). MAJOR: 1.13.4 → 1.13.7 (verificado mediante el manifiesto; versiones estable y beta convergieron); la nota de especificación de MCP del 2026-07-28 aún decía «la especificación final se publica el 28 de julio» diecisiete días después de haberse publicado como la revisión Current (se pasó a tiempo pasado; 9 se reescribió como histórico, apuntando a 24); la comparación con Codex enseñaba los modos de aprobación eliminados suggest/auto-edit/full-auto y «hooks/skills no compatibles» — ambos son superficies estables de Codex desde mediados de 2026, por lo que se reconstruyeron la tabla y el párrafo (la celda de CC ahora nombra los modos de permisos reales, incluido el valor predeterminado automático del 14 de agosto); se actualizaron las filas de la matriz de Zed/Continue/Windsurf. Menores: se eliminó la variante de proyecto .codex/config.toml (solo $CODEX_HOME), mcpvault 0.12.4 → 0.15.0, se eliminaron referencias relativas «a fecha de», y se incorporó en la sección de entrada el prometido uso de la variable url de la Hoja para compartir de iOS 1.13. R2 confirmó las correcciones, pero detectó residuos en sus bordes, resueltos en una segunda pasada: los bloques de inicio rápido de Codex/Cursor seguían invocando el binario de la colisión (ahora npx -y obsidian-mcp@2 serve en las tres herramientas, coincidiendo con la sintaxis v2 del paquete instalado), sobrevivió una oración sobre PreToolUse-injects-context debajo de la sección de hooks reescrita (la guía de inyección ahora se dirige sistemáticamente a UserPromptSubmit), y cuatro líneas breves (paréntesis sin cerrar, una referencia obsoleta a 1.13.4, la versión de 13 y la oración restante de hoja de ruta de 9). 24 26
2026-08-07 Obsidian 1.13 llegó al canal público: 1.13.4 se promovió el 30 de julio de 2026 (verificado mediante manifiesto: desktop-releases.json latestVersion 1.13.4, beta.latestVersion 1.13.6). Se actualizaron las tres referencias del cuerpo a «el canal público sigue en 1.12.7». Lo que entrega la línea 1.13, ahora que está disponible de forma general: una renovación de configuración (ventana separada, búsqueda por nombre/descripción, navegación con teclado + Vim), un visor de imágenes a pantalla completa con navegación por archivo y controles de redimensionamiento en Live Preview, Bookmarks con búsqueda, selección múltiple de Sync y —lo más relevante para la audiencia de esta guía— seguridad de URI de Obsidian: las acciones de obsidian:// ahora requieren un diálogo de confirmación salvo que estén en la lista de permitidas. La historia de automatización de esta guía funciona mediante MCP y CLI, que no se ven afectados, pero cualquier flujo que controle Obsidian mediante URI (Shortcuts, scripts u otros lanzadores) ahora necesita permitir sus acciones una vez o mostrará una solicitud cada vez. Para desarrolladores: una nueva Configuración API con guía de migración, un cambio incompatible en --callout-color (requiere colores CSS válidos, ya no tripletes RGB —los temas y snippets deben actualizarse), Electron 43.1.1 y actualizaciones de CodeMirror y Mermaid 11.13.0. Sin cambios en AI, MCP ni CLI. El seguimiento de Catalyst pasa a 1.13.6. 26
2026-07-27 Barrido de versiones + una corrección de aviso. MCPVault pasó de 0.12.1 → 0.12.4 en tres parches del mismo día el 23 de julio, todos omitidos por el barrido del 22 de julio porque se publicaron al día siguiente. v0.12.3 añade una herramienta wiki_link — resuelve [[Document Name]], [[Name\|Display]], formatos con escape para tablas y #fragment, y devuelve el contenido junto con la ruta resuelta y alternativas ambiguas — y excluye .trash/ de todas las herramientas mediante el filtro de rutas predeterminado; v0.12.4 lo amplía a enlaces con ruta calificada [[folder/Note]]; v0.12.2 corrige que patch_note corrompiera inserciones con patrones $, normaliza rutas con prefijo de vault y elimina hallazgos de alta gravedad de npm audit. La sección del servidor MCP y [^24] ahora describen los tres. Corrección: la fila del 2026-07-07 decía que v0.12.1 «tenía dos avisos de gravedad media sobre filtros de ruta». No era así. El GitHub Advisory API indica que GHSA-9c83-rr99-vfwj tiene un rango vulnerable de < 0.11.5 y GHSA-j99q-93c9-h869 < 0.11.4 — ambos se corrigieron antes de que se abriera la línea 0.12, por lo que 0.12.1 ya estaba libre de ellos cuando se escribió esa fila. El cuerpo y la nota al pie ahora indican las primeras versiones corregidas en lugar de dejar que «ejecuta una versión actual» implique una exposición abierta. Además: Obsidian 1.13.4 para escritorio + móvil (27 de julio) es acceso anticipado de Catalyst; el manifiesto desktop-releases.json aún informa latestVersion 1.12.7 con beta.latestVersion 1.13.4, por lo que el canal público no cambia y las referencias de versión aquí se mantienen. El contenido es de nivel UX (visualización del nombre de archivo en lightbox, alineación y relleno de imágenes de Live Preview, una condición de carrera al guardar archivos atascados, diseño de configuración) sin cambios en AI, MCP ni CLI. 13 26
2026-07-22 Barrido de versiones, sin cambios de flujo de trabajo. Obsidian 1.13.3 para escritorio + móvil (21 de julio) es solo acceso anticipado de Catalyst —el canal público verificado por manifiesto se mantiene en 1.12.7; el contenido es de nivel UX (lightbox/zoom de imágenes incrustadas, corrección de altura de línea de Live Preview, teclas de flecha de File Recovery, corrección de unique URI paneType), sin cambios en AI/MCP/CLI. El seguimiento de Catalyst pasa de 1.13.2 → 1.13.3. Nota: 1.13.3 se publicó más tarde el 21 de julio, después de que cerrara el barrido de ese día; «sin nuevas versiones» de la fila anterior era correcto cuando se escribió. Web Clipper 1.7.1 (22 de julio, versión de GitHub): importación de resaltados, variables de plantilla Interpreter {{model}}/{{modelId}}/{{modelProvider}}, presets de proveedores actualizados, Defuddle 0.19.2, correcciones de Interpreter para modelos recientes de Anthropic, claves API nativas de Gemini y manejo de DeepSeek y Azure OpenAI; los lanzamientos en tiendas pueden demorarse respecto a la fecha de GitHub. Sin noticias oficiales del servidor MCP; la especificación sin estado seguía prevista para el 28 de julio. 26
2026-07-21 Corrección de precisión: el canal público de escritorio es 1.12.7, no 1.13.1. La entrada del 2026-06-10 (y las referencias del cuerpo desde entonces) trataba 1.13.1 como una versión del canal público; la página del changelog de 1.13.1 lleva la insignia Early access, y el manifiesto oficial de actualización automática (obsidianmd/obsidian-releases, desktop-releases.json) indica la versión pública latestVersion 1.12.7 con 1.13.2 en el canal beta —toda la línea 1.13.x es solo de Catalyst. Se corrigieron las referencias del cuerpo y 26. El barrido de versiones de 2026-07-17 → 2026-07-21 no encontró nuevas versiones: el núcleo sigue en 1.13.2 Catalyst, Clipper 1.7.0, sin noticias oficiales del servidor MCP y la especificación sin estado de MCP seguía prevista para el 28 de julio. 26
2026-07-17 Barrido de versiones, sin cambios de flujo de trabajo. Obsidian 1.13.2 (14 de julio) es solo acceso anticipado de Catalyst —el canal público se mantiene en 1.13.1, por lo que las referencias de versión aquí siguen vigentes; su único elemento próximo a la guía es una nueva variable url en la plantilla de Hoja para compartir de iOS (inserta el enlace compartido en la nota), que se incorporará a la sección de ruta de captura cuando 1.13.2 llegue al canal público. Web Clipper 1.7.0 (16 de junio, descubierto anteriormente): actualización a Defuddle 0.19.0, {{content}} ahora conserva marcadores ==highlight== y los resaltados persisten entre la página activa y la vista Reader. No se ha anunciado ningún servidor oficial de Obsidian MCP ni integración de AI; la versión sin estado de la especificación MCP seguía programada para el 28 de julio. Verificado frente a obsidian.md/changelog, las versiones de github.com/obsidianmd/obsidian-clipper y blog.modelcontextprotocol.io.
2026-07-07 Correcciones de precisión. MCPVault se aclaró como proyecto propio (npm @bitbonsai/mcpvault, repositorio bitbonsai/mcpvault), ahora en v0.12.1, con dos avisos de gravedad media sobre filtros de ruta (GHSA-9c83-rr99-vfwj, GHSA-j99q-93c9-h869) —el enlace anterior [^24] apuntaba al repositorio equivocado (MarkusPfundstein/mcp-obsidian). Se corrigió el estado de MarkusPfundstein/mcp-obsidian: tiene mantenimiento activo (commits hasta el 15 de mayo de 2026, que añaden search_by_tag/get_frontmatter), no está «inactivo desde junio de 2025»; sigue sin publicar versiones etiquetadas. Verificado frente al historial de commits de GitHub, los avisos de seguridad de GitHub y npm.
2026-07-06 Reestructuración editorial para facilitar el descubrimiento: se cambió el título «Quick Start: First AI-Connected Vault» a Configuración de Obsidian MCP (ancla #obsidian-mcp-setup) y se añadió un resumen de capacidades «Lo que Claude puede hacer una vez conectado» (buscar, leer, listar, contexto con formato; límite de solo lectura con escrituras gestionadas por hooks), consolidado desde la sección Arquitectura del servidor MCP. Sin hechos nuevos; enlaces internos actualizados.
2026-06-10 Actualización de vigencia de versión. Obsidian 1.13.1 para escritorio llegó al canal público (9 de junio de 2026) —una actualización de UX de configuración + CodeMirror sobre 1.13.0, sin cambios importantes de AI/automatización. Las referencias de versión actual del cuerpo pasaron de 1.13.0 a 1.13.1 (pública, 9 de junio de 2026). 26
2026-06-09 Actualización del ecosistema. La especificación MCP 2026-07-28 entró en Release Candidate (anunciada el 21 de mayo de 2026) —la mayor revisión de MCP desde el lanzamiento: núcleo de protocolo sin estado (elimina el handshake initialize y Mcp-Session-Id), Apps de MCP (HTML renderizado por el servidor en iframes aislados), Tasks pasa del núcleo experimental a una extensión oficial, endurecimiento de OAuth 2.0/OIDC y una política de ciclo de vida de desuso de 12 meses (especificación final el 28 de julio de 2026); se reemplazó el enfoque especulativo de hoja de ruta «tentativamente a mediados de 2026» en la nota Evolución de la especificación MCP por el RC concreto. sqlite-vec v0.1.10-alpha (31 de marzo – 18 de mayo de 2026) añade tipos de índice de vecinos más cercanos aproximados (rescore, ivf experimental, DiskANN basado en disco) además de KNN de fuerza bruta —se marcó como próximo/experimental, ya que la línea 0.1.10 sigue siendo pre-release. Obsidian 1.13.0 para escritorio (acceso anticipado, 28 de mayo de 2026) se actualizó como la versión actual en todas las referencias del cuerpo; es una versión de UX/seguridad/herramientas de desarrollo sin nuevas capacidades de AI/automatización. 24 23 25
2026-06-08 Revisión de mantenimiento. Model2Vec v0.8.2 (29 de mayo de 2026) se publicó: una versión de mantenimiento que añade una opción de pesos congelados para entrenamiento, además de correcciones de tokens de varias palabras, una refactorización del entrenamiento y correcciones para el manejo de pesos no cuantizados; nota al pie actualizada. Nada más reciente que la base existente: la última versión de Obsidian sigue siendo 1.13.0 (28 de mayo, ya documentada abajo), sqlite-vec estable sigue siendo v0.1.9 (v0.1.10 sigue en alpha) y la especificación MCP sigue siendo la revisión 2025-11-25. Sin cambios en el cuerpo más allá de la nota de versión de Model2Vec. 10
2026-05-28 Se publicaron Obsidian 1.13.0 para escritorio + 1.13.0 para móvil (acceso anticipado de Catalyst). Escritorio: panel de Configuración renovado que se abre en su propia ventana con búsqueda integrada y navegación por teclado; los URI de Obsidian ahora presentan un diálogo de confirmación antes de ejecutar acciones; nueva advertencia antes de cargar recursos HTML desde unidades de red; se añadió Search a la vista Bookmarks; manejo mejorado de imágenes del editor; mejoras de File Explorer / Properties / Sync; numerosas correcciones de API para desarrolladores y de errores. Móvil: nueva Hoja para compartir de iOS con ubicaciones de destino configurables; reordenamiento de pestañas desde el selector de pestañas; gestos de mantener pulsado en tabletas para redimensionar divisiones y barras laterales fijadas; Bases obtiene una opción de menú para redimensionar columnas en vistas de tabla; correcciones de errores de iOS y Search. Implicaciones para los flujos de trabajo de AI: el diálogo de confirmación en URI de Obsidian añade una compuerta deliberada a las integraciones MCP/de agentes controladas por URI; el menú de redimensionamiento de columnas de Bases hace que Bases sea más útil como índice frontal del vault que consultan los agentes; el destino configurable de la Hoja para compartir de iOS permite conectar más rápido la ruta de captura del iPhone (ya documentada como la entrada principal) para pipelines de Claude/Codex.
2026-05-06 Actualización de vigencia verificada por fuentes: Smart Connections v4.5.0 movió las conexiones del pie de página a Core; las versiones estables sqlite-vec v0.1.8/v0.1.9 actualizaron el empaquetado y el comportamiento de DELETE; Model2Vec v0.8.x actualizó los componentes internos de tokenizador/persistencia y las tablas de benchmarks; se corrigió la cronología de Obsidian CLI de «1.12.7 introdujo CLI» a «1.12.0 introdujo CLI, 1.12.7 mejoró el empaquetado de instalación/ejecución».
2026-04-27 Ciclo de abril de Web Clipper: 1.4.0 (UI interactiva de transcripciones de YouTube + Open in Reader predeterminado), 1.5.0 (visor de Highlights), 1.6.0 (renovación de UX de Highlighter + extractores de fuente Defuddle 0.18 para LinkedIn/Threads/Bluesky/Discourse/Medium), 1.6.1 + 1.6.2 (correcciones de Reader y Safari). Se replanteó Web Clipper como la ruta principal de entrada del navegador para flujos de trabajo de AI en lugar de una mención pasajera de marcadores. Sin versiones de Obsidian para escritorio, Sync ni Bases en el período.
2026-04-16 Smart Connections v4.3.0 (vista de grafo, dock configurable, recuperación de block-embedding, entorno entre plugins de Substrate). Se documentó la ola de plugins nativos de AI de abril de 2026 (Cortex, VaultSearch, LLM Wiki, Drift, EngramQuest, Hybrid Search MCP). Se marcó MarkusPfundstein/mcp-obsidian como en modo mantenimiento (último commit en junio de 2025). Dataview está inactivo; Bases es el sucesor para trabajo nuevo. Obsidian CLI 1.12.7 sigue siendo el puente preferido para asistentes de AI.
2026-04-01 Se añadió la sección Obsidian CLI (comandos v1.12 para flujos de trabajo de AI). Se añadió la sección de plugins de agentes (Claudian, Agent Client). Se documentó el plugin central Bases para organización del vault. Se actualizó el número de plugins a más de 2.500. Se añadió la extensión para compartir de iOS como fuente de entrada. Se actualizó la matriz de compatibilidad con plugins de agentes integrados.
2026-03-30 MCPVault v0.11.0: herramienta list_all_tags, soporte para .base/.canvas, cambio de nombre a @bitbonsai/mcpvault. Obsidian Desktop v1.12.7 incluye el binario CLI para interacciones de terminal más rápidas.
2026-03-23 Se documentó sqlite-vec v0.1.7 estable: soporte DELETE para tablas vec0, restricciones de distancia KNN para paginación. Se anunció el índice de vecinos más cercanos aproximados DiskANN para una próxima versión.
2026-03-07 Se añadió potion-multilingual-128M (101 idiomas, mayo de 2025) a la comparación de modelos de embeddings. sqlite-vec en v0.1.7-alpha.10 (correcciones de CI/CD, sin cambios de funciones). Se confirmó que la especificación MCP y las técnicas de retrieval siguen vigentes.
2026-03-03 Se actualizó la evolución de la especificación MCP (noviembre de 2025 publicado: Streamable HTTP, .well-known, anotaciones de herramientas). Se añadieron el fine-tuning de Model2Vec y el soporte de tokenizador BPE/Unigram. Se añadió una tabla comparativa de servidores comunitarios MCP. Se actualizó Smart Connections a v4.
2026-03-02 Se añadieron potion-base-32M y potion-retrieval-32M a la comparación de modelos. Se añadió la sección de cuantización/reducción de dimensionalidad. Se añadió la nota sobre evolución de la especificación MCP.
2026-03-01 Lanzamiento inicial

Referencias


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

  2. Nicopreme, skill de agente “Visual Explainer” con comandos slash, x.com/nicopreme/status/2023495040258261460

  3. Cormack, G.V., Clarke, C.L.A. y Buettcher, S. Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods. SIGIR, 2009. Presenta RRF con k=60 como un método sin parámetros para combinar listas clasificadas. 

  4. OpenAI Embeddings Pricing. text-embedding-3-small: $0.02 por millón de tokens. Costo estimado del vault por reindexación completa: ~ $0.30. 

  5. van Dongen, T. et al. Model2Vec: Turn any Sentence Transformer into a Small Fast Model. arXiv, 2025. Describe el enfoque de destilación que genera embeddings estáticos a partir de transformadores de oraciones. 

  6. potion-base-8M Model Card y Model2Vec results. Las tablas publicadas actualmente muestran potion-base-8M con 51.32 Avg (All) / 51.08 Avg (MTEB), frente a all-MiniLM-L6-v2 con 55.80 Avg (All) / 55.93 Avg (MTEB), o aproximadamente un 92 % de retención en la puntuación de todas las tareas. 

  7. Model Context Protocol Specification. El estándar MCP para conectar herramientas de AI con fuentes de datos. 

  8. Model2Vec Potion Models, potion-base-32M y potion-retrieval-32M. Las tarjetas de modelo actuales indican que potion-base-32M obtiene 52.83 Avg (All) y potion-retrieval-32M 35.06 en la tabla de recuperación. 

  9. Update on the Next MCP Protocol Release. Histórico: la versión de noviembre de 2025 incorporó transporte Streamable HTTP, descubrimiento de URL .well-known, anotaciones estructuradas de herramientas y estandarización del nivel SDK. El ciclo de lanzamientos que anticipaba concluyó con la revisión del 28 de julio de 2026 — la especificación actual (consulta 24). 

  10. Model2Vec Releases. v0.4.0 (feb. de 2025): compatibilidad con entrenamiento y ajuste fino. v0.5.0 (abr. de 2025): reescritura del backend, cuantización y reducción de dimensionalidad. v0.7.0 (oct. de 2025): cuantización de vocabulario, compatibilidad con tokenizadores BPE/Unigram. v0.8.0/v0.8.1 (mar. de 2026): refactorizaciones de tokenizador y persistencia, desuso de Python 3.9, actualizaciones de resultados de MTEB V2 y compatibilidad con rutas de Windows. v0.8.2 (29 de mayo de 2026): una versión de mantenimiento que añade una opción de pesos congelados para el entrenamiento, además de correcciones para tokens de varias palabras, una refactorización del entrenamiento y correcciones en el manejo de pesos no cuantizados. 

  11. Smart Connections for Obsidian. Smart Connections v4: embeddings de AI locales primero; la búsqueda semántica funciona sin conexión después de la indexación inicial. 

  12. potion-multilingual-128M. Minish Lab, mayo de 2025. Modelo de embeddings estáticos para 101 idiomas, los embeddings estáticos multilingües con mejor rendimiento. Misma dependencia exclusiva de numpy que otros modelos potion. 

  13. MCPVault — bitbonsai/mcpvault. npm @bitbonsai/mcpvault, versión más reciente v0.15.0 (publicada el 2026-08-09); toda la serie 0.12.2–0.12.4 se publicó el 2026-07-23 (0.12.2 a las 09:51, 0.12.4 a las 10:10 — 0.12.3 aparece entre ambas en el changelog del repositorio, pero nunca se publicó en npm); es un proyecto distinto de MarkusPfundstein/mcp-obsidian, no un cambio de nombre de este. v0.11.0 (marzo de 2026) añadió la herramienta list_all_tags para examinar frontmatter y hashtags con recuentos, mejoró el manejo de carpetas con puntos y añadió compatibilidad con archivos .base/.canvas. El contenido de 0.12.2–0.12.4 proviene del CHANGELOG.md del repositorio, que es el único registro de versiones: el endpoint de versiones de GitHub para este repositorio devuelve una lista vacía, por lo que las horas de publicación de npm y el changelog son las fuentes principales. 0.12.2: patch_note inserta newString literalmente en lugar de expandir $', $&, $`, $$ (issue #149 / PR #153); rutas absolutas con prefijo del vault o de estilo ~/ normalizadas a rutas relativas al vault (issue #122 / PR #151); hallazgos de alta gravedad de npm audit eliminados mediante actualizaciones únicamente del lockfile (PR #154). 0.12.3: nueva herramienta wiki_link (PR #101) y .trash/ excluida de todas las herramientas mediante el filtro de rutas predeterminado. 0.12.4: wiki_link resuelve enlaces con rutas calificadas como [[folder/Note]] mediante la ruta completa relativa al vault, en lugar del nombre base. Dos avisos de seguridad de gravedad media de GitHub afectan su filtro de rutas: GHSA-9c83-rr99-vfwj (los directorios restringidos se deniegan solo en la raíz del vault, no cuando están anidados) y GHSA-j99q-93c9-h869 (omisión de la lista de denegación mediante equivalencia de mayúsculas/minúsculas y punto o espacio final). Según la base de datos de avisos de GitHub, sus rangos vulnerables son < 0.11.5 y < 0.11.4, con las primeras versiones corregidas 0.11.5 y 0.11.4, respectivamente; ambas son anteriores a 0.12.0, por lo que todas las versiones 0.12.x, incluida 0.12.1, ya están corregidas. Rangos de los avisos y marcas de tiempo de npm verificados nuevamente el 2026-08-14. 

  14. sqlite-vec v0.1.7 Release. 17 de marzo de 2026. Versión estable: compatibilidad con DELETE para tablas virtuales vec0, restricciones de distancia KNN para paginación y mejoras en pruebas fuzz. Se anunció la indexación aproximada de vecinos más cercanos DiskANN para una versión futura. 

  15. Introduction to Bases. Plugin principal de Obsidian introducido en v1.9.10. Vistas similares a bases de datos (tablas, galerías, calendarios y tableros kanban) sobre archivos del vault que utilizan propiedades de frontmatter como campos. Los archivos se guardan en formato .base

  16. Obsidian Desktop v1.12.0 Changelog y Obsidian Desktop v1.12.7 Changelog. v1.12.0 introdujo el CLI para la automatización de vaults basada en terminal; v1.12.7 mejoró el empaquetado de instalación y ejecución con un binario independiente, TUI y comportamiento de archivos de socket. Consulta también la documentación de CLI

  17. Claudian. Plugin de Obsidian que integra Claude Code como colaborador de AI en el vault. Ofrece chat en la barra lateral, prompts con reconocimiento de contexto, compatibilidad con visión, comandos slash y modos de permisos. 

  18. Agent Client. Plugin de Obsidian que ofrece una interfaz unificada para Claude Code, Codex CLI y Gemini CLI mediante Agent Client Protocol (ACP). Admite menciones de notas, ejecución de shell y aprobación de acciones. 

  19. Obsidian iOS Changelog. Las actualizaciones de principios de 2026 incluyen Share Extension para guardar contenido de otras aplicaciones directamente en el vault, correcciones para los widgets Daily Note y Bookmark, y mejoras en la actualización del widget View Note. 

  20. MarkusPfundstein/mcp-obsidian. Mantenimiento activo — commits hasta el 15 de mayo de 2026, con trabajo reciente que añade herramientas como search_by_tag y get_frontmatter, además de cobertura de pruebas ampliada (verificado con el historial de commits del repositorio y tools.py). Aún no publica versiones etiquetadas, así que instálalo desde un commit fijado. Basado en Local-REST-API; los debates del foro (abril de 2026) informan de una migración de la comunidad hacia el puente CLI de Obsidian de primera clase (1.12.x) para configuraciones nuevas, pero mcp-obsidian sigue siendo una opción funcional y actualizada para implementaciones REST-API existentes. 

  21. Smart Connections v4.5.0 Release. 5 de mayo de 2026. Las conexiones del pie de página pasaron a ser una función Core; las versiones recientes de v4 también incluyen vistas de grafo para listas de conexiones, ubicaciones configurables para el panel de conexiones, recuperación mejorada de embeddings de bloques, estado entre plugins de Substrate, correcciones de respaldo del transformador y menos cálculos duplicados de conexiones. 

  22. obsidianmd/obsidian-clipper releases — fuente principal para la correspondencia entre versiones y funciones de Web Clipper. Ciclo de abril de 2026: 1.4.0 (9 de abril, interfaz de transcripciones de YouTube + Open in Reader como valor predeterminado), 1.5.0 (15 de abril, visor Highlights + aparición gradual de Reader), 1.5.1 (15 de abril, corrección de compilación de webpack), 1.6.0 (21 de abril, UX de Highlighter + Defuddle 0.18 con extractores de LinkedIn/Threads/Bluesky/Discourse/Medium), 1.6.1 (22 de abril, correcciones del esquema de Reader + búsqueda en highlights), 1.6.2 (23 de abril, corrección del portapapeles en modo incrustado de Safari). También aparece en Mozilla Add-ons store y Chrome Web Store

  23. sqlite-vec v0.1.8, sqlite-vec v0.1.9, sqlite-vec v0.1.10-alpha.3 y sqlite-vec v0.1.10-alpha.4. v0.1.8 corrigió el empaquetado de npm; v0.1.9 corrigió un error de DELETE para columnas de texto de metadatos de más de 12 caracteres; v0.1.10-alpha.3 añade compatibilidad adecuada con INSERT OR REPLACE INTO; v0.1.10-alpha.4 (18 de mayo de 2026) corrige el fallo de ALTER TABLE RENAME en tablas vec0 que utilizan las nuevas funciones ivf/diskann y un error de limpieza de sentencias almacenadas en caché en DiskANN. La línea 0.1.10 aún está en versión preliminar. 

  24. MCP 2026-07-28 Specification Release Candidate. Anunciada el 21 de mayo de 2026; la especificación final se publicó el 28 de julio de 2026. La mayor revisión de MCP desde su lanzamiento: núcleo de protocolo sin estado (elimina el handshake initialize y el encabezado Mcp-Session-Id), Apps de MCP (HTML renderizado por el servidor en iframes de cliente aislados), Tasks pasan del núcleo experimental a una extensión oficial (tasks/get, tasks/update, tasks/cancel), refuerzo de autorización de OAuth 2.0 / OIDC y una política de ciclo de vida de desuso de funciones de 12 meses. 

  25. Obsidian Desktop v1.13.0 Changelog. Acceso anticipado, 28 de mayo de 2026. Versión de UX/seguridad/herramientas para desarrolladores: panel Settings renovado que se abre en su propia ventana con búsqueda y navegación por teclado, diálogos de confirmación antes de que se activen las URI de Obsidian, un nuevo API de Settings para desarrolladores de plugins y una corrección de CLI para instalaciones flatpak. No hay nuevas capacidades importantes de AI/automatización más allá de la superficie de CLI de 1.12.x. 

  26. Obsidian Changelog. Obsidian 1.13.1 para escritorio se publicó el 9 de junio de 2026 como una versión de acceso anticipado Catalyst — un refinamiento de la UX de configuración y una actualización de CodeMirror respecto de 1.13.0, sin nuevas capacidades de AI/automatización. La propia página del changelog de 1.13.1 lleva la etiqueta “Early access”, y el manifiesto oficial de actualización automática (obsidianmd/obsidian-releases, desktop-releases.json) muestra latestVersion público 1.12.7 con 1.13.2 en el canal beta; verificado el 2026-07-21. Verificado nuevamente el 2026-07-27: el manifiesto aún informa latestVersion 1.12.7, y beta.latestVersion ahora es 1.13.4. El feed Atom en obsidian.md/changelog.xml etiqueta cada entrada 1.13.x — 1.13.1 a 1.13.4 — como “(Early access)”; la entrada más reciente titulada “(Public)” sigue siendo 1.12.7, con fecha 2026-03-23, lo que coincide con la lista de versiones de GitHub de obsidian-releases. Verificado nuevamente el 2026-08-07: el manifiesto ahora informa latestVersion 1.13.4 (promoción pública el 30 de julio de 2026) con beta.latestVersion 1.13.6 — la línea 1.13 está disponible de forma general y las filas históricas anteriores describen con precisión el periodo exclusivo de Catalyst según sus fechas. Verificado nuevamente el 2026-08-14: el manifiesto informa latestVersion 1.13.7 con beta.latestVersion 1.13.7 — las versiones estable y beta han convergido. 

VAULT obsidian.md INDEXED