Obsidian MCP + Hybrid Retrieval: Referenz 2026
# Binden Sie Obsidian über MCP in Claude und andere Agenten ein: Servereinrichtung, hybride BM25- und Vektorsuche sowie Indexierung eines Vaults mit 16.894 Dateien — mit funktionierenden Konfigurationen.
Obsidian ist keine Notiz-App. Es ist ein lokal-first ausgerichtetes, plaintext-basiertes, graphstrukturiertes Markdown-Korpus, das zu einem KI-Kontextreservoir wird, wenn Sie Retrieval-Infrastruktur hinzufügen. 16.894 Dateien. 49.746 Chunks. Abfragen in 23 ms. Null API-Aufrufe. Eine 83-MB-SQLite-Datei. Dieser Leitfaden behandelt das gesamte System: von der Architektur des Obsidian-Tresors über hybrides Retrieval bis zur MCP-Integration und zu operativen Workflows.
Zentrale Erkenntnisse
Context Engineering, nicht Notizenmachen. Der Wert eines Obsidian-Vaults für AI liegt nicht in den Notizen selbst, sondern in der Retrieval-Schicht, die sie abfragbar macht. Ein Vault mit 16.000 Dateien ohne Retrieval ist eine reine Schreibdatenbank. Ein Vault mit 200 Dateien, hybrider Suche und MCP-Integration ist eine AI-Wissensbasis. Die Retrieval-Infrastruktur ist das Produkt. Die Notizen sind das Rohmaterial.
Hybrid Retrieval schlägt reine Keyword- oder rein semantische Suche. BM25 findet exakte Bezeichner und Funktionsnamen. Vektorsuche findet Synonyme und konzeptionelle Treffer über unterschiedliche Terminologie hinweg. Reciprocal Rank Fusion (RRF) führt beides zusammen, ohne eine Score-Kalibrierung zu erfordern. Keine der beiden Methoden deckt allein beide Fehlermodi ab. Forschung zum MS MARCO Passage Ranking bestätigt dieses Muster: Hybrid Retrieval übertrifft jede Methode für sich genommen konsistent.3 Der Deep Dive zum Hybrid Retriever behandelt die RRF-Mathematik, durchgerechnete Beispiele mit echten Zahlen, Fehlermodusanalysen und einen interaktiven Fusion-Rechner.
MCP gibt AI-Tools direkten Vault-Zugriff. Model Context Protocol (MCP)-Server stellen den Retriever als Tool bereit, das Claude Code, Codex CLI, Cursor und andere AI-Tools direkt aufrufen können. Der Agent fragt den Vault ab, erhält gerankte Ergebnisse mit Quellenzuordnung und nutzt den Kontext, ohne ganze Dateien zu laden. Der MCP-Server ist ein schlanker Wrapper um die Retrieval-Engine.
Local-first bedeutet keine API-Kosten und volle Privatsphäre. Der gesamte Stack läuft auf einem einzelnen Rechner: SQLite für Speicherung, Model2Vec für Embeddings, FTS5 für Keyword-Suche, sqlite-vec für Vektor-KNN. Keine Cloud-Dienste, keine API-Aufrufe, keine Netzwerkabhängigkeit. Persönliche Notizen verlassen den Rechner nie. Das vollständige erneute Einbetten von 49.746 Chunks würde bei OpenAI-API-Preisen ungefähr 0,30 US-Dollar kosten, aber die eigentlichen Kosten sind Latenz, Datenschutzrisiko und die Netzwerkabhängigkeit eines Systems, das offline funktionieren sollte.4
Inkrementelle Indexierung hält das System in unter 10 Sekunden aktuell. Der Vergleich von Dateiänderungszeiten erkennt Änderungen. Nur geänderte Dateien werden erneut gechunkt und erneut eingebettet. Eine vollständige Neuindexierung dauert auf Apple-M-Series-Hardware etwa vier Minuten. Inkrementelle Updates nach typischen Tagesänderungen laufen in unter zehn Sekunden. Das System bleibt ohne manuelles Eingreifen aktuell.
Die Architektur skaliert von 200 auf über 20.000 Notizen. Dasselbe dreischichtige Design (Intake, Retrieval, Integration) funktioniert bei jeder Vault-Größe. Beginnen Sie mit reiner BM25-Suche über einen kleinen Vault. Fügen Sie Vektorsuche hinzu, wenn Keyword-Kollisionen zum Problem werden. Ergänzen Sie RRF Fusion, wenn Sie sowohl exakte als auch semantische Treffer benötigen. Jede Schicht ist eigenständig nützlich und eigenständig entfernbar.
So verwenden Sie diesen Leitfaden
Dieser Leitfaden deckt das vollständige System ab. Ihr Einstiegspunkt hängt davon ab, wo Sie stehen:
| Sie sind… | Beginnen Sie hier | Erkunden Sie danach |
|---|---|---|
| Neu bei Obsidian + AI | Warum Obsidian für AI-Infrastruktur, Obsidian-MCP-Setup | Vault-Architektur, MCP-Server-Architektur |
| Bestehender Vault, Sie möchten AI-Zugriff | MCP-Server-Architektur, Claude Code-Integration | Embedding-Modelle, Volltextsuche |
| Sie bauen ein Retrieval-System | Die vollständige Retrieval-Pipeline, Reciprocal Rank Fusion | Performance-Tuning, Fehlerbehebung |
| Team- oder Enterprise-Kontext | Entscheidungsframework, Knowledge-Graph-Muster | Developer-Workflow-Rezepte, Migrationsleitfaden |
Abschnitte mit der Markierung Contract enthalten Implementierungsdetails, Konfigurationsblöcke und Fehlermodi. Abschnitte mit der Markierung Narrative konzentrieren sich auf Konzepte, Architekturentscheidungen und die Begründung hinter Designentscheidungen. Abschnitte mit der Markierung Recipe bieten Schritt-für-Schritt-Workflows.
Warum Obsidian für AI-Infrastruktur
Die These dieses Leitfadens: Obsidian-Vaults sind das beste Substrat für persönliche AI-Wissensbasen, weil sie local-first, plaintext-basiert und graphstrukturiert sind und der Benutzer jede Schicht des Stacks kontrolliert.
Was Obsidian AI bietet, was Alternativen nicht bieten
Plaintext-Markdown-Dateien. Jede Notiz ist eine .md-Datei in Ihrem Dateisystem. Kein proprietäres Format, kein Datenbankexport, keine API erforderlich, um den Inhalt zu lesen. Jedes Tool, das Dateien lesen kann, kann Ihren Vault lesen. grep, ripgrep, Pythons pathlib, SQLite FTS5 — sie alle arbeiten direkt mit den Quelldateien. Wenn Sie ein Retrieval-System bauen, indexieren Sie Dateien, keine API-Antworten. Der Index ist immer konsistent mit der Quelle, weil die Quelle das Dateisystem ist.
Local-first-Architektur. Der Vault liegt auf Ihrem Rechner. Kein Server, keine Cloud-Sync-Abhängigkeit, keine API-Rate-Limits, keine Nutzungsbedingungen, die regeln, wie Sie Ihre eigenen Inhalte verarbeiten. Sie können Ihre Notizen ohne externen Dienst einbetten, indexieren, chunken und durchsuchen. Für AI-Infrastruktur ist das wichtig, weil die Retrieval-Pipeline so schnell läuft, wie Ihre Festplatte es zulässt, nicht so schnell, wie ein API-Endpoint antwortet. Es ist auch für die Privatsphäre wichtig: Persönliche Notizen mit Zugangsdaten, Gesundheitsdaten, Finanzinformationen und privaten Gedanken verlassen Ihren Rechner nie.
Graphstruktur durch wiki-links. Obsidian’s [[wiki-link]]-Syntax erzeugt einen gerichteten Graphen über Notizen hinweg. Eine Notiz zur OAuth-Implementierung verlinkt auf Notizen zu Token-Rotation, Sitzungsverwaltung und API-Sicherheit. Die Graphstruktur kodiert menschengesteuerte Beziehungen zwischen Konzepten. Vektor-Embeddings erfassen semantische Ähnlichkeit, aber wiki-links erfassen absichtliche Verbindungen, die der Autor beim Nachdenken über das Thema hergestellt hat. Der Graph ist ein Signal, das Embeddings nicht replizieren können.
Plugin-Ökosystem. Obsidian hat mehr als 2.500 Community-Plugins (Stand März 2026, gestiegen von über 1.800 Mitte 2025). Dataview fragt Ihren Vault wie eine Datenbank ab. Templater erzeugt Notizen aus Vorlagen mit JavaScript-Logik. Git-Integration synchronisiert Ihren Vault mit einem Repository. Linter erzwingt Formatierungskonsistenz. Das Bases-Core-Plugin (eingeführt in v1.9.10) ergänzt datenbankähnliche Ansichten — Tabellen, Galerien, Kalender und Kanban-Boards — über Vault-Dateien hinweg und nutzt frontmatter-Eigenschaften als Felder, gespeichert als .base-Dateien.15 Diese Plugins fügen dem Vault Struktur hinzu, ohne das zugrunde liegende Plaintext-Format zu verändern. Das Retrieval-System indexiert die Ausgabe dieser Plugins, nicht die Plugins selbst.
Über 5 Millionen Benutzer. Obsidian hat eine große aktive Community, die Vorlagen, Workflows, Plugins und Dokumentation erstellt. Wenn Sie auf ein Problem mit Vault-Organisation oder Plugin-Konfiguration stoßen, hat wahrscheinlich bereits jemand eine Lösung dokumentiert. Die Community erstellt außerdem Obsidian-nahe Tools: MCP-Server, Indexierungsskripte, Publishing-Pipelines und API-Wrapper.
Was Ihnen ein Dateisystem allein nicht gibt
Ein Ordner mit Markdown-Dateien hat den Plaintext-Vorteil, aber ihm fehlen drei Dinge, die Obsidian ergänzt:
-
Bidirektionale Links. Obsidian verfolgt Backlinks automatisch. Wenn Sie von Notiz A auf Notiz B verlinken, zeigt Notiz B an, dass Notiz A sie referenziert. Das Graph-Panel visualisiert Verbindungscluster. Dieses bidirektionale Bewusstsein ist Metadata, die ein rohes Dateisystem nicht bereitstellt.
-
Live-Vorschau mit Plugin-Rendering. Dataview-Abfragen, Mermaid-Diagramme und Callout-Blöcke werden in Echtzeit gerendert. Das Schreiberlebnis ist reichhaltiger als in einem Texteditor, während das Speicherformat Plaintext bleibt. Sie schreiben und organisieren in einer reichhaltigen Umgebung; das Retrieval-System indexiert das rohe Markdown.
-
Community-Infrastruktur. Plugin-Discovery, Theme-Marktplatz, Sync-Dienst (optional), Publish-Dienst (optional) und ein Dokumentationsökosystem. Sie können jede einzelne Funktion mit eigenständigen Tools nachbauen, aber Obsidian bündelt sie in einem kohärenten Workflow.
Was Obsidian NICHT tut (und was Sie bauen)
Obsidian enthält keine Retrieval-Infrastruktur. Es bietet einfache Suche (Volltext, Dateiname, Tag), aber keine Embedding-Pipeline, keine Vektorsuche, kein Fusion-Ranking, keinen MCP-Server, kein Credential Filtering, keine Chunking-Strategie und keine Integrationshooks für externe AI-Tools. Dieser Leitfaden behandelt die Infrastruktur, die Sie auf Obsidian aufbauen. Der Vault ist das Substrat. Die Retrieval-Pipeline, der MCP-Server und die Integrationshooks sind die Infrastruktur.
Die hier beschriebene Architektur ist markdown-first, nicht Obsidian-exklusiv. Wenn Sie Logseq, Foam, Dendron oder einen einfachen Ordner mit Markdown-Dateien verwenden, funktioniert die Retrieval-Pipeline identisch. Der Chunker liest .md-Dateien. Der Embedder verarbeitet Textstrings. Der Indexer schreibt in SQLite. Keine dieser Komponenten hängt von Obsidian-spezifischen Funktionen ab. Obsidian leistet seinen Beitrag als Schreib- und Organisationsumgebung, die die Markdown-Dateien erzeugt, die der Retriever indexiert.
Obsidian MCP-Setup
Model Context Protocol (MCP) ist die Standardschnittstelle, die Claude Code, Codex CLI, Cursor und anderen AI-Tools direkten Zugriff auf einen Obsidian-Vault gibt. In diesem Abschnitt verbinden Sie einen Vault in fünf Minuten mit einem AI-Tool. Sie installieren Obsidian, erstellen einen Vault, installieren einen MCP-Server und führen Ihre erste Abfrage aus. Der Schnellstart nutzt einen Community-MCP-Server für sofortige Ergebnisse. Spätere Abschnitte behandeln den Aufbau einer eigenen Retrieval-Pipeline für den Produktionseinsatz.
Voraussetzungen
- macOS, Linux oder Windows
- Node.js 18+ (für den MCP-Server)
- Obsidian 1.12+ (für die CLI-Integration; 1.13.1 ist die aktuelle öffentliche Desktop-Version; frühere Versionen funktionieren für reine MCP-Setups)
- Claude Code, Codex CLI oder Cursor installiert
Schritt 1: Einen Vault erstellen
Laden Sie Obsidian von obsidian.md herunter und erstellen Sie einen neuen Vault. Wählen Sie einen Speicherort, den Sie sich merken können — der MCP-Server benötigt den absoluten Pfad.
# Example vault location
~/Documents/knowledge-base/
Fügen Sie ein paar Notizen hinzu, damit der Retriever Material hat, mit dem er arbeiten kann. Schon 10-20 Notizen reichen aus, um Ergebnisse zu sehen. Jede Notiz sollte eine .md-Datei mit einem aussagekräftigen Titel und mindestens einem Absatz Inhalt sein.
Schritt 2: Einen MCP-Server installieren
Mehrere Community-MCP-Server bieten sofortigen Vault-Zugriff. Das Ökosystem ist 2025-2026 deutlich gewachsen. Ein erwähnenswerter Server ist MCPVault (npm @bitbonsai/mcpvault, Repo bitbonsai/mcpvault), inzwischen bei v0.12.1 — ein eigenständiges Projekt neben MarkusPfundstein/mcp-obsidian unten, keine Umbenennung davon. Version v0.11.0 (März 2026) ergänzte list_all_tags zum Scannen von frontmatter und Hashtags mit Zählwerten, verbesserte die Behandlung von Ordnern mit Punkten im Namen und fügte Unterstützung für .base/.canvas hinzu. Zwei Advisories mit mittlerem Schweregrad (GHSA-9c83-rr99-vfwj und GHSA-j99q-93c9-h869) wurden zur Deny-List für pfadfilterbasierte eingeschränkte Verzeichnisse gemeldet; verwenden Sie deshalb eine aktuelle Version.13
Wechsel im April 2026 — Obsidian CLI als bevorzugte Brücke: Obsidian 1.12.0 führte den erstklassigen CLI ein, und der öffentliche Installer 1.12.7 (23. März 2026) bündelte die eigenständige Binary, TUI und Socket-Datei-Verbesserungen, wodurch Terminal-Workflows leichter zu installieren und auszuführen wurden.16 Die aktuelle öffentliche Desktop-Version, 1.13.1 (Public Channel, 9. Juni 2026), ist gegenüber 1.13.0 vor allem ein Aktualitätsschritt — Verbesserungen an der Einstellungs-UX und ein CodeMirror-Upgrade — ohne neue AI-/Automatisierungsfunktionen über die CLI-Oberfläche aus 1.12.x hinaus.2526 Community-Tools migrieren aktiv vom Local REST API-Plugin (das
mcp-obsidianantrieb) zu CLI-basierter Integration, weil sie schneller und stabiler ist. Das RepoMarkusPfundstein/mcp-obsidianwird weiterhin gepflegt — Commits bis Mai 2026 ergänzten Tools wiesearch_by_tagundget_frontmatter— veröffentlicht allerdings keine getaggten Releases (installieren Sie von einem gepinnten Commit). Es bleibt Local-REST-API-basiert; für neue Setups ist die CLI-Brücke in der Regel schneller und stabiler, daher sollten Sie diese oder die unten aufgeführten neueren Community-Alternativen bevorzugen.20 Die empfohlene Einrichtung finden Sie später in diesem Guide im Abschnitt „Obsidian CLI for AI Workflows“.
| Server | Autor | Transport | Benötigt Plugin | Zentrale Funktion |
|---|---|---|---|---|
| obsidian-mcp-server | StevenStavrakis | STDIO | Nein | Leichtgewichtig, dateibasiert |
| mcp-obsidian | MarkusPfundstein | STDIO | Local REST API | Vollständiges Vault-CRUD über REST, plus search_by_tag/get_frontmatter — aktiv gepflegt (Commits bis Mai 2026); keine getaggten Releases, pinnen Sie einen Commit20 |
| obsidian-mcp-tools | jacksteamdev | STDIO | Ja (Plugin) | Semantische Suche + Templater |
| obsidian-claude-code-mcp | iansinnott | WebSocket | Ja (Plugin) | Auto-Discovery für Claude Code |
| obsidian-mcp-server | cyanheads | STDIO | Local REST API | Tags, frontmatter-Verwaltung |
| Hybrid Search MCP | Community | STDIO | Nein | BM25 + semantische Suche, MCP-Server + CLI. Neu und seit April 2026 aktiv gepflegt. |
Für den Schnellstart ist ein dateibasierter Server, der .md-Dateien direkt liest, die einfachste Option:
npm install -g obsidian-mcp-server
Schritt 3: Ihr AI-Tool konfigurieren
Claude Code — zu ~/.claude/settings.json hinzufügen:
{
"mcpServers": {
"obsidian": {
"command": "obsidian-mcp-server",
"args": ["--vault", "/absolute/path/to/your/vault"]
}
}
}
Codex CLI — zu .codex/config.toml hinzufügen:
[mcp_servers.obsidian]
command = "obsidian-mcp-server"
args = ["--vault", "/absolute/path/to/your/vault"]
Cursor — zu .cursor/mcp.json hinzufügen:
{
"mcpServers": {
"obsidian": {
"command": "obsidian-mcp-server",
"args": ["--vault", "/absolute/path/to/your/vault"]
}
}
}
Schritt 4: Ihre erste Abfrage ausführen
Öffnen Sie Ihr AI-Tool und stellen Sie eine Frage, die Ihre Vault-Notizen beantworten können:
Search my Obsidian vault for notes about [topic you wrote about]
Das AI-Tool ruft den MCP-Server auf, der Ihren Vault durchsucht und passende Inhalte zurückgibt. Sie sollten Ergebnisse mit Dateipfaden und relevanten Auszügen sehen.
Was Claude nach der Verbindung tun kann
Die genauen Tool-Namen variieren je nach Server, aber die grundlegenden Fähigkeiten sind über Implementierungen hinweg konsistent:
| Fähigkeit | Typisches Tool | Was der Agent damit macht |
|---|---|---|
| Vault durchsuchen | obsidian_search / search |
Findet Notizen, die zu einer Abfrage passen, und gibt gerankte Auszüge mit Dateipfaden und Quellenangaben zurück |
| Vollständige Notiz lesen | obsidian_read_note / read_note |
Ruft den vollständigen Notizinhalt ab, wenn ein Suchauszug nicht ausreicht |
| Auflisten und browsen | obsidian_list_notes / list_notes |
Erkundet Notizen nach Ordner, Tag oder Datumsbereich, wenn es keine konkrete Abfrage gibt |
| Formatierten Kontext abrufen | obsidian_get_context |
Gibt einen thematisch geformten Kontextblock in der Größe eines Token-Budgets zurück, bereit zur Einfügung in die Unterhaltung |
In der Praxis beantwortet Claude Fragen aus Ihren Notizen mit Quellenangaben, zieht frühere Entscheidungen und Referenzmaterial in Coding-Sessions und erkundet die Vault-Struktur, ohne ganze Dateien in den Kontext zu laden. Einige Community-Server stellen auch Schreiboperationen bereit (Erstellen, Anhängen, Tag- und frontmatter-Verwaltung); der später in diesem Guide gebaute eigene Server ist bewusst read-only, während die Notizerstellung über Hooks läuft.
Vertiefungen: MCP-Serverarchitektur für Tool- und Berechtigungsdesign, Claude Code-Integration für Hooks und das Brückenmuster, Codex CLI-Integration und Cursor und andere Tools für weitere Agenten.
Was Sie gerade gebaut haben
Sie haben eine lokale Wissensdatenbank über ein Standardprotokoll mit einem AI-Tool verbunden. Der MCP-Server liest Ihre Vault-Dateien, führt eine einfache Suche aus und gibt Ergebnisse zurück. Das ist die minimal funktionsfähige Version.
Was Ihnen dieser Schnellstart NICHT gibt: - Hybrid Retrieval (BM25 + Vektorsuche + RRF-Fusion) - Embedding-basierte semantische Suche - Credential Filtering - Inkrementelle Indexierung - Hook-basierte automatische Kontextinjektion
Der Rest dieses Guides behandelt den Aufbau jeder dieser Fähigkeiten. Der Schnellstart beweist das Konzept. Die vollständige Pipeline liefert Retrieval in Produktionsqualität.
Obsidian CLI für AI Workflows
Obsidian 1.12 (Februar 2026) führte ein integriertes Command Line Interface ein, das eine neue Integrationsfläche für AI Workflows eröffnet; es ist auch in der öffentlichen Desktop-Version 1.13.1 weiterhin aktuell (Public Channel, 9. Juni 2026), einem Settings-UX- und CodeMirror-Versionsupdate ohne neue CLI-Funktionen.162526 Das CLI funktioniert als Fernsteuerung für die Obsidian-GUI — Obsidian muss laufen (oder wird beim ersten Befehl automatisch gestartet). Aktivieren Sie es unter Settings > General > Command line interface.
Warum das CLI für AI-Infrastruktur wichtig ist
Das CLI bietet programmatischen Zugriff auf Obsidian-native Operationen, die zuvor die GUI oder Plugin-APIs erforderten. Für AI Workflows sind die wichtigsten Funktionen:
- Suche aus Skripten und Hooks.
obsidian search "query"undobsidian search:context "query"führen Vault-Suchen aus jedem Shell-Skript, Hook oder jeder Automatisierungspipeline aus. Die Variantesearch:contextgibt Trefferzeilen mit umgebendem Kontext zurück, was nützlich ist, um Ergebnisse in AI Prompts einzuspeisen. - Automatisierung täglicher Notizen.
obsidian dailyöffnet oder erstellt die tägliche Notiz für heute. In Kombination mit Shell-Skripting ermöglicht dies automatisierte tägliche Briefing-Workflows — ein Hook kann AI-generierte Zusammenfassungen an die tägliche Notiz anhängen. - Vorlagenbasierte Notizerstellung.
obsidian template listundobsidian template createerzeugen Notizen aus Templater oder Core-Templates, sodass AI Agents strukturierte Vault-Einträge erstellen können, ohne direkt Markdown-Dateien zu schreiben. - Property-Verwaltung.
obsidian property setundobsidian property getlesen und schreiben frontmatter-Properties, sodass Metadaten aus Skripten aktualisiert werden können, ohne YAML zu parsen. - Plugin-Steuerung.
obsidian plugin enable/disable/listverwaltet Plugins programmatisch, was beim Umschalten von Indexierungs-Plugins während Batch-Operationen nützlich ist. - Aufgabenverwaltung.
obsidian task list/add/completebietet strukturierten Zugriff auf Aufgaben, nützlich für AI Agents, die Arbeitselemente im Vault verwalten.
CLI vs. MCP für AI-Zugriff
Das CLI und MCP Server erfüllen unterschiedliche Rollen und ergänzen sich, statt miteinander zu konkurrieren:
| Aspekt | Obsidian CLI | MCP Server |
|---|---|---|
| Aufrufer | Shell-Skripte, Hooks, Cronjobs | AI Agents (Claude Code, Codex, Cursor) |
| Protokoll | POSIX-Prozess (stdin/stdout/stderr) | MCP (JSON-RPC über STDIO oder HTTP) |
| Stärke | Obsidian-native Operationen (Templates, Plugins, Properties) | Benutzerdefinierter Retrieval (Embeddings, BM25, RRF Fusion) |
| Einschränkung | Keine Vektorsuche, keine Embedding-Pipeline | Kein Zugriff auf Obsidian-interne Operationen |
| Am besten für | Automatisierungsskripte, Intake-Pipelines, Hook-Aktionen | Echtzeitabfragen von AI Agents während Sitzungen |
Empfehlung: Nutzen Sie das CLI für Intake-Automatisierung (Notizen erstellen, Properties verwalten, Obsidian-native Suche ausführen) und MCP für Retrieval (hybride Suche mit Embeddings). Ein PreToolUse-Hook kann obsidian search:context als schnelle Vorprüfung aufrufen, bevor er für gerankte Ergebnisse auf den vollständigen MCP Retriever zurückgreift.
Beispiel: Intake-Hook mit 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}"
Obsidian Agent Plugins
Eine wachsende Kategorie von Obsidian-Plugins bettet AI Coding Agents direkt in die Vault-UI ein und bietet damit eine Alternative zur externen MCP Server-Konfiguration. Diese Plugins führen den AI Agent in der Obsidian-Seitenleiste aus, statt eine Verbindung aus einem externen Tool herzustellen.
Claudian
Claudian bettet Claude Code als AI-Kollaborator in den Vault ein. Das Vault-Verzeichnis wird zum Arbeitsverzeichnis von Claude und gibt ihm vollständige agentische Fähigkeiten: Dateien lesen/schreiben, suchen, Bash-Befehle ausführen und mehrstufige Workflows bearbeiten.17
Wichtige Funktionen für AI-Infrastruktur:
- Kontextbewusste Prompts. Hängt automatisch die fokussierte Notiz an, unterstützt @notename-Dateierwähnungen, tagbasierte Ausschlüsse und die Editor-Auswahl als Kontext.
- Vision-Unterstützung. Analysieren Sie Bilder per Drag-and-drop, Einfügen oder Dateipfad — nützlich für die Verarbeitung von Screenshots und Diagrammen, die im Vault erfasst wurden.
- Slash Commands. Erstellen Sie wiederverwendbare Prompt-Templates, die durch /command ausgelöst werden und standardisierte Vault-Operationen ermöglichen.
- Berechtigungsmodi. YOLO (automatisch genehmigen), Safe (jede Aktion genehmigen) und Plan (nur planen) mit Sicherheits-Blocklist und Vault-Begrenzung.
Agent Client
Agent Client bringt Claude Code, Codex CLI und Gemini CLI über das Agent Client Protocol (ACP) in eine einheitliche Obsidian-Seitenleiste.18
Wichtige Funktionen:
- Multi-Agent-Wechsel. Chatten Sie mit Claude Code, Codex oder Gemini CLI im selben Panel und wechseln Sie bei Bedarf zwischen Agents.
- Notizerwähnungen. Verwenden Sie @notename, um Notizinhalte in Prompts einzubeziehen, ähnlich wie bei Claudian, aber Agent-agnostisch.
- Shell-Ausführung. Führen Sie Terminalbefehle inline im Chat aus — Build-Skripte, git-Befehle oder jede andere Terminaloperation, ohne die Unterhaltung zu verlassen.
- Aktionsgenehmigung. Feingranulare Kontrolle über Dateilesezugriffe, Bearbeitungen und Befehlsausführungen.
Wann Agent Plugins und wann externes MCP nutzen
| Szenario | Agent Plugin | Externes MCP |
|---|---|---|
| Schreiben und Bearbeiten von Vault-Notizen mit AI-Unterstützung | Besser — der Agent sieht den Editor-Kontext | Funktioniert, aber ohne Editor-Bewusstsein |
| Codeentwicklung über mehrere Repos hinweg | Begrenzt — auf den Vault beschränkt | Besser — projektbezogen mit vollständigem Dateisystem |
| Retrieval aus einem großen indexierten Korpus | Nur einfache Suche | Vollständige hybride Retrieval-Pipeline |
| Schnelle Vault-Q&A während Notizsitzungen | Ideal — kein Kontextwechsel | Erfordert Wechsel ins Terminal |
Empfehlung: Nutzen Sie Agent Plugins für vault-zentrierte Workflows (Notizen schreiben, organisieren, zusammenfassen). Nutzen Sie externe MCP Server für Entwicklungs-Workflows, bei denen der AI Agent die vollständige Retrieval-Pipeline und Zugriff auf Codebasen außerhalb des Vaults benötigt. Beide Ansätze können nebeneinander bestehen — führen Sie Claudian in Obsidian für Notizarbeit aus und Claude Code mit MCP extern für Entwicklung.
Entscheidungsrahmen: Obsidian vs. Alternativen
Nicht jeder Anwendungsfall braucht Obsidian. Dieser Abschnitt zeigt, wann Obsidian die richtige Grundlage ist, wann es überdimensioniert ist und wann etwas anderes besser passt.
Entscheidungsbaum
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.
Vergleichsmatrix
| Kriterium | Obsidian | Notion | Apple Notes | Einfaches Dateisystem | CLAUDE.md |
|---|---|---|---|---|---|
| Local-first | Ja | Nein (Cloud) | Teilweise (iCloud) | Ja | Ja |
| Plaintext | Ja (Markdown) | Nein (Blöcke) | Nein (proprietär) | Ja | Ja |
| Graphstruktur | Ja (wiki-links) | Teilweise (Erwähnungen) | Nein | Nein | Nein |
| Für AI indexierbar | Direkter Dateizugriff | API erforderlich | Export erforderlich | Direkter Dateizugriff | Bereits im Kontext |
| Plugin-Ökosystem | Über 2.500 Plugins | Integrationen | Keine | N/A | N/A |
| Offlinefähig | Vollständig | Schreibgeschützt zwischengespeichert | Teilweise | Vollständig | Vollständig |
| Skaliert auf 10.000+ Notizen | Ja | Ja (mit API) | Verschlechtert sich | Ja | Nein (Einzeldatei) |
| Kosten | Kostenlos (Kernfunktionen) | Ab 10 $/Monat | Kostenlos | Kostenlos | Kostenlos |
Wann Obsidian überdimensioniert ist
- Kontext für ein einzelnes Projekt. Wenn die AI nur Kontext zur aktuellen Codebasis braucht, legen Sie ihn in
CLAUDE.md,AGENTS.mdoder in projektbezogener Dokumentation ab. Diese Dateien bleiben beim Repo und werden automatisch geladen. - Strukturierte Daten. Wenn der Inhalt aus Tabellen, Datensätzen oder Schemata besteht, verwenden Sie eine Datenbank. Obsidian-Notizen sind primär für Fließtext gedacht. Dataview kann frontmatter-Felder abfragen, aber eine echte Datenbank verarbeitet strukturierte Abfragen besser.
- Temporäre Recherche. Wenn die Notizen nach Projektende verworfen werden, ist ein Arbeitsordner mit Markdown-Dateien einfacher. Bauen Sie keine Retrieval-Infrastruktur für kurzlebige Inhalte auf.
Wann Obsidian die richtige Wahl ist
- Wissen, das sich über Monate oder Jahre ansammelt. Der Wert wächst mit dem Korpus. Ein Vault mit 200 Notizen, der sechs Monate lang täglich abgefragt wird, liefert mehr Wert als ein Vault mit 5.000 Notizen, der nur einmal abgefragt wird.
- Mehrere Domänen in einem Korpus. Ein Vault mit Notizen zu Programmierung, Architektur, Sicherheit, Design und persönlichen Projekten profitiert von domänenübergreifendem Retrieval, das ein projektspezifisches
CLAUDE.mdnicht bieten kann. - Datenschutzsensible Inhalte. Local-first bedeutet, dass die Retrieval-Pipeline niemals Inhalte an externe Dienste sendet. Der Vault enthält alles, was Sie dort ablegen, einschließlich Inhalten, die Sie nicht in einen Cloud-Dienst hochladen würden.
Mentales Modell: Drei Ebenen
Das System besteht aus drei Ebenen, die unabhängig voneinander funktionieren, sich kombiniert aber gegenseitig verstärken. Jede Ebene hat einen anderen Zuständigkeitsbereich und einen anderen Fehlermodus.
┌─────────────────────────────────────────────────────┐
│ 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 bestimmt, was in den Vault gelangt. Ohne Kuratierung sammelt der Vault Rauschen an: Screenshots von Tweets, kopierte Artikel ohne Annotation, halb fertige Gedanken ohne Kontext. Die Intake-Ebene ist für die Qualitätskontrolle beim Eintrittspunkt verantwortlich. Eine Scoring-Pipeline, Tagging-Konvention oder ein manueller Review-Prozess - jeder Mechanismus, der sicherstellt, dass der Vault Inhalte enthält, deren Retrieval sich lohnt.
Retrieval macht den Vault abfragbar. Das ist die Engine: Chunking von Notizen in Sucheinheiten, Einbetten von Chunks in den Vektorraum, Indexierung für Keyword- und semantische Suche, Zusammenführen von Ergebnissen mit RRF. Die Retrieval-Ebene verwandelt einen Ordner mit Dateien in eine abfragbare Wissensdatenbank. Ohne diese Ebene kann der Vault manuell durchsucht und über einfache Suche navigiert werden, ist für AI-Tools aber nicht programmatisch zugänglich.
Integration verbindet die Retrieval-Ebene mit AI-Tools. Ein MCP-Server stellt Retrieval als aufrufbares Tool bereit. Hooks fügen Kontext automatisch ein. Skills schreiben neues Wissen zurück in den Vault. Die Integrationsebene ist die Schnittstelle zwischen der Wissensdatenbank und den AI-Agenten, die sie nutzen.
Die Ebenen sind bewusst entkoppelt. Die Intake-Scoring-Pipeline weiß nichts über Embeddings. Der Retriever weiß nichts über Signal-Routing-Regeln. Der MCP-Server weiß nichts darüber, wie Notizen erstellt wurden. Diese Entkopplung bedeutet, dass Sie jede Ebene unabhängig verbessern können. Tauschen Sie das Embedding-Modell aus, ohne die Intake-Pipeline zu ändern. Fügen Sie eine neue MCP-Funktion hinzu, ohne den Retriever anzupassen. Ändern Sie die Signal-Scoring-Heuristiken, ohne den Index anzufassen.
Vault-Architektur für AI Consumption
Ein für AI Retrieval optimierter Vault folgt anderen Konventionen als ein Vault, der für persönliches Browsing optimiert ist. Dieser Abschnitt behandelt Ordnerstruktur, Notizschema, frontmatter-Konventionen und die konkreten Muster, die die Retrieval-Qualität verbessern.
Ordnerstruktur
Verwenden Sie nummerierte Präfixe für Ordner auf oberster Ebene, um eine vorhersehbare Organisationshierarchie zu schaffen. Die Zahlen bedeuten keine Priorität — sie gruppieren verwandte Bereiche und machen die Struktur leichter erfassbar.
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
Ordner, die indexiert werden sollten: Alles, was Markdown-Prosa enthält — Projekte, Bereiche, Ressourcen, Signale, tägliche Notizen.
Ordner, die von der Indexierung ausgeschlossen werden sollten: Templates (sie enthalten Platzhaltervariablen, keine Inhalte), Anhänge (Binärdateien), Obsidian-Konfiguration und jeder Ordner mit sensiblen Inhalten, die Sie nicht im Retrieval-Index haben möchten.
Die Datei .indexignore
Erstellen Sie im Vault-Stammverzeichnis eine .indexignore-Datei, um Pfade explizit vom Retrieval-Index auszuschließen. Die Syntax entspricht .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/
Der Indexer liest diese Datei vor dem Scannen und überspringt passende Pfade vollständig. Dateien in ausgeschlossenen Pfaden werden nie gechunkt, nie eingebettet und erscheinen nie in Suchergebnissen.
Notizschema
Jede Notiz sollte YAML frontmatter haben. Der Retriever nutzt frontmatter-Felder für Filterung und Kontextanreicherung:
---
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
---
Erforderliche Felder für Retrieval:
title— Wird in der Anzeige von Suchergebnissen und als Überschriftenkontext für BM25 verwendettype— Ermöglicht nach Typ gefilterte Abfragen („Zeigen Sie mir nur MOCs“ oder „nur Signale“)tags— Werden im FTS5-Überschriftenkontext mit einer Gewichtung von 0,3 indexiert und liefern Keyword-Treffer, selbst wenn der Haupttext andere Begriffe verwendet
Optionale, aber wertvolle Felder:
domain— Ermöglicht auf Bereiche beschränkte Abfragen („Durchsuchen Sie nur Sicherheitsnotizen“)source— Quellenangabe für erfasste Inhalte; der Retriever kann Quell-URLs in Ergebnissen einschließenstatus— Ermöglicht, archivierte Notizen oder Entwürfe aus der aktiven Suche auszuschließen
Chunking-Konventionen
Der Retriever teilt Inhalte an H2-Überschriftengrenzen (##) in Chunks auf. Dadurch beeinflusst Ihre Notizstruktur direkt die Granularität des Retrievals:
Gut für Retrieval:
## 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...
Drei H2-Abschnitte erzeugen drei unabhängig durchsuchbare Chunks. Jeder Chunk hat genug Kontext, damit das Embedding seine Bedeutung erfassen kann. Eine Abfrage zu „expired token handling“ trifft gezielt den dritten Chunk.
Schlecht für Retrieval:
# 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...
Ein langer Abschnitt ohne H2-Überschriften erzeugt einen großen Chunk. Das Embedding mittelt über alle Themen im Abschnitt hinweg. Eine Abfrage zu einem beliebigen Unterthema trifft die gesamte Notiz gleichermaßen.
Faustregel: Wenn ein Abschnitt mehr als ein Konzept behandelt, teilen Sie ihn in H2-Unterabschnitte auf. Den Rest übernimmt der Chunker.
Was nicht in Notizen gehört
Inhalte, die die Retrieval-Qualität verschlechtern:
- Unkommentierte Rohkopien vollständiger Artikel. Der Retriever indexiert die Keywords des Originalartikels und verwässert Ihren Vault mit Inhalten, die Sie nicht geschrieben haben. Fügen Sie stattdessen eine Zusammenfassung hinzu, extrahieren Sie Kernpunkte oder verlinken Sie auf die Quell-URL.
- Screenshots ohne Textbeschreibung. Der Retriever indexiert Markdown-Text. Ein Bild ohne Alt-Text oder umgebende Beschreibung ist sowohl für BM25 als auch für vector search unsichtbar.
- Credential-Strings. API keys, Tokens, Passwörter, Connection Strings. Selbst mit Credential Filtering ist es am sichersten, Geheimnisse nie in Notizen einzufügen. Verweisen Sie stattdessen namentlich darauf („das Cloudflare API token in
~/.env“). - Automatisch generierte Inhalte ohne Kuratierung. Wenn ein Tool eine Notiz erzeugt (Meeting-Transkript, Readwise-Highlights, RSS-Import), prüfen und annotieren Sie sie, bevor sie in den permanenten Vault gelangt. Unkuratierte Auto-Importe erhöhen das Volumen, ohne auffindbaren Wert zu schaffen.
Plugin-Ökosystem für AI Workflows
Obsidian-Plugins, die die Vault-Qualität für AI Retrieval verbessern, fallen in drei Kategorien: Struktur (Konsistenz erzwingen), Abfragen (Metadaten zugänglich machen) und Sync (den Vault aktuell halten).
Wesentliche Plugins
Dataview. Fragt Ihren Vault wie eine Datenbank über frontmatter-Felder ab. Erstellen Sie dynamische Indizes: „alle Notizen mit dem Tag security, die in den letzten 30 Tagen aktualisiert wurden“ oder „alle Projektnotizen mit dem Status active“. Dataview hilft dem Retrieval nicht direkt, unterstützt Sie aber dabei, Lücken in der Abdeckung Ihres Vaults zu erkennen und Notizen zu finden, die aktualisiert werden müssen.
TABLE type, domain, updated
FROM "03-resources"
WHERE status = "active"
SORT updated DESC
LIMIT 20
Templater. Erstellt Notizen aus Vorlagen mit dynamischen Feldern. Stellen Sie sicher, dass jede neue Notiz mit korrektem frontmatter beginnt, indem Sie eine Vorlage verwenden, die die Felder created, type und domain vorausfüllt. Konsistentes frontmatter verbessert die Retrieval-Filterung.
<%* /* 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. Erzwingt Formatierungsregeln im gesamten Vault. Eine konsistente Überschriftenhierarchie (H1 für Titel, H2 für Abschnitte, H3 für Unterabschnitte) sorgt dafür, dass der Chunker vorhersehbare Ergebnisse erzeugt. Linter-Regeln, die für Retrieval relevant sind:
- Überschriftenabfolge: sequenzielle Überschriftenebenen erzwingen (kein Sprung von H1 zu H3)
- YAML-Titel: mit dem Dateinamen abgleichen
- Nachgestellte Leerzeichen: entfernen (vermeidet FTS5-Tokenisierungsartefakte)
- Aufeinanderfolgende Leerzeilen: auf 1 begrenzen (sauberere Chunks)
Git-Integration. Versionskontrolle für Ihren Vault. Verfolgen Sie Änderungen im Zeitverlauf, synchronisieren Sie zwischen Maschinen und stellen Sie versehentlich gelöschte Inhalte wieder her. Git liefert außerdem mtime-Daten, die der Indexer für die inkrementelle Änderungserkennung nutzt.
Plugins, die beim Indexing helfen
Smart Connections. Ein Obsidian-Plugin, das AI-gestützte semantische Suche direkt in Obsidian bereitstellt. Smart Connections v4 erstellt standardmäßig lokale Embeddings — sobald Ihr Vault indexiert ist, funktionieren semantische Verbindungen und Nachschlagen vollständig offline ohne API-Aufrufe.11 v4.5.0 (5. Mai 2026) macht Footer-Verbindungen zu einem Bestandteil von Smart Connections Core, sodass jede Installation verwandte Notizverbindungen im Footer anzeigen kann, ohne ein Seitenpanel zu öffnen. Neuere v4-Versionen haben außerdem Graph-Ansichten für Verbindungslisten, konfigurierbare Dock-Positionen, eine verbesserte Wiederherstellung von Block-Embeddings nach unterbrochenen Indexing-Läufen und „Substrate“ hinzugefügt, eine Cross-Plugin-Umgebung, in der Smart Connections, Smart Chat und Smart Composer gemeinsamen Zustand teilen können.21 Das Retrieval-System in diesem Guide liegt zwar außerhalb von Obsidian (es läuft als Python-Pipeline), doch Smart Connections ist nützlich, um beim Schreiben semantische Beziehungen zu erkunden. Beide Systeme indexieren dieselben Inhalte, bedienen aber unterschiedliche Anwendungsfälle: Smart Connections für die Entdeckung im Editor, der externe Retriever für die AI Tool-Integration über MCP.
AI-native Plugins, die im April 2026 veröffentlicht wurden. Eine Welle neuer Community-Plugins zielt direkt auf den Claude Code / Codex / Gemini-CLI-Workflow:
| Plugin | Veröffentlicht | Funktion |
|---|---|---|
| Cortex | 4. April | Vault-Agent, betrieben mit Claude Code — behandelt den Vault als Agent-Workspace, nicht nur als Notizspeicher |
| VaultSearch | 7. April | Local-first Hybrid-Suche: BM25 + semantisch + fuzzy (direkte Überschneidung mit dem Retrieval-Stack dieses Guides) |
| LLM Wiki | 9. April | Verwandelt Ihren Vault in eine privat abfragbare Wissensdatenbank |
| Drift | 11. April | Diff-Viewer im VS Code-Stil für AI-gestützte Obsidian-Bearbeitung; für Claude Code-Workflows positioniert |
| EngramQuest | 11. April | Generiert Gedächtnisaufgaben aus Notizen; liefert „AI Skills“ für Claude Code / Gemini CLI / Cursor |
| Hybrid Search MCP | März (immer noch neu) | MCP-Server + CLI mit BM25 + semantischer Suche — gezielt für AI Assistants gebaut |
Betrachten Sie das als entstehende Oberfläche — mehrere dieser Plugins werden sich in den nächsten Quartalen wahrscheinlich konsolidieren oder in Smart Connections / Obsidian Core aufgehen. Wenn Sie heute eines auswählen, liegen VaultSearch und Hybrid Search MCP der Philosophie des externen Retrievers in diesem Guide am nächsten.
Dataview-Hinweis: Dataview (das langjährige Obsidian-Abfrage-Plugin) hat Version 0.5.70 zuletzt im April 2025 veröffentlicht und ist seitdem faktisch inaktiv. Für neue Arbeit ist Obsidian’s integrierte Funktion Bases (1.9+) der implizite Nachfolger und der empfohlene Weg.
Metadata Menu. Bietet strukturierte frontmatter-Bearbeitung mit Autovervollständigung für Feldwerte. Reduziert Tippfehler in den Feldern type, domain und tags. Konsistente Metadaten verbessern die Genauigkeit der Retrieval-Filterung.
Plugins, die Indexing verschlechtern
Excalidraw. Speichert Zeichnungen als in Markdown-Dateien eingebettetes JSON. Das JSON ist syntaktisch gültiges Markdown, erzeugt beim Chunking und Einbetten jedoch unbrauchbare Ergebnisse. Schließen Sie Excalidraw-Dateien über .indexignore vom Index aus oder filtern Sie nach Dateiendung.
Kanban. Speichert den Board-Zustand als speziell formatiertes Markdown. Das Format ist für Kanban-Rendering ausgelegt, nicht für Prosa-Retrieval. Der Chunker erzeugt Fragmente von Kartentiteln und Metadaten, die sich nicht gut einbetten lassen. Schließen Sie Kanban-Boards vom Index aus.
Calendar. Erstellt tägliche Notizen mit minimalem Inhalt (oft nur eine Datumsüberschrift). Leere oder nahezu leere Notizen erzeugen minderwertige Chunks. Wenn Sie tägliche Notizen verwenden, schreiben Sie dort substanzielle Inhalte hinein oder schließen Sie den Ordner für tägliche Notizen vom Index aus.
Plugin-Konfiguration, die zählt
Dateiwiederherstellung → Aktiviert. Schützt vor versehentlichem Löschen von Notizen. Nicht direkt mit Retrieval verbunden, aber kritisch für eine Wissensdatenbank, auf die Sie angewiesen sind.
Strikte Zeilenumbrüche → Deaktiviert. Markdown-standardkonforme Zeilenumbrüche (doppelte Leerzeile für Absätze) erzeugen sauberere Chunks als Obsidian’s strikter Modus (einzelner Zeilenumbruch für <br>).
Standardspeicherort für neue Dateien → Festgelegter Ordner. Leiten Sie neue Dateien nach 00-inbox/, damit nicht kategorisierte Notizen keine Domain-Ordner verunreinigen. Die Inbox ist ein Staging-Bereich; Dateien wandern nach der Triage in Domain-Ordner.
Wiki-link-Format → Kürzester Pfad, wenn möglich. Kürzere Link-Ziele sind für den Retriever beim Indexieren der Link-Struktur leichter aufzulösen.
Embedding-Modelle: Auswahl und Konfiguration
Das Embedding-Modell wandelt Text-Chunks in numerische Vektoren für die semantische Suche um. Die Modellwahl bestimmt die Retrieval-Qualität, die Indexgröße, die Embedding-Geschwindigkeit und die Laufzeitabhängigkeiten. Dieser Abschnitt erklärt, warum Model2Vecs potion-base-8M die Standardwahl ist und wann Alternativen sinnvoll sind.
Warum Model2Vec potion-base-8M
Modell: minishlab/potion-base-8M
Parameter: 7,6 Millionen
Dimensionen: 256
Größe: ~30 MB
Abhängigkeiten: model2vec (nur numpy, kein PyTorch)
Inference: nur CPU, statische Word Embeddings (keine Attention-Layer)
Model2Vec destilliert das Wissen eines Sentence Transformers in statische Token Embeddings. Statt Attention-Layer über die Eingabe laufen zu lassen (wie BERT, MiniLM und andere Transformer-Modelle), erzeugt Model2Vec Vektoren durch gewichtete Mittelung vorberechneter Token Embeddings.5 Die praktische Folge: Die Embedding-Geschwindigkeit ist 50- bis 500-mal höher als bei transformerbasierten Modellen, weil keine sequenzielle Berechnung stattfindet.
Auf der aktuellen Model2Vec-Ergebnisseite erreicht potion-base-8M etwa 92 % des All-Task-Scores von all-MiniLM-L6-v2 (51,32 gegenüber 55,80), bleibt dabei aber um Größenordnungen schneller.6 Die verbleibende Qualitätslücke ist der Preis für die Geschwindigkeits- und Einfachheitsvorteile. Bei kurzen Markdown-Chunks (durchschnittlich 200-400 Wörter in einem typischen Vault) fällt der Qualitätsunterschied weniger stark aus als bei längeren Dokumenten, weil beide Modelle bei kurzen, fokussierten Texten zu ähnlichen Repräsentationen konvergieren.
Konfiguration
# 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]
Lazy Loading. Das Modell wird erst bei der ersten Nutzung geladen, nicht beim Import. Das Importieren des Embedder-Moduls kostet nichts, wenn der Retriever im reinen BM25-Fallback-Modus arbeitet (z. B. wenn das Embedding-venv nicht installiert ist).
Isolierte virtuelle Umgebung. Das Modell läuft in einem dedizierten venv (z. B. ~/.claude/venvs/memory/), um Abhängigkeitskonflikte mit dem Rest der Toolchain zu vermeiden. Die Funktion _activate_venv() fügt die site-packages des venv zur Laufzeit zu sys.path hinzu.
# Create isolated venv
python3 -m venv ~/.claude/venvs/memory
~/.claude/venvs/memory/bin/pip install model2vec
Batch-Verarbeitung. Der Embedder verarbeitet Texte in Batches von 64, um den Overhead von Model2Vec zu amortisieren. Der Indexer übergibt Chunks an embed_batch(), statt jeweils einen Chunk einzeln einzubetten.
Wann Alternativen sinnvoll sind
| Modell | Dim | Größe | Geschwindigkeit | Qualität (MTEB) | Am besten geeignet für |
|---|---|---|---|---|---|
| potion-base-8M | 256 | 30 MB | 500x | 51,32 | Standard: lokal, schnell, kein GPU |
| potion-base-32M | 256 | 120 MB | 400x | 52,83 | Höhere Qualität, weiterhin statisch |
| potion-retrieval-32M | 256 | 120 MB | 400x | 35,06 (Retrieval) | Retrieval-optimiert, statisch |
| potion-multilingual-128M | 256 | ~500 MB | 300x | — | Mehrsprachige Vaults (101 Sprachen) |
| all-MiniLM-L6-v2 | 384 | 80 MB | 1x | 55,80 | Höhere Qualität, weiterhin lokal |
| nomic-embed-text-v1.5 | 768 | 270 MB | 0,5x | 62,28 | Beste lokale Qualität |
| text-embedding-3-small | 1536 | API | N/A | 62,30 | API-basiert, höchste Qualität |
Wählen Sie potion-base-32M, wenn Sie eine bessere Qualität als bei potion-base-8M möchten, ohne die Familie statischer Embeddings zu verlassen. Es verwendet ein größeres Vokabular, das aus baai/bge-base-en-v1.5 destilliert wurde, erreicht einen All-Task-Score von 52,83 (etwa 3 % höher als potion-base-8M) und behält dabei dieselbe 256-dimensionale Ausgabe sowie die reine numpy-Abhängigkeit bei.8 Die 4-mal größere Modelldatei erhöht den Speicherbedarf, die Embedding-Geschwindigkeit bleibt aber um Größenordnungen höher als bei Transformer-Modellen.
Wählen Sie potion-retrieval-32M, wenn Ihr primärer Anwendungsfall Retrieval ist (was bei der Vault-Suche der Fall ist). Diese Variante ist speziell für Retrieval-Aufgaben aus potion-base-32M feinabgestimmt und erreicht in der Retrieval-Benchmark-Tabelle von Model2Vec einen Wert von 35,06 gegenüber 32,67 für potion-base-32M.8 Der Kompromiss besteht darin, dass es für Retrieval statt für allgemeine Embedding-Qualität optimiert ist.
Wählen Sie potion-multilingual-128M, wenn Ihr Vault Notizen in mehreren Sprachen enthält. Dieses im Mai 2025 veröffentlichte Modell für 101 Sprachen ist das leistungsstärkste statische Embedding-Modell für mehrsprachige Aufgaben. Es erzeugt Embeddings für beliebige Texte in beliebigen Sprachen und behält dieselbe reine numpy-Abhängigkeit wie andere potion-Modelle bei.12 Die größere Modelldatei (~500 MB) ist der Kompromiss für sprachübergreifende Fähigkeiten. Nutzen Sie es, wenn Sie neben englischen Inhalten auch Notizen auf Japanisch, Chinesisch, Deutsch oder in anderen nicht englischen Sprachen haben.
Wählen Sie all-MiniLM-L6-v2, wenn Retrieval-Qualität wichtiger ist als Geschwindigkeit und PyTorch installiert ist. Die 384-dimensionalen Vektoren erhöhen die Größe der SQLite-Datenbank im Vergleich zu 256-dimensionalen Vektoren um ~50 %. Die Embedding-Geschwindigkeit sinkt bei einer vollständigen Neuindizierung von 15.000 Dateien auf M-Series-Hardware von <1 Minute auf ~10 Minuten.
Wählen Sie nomic-embed-text-v1.5, wenn Sie die bestmögliche lokale Retrieval-Qualität benötigen und langsameres Indexing akzeptieren. Die 768-dimensionalen Vektoren verdreifachen die Datenbankgröße ungefähr. Erfordert PyTorch und eine moderne CPU oder GPU.
Wählen Sie text-embedding-3-small, wenn Netzwerklatenz und Datenschutz vertretbare Kompromisse sind. Das API erzeugt Embeddings mit der höchsten Qualität, bringt aber eine Cloud-Abhängigkeit, Kosten pro Token (0,02 $/Million Tokens) und die Übertragung Ihrer Inhalte an OpenAIs Server mit sich.
Bleiben Sie in allen anderen Fällen bei potion-base-8M. Der Geschwindigkeitsvorteil ist entscheidend für iteratives Indexing (Neuindizierung während der Entwicklung), die reine numpy-Abhängigkeit vermeidet die Installationskomplexität von PyTorch, und die 256-dimensionalen Vektoren halten die Datenbank kompakt.
Quantisierung und Dimensionsreduktion
Model2Vec v0.5.0+ unterstützt das Laden von Modellen mit reduzierter Präzision und reduzierten Dimensionen.8 Das ist nützlich für Deployments auf eingeschränkter Hardware oder zur Verringerung der Datenbankgröße, ohne das Modell zu wechseln:
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)
Quantisierte Modelle behalten nahezu identische Retrieval-Qualität bei einem Bruchteil des Speicherbedarfs. Die Dimensionsreduktion folgt einer Matryoshka-artigen Trunkierung: Die ersten N Dimensionen enthalten die meisten Informationen. Eine Reduktion von 256 auf 128 Dimensionen halbiert den Vektorspeicher mit minimalem Qualitätsverlust beim Retrieval kurzer Texte.
Model2Vec v0.8.x aktualisiert die Interna für Tokenizer und Persistenz, beendet die Unterstützung für Python 3.9 und aktualisiert veröffentlichte Ergebnisse auf die neueren MTEB-Tabellen. Pinnen oder testen Sie model2vec, bevor Sie einen Produktions-Indexer aktualisieren, da Bibliotheksupgrades die Ladepfade für Modelle ändern können, selbst wenn der Name des Embedding-Modells gleich bleibt.10
Fine-Tuning für Vault-spezifische Embeddings
Model2Vec v0.4.0+ unterstützt das Trainieren benutzerdefinierter Klassifikationsmodelle auf statischen Embeddings, v0.7.0 ergänzt Vokabularquantisierung und konfigurierbares Pooling für die Destillation, und v0.8.x überarbeitet Tokenizer- und Persistenzverhalten.10 Das ist relevant für Vaults mit spezialisiertem Vokabular (medizinische Notizen, juristische Referenzen, domänenspezifischer Jargon), bei denen die Standard-potion-Modelle semantische Nuancen möglicherweise nicht erfassen:
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")
Für die meisten Vaults liefert das standardmäßige potion-base-8M eine ausreichende Retrieval-Qualität. Fine-Tuning lohnt sich nur, wenn Retrieval wiederholt domänenspezifische Verbindungen übersieht, die ein Allzweckmodell nicht erfassen kann.
Model Hash Tracking
Der Indexer speichert einen Hash, der aus dem Modellnamen und der Vokabulargröße abgeleitet wird. Wenn Sie das Embedding-Modell ändern, erkennt der Indexer beim nächsten inkrementellen Lauf die Abweichung und löst automatisch eine vollständige Neuindizierung aus.
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]
So wird verhindert, dass Vektoren verschiedener Modelle in derselben Datenbank gemischt werden, was unsinnige cosine similarity Scores erzeugen würde.
Fehlermodi
Fehler beim Modelldownload. Beim ersten Lauf wird das Modell von Hugging Face heruntergeladen. Wenn der Download fehlschlägt (Netzwerkproblem, Unternehmens-Firewall), fällt der Retriever auf den reinen BM25-Modus zurück. Nach dem ersten Download wird das Modell lokal gecacht.
Dimensionskonflikt. Wenn Sie Modelle wechseln, ohne die Datenbank zu löschen, haben die gespeicherten Vektoren eine andere Dimension als neue Embeddings. Der Indexer erkennt dies über den Modell-Hash und löst eine vollständige Neuindizierung aus. Wenn die Hash-Prüfung fehlschlägt (benutzerdefiniertes Modell ohne korrekten Hash), gibt sqlite-vec bei KNN-Abfragen mit nicht übereinstimmenden Dimensionen einen Fehler aus.
Speicherdruck bei großen Vaults. Das Einbetten von mehr als 50.000 Chunks in einem einzigen Batch kann erheblichen Speicher verbrauchen. Der Indexer verarbeitet in Batches von 64, um die maximale Speichernutzung zu begrenzen. Wenn der Speicher weiterhin ein Problem ist, reduzieren Sie die Batch-Größe.
Volltextsuche mit FTS5
Die FTS5-Erweiterung von SQLite bietet Volltextsuche mit BM25-Ranking. FTS5 ist die Keyword-Suchkomponente der hybrid Retrieval Pipeline. Dieser Abschnitt behandelt die FTS5-Konfiguration, wann BM25 besonders stark ist und welche spezifischen Fehlermodi auftreten.
Virtuelle FTS5-Tabelle
CREATE VIRTUAL TABLE chunks_fts USING fts5(
chunk_text,
section,
heading_context,
content=chunks,
content_rowid=id
);
Content-Sync-Modus. Der Parameter content=chunks weist FTS5 an, direkt auf die Tabelle chunks zu verweisen, statt eine doppelte Kopie des Textes zu speichern. Das halbiert den Speicherbedarf, bedeutet aber, dass FTS5 manuell synchronisiert werden muss, wenn chunks eingefügt, aktualisiert oder gelöscht werden.
Spalten. Drei Spalten werden indexiert:
- chunk_text — Der primäre Inhalt jedes chunks (BM25-Gewicht: 1,0)
- section — Der H2-Überschriftentext (BM25-Gewicht: 0,5)
- heading_context — Notiztitel, Tags und Metadaten (BM25-Gewicht: 0,3)
BM25-Ranking
BM25 bewertet Dokumente nach Termfrequenz, inverser Dokumentfrequenz und Normalisierung der Dokumentlänge. Die Hilfsfunktion bm25() in FTS5 akzeptiert spaltenspezifische Gewichtungen:
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;
Die Spaltengewichtungen (1,0, 0,5, 0,3) bedeuten:
- Ein Keyword-Treffer in chunk_text trägt am stärksten zum Score bei
- Ein Treffer in section (Überschrift) trägt halb so viel bei
- Ein Treffer in heading_context (Titel, Tags) trägt 30 % so viel bei
Diese Gewichtungen sind anpassbar. Wenn Ihr Obsidian-Tresor aussagekräftige Überschriften hat, die die Inhaltsqualität stark vorhersagen, erhöhen Sie das Gewicht für section. Wenn Ihre Tags umfassend und korrekt sind, erhöhen Sie das Gewicht für heading_context.
Wann BM25 gewinnt
BM25 ist besonders stark bei Abfragen mit exakten Bezeichnern:
- Funktionsnamen:
_rrf_fuse,embed_batch,get_stale_files - CLI-Flags:
--incremental,--vault,--model - Konfigurationsschlüssel:
bm25_weight,max_tokens,batch_size - Fehlermeldungen:
SQLITE_LOCKED,ConnectionRefusedError - Spezifische Fachbegriffe:
PostToolUse,PreToolUse,AGENTS.md
Bei diesen Abfragen findet BM25 die exakte Übereinstimmung sofort. Die Vektorsuche würde semantisch verwandte Inhalte zurückgeben, könnte die exakte Übereinstimmung aber niedriger einstufen als eine konzeptionelle Diskussion.
Wann BM25 scheitert
BM25 scheitert bei Abfragen, die andere Begriffe verwenden als die gespeicherten Inhalte:
- Abfrage: “how to handle authentication failures” → Der Obsidian-Tresor enthält Notizen zu “login error recovery” und “session expiration handling.” BM25 findet keine Übereinstimmung, weil sich die Keywords unterscheiden.
- Abfrage: “what is the best way to manage state” → Der Obsidian-Tresor enthält Notizen zu “Redux store patterns” und “context providers.” BM25 verfehlt sie, weil “state management” über konkrete Technologienamen ausgedrückt wird.
BM25 scheitert außerdem bei Keyword-Kollisionen im großen Maßstab. In einem Tresor mit 15.000 Dateien findet eine Suche nach “configuration” Hunderte von Notizen, weil fast jede Projektnotiz Konfiguration erwähnt. Die Ergebnisse sind technisch korrekt, praktisch aber unbrauchbar — das Ranking kann nicht bestimmen, welche “configuration”-Notiz für die aktuelle Abfrage relevant ist.
FTS5-Tokenizer
FTS5 verwendet standardmäßig den unicode61-Tokenizer, der ASCII- und Unicode-Text verarbeitet. Für Tresore mit vielen CJK-Inhalten (Chinesisch, Japanisch, Koreanisch) sollten Sie den trigram-Tokenizer in Betracht ziehen:
-- For CJK-heavy vaults
CREATE VIRTUAL TABLE chunks_fts USING fts5(
chunk_text, section, heading_context,
content=chunks, content_rowid=id,
tokenize='trigram'
);
Der standardmäßige unicode61-Tokenizer trennt an Wortgrenzen, was bei Sprachen ohne Leerzeichen zwischen Wörtern schlecht funktioniert. Der trigram-Tokenizer trennt alle drei Zeichen und ermöglicht dadurch Substring-Matching, allerdings auf Kosten der Indexgröße (ungefähr 3-mal größer).
Wartung
FTS5 erfordert eine explizite Synchronisierung, wenn sich die zugrunde liegende Tabelle chunks ändert:
# After inserting chunks
cursor.execute("""
INSERT INTO chunks_fts(chunks_fts)
VALUES('rebuild')
""")
Der Befehl rebuild rekonstruiert den FTS5-Index aus der Inhaltstabelle. Führen Sie ihn nach Masseneinfügungen aus (vollständige Neuindexierung), aber nicht nach einzelnen inkrementellen Aktualisierungen — verwenden Sie dafür INSERT INTO chunks_fts(rowid, chunk_text, section, heading_context), um einzelne Zeilen zu synchronisieren.
Vector Search mit sqlite-vec
Die sqlite-vec-Erweiterung bringt Vector-KNN-Suche (K-Nearest Neighbors) in SQLite. Dieser Abschnitt behandelt die sqlite-vec-Konfiguration, die Embedding-Pipeline von der Notiz bis zum durchsuchbaren Vektor und die konkreten Query-Muster.
sqlite-vec Virtual Table
CREATE VIRTUAL TABLE chunk_vecs USING vec0(
id INTEGER PRIMARY KEY,
embedding float[256]
);
Das vec0-Modul speichert 256-dimensionale Float-Vektoren als gepackte Binärdaten. Die Spalte id wird 1:1 der Tabelle chunks zugeordnet und ermöglicht Joins zwischen Vector-Ergebnissen und Chunk-Metadaten.
Embedding-Pipeline
Die Pipeline läuft von der Notiz zum durchsuchbaren Vektor:
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
Vector-Serialisierung
Das struct-Modul von Python serialisiert Float-Vektoren für die sqlite-vec-Speicherung:
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))
KNN Query
Eine Vector-Search-Query bettet die Eingabe-Query ein und findet dann die K nächsten Chunks anhand der Kosinusdistanz:
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
Der Operator MATCH in sqlite-vec führt eine Approximate-Nearest-Neighbor-Suche aus. Der Parameter k steuert, wie viele Ergebnisse zurückgegeben werden. Die Spalte distance enthält die Kosinusdistanz (0 = identisch, 2 = entgegengesetzt).
KNN-Paginierung mit Distanzbeschränkungen
Seit sqlite-vec v0.1.7 unterstützen KNN-Queries Constraints wie WHERE distance < ?. Damit wird cursorbasierte Paginierung durch große Ergebnismengen möglich, ohne frühere Seiten erneut zu scannen.14 Die späteren stabilen Releases v0.1.8 und v0.1.9 sind Packaging- und DELETE-Bugfix-Releases, keine Releases mit neuem Query-Modell. Daher bleibt v0.1.7 die Funktionsgrenze für dieses Paginierungsmuster.23
Am Horizont ist die v0.1.10-alpha-Linie (31. März bis 18. Mai 2026) die erste, die sqlite-vec über Brute-Force-KNN hinausführt: Sie führt Approximate-Nearest-Neighbor-Indextypen ein — rescore, einen experimentellen ivf-Index (Inverted File), der standardmäßig nicht aktiviert ist, sowie einen festplattenbasierten DiskANN-Index für Vaults, die zu groß sind, um Vektoren dauerhaft im Arbeitsspeicher zu halten.23 Das würde die Skalierungsgeschichte für sehr große Vaults verändern, aber die 0.1.10-Linie ist weiterhin Pre-Release (Alpha) — behandeln Sie ANN-Indexierung als experimentell und bauen Sie für Produktions-Vaults weiter auf dem stabilen Brute-Force-KNN-Pfad von v0.1.9 auf, bis eine stabile 0.1.10 erscheint.
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
Dies ersetzt das frühere Muster, ein großes k abzurufen und in Python zu slicen, wodurch der Speicherverbrauch bei explorativen Queries über große Vaults sinkt.
DELETE-Unterstützung in vec0-Tabellen
sqlite-vec v0.1.7 fügte native DELETE-Unterstützung für vec0 Virtual Tables hinzu, und v0.1.9 behob einen DELETE-Fehlerpfad mit Metadaten-Textspalten, die länger als 12 Zeichen sind.1423 Zuvor erforderte das Entfernen von Vektoren, die Tabelle zu löschen und neu zu erstellen. Jetzt kann der Datei-Entfernungspfad des Indexers Vektoren direkt löschen:
# 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])
Das vereinfacht die inkrementelle Neuindexierung, wenn Notizen gelöscht oder verschoben werden. Der Indexer muss keine Schatten-Tabelle mit „active IDs” mehr pflegen und auch keine Batch-Rebuilds durchführen.
Wann Vector Search gewinnt
Vector Search ist besonders stark bei Queries, bei denen das Konzept wichtiger ist als die konkreten Wörter:
- Query: “how to handle authentication failures” → Findet Notizen zu “login error recovery” (derselbe semantische Raum, andere Keywords)
- Query: “what patterns exist for caching” → Findet Notizen zu “memoization,” “Redis TTL strategies,” und “HTTP cache headers” (verwandte Konzepte, unterschiedliche Terminologie)
- Query: “approaches to testing asynchronous code” → Findet Notizen zu “pytest-asyncio fixtures,” “mock event loops,” und “async test patterns” (dasselbe Konzept, ausgedrückt über Implementierungsdetails)
Wann Vector Search scheitert
Vector Search hat Schwierigkeiten mit exakten Bezeichnern:
- Query:
_rrf_fuse→ Gibt Notizen zu “fusion algorithms” und “rank merging” zurück, kann aber die eigentliche Funktionsdefinition niedriger einstufen als konzeptuelle Diskussionen - Query:
PostToolUse→ Gibt eher Notizen zu “tool lifecycle hooks” und “post-execution handlers” zurück als den konkreten Hook-Namen
Vector Search hat außerdem Schwierigkeiten mit strukturierten Daten. JSON-Konfigurationsdateien, YAML-Blöcke und Code-Snippets erzeugen Embeddings, die eher strukturelle Muster als semantische Bedeutung erfassen. Eine JSON-Datei mit "review": true wird anders eingebettet als eine Prosadiskussion über Code Review.
Graceful Degradation
Wenn sqlite-vec nicht geladen werden kann (fehlende Erweiterung, inkompatible Plattform, beschädigte Bibliothek), fällt der Retriever auf reine BM25-Suche zurück:
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
Der Retriever prüft vec_available, bevor er Vector-Queries versucht. Wenn die Funktion deaktiviert ist, verwenden alle Suchvorgänge nur BM25, und der RRF-Fusion-Schritt wird übersprungen.
Reciprocal Rank Fusion (RRF)
RRF führt zwei Ranking-Listen zusammen, ohne dass dafür eine Score-Kalibrierung nötig ist. Dieser Abschnitt behandelt den Algorithmus, eine durchgerechnete Query-Spur, das Tuning des Parameters k und warum RRF gegenüber Alternativen gewählt wird. Einen interaktiven Rechner mit bearbeitbaren Rängen, Szenario-Presets und einem visuellen Architektur-Explorer finden Sie im Deep Dive zum hybrid Retriever.
Der Algorithmus
RRF weist jedem Dokument einen Score zu, der ausschließlich auf seiner Rangposition in jeder Liste basiert:
score(d) = Σ (weight_i / (k + rank_i))
Dabei gilt:
- k ist eine Glättungskonstante (60, nach Cormack et al.3)
- rank_i ist der 1-basierte Rang des Dokuments in der Ergebnisliste i
- weight_i ist ein optionaler Multiplikator pro Liste (Standard 1.0)
Dokumente, die in mehreren Listen gut ranken, erhalten höhere fusionierte Scores. Dokumente, die nur in einer Liste vorkommen, erhalten einen Score aus dieser einzelnen Quelle.
Warum RRF statt Alternativen
Gewichtete lineare Kombination erfordert, BM25-Scores gegen cosine distances zu kalibrieren. BM25-Scores sind unbeschränkt und skalieren mit der Korpusgröße. Cosine distances sind auf [0, 2] beschränkt. Um sie zu kombinieren, ist eine Normalisierung nötig, und die Normalisierungsparameter hängen vom Datensatz ab. RRF verwendet nur Rangpositionen, die unabhängig von der Scoring-Methode immer Ganzzahlen ab 1 sind.
Gelernte Fusion-Modelle benötigen gelabelte Trainingsdaten — also Query-Dokument-Relevanzpaare. Für eine persönliche Wissensbasis existieren solche Trainingsdaten nicht. Sie müssten Hunderte Query-Dokument-Paare manuell bewerten, um ein brauchbares Modell zu trainieren. RRF funktioniert ohne Trainingsdaten.
Condorcet-Voting-Methoden (Borda count, Schulze method) sind theoretisch elegant, aber komplexer zu implementieren und abzustimmen. Das ursprüngliche RRF-Paper zeigte, dass RRF Condorcet-Methoden auf TREC-Evaluationsdaten übertrifft.3
Fusion in der Praxis
Query: “how does the review aggregator handle disagreements”
BM25 rankt review-aggregator.py auf Position 3 (exakte Keyword-Treffer bei “review”, “aggregator”, “disagreements”), platziert aber zwei Konfigurationsdateien höher (sie treffen “review” prominenter). Vector search rankt denselben Chunk auf Position 1 (semantischer Treffer zu Konfliktlösung). Nach der RRF-Fusion:
| Chunk | BM25 | Vec | Fusionierter Score |
|---|---|---|---|
| review-aggregator.py “Disagreement Resolution” | #3 | #1 | 0.0323 |
| code-review-patterns.md “Multi-Reviewer” | #4 | #2 | 0.0317 |
| deliberation-config.json “Review Weights” | #1 | — | 0.0164 |
Chunks, die in beiden Listen gut ranken, steigen nach oben. Chunks, die nur in einer Liste auftauchen, erhalten einen Single-Source-Score und fallen unter Ergebnisse, die in beiden Listen ranken. Die tatsächliche Logik zur Auflösung von Meinungsverschiedenheiten gewinnt, weil beide Methoden sie gefunden haben — BM25 über Keywords, vector search über Semantik.
Die vollständige Schritt-für-Schritt-Spur mit RRF-Berechnungen pro Rang finden Sie im interaktiven RRF-Rechner, in dem Sie verschiedene k-Werte ausprobieren können.
Implementierung
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
k abstimmen
Die Konstante k steuert, wie stark top-gerankte Ergebnisse gegenüber niedriger gerankten Ergebnissen gewichtet werden:
- Niedrigeres k (z. B. 10): Top-gerankte Ergebnisse dominieren. Rang 1 erzielt 1/11 = 0.091, Rang 10 erzielt 1/20 = 0.050 (1,8-facher Unterschied). Gut, wenn Sie den einzelnen Rankern zutrauen, das beste Ergebnis korrekt zu bestimmen.
- Standard-k (60): Ausgewogen. Rang 1 erzielt 1/61 = 0.0164, Rang 10 erzielt 1/70 = 0.0143 (1,15-facher Unterschied). Rangunterschiede werden komprimiert, wodurch das Auftauchen in mehreren Listen stärker gewichtet wird.
- Höheres k (z. B. 200): Das Auftauchen in beiden Listen zählt deutlich mehr als die Rangposition. Rang 1 erzielt 1/201, Rang 10 erzielt 1/210 — fast identisch. Verwenden Sie dies, wenn die einzelnen Ranker verrauschte Rankings liefern, die Übereinstimmung zwischen Listen aber zuverlässig ist.
Beginnen Sie mit k=60. Das ursprüngliche RRF-Paper stellte fest, dass dieser Wert über unterschiedliche TREC-Datensätze hinweg robust ist. Stimmen Sie ihn erst ab, nachdem Sie Fehlerfälle in Ihrer eigenen Query-Verteilung gemessen haben.
Tie-Breaking
Wenn zwei Chunks identische RRF-Scores haben (selten, aber möglich bei demselben Rang in einer Liste und keinem Auftauchen in der anderen), lösen Sie Gleichstände so auf:
- Bevorzugen Sie Chunks, die in beiden Listen auftauchen, gegenüber Chunks, die nur in einer auftauchen
- Bevorzugen Sie unter Chunks in beiden Listen den Chunk mit dem niedrigeren kombinierten Rang
- Bevorzugen Sie unter Chunks in nur einer Liste den Chunk mit dem niedrigeren Rang in dieser Liste
Die vollständige Retrieval-Pipeline
Dieser Abschnitt verfolgt eine Abfrage von der Eingabe bis zur Ausgabe durch die gesamte Pipeline: BM25-Suche, Vektorsuche, RRF-Fusion, Kürzung nach Token-Budget und Kontextzusammenstellung.
End-to-End-Ablauf
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
Gesamtlatenz: ~23ms für eine Datenbank mit 49.746 chunks auf Apple M3 Pro-Hardware.
Die Search API
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
Kürzung nach Token-Budget
Der Parameter max_tokens verhindert, dass der Retriever mehr Kontext zurückgibt, als das AI-Tool verwenden kann. Die Schätzung verwendet 4 Zeichen pro Token, eine sinnvolle Näherung für englische Prosa. Ergebnisse werden gierig gekürzt: Ergebnisse werden in Rangfolge hinzugefügt, bis das Budget ausgeschöpft ist.
Das ist eine konservative Strategie. Ein ausgefeilterer Ansatz würde Qualitätswerte pro Ergebnis berücksichtigen und kürzere, hochwertigere Ergebnisse längeren, schlechteren Ergebnissen vorziehen. Der gierige Ansatz ist einfacher und funktioniert in der Praxis gut, weil das RRF-Ranking die Ergebnisse bereits nach Relevanz sortiert.
Datenbankschema (vollständig)
-- 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
);
Graceful-Degradation-Pfad
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
Der Retriever prüft seine Fähigkeiten bei der Initialisierung und passt seine Abfragestrategie an. Eine fehlende Komponente senkt die Qualität, verursacht aber keine Fehler. Der einzige harte Fehler ist eine fehlende Datenbankdatei.
Produktionsstatistiken
Gemessen an einem vault mit 16.894 Dateien, 49.746 chunks, einer 83 MB großen SQLite-Datenbank, Apple M3 Pro:
| Metrik | Wert |
|---|---|
| Dateien insgesamt | 16.894 |
| chunks insgesamt | 49.746 |
| Datenbankgröße | 83 MB |
| BM25-Abfragelatenz (p50) | 12ms |
| Vektorabfragelatenz (p50) | 8ms |
| RRF-Fusionslatenz | 3ms |
| End-to-End-Suchlatenz (p50) | 23ms |
| Zeit für vollständige Neuindexierung | ~4 Minuten |
| Zeit für inkrementelle Neuindexierung | <10 Sekunden |
| Embedding-Modell | potion-base-8M (256-dim) |
| BM25-Kandidatenpool | 30 |
| Vektor-Kandidatenpool | 30 |
| Standard-Ergebnislimit | 10 |
| Standard-Token-Budget | 4.000 tokens |
Content Hashing und Änderungserkennung
Der Indexer muss wissen, welche Dateien sich seit dem letzten Indexlauf geändert haben. Dieser Abschnitt behandelt den Mechanismus zur Änderungserkennung und die Hashing-Strategie.
Vergleich der Dateiänderungszeit
Der Indexer speichert mtime_ns (Dateiänderungszeit in Nanosekunden) für jeden chunk in der Tabelle chunks. Bei einem inkrementellen Lauf führt der Indexer Folgendes aus:
- Scannt den vault nach allen
.md-Dateien in erlaubten Ordnern - Liest
mtime_nsfür jede Datei aus dem Dateisystem - Vergleicht den Wert mit dem gespeicherten
mtime_nsin der Datenbank - Erkennt drei Kategorien:
- Neue Dateien: Pfad existiert im Dateisystem, aber nicht in der Datenbank
- Geänderte Dateien: Pfad existiert in beiden, aber
mtime_nsunterscheidet sich - Gelöschte Dateien: Pfad existiert in der Datenbank, aber nicht im Dateisystem
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)
Warum mtime statt Content Hash
Content Hashing (SHA-256 des Dateiinhalts) wäre zuverlässiger als der mtime-Vergleich, denn es würde Fälle erkennen, in denen eine Datei berührt wurde, ohne sich zu ändern (z. B. wenn git checkout die ursprüngliche mtime wiederherstellt). Hashing erfordert allerdings, bei jedem inkrementellen Lauf jede Datei zu lesen. Bei 16.894 Dateien dauert das Lesen der Dateiinhalte 2-3 Sekunden. Das Lesen der mtimes aus dem Dateisystem dauert <100ms.
Der Kompromiss: Der mtime-Vergleich löst gelegentlich unnötige Neuindexierungen unveränderter Dateien aus (False Positives), übersieht aber keine tatsächlichen Änderungen. False Positives kosten pro Lauf ein paar zusätzliche Embedding-Aufrufe. Der Geschwindigkeitsunterschied (100ms gegenüber 3 Sekunden) macht mtime zur pragmatischen Wahl für ein System, das bei jeder AI-Interaktion läuft.
Umgang mit Löschungen
Wenn eine Datei aus dem vault gelöscht wird, entfernt der Indexer alle zugehörigen chunks aus der Datenbank:
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],
)
Die Anweisung DELETE FROM chunk_vecs funktioniert seit sqlite-vec v0.1.7 nativ, mit einem Bugfix in v0.1.9 für DELETE-Operationen auf vec0-Tabellen mit längeren Metadaten-Textspalten.1423 Frühere Versionen erforderten Workarounds (Löschen und Neuerstellen der virtuellen Tabelle oder Pflege eines externen Satzes „aktiver IDs“). Wenn Sie eine Version vor 0.1.9 verwenden, sollten Sie ein Upgrade durchführen, bevor Sie sich in metadatenlastigen Schemas auf direkte Löschungen verlassen.
FTS5-Content-Sync-Tabellen erfordern für jede entfernte Zeile eine explizite Löschung über INSERT INTO chunks_fts(chunks_fts, rowid, ...) VALUES('delete', ?, ...). Der Indexer erledigt dies als Teil des Dateientfernungsprozesses.
Inkrementelles vs. vollständiges Reindexing
Der Indexer unterstützt zwei Modi: inkrementell (schnell, für den täglichen Einsatz) und vollständig (langsam, gelegentlich). Dieser Abschnitt erklärt, wann Sie welchen Modus verwenden sollten, welche Idempotenzgarantien gelten und wie Sie Beschädigungen beheben.
Inkrementelles Reindexing
Wann verwenden: Tägliches Indexing nach dem Bearbeiten von Notizen. Dies ist der Standardmodus.
Was dabei passiert: 1. Vault auf Dateiänderungen scannen (mtime-Vergleich) 2. Chunks für gelöschte Dateien löschen 3. Geänderte Dateien erneut in Chunks aufteilen und erneut einbetten 4. Neue Chunks für neue Dateien einfügen 5. FTS5-Index synchronisieren
Typische Dauer: <10 Sekunden für die Änderungen eines Tages in einem Vault mit 16.000 Dateien.
python index_vault.py --incremental
Vollständiges Reindexing
Wann verwenden: - Nach dem Ändern des Embedding-Modells (Abweichung beim Modell-Hash erkannt) - Nach einer Schemamigration (neue Spalten, geänderte Indizes) - Nach einer Datenbankbeschädigung (Integritätsprüfung schlägt fehl) - Wenn inkrementelles Indexing unerwartete Ergebnisse liefert
Was dabei passiert: 1. Alle vorhandenen Daten löschen (Chunks, Vektoren, FTS5-Einträge) 2. Gesamten Vault scannen 3. Alle Dateien in Chunks aufteilen 4. Alle Chunks einbetten 5. FTS5-Index von Grund auf neu erstellen
Typische Dauer: ~4 Minuten für 16.894 Dateien auf Apple M3 Pro.
python index_vault.py --full
Idempotenz
Beide Modi sind idempotent: Wird derselbe Befehl zweimal ausgeführt, entsteht dasselbe Ergebnis. Der Indexer löscht vorhandene Chunks für eine Datei, bevor er neue einfügt. Deshalb führt ein erneuter Durchlauf des inkrementellen Indexings bei einer bereits aktuellen Datenbank zu null Änderungen. Ein erneuter vollständiger Indexing-Durchlauf erzeugt eine identische Datenbank.
Wiederherstellung nach Beschädigung
Wenn die SQLite-Datenbank beschädigt wird (Stromausfall während eines Schreibvorgangs, Datenträgerfehler, beendeter Prozess mitten in einer Transaktion):
# Check integrity
sqlite3 vectors.db "PRAGMA integrity_check;"
# If corruption detected, full reindex rebuilds from source files
python index_vault.py --full
Die Quelle der Wahrheit sind immer die Vault-Dateien, nicht die Datenbank. Die Datenbank ist ein abgeleitetes Artefakt, das jederzeit neu erstellt werden kann. Das ist eine zentrale Designeigenschaft: Sie müssen die Datenbank nie sichern.
Das --incremental-Flag
Wenn der Indexer mit --incremental läuft:
- Modell-Hash prüfen. Gespeicherten Modell-Hash mit dem aktuellen Modell vergleichen. Bei Abweichung automatisch in den vollständigen Reindexing-Modus wechseln und den Benutzer warnen.
- Dateiscan. Erlaubte Ordner durchlaufen, Dateipfade und mtimes erfassen.
- Änderungserkennung. Mit gespeicherten Daten vergleichen.
- Batch-Verarbeitung. Geänderte Dateien in Batches von 64 erneut in Chunks aufteilen und einbetten.
- Fortschrittsausgabe. Anzahl der verarbeiteten Dateien und verstrichene Zeit ausgeben.
- Kontrolliertes Beenden. SIGINT behandeln, indem die aktuelle Datei vor dem Stoppen abgeschlossen wird.
Credential-Filtering und Datengrenzen
Persönliche Notizen enthalten Geheimnisse: API-Schlüssel, Bearer-Tokens, Datenbankverbindungsstrings, private Schlüssel, die während Debugging-Sitzungen eingefügt wurden. Der Credential-Filter verhindert, dass diese in den Retrieval-Index gelangen.
Das Problem
Eine Notiz über das Debugging einer OAuth-Integration könnte Folgendes enthalten:
The token was: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
I used this curl command:
curl -H "Authorization: Bearer sk-ant-api03-abc123..."
Ohne Filterung würden sowohl das JWT als auch der API-Schlüssel in Chunks aufgeteilt, eingebettet und in der Datenbank gespeichert. Eine Suche nach „authentication“ würde den Chunk mit echten Geheimnissen zurückgeben. Schlimmer noch: Wenn der Retriever Ergebnisse über MCP an ein AI-Tool weitergibt, erscheinen die Geheimnisse im Kontextfenster der AI und möglicherweise in den Logs des Tools.
Musterbasierte Filterung
Der Credential-Filter läuft vor der Speicherung auf jedem Chunk und gleicht 25 anbieterspezifische Muster sowie generische Muster ab:
Anbieterspezifische Muster:
| Muster | Beispiel | Regex |
|---|---|---|
| OpenAI API-Schlüssel | sk-... |
sk-[a-zA-Z0-9_-]{20,} |
| Anthropic-API-Schlüssel | sk-ant-api03-... |
sk-ant-api\d{2}-[a-zA-Z0-9_-]{20,} |
| GitHub PAT | ghp_... |
gh[ps]_[a-zA-Z0-9]{36,} |
| AWS Access Key | AKIA... |
AKIA[0-9A-Z]{16} |
| Stripe-Schlüssel | sk_live_... |
[sr]k_(live\|test)_[a-zA-Z0-9]{24,} |
| Cloudflare-Token | ... |
Verschiedene Muster |
Generische Muster:
| Muster | Erkennung |
|---|---|
| JWT-Tokens | eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+ |
| Bearer-Tokens | Bearer\s+[a-zA-Z0-9_\-\.]+ |
| Private Schlüssel | -----BEGIN (RSA\|EC\|OPENSSH) PRIVATE KEY----- |
| Base64 mit hoher Entropie | Strings mit >4,5 Bit/Zeichen Entropie, 40+ Zeichen |
| Passwortzuweisungen | password\s*[:=]\s*["'][^"']+["'] |
Filterimplementierung
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
Wichtige Designentscheidungen:
-
Vor dem Embedding filtern. Der bereinigte Text wird eingebettet. Die Vektordarstellung codiert nie Credential-Muster. Eine Abfrage nach „API key“ gibt Notizen zurück, in denen es um die Verwaltung von API-Schlüsseln geht, nicht Notizen, die echte Schlüssel enthalten.
-
Ersetzen, nicht entfernen. Das Token
[REDACTED:pattern-name]bewahrt den semantischen Kontext des umgebenden Texts. Das Embedding erfasst, dass „hier etwas Credential-Ähnliches stand“, ohne das Credential selbst zu codieren. -
Muster loggen, keine Werte. Der Filter protokolliert, welche Muster gefunden wurden (z. B. „Scrubbed 2 credential(s) from oauth-debug.md [jwt, bearer-token]“), aber niemals den Credential-Wert.
Pfadbasierter Ausschluss
Die Datei .indexignore ermöglicht grobkörnige Ausschlüsse nach Pfad. Der Credential-Filter bietet feinkörniges Scrubbing innerhalb indexierter Dateien. Beides ist notwendig:
.indexignorefür ganze Ordner, von denen Sie wissen, dass sie sensible Inhalte enthalten (Gesundheitsnotizen, Finanzunterlagen, Bewerbungsunterlagen)- Credential-Filter für Geheimnisse, die versehentlich in ansonsten indexierbare Inhalte eingebettet wurden
Datenklassifizierung
Bei Vaults mit unterschiedlichen Inhalten sollten Sie Notizen nach Sensibilität klassifizieren:
| Stufe | Beispiele | Indexieren? | Filtern? |
|---|---|---|---|
| Öffentlich | Blogentwürfe, technische Notizen | Ja | Ja |
| Intern | Projektpläne, Architekturentscheidungen | Ja | Ja |
| Sensibel | Gehaltsdaten, Gesundheitsakten | Nein (.indexignore) | N/A |
| Eingeschränkt | Credentials, private Schlüssel | Nein (.indexignore) | N/A |
MCP-Serverarchitektur
Model Context Protocol (MCP)-Server stellen den Retriever als Tool bereit, das AI Agents aufrufen können. Dieser Abschnitt behandelt das Serverdesign, die Funktionsoberfläche und Berechtigungsgrenzen.
Protokollwahl: STDIO vs HTTP
MCP unterstützt zwei Transportmodi:
STDIO — Das AI Tool startet den MCP-Server als Kindprozess und kommuniziert über stdin/stdout. Dies ist der Standardmodus für lokale Tools. Claude Code, Codex CLI und Cursor unterstützen alle STDIO-MCP-Server.
{
"mcpServers": {
"obsidian": {
"command": "python",
"args": ["/path/to/obsidian_mcp.py"],
"env": {
"VAULT_PATH": "/path/to/vault",
"DB_PATH": "/path/to/vectors.db"
}
}
}
}
HTTP — Der MCP-Server läuft als eigenständiger HTTP-Dienst. Nützlich für Remote-Zugriff, Multi-Client-Setups oder Teamkonfigurationen, bei denen der Vault auf einem gemeinsam genutzten Server liegt.
{
"mcpServers": {
"obsidian": {
"url": "http://localhost:3333/mcp"
}
}
}
Empfehlung: Verwenden Sie STDIO für persönliche Vaults. Es ist einfacher, sicherer (keine Netzwerkexposition), und der Serverlebenszyklus wird vom AI Tool verwaltet. Verwenden Sie HTTP nur, wenn mehrere Tools oder mehrere Maschinen gleichzeitigen Zugriff auf denselben Vault benötigen.
MCP-Spezifikationsentwicklung. Die MCP-Spezifikation vom Juni 2025 ergänzte OAuth 2.1-Autorisierung, strukturierte Tool-Ausgaben (typisierte Rückgabeschemas) und Elicitation (serverinitiierte Benutzerabfragen). Das Release vom November 2025 lieferte Streamable HTTP als Transportmodus erster Klasse,
.well-known-URL-Discovery zum automatischen Durchsuchen von Serverfunktionen, strukturierte Tool-Annotationen, die deklarieren, ob ein Tool schreibgeschützt oder verändernd ist, sowie ein SDK-Tier-Standardisierungssystem.79 Die nächste Revision ist jetzt konkret: Die Spezifikation 2026-07-28 ist am 21. Mai 2026 in den Release Candidate eingetreten - die größte MCP-Revision seit dem Start. Die wichtigsten Änderungen sind ein zustandsloser Protokollkern (derinitialize-Handshake und derMcp-Session-Id-Header werden entfernt, sodass Server keinen sitzungsbezogenen Zustand pro Verbindung mehr verfolgen), MCP Apps (Server können servergerendertes HTML zurückgeben, das in sandboxed Client-iframes angezeigt wird), Tasks, die vom experimentellen Kern zu einer offiziellen Erweiterung werden (tasks/get,tasks/update,tasks/cancelfür lang laufende Operationen), gehärtete OAuth 2.0 / OIDC-Autorisierung und eine 12-monatige Richtlinie für den Lebenszyklus von Feature-Deprecations. Die finale Spezifikation erscheint am 28. Juli 2026.24 Für persönliche Vault-Server bleibt STDIO der einfachste Weg, und der zustandslose Kern macht Single-User-STDIO-Server noch schlanker. Der Streamable-HTTP-Transport,.well-known-Discovery und MCP Apps nützen vor allem Enterprise-HTTP-Deployments mit Multi-Tenant-Routing und Load Balancing. Beobachten Sie die MCP roadmap, um Updates zu verfolgen, die Ihre Transportwahl beeinflussen.
Funktionsdesign
Der MCP-Server sollte nur eine minimale Tool-Auswahl bereitstellen:
search — Das primäre Tool. Führt hybrides Retrieval aus und gibt gerankte Ergebnisse zurück.
{
"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 — Liest den vollständigen Inhalt einer bestimmten Notiz anhand des Pfads. Nützlich, wenn der Agent den vollständigen Kontext eines Suchergebnisses sehen möchte.
{
"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 — Listet Notizen auf, die einem Filter entsprechen (nach Ordner, Tag, Typ oder Datumsbereich). Nützlich zur Erkundung, wenn der Agent keine konkrete Abfrage hat.
{
"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 — Ein Komfort-Tool, das eine Suche ausführt und die Ergebnisse als Kontextblock formatiert, der sich für die Einfügung in eine Unterhaltung eignet.
{
"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 }
}
}
Berechtigungsgrenzen
Der MCP-Server sollte strikte Grenzen erzwingen:
-
Schreibgeschützt. Der Server liest den Vault und die Indexdatenbank. Er erstellt, ändert oder löscht keine Notizen. Schreiboperationen (das Erfassen neuer Notizen) werden von separaten Hooks oder Skills übernommen, nicht vom MCP-Server.
-
Auf den Vault beschränkt. Der Server liest nur Dateien innerhalb des konfigurierten Vault-Pfads. Path-Traversal-Versuche (
../../etc/passwd) müssen abgelehnt werden. -
Ausgabe mit Credential-Filtering. Selbst wenn die Datenbank vorgefilterte Inhalte enthält, wenden Sie Credential-Filtering bei der Ausgabe als Defense-in-Depth-Maßnahme an.
-
Token-begrenzte Antworten. Erzwingen Sie
max_tokensfür alle Tool-Antworten, damit das AI Tool keine übermäßig großen Kontextblöcke erhält.
Fehlerbehandlung
MCP-Tools sollten strukturierte Fehlermeldungen zurückgeben, die dem AI Tool bei der Wiederherstellung helfen:
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,
}
Claude Code-Integration
Claude Code ist der wichtigste Verbraucher des Obsidian-Retrieval-Systems. Dieser Abschnitt behandelt die MCP-Konfiguration, die Hook-Integration und das Muster obsidian_bridge.py.
MCP-Konfiguration
Fügen Sie den Obsidian-MCP-Server zu ~/.claude/settings.json hinzu:
{
"mcpServers": {
"obsidian": {
"command": "python",
"args": ["/path/to/obsidian_mcp.py"],
"env": {
"VAULT_PATH": "/absolute/path/to/vault",
"DB_PATH": "/absolute/path/to/vectors.db"
}
}
}
}
Nachdem Sie die Konfiguration hinzugefügt haben, starten Sie Claude Code neu. Der MCP-Server wird als untergeordneter Prozess gestartet. Prüfen Sie, ob er läuft:
> What tools do you have from the obsidian MCP server?
Claude Code sollte die verfügbaren Tools auflisten (obsidian_search, obsidian_read_note usw.).
Hook-Integration
Hooks erweitern das Verhalten von Claude Code an definierten Punkten im Lebenszyklus. Für die Obsidian-Integration sind 2 Hooks relevant:
PreToolUse-Hook — Fragt den Vault ab, bevor der Agent einen Tool-Aufruf verarbeitet. Relevanter Kontext wird automatisch eingefügt.
#!/bin/bash
# ~/.claude/hooks/pre-tool-use/obsidian-context.sh
# Automatically inject vault context before tool execution
TOOL_NAME="$1"
PROMPT="$2"
# Only inject context for code-related tools
case "$TOOL_NAME" in
Edit|Write|Bash)
# Query the vault
CONTEXT=$(python /path/to/retriever.py search "$PROMPT" --limit 3 --max-tokens 1500)
if [ -n "$CONTEXT" ]; then
echo "---"
echo "Relevant vault context:"
echo "$CONTEXT"
echo "---"
fi
;;
esac
PostToolUse-Hook — Erfasst wichtige Tool-Ausgaben zurück in den Vault, damit sie künftig abgerufen werden können.
#!/bin/bash
# ~/.claude/hooks/post-tool-use/capture-insight.sh
# Capture significant outputs to vault (selective)
TOOL_NAME="$1"
OUTPUT="$2"
# Only capture substantial outputs
if [ ${#OUTPUT} -gt 500 ]; then
python /path/to/capture.py --text "$OUTPUT" --source "claude-code-$TOOL_NAME"
fi
Das obsidian_bridge.py-Muster
Ein Bridge-Modul stellt eine Python-API bereit, die Hooks und Skills aufrufen können:
# 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)
Der /capture-Skill
Ein Claude Code-Skill, um Erkenntnisse zurück in den Vault zu erfassen:
/capture "OAuth token rotation requires both access and refresh token invalidation"
--domain security
--tags oauth,tokens
Der Skill erstellt eine neue Notiz in 00-inbox/ mit korrektem frontmatter und stößt eine inkrementelle Neuindizierung an, sodass die neue Notiz sofort durchsuchbar ist.
Muster für benutzerdefinierte Befehle
Claude Code-Skills können Vault-Operationen in benannte Befehle kapseln. Praktiker haben Bibliotheken mit Obsidian-spezifischen Befehlen aufgebaut, die den Vault zugleich als Lesequelle und Schreibziel behandeln.
Signalscans. Ein /scan-intel-Befehl fragt externe Quellen ab, bewertet Fundstellen anhand persönlicher Forschungsinteressen und schreibt passende Signale als Vault-Notizen mit frontmatter:
/scan-intel --topics "agent infrastructure, security" --lookback 7d
Der Befehl ruft Daten aus konfigurierten Quellen ab (arXiv, HN, RSS), wendet ein Bewertungsmodell an (Relevanz, Umsetzbarkeit, Tiefe, Autorität) und schreibt bestandene Signale in themenspezifische Vault-Ordner. Der Vault wird damit zum nachgelagerten Verbraucher einer automatisierten Intelligence-Pipeline.
Captain’s Log. Ein /captains-log-Befehl aggregiert tägliche git-Aktivitäten über alle Repositories hinweg, schreibt einen strukturierten Journaleintrag in den Vault und enthält getroffene Entscheidungen, Erkenntnisse und offene Themen:
/captains-log
Der Befehl zieht die Commit-Historie aus GitHub, gruppiert sie nach Repository und formatiert sie als narrativen Journaleintrag. Mit der Zeit entsteht durch die täglichen Logs ein durchsuchbarer Verlauf dessen, was ausgeliefert wurde und warum.
Obsidian-Erfassung. Ein /obsidian-capture-Befehl nimmt eine Erkenntnis aus der aktuellen Claude Code-Sitzung und schreibt sie mit korrekten Metadaten direkt in den Vault:
/obsidian-capture "SAST gates in agent loops increase security degradation"
--folder AI-Tools --tags security,agents
Das Muster lässt sich auf jede Vault-Operation erweitern: MOCs erstellen, Projektstatusnotizen aktualisieren, verwandte Signale verlinken oder wöchentliche Zusammenfassungen aus angesammelten Tageslogs erzeugen.
Community-Beispiele. Praktiker veröffentlichen ihre Befehlsbibliotheken. Ein Entwickler teilte 22 benutzerdefinierte Obsidian- + Claude Code-Befehle für tägliche Reviews, Projektplanung, Forschungserfassung und Content-Workflows.1 Ein anderer baute einen „Visual Explainer“-Skill, der aus Codeanalysen Diagrammnotizen im Vault erzeugt.2 Die Befehle unterscheiden sich, doch die Architektur bleibt konsistent: Claude Code-Skills als Schnittstelle, Vault-Notizen als Speicherschicht und Retrieval-Infrastruktur als Abfrage-Engine.
Verwaltung des Kontextfensters
Die Integration sollte das Kontextfenster von Claude Code berücksichtigen:
- Begrenzen Sie eingefügten Kontext auf 1.500-2.000 Tokens pro Abfrage. Mehr konkurriert mit dem Arbeitsspeicher des Agents.
- Fügen Sie Quellenangaben hinzu. Geben Sie immer den Dateipfad und die Abschnittsüberschrift an, damit der Agent die Quelle referenzieren kann.
- Kürzen Sie Chunk-Text. Lange Chunks sollten mit
...gekürzt werden, statt vollständig ausgelassen zu werden. Die ersten 300-500 Zeichen enthalten in der Regel die wichtigsten Informationen. - Fügen Sie nicht bei jedem Tool-Aufruf Kontext ein. Der PreToolUse-Hook sollte Kontext selektiv danach einfügen, welches Tool aufgerufen wird. Leseoperationen benötigen keinen Vault-Kontext. Schreib- und Edit-Operationen profitieren davon.
Codex CLI-Integration
Codex CLI verbindet sich über config.toml mit MCP-Servern. Das Integrationsmuster unterscheidet sich von Claude Code in der Konfigurationssyntax und in der Bereitstellung von Anweisungen.
MCP-Konfiguration
Fügen Sie Folgendes zu .codex/config.toml oder ~/.codex/config.toml hinzu:
[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"
AGENTS.md-Muster
Codex CLI liest AGENTS.md für Anweisungen auf Projektebene. Fügen Sie Hinweise zur Vault-Suche hinzu:
## 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"
Unterschiede zu Claude Code
| Funktion | Claude Code | Codex CLI |
|---|---|---|
| MCP-Konfiguration | settings.json |
config.toml |
| Hooks | ~/.claude/hooks/ |
Nicht unterstützt |
| Skills | ~/.claude/skills/ |
Nicht unterstützt |
| Anweisungsdatei | CLAUDE.md |
AGENTS.md |
| Genehmigungsmodi | --dangerously-skip-permissions |
suggest / auto-edit / full-auto |
Wichtigster Unterschied: Codex CLI unterstützt keine Hooks. Das Muster für automatische Kontexteinfügung (PreToolUse-Hook) ist nicht verfügbar. Fügen Sie stattdessen explizite Anweisungen in AGENTS.md ein, die den Agent anweisen, vor Arbeitsbeginn den Vault zu durchsuchen.
Cursor und andere Tools
Cursor und andere AI-Tools, die MCP unterstützen, können sich mit demselben Obsidian-MCP-Server verbinden. Dieser Abschnitt behandelt die Konfiguration für gängige Tools.
Cursor
Fügen Sie .cursor/mcp.json im Projektstamm hinzu:
{
"mcpServers": {
"obsidian": {
"command": "python",
"args": ["/path/to/obsidian_mcp.py"],
"env": {
"VAULT_PATH": "/absolute/path/to/vault",
"DB_PATH": "/absolute/path/to/vectors.db"
}
}
}
}
Die .cursorrules-Datei von Cursor kann Anweisungen zur Nutzung des Vaults enthalten:
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.
Kompatibilitätsmatrix
| Tool | MCP-Unterstützung | Transport | Konfigurationsort |
|---|---|---|---|
| Claude Code | Vollständig | STDIO | ~/.claude/settings.json |
| Codex CLI | Vollständig | STDIO | .codex/config.toml |
| Cursor | Vollständig | STDIO | .cursor/mcp.json |
| Windsurf | Vollständig | STDIO | .windsurf/mcp.json |
| Continue.dev | Teilweise | HTTP | ~/.continue/config.json |
| Zed | In Arbeit | STDIO | Settings UI |
| Claudian (Obsidian plugin) | N/A (eingebettet) | Claude Code CLI | Obsidian plugin settings |
| Agent Client (Obsidian plugin) | N/A (eingebettet) | ACP | Obsidian plugin settings |
Fallback für Tools ohne MCP
Für Tools, die MCP nicht unterstützen, kann der Retriever als CLI verpackt werden:
# 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
Der CLI gibt strukturierten Text aus, der manuell in die Eingabe eines beliebigen AI-Tools eingefügt werden kann. Das ist weniger elegant als eine MCP-Integration, funktioniert aber universell.
Prompt Caching aus strukturierten Notizen
Strukturierte Notizen im Vault können als wiederverwendbare Kontextblöcke dienen, die den Token-Verbrauch über AI-Interaktionen hinweg reduzieren. Dieser Abschnitt behandelt das Design von Cache-Schlüsseln und die Verwaltung des Token-Budgets.
Das Muster
Statt bei jeder Interaktion nach Kontext zu suchen, erstellen Sie Kontextblöcke aus gut strukturierten Vault-Notizen vorab und cachen sie:
# 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
},
}
Cache-Invalidierung
Die Cache-Invalidierung basiert auf zwei Signalen:
- TTL-Ablauf. Jeder Kontextblock hat eine Time-to-live. Wenn die TTL abläuft, wird der Block durch eine erneute Abfrage des Vaults neu aufgebaut.
- Erkennung von Vault-Änderungen. Wenn der Indexer Änderungen an Dateien erkennt, die zu einem gecachten Kontextblock beigetragen haben, wird der Block sofort invalidiert.
Verwaltung des Token-Budgets
Eine Sitzung startet mit einem gesamten Kontextbudget. Gecachte Blöcke verbrauchen einen Teil dieses Budgets:
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)
Die gecachten Blöcke werden beim Sitzungsstart geladen. Dynamische Suchergebnisse füllen das verbleibende Budget pro Abfrage auf. Dieser hybride Ansatz gibt dem Agent eine Basis häufig benötigten Kontexts und erhält zugleich Budget für spezifische Abfragen.
Token-Verbrauch vorher/nachher
Ohne Caching: Jede relevante Abfrage löst eine Vault-Suche aus und gibt 1.500-2.000 Token Kontext zurück. Über 10 Abfragen in einer Sitzung verbraucht der Agent 15.000-20.000 Token Vault-Kontext.
Mit Caching: Drei vorab erstellte Kontextblöcke verbrauchen insgesamt 4.500 Token. Zusätzliche Suchen fügen 1.500-2.000 Token pro eindeutiger Abfrage hinzu. Über 10 Abfragen, von denen 6 durch gecachte Blöcke abgedeckt sind, verbraucht der Agent 4.500 + (4 * 1.500) = 10.500 Token — etwa die Hälfte des Verbrauchs ohne Cache.
PostToolUse-Hooks für Kontextkomprimierung
Tool-Ausgaben können ausführlich sein: Stack Traces, Dateilisten, Testergebnisse. Ein PostToolUse-Hook kann diese Ausgaben komprimieren, bevor sie Platz im Kontextfenster verbrauchen.
Das Problem
Ein Bash-Tool-Aufruf, der Tests ausführt, könnte Folgendes zurückgeben:
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
Die vollständige Ausgabe umfasst 5.000 Token, aber das Signal steckt in 2 Zeilen: 200 bestanden, 1 fehlgeschlagen.
Hook-Implementierung
#!/bin/bash
# ~/.claude/hooks/post-tool-use/compress-output.sh
# Compress verbose tool outputs to preserve context window
TOOL_NAME="$1"
OUTPUT="$2"
OUTPUT_LEN=${#OUTPUT}
# Only compress large outputs
if [ "$OUTPUT_LEN" -lt 2000 ]; then
exit 0 # Pass through unchanged
fi
case "$TOOL_NAME" in
Bash)
# Compress test output
if echo "$OUTPUT" | grep -q "PASSED\|FAILED"; then
PASSED=$(echo "$OUTPUT" | grep -c "PASSED")
FAILED=$(echo "$OUTPUT" | grep -c "FAILED")
FAILURES=$(echo "$OUTPUT" | grep "FAILED")
echo "Tests: $PASSED passed, $FAILED failed"
if [ "$FAILED" -gt 0 ]; then
echo "Failures:"
echo "$FAILURES"
fi
fi
;;
esac
Verhindern rekursiver Trigger
Ein Komprimierungs-Hook, der Ausgaben erzeugt, könnte sich selbst auslösen, wenn er nicht abgesichert ist:
# Guard against recursive invocation
if [ -n "$COMPRESS_HOOK_ACTIVE" ]; then
exit 0
fi
export COMPRESS_HOOK_ACTIVE=1
Komprimierungsheuristiken
| Ausgabetyp | Erkennung | Komprimierungsstrategie |
|---|---|---|
| Testergebnisse | Schlüsselwörter PASSED / FAILED |
Bestehende/fehlgeschlagene Tests zählen, nur Fehler anzeigen |
| Dateilisten | ls oder find im Befehl |
Auf die ersten 20 Einträge + Anzahl kürzen |
| Stack Traces | Schlüsselwort Traceback |
Ersten und letzten Frame + Fehlermeldung behalten |
| Git-Status | modified: / new file: |
Anzahl nach Status zusammenfassen |
| Build-Ausgabe | warning: / error: |
Info-Zeilen entfernen, Warnungen/Fehler behalten |
Signalaufnahme- und Triage-Pipeline
Die Aufnahmeschicht bestimmt, was in den Vault gelangt. Ohne Kuratierung sammelt der Vault Rauschen an. Dieser Abschnitt behandelt die Scoring-Pipeline, die Signale in Domain-Ordner weiterleitet.
Quellen
Signale stammen aus mehreren Kanälen:
- RSS-Feeds: Technische Blogs, Sicherheitshinweise, Release Notes
- Lesezeichen über Web Clipper: Die offizielle Obsidian Web Clipper-Erweiterung (Chrome, Firefox, Safari) ist der Aufnahmeweg mit der höchsten Wiedergabetreue für browserseitige Erfassung. Der Release-Zyklus im April 2026 machte sie für AI-Workflows deutlich nützlicher:22
- 1.4.0 (9. Apr.): Interaktive YouTube-Transkript-UI — Video anheften, durch das Transkript scrubben, automatisch scrollen und die aktuelle Position hervorheben. Dazu kommt eine standardmäßige Option “Open in Reader”, die eine Ein-Klick-Erfassung direkt in den Reader-Modus sendet.
- 1.5.0–1.5.1 (15. Apr.): Highlights-Viewer — erfasste Highlights im gesamten Vault durchsuchen und durchsuchen. Fade-in-Übergang in den Reader. Reibungsloseres YouTube-Play/Pause. 1.5.1 behob eine Regression bei der webpack-Kompilierung.
- 1.6.0–1.6.2 (21.–23. Apr.): Überarbeitung der Highlighter-UX mit mobiler Unterstützung. Defuddle 0.18 fügt quellenspezifische Extraktoren für LinkedIn, Threads, Bluesky, Discourse und Medium hinzu. 1.6.2 behebt eine Clipboard-Regression im eingebetteten Safari-Modus. Konfigurieren Sie Templates pro Quelldomain, damit YouTube-Transkripte, GitHub READMEs und Longform-Artikel jeweils in einer sinnvoll benannten Notiz mit dem passenden frontmatter für die unten beschriebene Scoring-Pipeline landen.
- Newsletter: Wichtige Auszüge aus E-Mail-Newslettern
- Manuelle Erfassung: Notizen, die beim Lesen, in Gesprächen oder bei der Recherche entstehen
- Tool-Ausgabe: Wichtige Ausgaben von AI-Tools, die über Hooks erfasst werden
- iOS Share Extension: Die iOS-App von Obsidian (Anfang 2026 aktualisiert) enthält eine Share Extension, die Inhalte aus Safari, sozialen Netzwerken und anderen Apps direkt im Vault speichert, ohne Obsidian zu öffnen.19 Dadurch entsteht ein reibungsarmer mobiler Aufnahmeweg — teilen Sie einen Artikel aus Safari, und er kommt als Vault-Notiz an, bereit für das Scoring.
- Obsidian CLI: Shell-Skripte und Hooks können über
obsidian file createNotizen erstellen oder überobsidian file appendan bestehende Notizen anhängen, wodurch automatisierte Aufnahme-Pipelines auf dem Desktop möglich werden.
Scoring-Dimensionen
Jedes Signal wird in vier Dimensionen bewertet (jeweils 0,0 bis 1,0):
| Dimension | Frage | Niedriger Score (0,0-0,3) | Hoher Score (0,7-1,0) |
|---|---|---|---|
| Relevanz | Bezieht sich das auf meine aktiven Domains? | Randständig, außerhalb des Umfangs | Direkt relevant für aktive Arbeit |
| Handlungsrelevanz | Kann ich diese Informationen nutzen? | Reine Theorie, keine Anwendung | Konkrete Technik oder Muster, das ich anwenden kann |
| Tiefe | Wie substanziell ist der Inhalt? | Überschriften, oberflächliche Zusammenfassung | Detaillierte Analyse mit Beispielen |
| Autorität | Wie glaubwürdig ist die Quelle? | Anonymer Blog, nicht verifiziert | Primärquelle, peer-reviewed, anerkannter Experte |
Zusammengesetzter Score und Routing
composite = (relevance * 0.35) + (actionability * 0.25) +
(depth * 0.25) + (authority * 0.15)
| Score-Bereich | Aktion |
|---|---|
| 0,55+ | Automatisch in Domain-Ordner routen |
| 0,40 - 0,55 | Für manuelle Prüfung einreihen |
| < 0,40 | Verwerfen (nicht speichern) |
Domain-Routing
Signale mit einem Score über 0,55 werden basierend auf Keyword-Matching und Themenklassifizierung in einen von 12 Domain-Ordnern geroutet:
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
Produktionsstatistiken
Über 14 Monate Betrieb:
| Metrik | Wert |
|---|---|
| Insgesamt verarbeitete Signale | 7.771 |
| Automatisch geroutet (>0,55) | 4.832 (62 %) |
| Zur Prüfung eingereiht (0,40-0,55) | 1.543 (20 %) |
| Verworfen (<0,40) | 1.396 (18 %) |
| Aktive Domain-Ordner | 12 |
| Durchschnittliche Signale pro Tag | ~18 |
Knowledge Graph-Muster
Der wiki-link-Graph von Obsidian codiert Beziehungen zwischen Notizen. Dieser Abschnitt behandelt Link-Semantik, Graph Traversal zur Kontexterweiterung und Anti-Patterns, die die Graph-Qualität verschlechtern.
Backlink-Semantik
Jeder wiki-link erstellt eine gerichtete Kante im Graph. Obsidian verfolgt sowohl Forward Links als auch backlinks:
- Forward Link: Notiz A enthält
[[Note B]]→ A verlinkt auf B - Backlink: Notiz B zeigt, dass Notiz A sie referenziert
Der Graph codiert je nach Kontext unterschiedliche Beziehungstypen:
| Link-Muster | Semantik | Beispiel |
|---|---|---|
| Inline-Link | “Steht in Bezug zu” | “Siehe [[OAuth Token Rotation]] für Details” |
| Header-Link | “Hat Unterthema” | ”## Related\n- [[Token Rotation]]\n- [[Session Management]]” |
| Tag-ähnlicher Link | “Ist kategorisiert als” | ”[[type/reference]]” |
| MOC-Link | “Ist Teil von” | Eine Map of Content-Notiz, die verwandte Notizen auflistet |
Maps of Content (MOCs)
MOCs sind Indexnotizen, die verwandte Notizen in einer navigierbaren Struktur organisieren:
---
title: "Authentication & Security MOC"
type: moc
domain: security
---
## Core Concepts
- [[OAuth 2.0 Overview]]
- [[JWT Token Anatomy]]
- [[Session Management Patterns]]
## Implementation Patterns
- [[OAuth Token Rotation]]
- [[Refresh Token Security]]
- [[PKCE Flow Implementation]]
## Failure Modes
- [[Token Expiry Handling]]
- [[Session Fixation Prevention]]
- [[CSRF Defense Strategies]]
MOCs verbessern Retrieval auf zwei Arten:
- Direkter Match. Eine Suche nach “authentication overview” findet die MOC selbst und liefert dem Agent eine kuratierte Liste verwandter Notizen.
- Kontexterweiterung. Nachdem eine bestimmte Notiz gefunden wurde, kann der Retriever prüfen, ob die Notiz in MOCs vorkommt, und die Struktur der MOC in die Ergebnisse aufnehmen. So erhält der Agent eine Karte des übergeordneten Themas.
Graph Traversal zur Kontexterweiterung
Eine zukünftige Erweiterung des Retrievers: Nach dem Finden der Top-Ergebnisse wird der Kontext durch das Folgen von Links erweitert:
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)
Dies ist im aktuellen Retriever nicht implementiert, stellt aber eine natürliche Erweiterung der Graph-Struktur dar.
Anti-Patterns
Verwaiste Cluster. Gruppen von Notizen, die aufeinander verlinken, aber keine Verbindungen zum Rest des Vault haben. Das Graph-Panel in Obsidian macht sie als getrennte Inseln sichtbar. Verwaiste Cluster weisen auf fehlende MOCs oder fehlende domainübergreifende Links hin.
Tag-Wildwuchs. Tags inkonsistent verwenden oder zu viele feingranulare Tags erstellen. Ein Vault mit 500 eindeutigen Tags über 5.000 Notizen hinweg hat im Durchschnitt 1 Notiz pro 10 Tags — die Tags sind zum Filtern nicht nützlich. Konsolidieren Sie auf 20-50 übergeordnete Tags, die Ihren Domain-Ordnern entsprechen.
Linklastige, inhaltsarme Notizen. Notizen, die vollständig aus wiki-links ohne Fließtext bestehen. Diese Notizen werden schlecht indexiert, weil der chunker keinen Text zum Einbetten hat. Fügen Sie mindestens einen Absatz Kontext hinzu, der erklärt, warum die verlinkten Notizen zusammenhängen.
Bidirektionale Links für alles. Nicht jede Referenz muss ein wiki-link sein. Eine beiläufige Erwähnung von “OAuth” erfordert kein [[OAuth 2.0 Overview]]. Reservieren Sie wiki-links für bewusste, navigierbare Beziehungen, bei denen ein Klick auf den Link nützlichen Kontext liefern würde.
Developer-Workflow-Rezepte
Praktische Workflows, die Vault-Retrieval mit täglichen Entwicklungsaufgaben verbinden.
Morgenkontext laden
Beginnen Sie den Tag, indem Sie relevanten Kontext laden:
Search my vault for notes about [current project] updated in the last week
Der Retriever gibt aktuelle Notizen zu Ihrem aktiven Projekt zurück und verschafft Ihnen so schnell einen Überblick darüber, wo Sie aufgehört haben. Das ist effektiver, als die Commit-Nachrichten von gestern erneut zu lesen.
Rechercheerfassung beim Coden
Während Sie eine Funktion implementieren, können Sie Erkenntnisse erfassen, ohne den Editor zu verlassen:
/capture "FastAPI dependency injection with async generators requires yield,
not return. The generator is the dependency lifecycle."
--domain programming
--tags fastapi,dependency-injection
Die erfasste Erkenntnis wird sofort indexiert und steht künftig für Retrieval zur Verfügung. Über Monate entsteht aus diesen Mikroerfassungen ein Korpus aus implementierungsspezifischem Wissen.
Projektstart
Wenn Sie ein neues Projekt oder eine neue Funktion beginnen:
- Durchsuchen Sie den Vault: „Was weiß ich über [Technologie/Muster]?”
- Prüfen Sie die Top-5-Ergebnisse auf frühere Entscheidungen und Stolperfallen
- Prüfen Sie, ob für die Domäne ein MOC existiert; falls nicht, erstellen Sie eines
- Suchen Sie nach Fehlermodi: „Probleme mit [Technologie]”
Debugging mit Vault Search
Wenn ein Fehler oder unerwartetes Verhalten auftritt:
Search my vault for [error message or symptom]
Frühere Debugging-Notizen enthalten oft die Ursache und die Lösung. Das ist besonders wertvoll bei wiederkehrenden Problemen über mehrere Projekte hinweg — der Vault merkt sich, was Sie vergessen.
Vorbereitung auf Code Reviews
Bevor Sie einen PR reviewen:
Search my vault for patterns and conventions about [module being changed]
Der Vault gibt frühere Entscheidungen, Architekturvorgaben und Coding-Standards zurück, die für den zu reviewenden Code relevant sind. Der Review stützt sich auf institutionelles Wissen, nicht nur auf das Diff.
Performance-Tuning
Dieser Abschnitt behandelt Optimierungsstrategien für unterschiedliche Vault-Größen und Nutzungsmuster.
Indexgrößenverwaltung
| Vault-Größe | Chunks | DB-Größe | Vollständige Neuindexierung | Inkrementell |
|---|---|---|---|---|
| 500 Notizen | ~1.500 | 3 MB | 15 Sekunden | <1 Sekunde |
| 2.000 Notizen | ~6.000 | 12 MB | 45 Sekunden | 2 Sekunden |
| 5.000 Notizen | ~15.000 | 30 MB | 2 Minuten | 4 Sekunden |
| 15.000 Notizen | ~50.000 | 83 MB | 4 Minuten | <10 Sekunden |
| 50.000 Notizen | ~150.000 | 250 MB | 15 Minuten | 30 Sekunden |
Bei mehr als 50.000 Notizen sollten Sie Folgendes erwägen: - Erhöhen Sie die batch_size von 64 auf 128, um schneller Embeddings zu erzeugen - Verwenden Sie den WAL-Modus (Standard) für gleichzeitigen Zugriff - Führen Sie vollständige Neuindexierungen außerhalb der Hauptarbeitszeiten aus
Abfrageoptimierung
WAL-Modus. Der Write-Ahead-Logging-Modus von SQLite ermöglicht gleichzeitige Lesezugriffe, während der Indexer schreibt:
db.execute("PRAGMA journal_mode=WAL")
Das ist entscheidend, wenn der MCP Server Abfragen verarbeitet, während der Indexer ein inkrementelles Update ausführt.
Connection Pooling. Der MCP Server sollte Datenbankverbindungen wiederverwenden, statt pro Abfrage eine neue Verbindung zu öffnen. Eine einzelne langlebige Verbindung mit WAL-Modus unterstützt gleichzeitige Lesezugriffe.
# 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
Memory-mapped I/O. Das mmap_size-Pragma weist SQLite an, memory-mapped I/O für die Datenbankdatei zu verwenden. Bei einer Datenbank mit 83 MB werden die meisten Festplattenlesevorgänge vermieden, wenn die gesamte Datei in den Speicher gemappt wird.
FTS5-Optimierung. Führen Sie nach einer vollständigen Neuindexierung Folgendes aus:
INSERT INTO chunks_fts(chunks_fts) VALUES('optimize');
Dadurch werden die internen b-tree-Segmente von FTS5 zusammengeführt, was die Abfragelatenz für nachfolgende Suchen reduziert.
Skalierungsbenchmarks
Gemessen auf Apple M3 Pro, 36 GB RAM, NVMe SSD:
| Operation | 500 Notizen | 5.000 Notizen | 15.000 Notizen | 50.000 Notizen |
|---|---|---|---|---|
| BM25-Abfrage | 2ms | 5ms | 12ms | 25ms |
| Vector-Abfrage | 1ms | 3ms | 8ms | 20ms |
| RRF-Fusion | <1ms | <1ms | 3ms | 5ms |
| Vollständige Suche | 3ms | 8ms | 23ms | 50ms |
Alle Benchmarks umfassen Datenbankzugriff, Abfrageausführung und Ergebnisformatierung. Die Netzwerklatenz für die MCP STDIO-Kommunikation fügt 1-2ms hinzu.
Fehlerbehebung
Index Drift
Symptom: Die Suche gibt veraltete Ergebnisse zurück oder findet kürzlich hinzugefügte Notizen nicht.
Ursache: Der inkrementelle Indexer wurde nach dem Hinzufügen von Notizen nicht ausgeführt, oder die mtime einer Datei wurde nicht aktualisiert (z. B. bei Synchronisierung von einem anderen Rechner mit beibehaltenen Zeitstempeln).
Lösung: Führen Sie eine vollständige Neuindexierung aus: python index_vault.py --full
Wechsel des Embedding-Modells
Symptom: Nach dem Wechsel des Embedding-Modells liefert die Vector Search unsinnige Ergebnisse.
Ursache: Alte Vektoren (aus dem vorherigen Modell) werden mit neuen Abfragevektoren verglichen. Die Dimensionen oder die Semantik des Vektorraums sind inkompatibel.
Lösung: Der Indexer sollte die Abweichung beim Modellhash erkennen und automatisch eine vollständige Neuindexierung auslösen. Falls das nicht geschieht, leeren Sie die Datenbank manuell und indexieren Sie neu:
rm vectors.db
python index_vault.py --full
FTS5-Wartung
Symptom: FTS5-Abfragen liefern nach vielen inkrementellen Updates falsche oder unvollständige Ergebnisse.
Ursache: Interne FTS5-Segmente können nach vielen kleinen Updates fragmentieren.
Lösung: Neu aufbauen und optimieren:
INSERT INTO chunks_fts(chunks_fts) VALUES('rebuild');
INSERT INTO chunks_fts(chunks_fts) VALUES('optimize');
MCP Timeout
Symptom: Das AI Tool meldet, dass der MCP Server einen Timeout hatte.
Ursache: Die erste Abfrage löst das Laden des Modells aus (Lazy Initialization), was 2-5 Sekunden dauert. Der Standard-MCP-Timeout des AI Tools kann kürzer sein.
Lösung: Wärmen Sie das Modell beim Serverstart vor:
# In MCP server initialization
retriever = HybridRetriever(db_path, vault_path)
retriever.search("warmup", limit=1) # Trigger model load
SQLite-Dateisperren
Symptom: SQLITE_BUSY- oder SQLITE_LOCKED-Fehler.
Ursache: Mehrere Prozesse schreiben gleichzeitig in die Datenbank. Der WAL-Modus erlaubt gleichzeitige Lesezugriffe, aber nur einen Schreiber.
Lösung: Stellen Sie sicher, dass nur ein Prozess (der Indexer) in die Datenbank schreibt. Der MCP Server und Hooks sollten nur lesen. Wenn Sie gleichzeitige Schreibzugriffe benötigen, verwenden Sie den WAL-Modus und setzen Sie einen Busy Timeout:
db.execute("PRAGMA busy_timeout=5000") # Wait up to 5 seconds
sqlite-vec wird nicht geladen
Symptom: Vector Search ist deaktiviert; der Retriever läuft nur im BM25-Modus.
Ursache: Die sqlite-vec-Erweiterung ist nicht installiert, wird im Library-Pfad nicht gefunden oder ist mit der SQLite-Version inkompatibel.
Lösung:
# Install via pip
pip install sqlite-vec
# Or compile from source
git clone https://github.com/asg017/sqlite-vec
cd sqlite-vec && make
Prüfen Sie, ob die Erweiterung geladen wird:
import sqlite3
db = sqlite3.connect(":memory:")
db.enable_load_extension(True)
db.load_extension("vec0")
print("sqlite-vec loaded successfully")
Speicherprobleme bei großen Vaults
Symptom: Out-of-memory-Fehler während der vollständigen Neuindexierung eines großen Vaults (mehr als 50.000 Notizen).
Ursache: Die Embedding-batch_size ist zu groß, oder alle Dateiinhalte werden gleichzeitig in den Speicher geladen.
Lösung: Reduzieren Sie die batch_size und verarbeiten Sie Dateien inkrementell:
BATCH_SIZE = 32 # Reduce from 64
Stellen Sie außerdem sicher, dass der Indexer Dateien einzeln verarbeitet (jede Datei lesen, chunken und einbetten, bevor er zur nächsten wechselt), statt alle Dateien in den Speicher zu laden.
Migrationsleitfaden
Von Apple Notes
- Exportieren Sie Apple Notes über die Option „Export All” (macOS) oder verwenden Sie ein Migrationstool wie
apple-notes-liberator - Konvertieren Sie HTML-Exporte mit
markdownifyoderpandocnach markdown - Verschieben Sie die konvertierten Dateien in den Ordner
00-inbox/Ihres Vaults - Prüfen Sie jede Notiz und fügen Sie frontmatter hinzu
- Verschieben Sie Notizen in passende Domänenordner
Von Notion
- Exportieren Sie aus Notion: Settings → Export → Markdown & CSV
- Entpacken Sie den Export in den Ordner
00-inbox/Ihres Vaults - Korrigieren Sie Notion-spezifische markdown-Artefakte:
- Notion verwendet
- [ ]für Checklisten — das ist standardmäßiges markdown - Notion enthält Property-Tabellen als HTML — konvertieren Sie sie in YAML frontmatter
- Notion bettet Bilder als relative Pfade ein — kopieren Sie Bilder in Ihren Attachments-Ordner
- Fügen Sie standardmäßiges frontmatter hinzu (
type,domain,tags) - Ersetzen Sie Notion-Seitenlinks durch Obsidian wiki-links
Von Google Docs
- Verwenden Sie Google Takeout, um alle Dokumente zu exportieren
- Konvertieren Sie
.docx-Dateien nach markdown:pandoc -f docx -t markdown input.docx -o output.md - Batch-Konvertierung:
for f in *.docx; do pandoc -f docx -t markdown "$f" -o "${f%.docx}.md"; done - Verschieben Sie alles in den Vault, fügen Sie frontmatter hinzu und organisieren Sie die Dateien in Ordnern
Von Plain Markdown (ohne Obsidian)
Wenn Sie bereits ein Verzeichnis mit markdown-Dateien haben:
- Öffnen Sie das Verzeichnis als Obsidian Vault (Obsidian → Open Vault → Open folder)
- Fügen Sie
.obsidian/zu.gitignorehinzu, falls das Verzeichnis versioniert ist - Erstellen Sie frontmatter-Templates und wenden Sie sie auf vorhandene Dateien an
- Beginnen Sie beim Lesen und Organisieren damit, Notizen über
[[wiki-links]]zu verlinken - Führen Sie den Indexer sofort aus — das Retrieval-System funktioniert ab dem ersten Tag
Von einem anderen Retrieval-System
Wenn Sie von einem anderen Embedding-/Suchsystem migrieren:
- Versuchen Sie nicht, Vektoren zu migrieren. Unterschiedliche Modelle erzeugen inkompatible Vektorräume. Führen Sie mit dem neuen Modell eine vollständige Neuindexierung aus.
- Migrieren Sie die Inhalte, nicht den Index. Die Vault-Dateien sind die Source of Truth. Der Index ist ein abgeleitetes Artefakt.
- Prüfen Sie nach der Migration. Führen Sie 10-20 Abfragen aus, deren Antworten Sie kennen, und prüfen Sie, ob die Ergebnisse Ihren Erwartungen entsprechen.
Änderungsprotokoll
| Datum | Änderung |
|---|---|
| 2026-07-07 | Genauigkeitskorrekturen. MCPVault wurde als eigenes Projekt klargestellt (npm @bitbonsai/mcpvault, Repo bitbonsai/mcpvault), jetzt v0.12.1, mit zwei Path-Filter-Advisories mittleren Schweregrads (GHSA-9c83-rr99-vfwj, GHSA-j99q-93c9-h869) — der frühere [^24]-Link verwies auf das falsche Repo (MarkusPfundstein/mcp-obsidian). Status von MarkusPfundstein/mcp-obsidian korrigiert: Es wird aktiv gepflegt (Commits bis zum 15. Mai 2026, darunter search_by_tag/get_frontmatter), nicht „dormant since June 2025“; getaggte Releases liefert es weiterhin nicht aus. Verifiziert anhand der GitHub Commit-Historie, GitHub Security Advisories und npm. |
| 2026-07-06 | Redaktionelle Umstrukturierung für bessere Auffindbarkeit: „Quick Start: First AI-Connected Vault“ wurde in Obsidian MCP Setup umbenannt (Anker #obsidian-mcp-setup) und um eine Zusammenfassung „Was Claude nach der Verbindung kann“ ergänzt (Suche, Lesen, Auflisten, formatierter Kontext; Read-only-Grenze, während Schreibvorgänge über Hooks abgewickelt werden), konsolidiert aus dem Abschnitt zur MCP Server-Architektur. Keine neuen Fakten; interne Links aktualisiert. |
| 2026-06-10 | Aktualisierung der Versionsangaben. Obsidian 1.13.1 Desktop erreichte den Public Channel (9. Juni 2026) — ein Einstellungen-UX- und CodeMirror-Upgrade gegenüber 1.13.0, ohne größere Änderung bei AI/Automatisierung. Verweise auf die aktuelle Version im Haupttext wurden von 1.13.0 auf 1.13.1 verschoben (öffentlich, 9. Juni 2026). |
| 2026-06-09 | Ökosystem-Aktualisierung. Die MCP Spezifikation 2026-07-28 erreichte den Release Candidate (angekündigt am 21. Mai 2026) — die größte MCP Überarbeitung seit dem Start: zustandsloser Protokollkern (entfernt den initialize-Handshake und Mcp-Session-Id), MCP Apps (serverseitig gerenderte HTML in Sandbox-iframes), Tasks wechseln vom experimentellen Kern zu einer offiziellen Erweiterung, OAuth 2.0/OIDC-Härtung und eine 12-monatige Deprecation-Lifecycle-Richtlinie (finale Spezifikation am 28. Juli 2026); die spekulative Roadmap-Formulierung „tentatively mid-2026“ in der Notiz zur MCP Spezifikationsentwicklung wurde durch den konkreten RC ersetzt. sqlite-vec v0.1.10-alpha (31. März bis 18. Mai 2026) ergänzt Approximate-Nearest-Neighbor-Indextypen (rescore, experimentelles ivf, festplattenbasiertes DiskANN) über Brute-Force-KNN hinaus — als am Horizont/experimentell markiert, da die 0.1.10-Linie weiterhin ein Pre-Release ist. Obsidian 1.13.0 Desktop (Early Access, 28. Mai 2026) wurde in den Textverweisen als aktuelle Version angehoben; es handelt sich um ein UX-/Sicherheits-/Dev-Tooling-Release ohne neue AI-/Automatisierungsfunktionen. |
| 2026-06-08 | Wartungsprüfung. Model2Vec v0.8.2 (29. Mai 2026) veröffentlicht: ein Wartungsrelease mit einer Frozen-Weights-Option für Training sowie Korrekturen für Multiword-Tokens, einem Trainings-Refactor und Fixes für die Behandlung nicht quantisierter Gewichte; Fußnote aktualisiert. Nichts Weiteres ist neuer als die vorhandene Baseline: Die neueste Obsidian-Version bleibt 1.13.0 (28. Mai, unten bereits dokumentiert), sqlite-vec Stable bleibt v0.1.9 (v0.1.10 weiterhin Alpha), und die MCP Spezifikation bleibt die Revision vom 25. November 2025. Keine Textänderung über die Model2Vec-Versionsnotiz hinaus. |
| 2026-05-28 | Obsidian 1.13.0 Desktop + 1.13.0 Mobile (Catalyst Early Access) veröffentlicht. Desktop: überarbeitetes Einstellungsfenster, das sich in einem eigenen Fenster mit integrierter Suche und Tastaturnavigation öffnet; Obsidian URIs zeigen jetzt einen Bestätigungsdialog an, bevor Aktionen ausgelöst werden; neue Warnung vor dem Laden von HTML Ressourcen von Netzlaufwerken; Suche zur Bookmarks-Ansicht hinzugefügt; verbesserte Bildbehandlung im Editor; Verbesserungen an File Explorer / Properties / Sync; zahlreiche Entwickler-API und Fehlerkorrekturen. Mobile: neues iOS Share Sheet mit konfigurierbaren Zielorten; Neuanordnung von Tabs über den Tab-Umschalter; Press-and-Hold-Gesten auf Tablets zum Ändern der Größe von Splits und angehefteten Seitenleisten; Bases erhält einen Menüpunkt zum Ändern der Spaltenbreite in Tabellenansichten; iOS- und Suchfehlerkorrekturen. Auswirkungen auf AI-Workflows: Der Bestätigungsdialog für Obsidian URIs fügt URI-gesteuerten MCP/Agent-Integrationen eine bewusste Schutzschwelle hinzu; das Menü zur Spaltenbreitenänderung in Bases macht Bases als Vault-Frontindex, den Agenten abfragen, nutzbarer; das konfigurierbare Ziel im iOS Share Sheet macht den iPhone-Capture-Pfad (bereits als primärer Intake dokumentiert) schneller für Claude/Codex-Pipelines verdrahtbar. |
| 2026-05-06 | Quellenverifizierte Aktualität aufgefrischt: Smart Connections v4.5.0 verschob Footer-Verbindungen in Core; stabile Releases sqlite-vec v0.1.8/v0.1.9 aktualisierten Packaging und DELETE-Verhalten; Model2Vec v0.8.x aktualisierte Tokenizer-/Persistenz-Interna und Benchmark-Tabellen; Obsidian CLI Chronologie von „1.12.7 introduced CLI“ zu „1.12.0 introduced CLI, 1.12.7 improved installation/runtime packaging“ korrigiert. |
| 2026-04-27 | Web Clipper April-Zyklus: 1.4.0 (interaktive YouTube-Transkript-UI + Open in Reader als Standard), 1.5.0 (Highlights-Viewer), 1.6.0 (Highlighter-UX-Überarbeitung + Defuddle 0.18 Source-Extractors für LinkedIn/Threads/Bluesky/Discourse/Medium), 1.6.1 + 1.6.2 (Reader- und Safari-Fixes). Web Clipper als primären browserseitigen Intake-Pfad für AI-Workflows neu gerahmt, statt nur als beiläufige Bookmark-Erwähnung. Keine Obsidian Desktop-, Sync- oder Bases-Releases im Zeitraum. |
| 2026-04-16 | Smart Connections v4.3.0 (Graph View, konfigurierbares Dock, Block-Embedding-Wiederherstellung, Substrate Cross-Plugin-Env). AI-native Plugin-Welle vom April 2026 dokumentiert (Cortex, VaultSearch, LLM Wiki, Drift, EngramQuest, Hybrid Search MCP). MarkusPfundstein/mcp-obsidian als Maintenance-Mode markiert (letzter Commit Juni 2025). Dataview ruht; Bases ist der Nachfolger für neue Arbeit. Obsidian CLI 1.12.7 bleibt die bevorzugte Bridge für AI-Assistenten. |
| 2026-04-01 | Obsidian CLI Abschnitt hinzugefügt (v1.12-Befehle für AI-Workflows). Agent-Plugin-Abschnitt hinzugefügt (Claudian, Agent Client). Bases Core-Plugin für Vault-Organisation dokumentiert. Plugin-Anzahl auf 2.500+ aktualisiert. iOS Share Extension als Intake-Quelle hinzugefügt. Kompatibilitätsmatrix um eingebettete Agent-Plugins erweitert. |
| 2026-03-30 | MCPVault v0.11.0: Tool list_all_tags, Unterstützung für .base/.canvas, umbenannt in @bitbonsai/mcpvault. Obsidian Desktop v1.12.7 bündelt CLI Binary für schnellere Terminal-Interaktionen. |
| 2026-03-23 | sqlite-vec v0.1.7 Stable dokumentiert: DELETE-Unterstützung für vec0-Tabellen, KNN-Distanzbedingungen für Pagination. DiskANN Approximate-Nearest-Neighbor-Index für kommendes Release angekündigt. |
| 2026-03-07 | potion-multilingual-128M (101 Sprachen, Mai 2025) zum Vergleich der Embedding-Modelle hinzugefügt. sqlite-vec bei v0.1.7-alpha.10 (CI/CD-Fixes, keine Funktionsänderungen). MCP Spezifikation und Retrieval-Techniken als aktuell bestätigt. |
| 2026-03-03 | Entwicklung der MCP Spezifikation aktualisiert (Nov. 2025 ausgeliefert: Streamable HTTP, .well-known, Tool-Anmerkungen). Model2Vec Fine-Tuning und BPE/Unigram-Tokenizer-Unterstützung hinzugefügt. Vergleichstabelle für Community-MCP Server hinzugefügt. Smart Connections auf v4 aktualisiert. |
| 2026-03-02 | potion-base-32M und potion-retrieval-32M zum Modellvergleich hinzugefügt. Abschnitt zu Quantisierung/Dimensionalitätsreduktion hinzugefügt. Notiz zur Entwicklung der MCP Spezifikation hinzugefügt. |
| 2026-03-01 | Erstveröffentlichung |
Referenzen
-
Internet Vin, „22 commands I use with Obsidian and Claude Code“, März 2026, x.com/internetvin/status/2026461256677245131. ↩
-
Nicopreme, „Visual Explainer“-Agent-Skill mit Slash-Befehlen, x.com/nicopreme/status/2023495040258261460. ↩
-
Cormack, G.V., Clarke, C.L.A. und Buettcher, S. Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods. SIGIR, 2009. Führt RRF mit k=60 als parameterfreie Methode zum Kombinieren gerankter Listen ein. ↩↩↩
-
OpenAI Embeddings Pricing. text-embedding-3-small: 0,02 $ pro 1 Million Tokens. Geschätzte Vault-Kosten pro vollständigem Reindex: ca. 0,30 $. ↩
-
van Dongen, T. et al. Model2Vec: Turn any Sentence Transformer into a Small Fast Model. arXiv, 2025. Beschreibt den Distillationsansatz, der statische Embeddings aus Sentence Transformers erzeugt. ↩
-
potion-base-8M Model Card und Model2Vec results. Aktuell veröffentlichte Tabellen weisen potion-base-8M mit 51,32 Avg (All) / 51,08 Avg (MTEB) aus, verglichen mit all-MiniLM-L6-v2 mit 55,80 Avg (All) / 55,93 Avg (MTEB), also etwa 92 % Erhalt beim All-Task-Score. ↩
-
Model Context Protocol Specification. Der MCP-Standard zum Verbinden von AI-Tools mit Datenquellen. ↩
-
Model2Vec Potion Models, potion-base-32M und potion-retrieval-32M. Aktuelle Model Cards weisen potion-base-32M mit 52,83 Avg (All) und potion-retrieval-32M mit 35,06 in der Retrieval-Tabelle aus. ↩↩↩
-
Update on the Next MCP Protocol Release. Das Release vom November 2025 lieferte Streamable HTTP Transport, .well-known-URL-Discovery, strukturierte Tool-Annotationen und SDK-Tier-Standardisierung. Das nächste Release ist vorläufig für Mitte 2026 geplant, mit asynchronen Operationen, domainspezifischen Erweiterungen und Agent-to-Agent-Kommunikation. ↩
-
Model2Vec Releases. v0.4.0 (Feb. 2025): Unterstützung für Training/Fine-Tuning. v0.5.0 (Apr. 2025): Backend-Neuschreibung, Quantisierung, Dimensionsreduktion. v0.7.0 (Okt. 2025): Vokabularquantisierung, BPE/Unigram-Tokenizer-Unterstützung. v0.8.0/v0.8.1 (März 2026): Tokenizer- und Persistenz-Refactorings, Python-3.9-Deprecation, MTEB V2-Ergebnisaktualisierungen und Windows-Pfadkompatibilität. v0.8.2 (29. Mai 2026): ein Wartungsrelease mit einer Frozen-Weights-Option für Training sowie Fixes für Multiword-Tokens, einem Trainings-Refactoring und Korrekturen bei der Behandlung nicht quantisierter Gewichte. ↩↩
-
Smart Connections for Obsidian. Smart Connections v4: lokal zuerst arbeitende AI-Embeddings, semantische Suche funktioniert nach der ersten Indexierung offline. ↩
-
potion-multilingual-128M. Minish Lab, Mai 2025. Statisches Embedding-Modell für 101 Sprachen, die leistungsstärksten multilingualen statischen Embeddings. Dieselbe reine numpy-Abhängigkeit wie bei anderen potion-Modellen. ↩
-
MCPVault —
bitbonsai/mcpvault. npm@bitbonsai/mcpvault, neueste Version v0.12.1 (veröffentlicht am 23.06.2026); ein eigenständiges Projekt nebenMarkusPfundstein/mcp-obsidian, keine Umbenennung davon. v0.11.0 (März 2026) ergänzte das Toollist_all_tagszum Scannen von frontmatter und Hashtags mit Zählwerten, verbesserte den Umgang mit Ordnern mit Punkten und fügte Unterstützung für.base-/.canvas-Dateien hinzu. Zwei GitHub Security Advisories mit mittlerem Schweregrad betreffen den Pfadfilter: GHSA-9c83-rr99-vfwj (eingeschränkte Verzeichnisse wurden nur am Vault-Root verweigert, nicht verschachtelt) und GHSA-j99q-93c9-h869 (Deny-List-Bypass über Groß-/Kleinschreibung und Äquivalenz von abschließendem Punkt/Leerzeichen) — nutzen Sie v0.12.1 oder neuer. ↩ -
sqlite-vec v0.1.7 Release. 17. März 2026. Stabiles Release: DELETE-Unterstützung für virtuelle vec0-Tabellen, KNN-Distanzbeschränkungen für Pagination, Verbesserungen beim Fuzz Testing. DiskANN-Indexierung für approximative nächste Nachbarn wurde für ein künftiges Release angekündigt. ↩↩↩
-
Introduction to Bases. Obsidian-Core-Plugin, eingeführt in v1.9.10. Datenbankähnliche Ansichten (Tabellen, Galerien, Kalender, Kanban-Boards) über Vault-Dateien, wobei frontmatter-Eigenschaften als Felder verwendet werden. Dateien werden im
.base-Format gespeichert. ↩ -
Obsidian Desktop v1.12.0 Changelog und Obsidian Desktop v1.12.7 Changelog. v1.12.0 führte CLI für terminalbasierte Vault-Automatisierung ein; v1.12.7 verbesserte Installations-/Runtime-Packaging mit einem Standalone-Binary, TUI und Socket-Dateiverhalten. Siehe auch die CLI documentation. ↩↩
-
Claudian. Obsidian-Plugin, das Claude Code als AI-Kollaborator in den Vault einbettet. Bietet Sidebar-Chat, kontextbewusste Prompts, Vision-Unterstützung, Slash Commands und Berechtigungsmodi. ↩
-
Agent Client. Obsidian-Plugin, das eine einheitliche Oberfläche für Claude Code, Codex CLI und Gemini CLI über das Agent Client Protocol (ACP) bereitstellt. Unterstützt Notiz-Erwähnungen, Shell-Ausführung und Aktionsfreigabe. ↩
-
Obsidian iOS Changelog. Updates Anfang 2026 umfassen eine Share Extension zum direkten Speichern von Inhalten aus anderen Apps im Vault, Fixes für Daily Note- und Bookmark-Widgets sowie Verbesserungen beim Aktualisieren des View Note-Widgets. ↩
-
MarkusPfundstein/mcp-obsidian. Aktiv gepflegt — Commits bis zum 15. Mai 2026, mit neuerer Arbeit an zusätzlichen Tools, darunter
search_by_tagundget_frontmatter, plus erweiterter Testabdeckung (verifiziert anhand der Commit-Historie des Repositorys undtools.py). Es werden weiterhin keine getaggten Releases ausgeliefert, daher aus einem gepinnten Commit installieren. Basiert auf Local-REST-API; Forendiskussionen (April 2026) berichten, dass die Community bei neuen Setups zur First-Class-Obsidian-CLI-Bridge (1.12.x) migriert, mcp-obsidian bleibt für bestehende REST-API-Deployments aber eine funktionierende, aktualisierte Option. ↩↩ -
Smart Connections v4.5.0 Release. 5. Mai 2026. Footer-Verbindungen wurden zu einer Core-Funktion; neuere v4-Releases enthalten außerdem Graph-Ansichten für Verbindungslisten, konfigurierbare Positionen des Verbindungspanels, verbesserte Wiederherstellung von Block-Embeddings, Substrate-Cross-Plugin-State, Transformer-Fallback-Fixes und weniger doppelte Verbindungsberechnungen. ↩
-
obsidianmd/obsidian-clipper releases — Primärquelle für das Web Clipper-Version-Feature-Mapping. April-2026-Zyklus: 1.4.0 (9. Apr., YouTube-Transkript-UI + Open in Reader als Standard), 1.5.0 (15. Apr., Highlights-Viewer + Reader-Fade-in), 1.5.1 (15. Apr., webpack-Kompilierungsfix), 1.6.0 (21. Apr., Highlighter-UX + Defuddle 0.18 mit LinkedIn/Threads/Bluesky/Discourse/Medium-Extraktoren), 1.6.1 (22. Apr., Reader-Outline-Fixes + Highlight-Suche), 1.6.2 (23. Apr., Safari-Clipboard-Fix im Embedded Mode). Ebenfalls gelistet im Mozilla Add-ons store und im Chrome Web Store. ↩
-
sqlite-vec v0.1.8, sqlite-vec v0.1.9, sqlite-vec v0.1.10-alpha.3 und sqlite-vec v0.1.10-alpha.4. v0.1.8 korrigierte das npm-Packaging; v0.1.9 behob einen DELETE-Bug bei Metadata-Textspalten mit mehr als 12 Zeichen; v0.1.10-alpha.3 ergänzt korrekte Unterstützung für
INSERT OR REPLACE INTO; v0.1.10-alpha.4 (18. Mai 2026) behebt, dassALTER TABLE RENAMEbeivec0-Tabellen mit den neuen ivf/diskann-Funktionen fehlschlug, sowie einen Cleanup-Bug bei gecachten Statements in DiskANN. Die 0.1.10-Linie ist weiterhin ein Prerelease. ↩↩↩↩ -
MCP 2026-07-28 Specification Release Candidate. Angekündigt am 21. Mai 2026; die finale Spezifikation erscheint am 28. Juli 2026. Größte MCP-Revision seit dem Start: zustandsloser Protokollkern (entfernt den
initialize-Handshake und denMcp-Session-Id-Header), MCP Apps (servergerenderte HTML in sandboxed Client-iframes), Tasks wechseln vom experimentellen Core in eine offizielle Extension (tasks/get,tasks/update,tasks/cancel), Härtung von OAuth 2.0 / OIDC-Autorisierung und eine 12-monatige Feature-Deprecation-Lifecycle-Policy. ↩ -
Obsidian Desktop v1.13.0 Changelog. Early Access, 28. Mai 2026. UX-/Security-/Developer-Tooling-Release: überarbeitetes Einstellungen-Panel, das in einem eigenen Fenster mit Suche und Tastaturnavigation geöffnet wird, Bestätigungsdialoge vor dem Ausführen von Obsidian-URIs, ein neues Einstellungen-API für Plugin-Entwickler und ein CLI-Fix für flatpak-Installationen. Keine größeren neuen AI-/Automatisierungsfunktionen über die 1.12.x-CLI-Oberfläche hinaus. ↩↩
-
Obsidian Changelog. Obsidian 1.13.1 Desktop erreichte am 9. Juni 2026 den Public Channel — eine Verfeinerung der Einstellungen-UX und ein CodeMirror-Upgrade gegenüber 1.13.0, ohne neue AI-/Automatisierungsfunktion. ↩↩