obsidian:~/vault$ search --hybrid obsidian

Obsidian MCP + wyszukiwanie hybrydowe: dokumentacja referencyjna 2026

# Do podstaw aplikacji należy używać oficjalnej dokumentacji Obsidian; do MCP, wyszukiwania hybrydowego i indeksowania vaultu AI Blake’a z 16 894 plikami — jego materiałów referencyjnych.

words: 13400 read_time: 51m updated: 2026-05-29 10:01
$ retriever search --hybrid obsidian

Obsidian nie jest aplikacją do notatek. To lokalny w pierwszej kolejności, tekstowy korpus markdown o strukturze grafu, który po dodaniu infrastruktury wyszukiwania staje się rezerwuarem kontekstu dla AI. 16 894 pliki. 49 746 fragmentów. Zapytania w 23 ms. Zero wywołań API. Jeden plik SQLite o rozmiarze 83 MB. Ten przewodnik omawia cały system: od architektury skarbca, przez hybrid retrieval, po integrację z MCP i workflow operacyjne.


Najważniejsze wnioski

Inżynieria kontekstu, nie robienie notatek. Wartość vaulta Obsidian dla AI nie tkwi w samych notatkach, lecz w warstwie wyszukiwania, która umożliwia ich odpytywanie. Vault z 16 000 plików bez wyszukiwania jest bazą danych tylko do zapisu. Vault z 200 plikami, wyszukiwaniem hybrydowym (hybrid retrieval) i integracją MCP jest bazą wiedzy AI. Infrastrukturą wyszukiwania jest produkt. Notatki są surowcem.

Wyszukiwanie hybrydowe przewyższa wyszukiwanie wyłącznie po słowach kluczowych lub wyłącznie semantyczne. BM25 wychwytuje dokładne identyfikatory i nazwy funkcji. Wyszukiwanie wektorowe wychwytuje synonimy i dopasowania koncepcyjne mimo różnej terminologii. Reciprocal Rank Fusion (RRF) łączy oba podejścia bez konieczności kalibracji wyników. Żadna z tych metod sama nie obejmuje obu trybów awarii. Badania nad rankingiem fragmentów MS MARCO potwierdzają ten wzorzec: wyszukiwanie hybrydowe konsekwentnie przewyższa każdą z tych metod stosowaną osobno.3 Dogłębna analiza hybrid retriever omawia matematykę RRF, przepracowane przykłady z rzeczywistymi liczbami, analizę trybów awarii oraz interaktywny kalkulator fuzji.

MCP daje narzędziom AI bezpośredni dostęp do vaulta. Serwery Model Context Protocol (MCP) udostępniają retriever jako narzędzie, które Claude Code, Codex CLI, Cursor i inne narzędzia AI mogą wywoływać bezpośrednio. Agent odpytuje vault, otrzymuje uszeregowane wyniki z atrybucją źródeł i korzysta z kontekstu bez ładowania całych plików. Serwer MCP jest cienką nakładką na silnik wyszukiwania.

Local-first oznacza zerowe koszty API i pełną prywatność. Cały stos działa na jednej maszynie: SQLite do przechowywania danych, Model2Vec do embeddingów (embeddings), FTS5 do wyszukiwania po słowach kluczowych, sqlite-vec do wektorowego KNN. Bez usług chmurowych, bez wywołań API, bez zależności od sieci. Osobiste notatki nigdy nie opuszczają maszyny. Pełne ponowne osadzenie 49 746 chunków kosztowałoby około 0,30 USD według cen OpenAI API, ale rzeczywistymi kosztami są opóźnienia, ekspozycja prywatności i zależność od sieci w systemie, który powinien działać offline.4

Indeksowanie przyrostowe utrzymuje aktualność systemu w mniej niż 10 sekund. Porównanie czasu modyfikacji pliku wykrywa zmiany. Tylko zmodyfikowane pliki są ponownie dzielone na chunki (chunking) i ponownie osadzane. Pełne ponowne indeksowanie zajmuje około czterech minut na sprzęcie Apple z serii M. Aktualizacje przyrostowe po typowych zmianach z danego dnia uruchamiają się w mniej niż dziesięć sekund. System pozostaje aktualny bez ręcznej interwencji.

Architektura skaluje się od 200 do ponad 20 000 notatek. Ten sam trójwarstwowy projekt (pobieranie, wyszukiwanie, integracja) działa przy dowolnym rozmiarze vaulta. Przy małym vaulcie można zacząć od wyszukiwania wyłącznie BM25. Wyszukiwanie wektorowe warto dodać, gdy kolizje słów kluczowych staną się problemem. Fuzję RRF warto dodać wtedy, gdy potrzebne są zarówno dopasowania dokładne, jak i semantyczne. Każda warstwa jest niezależnie użyteczna i niezależnie usuwalna.


Jak korzystać z tego przewodnika

Ten przewodnik obejmuje kompletny system. Punkt startowy zależy od obecnej sytuacji:

Sytuacja Proszę zacząć tutaj Następnie warto przejrzeć
Początek pracy z Obsidian + AI Dlaczego Obsidian jako infrastruktura AI, Szybki start Architektura vaulta, Architektura serwera MCP
Istniejący vault, potrzebny dostęp AI Architektura serwera MCP, Integracja Claude Code Modele embeddingów, Wyszukiwanie pełnotekstowe
Budowa systemu wyszukiwania Kompletny pipeline wyszukiwania, Reciprocal Rank Fusion Dostrajanie wydajności, Rozwiązywanie problemów
Kontekst zespołowy lub firmowy Ramy decyzyjne, Wzorce grafu wiedzy Przepisy dla workflow deweloperskiego, Przewodnik migracji

Sekcje oznaczone jako Contract zawierają szczegóły implementacyjne, bloki konfiguracji i tryby awarii. Sekcje oznaczone jako Narrative koncentrują się na koncepcjach, decyzjach architektonicznych i uzasadnieniu wyborów projektowych. Sekcje oznaczone jako Recipe podają workflow krok po kroku.


Dlaczego Obsidian jako infrastruktura AI

Teza tego przewodnika brzmi: vaulty Obsidian są najlepszym podłożem dla osobistych baz wiedzy AI, ponieważ są local-first, plaintext, mają strukturę grafu, a użytkownik kontroluje każdą warstwę stosu.

Co Obsidian daje AI, czego nie dają alternatywy

Pliki markdown plaintext. Każda notatka jest plikiem .md w systemie plików. Bez własnościowego formatu, bez eksportu bazy danych, bez wymaganego API do odczytania treści. Każde narzędzie odczytujące pliki może odczytać vault. grep, ripgrep, pathlib z Python, SQLite FTS5 — wszystkie działają bezpośrednio na plikach źródłowych. Przy budowie systemu wyszukiwania indeksowane są pliki, a nie odpowiedzi API. Indeks jest zawsze spójny ze źródłem, ponieważ źródłem jest system plików.

Architektura local-first. Vault znajduje się na maszynie użytkownika. Bez serwera, bez zależności od synchronizacji w chmurze, bez limitów szybkości API, bez warunków korzystania z usługi określających, jak można przetwarzać własne treści. Notatki można osadzać, indeksować, dzielić na chunki i przeszukiwać bez żadnej usługi zewnętrznej. Ma to znaczenie dla infrastruktury AI, ponieważ pipeline wyszukiwania działa tak szybko, jak pozwala dysk, a nie tak szybko, jak odpowiada endpoint API. Ma to również znaczenie dla prywatności: osobiste notatki zawierające dane uwierzytelniające, dane zdrowotne, informacje finansowe i prywatne refleksje nigdy nie opuszczają maszyny.

Struktura grafu dzięki wiki-link. Składnia [[wiki-link]] w Obsidian tworzy skierowany graf pomiędzy notatkami. Notatka o implementacji OAuth linkuje do notatek o rotacji tokenów, zarządzaniu sesją i bezpieczeństwie API. Struktura grafu koduje relacje między pojęciami dobrane przez człowieka. Embeddingi wektorowe wychwytują podobieństwo semantyczne, ale wiki-link przechwytują intencjonalne połączenia utworzone przez autora podczas myślenia o temacie. Graf jest sygnałem, którego embeddingi nie potrafią odtworzyć.

Ekosystem pluginów. Obsidian ma ponad 2 500 pluginów społecznościowych (stan na marzec 2026, wzrost z ponad 1 800 w połowie 2025 roku). Dataview odpytuje vault jak bazę danych. Templater generuje notatki z szablonów z logiką JavaScript. Integracja Git synchronizuje vault z repozytorium. Linter wymusza spójność formatowania. Plugin rdzeniowy Bases (wprowadzony w v1.9.10) dodaje widoki podobne do baz danych — tabele, galerie, kalendarze i tablice kanban — nad plikami vaulta, używając właściwości frontmatter jako pól i zapisując je jako pliki .base.15 Te pluginy dodają strukturę do vaulta bez zmiany bazowego formatu plaintext. System wyszukiwania indeksuje wynik działania tych pluginów, a nie same pluginy.

Ponad 5 milionów użytkowników. Obsidian ma dużą, aktywną społeczność tworzącą szablony, workflow, pluginy i dokumentację. Gdy pojawia się problem z organizacją vaulta lub konfiguracją pluginu, ktoś prawdopodobnie już udokumentował rozwiązanie. Społeczność tworzy także narzędzia wokół Obsidian: serwery MCP, skrypty indeksujące, pipeline publikacji i wrappery API.

Czego nie daje sam system plików

Katalog plików markdown ma zaletę plaintext, ale brakuje mu trzech rzeczy, które dodaje Obsidian:

  1. Linki dwukierunkowe. Obsidian automatycznie śledzi backlinki. Gdy link prowadzi z Notatki A do Notatki B, Notatka B pokazuje, że Notatka A się do niej odwołuje. Panel grafu wizualizuje klastry połączeń. Ta dwukierunkowa świadomość jest metadanymi, których surowy system plików nie zapewnia.

  2. Podgląd na żywo z renderowaniem pluginów. Zapytania Dataview, diagramy Mermaid i bloki callout renderują się w czasie rzeczywistym. Doświadczenie pisania jest bogatsze niż w edytorze tekstu, a format przechowywania pozostaje plaintext. Pisanie i organizacja odbywają się w rozbudowanym środowisku; system wyszukiwania indeksuje surowy markdown.

  3. Infrastruktura społecznościowa. Wyszukiwanie pluginów, marketplace motywów, usługa synchronizacji (opcjonalna), usługa publikacji (opcjonalna) i ekosystem dokumentacji. Każdą pojedynczą funkcję można odtworzyć samodzielnymi narzędziami, ale Obsidian łączy je w spójny workflow.

Czego Obsidian NIE robi (i co należy zbudować)

Obsidian nie zawiera infrastruktury wyszukiwania. Ma podstawowe wyszukiwanie (pełnotekstowe, po nazwie pliku, po tagu), ale nie ma pipeline’u embeddingów, wyszukiwania wektorowego, rankingu fuzyjnego, serwera MCP, filtrowania danych uwierzytelniających, strategii chunkingu ani hooków integracyjnych dla zewnętrznych narzędzi AI. Ten przewodnik opisuje infrastrukturę budowaną na Obsidian. Vault jest podłożem. Pipeline wyszukiwania, serwer MCP i hooki integracyjne są infrastrukturą.

Opisana tutaj architektura jest markdown-first, a nie wyłącznie Obsidian. Jeśli używane są Logseq, Foam, Dendron albo zwykły katalog plików markdown, pipeline wyszukiwania działa identycznie. Chunker odczytuje pliki .md. Embedder przetwarza ciągi tekstowe. Indexer zapisuje dane do SQLite. Żaden z tych komponentów nie zależy od funkcji specyficznych dla Obsidian. Wkładem Obsidian jest środowisko pisania i organizacji, które wytwarza pliki markdown indeksowane przez retriever.


Szybki start: pierwszy magazyn połączony z AI

Ta sekcja pozwala w 5 minut połączyć magazyn z narzędziem AI. Należy zainstalować Obsidian, utworzyć magazyn, zainstalować serwer MCP i uruchomić pierwsze zapytanie. Szybki start wykorzystuje społecznościowy serwer MCP, aby od razu uzyskać wyniki. Późniejsze sekcje omawiają budowanie niestandardowego pipeline’u wyszukiwania do zastosowań produkcyjnych.

Wymagania wstępne

  • macOS, Linux lub Windows
  • Node.js 18+ (dla serwera MCP)
  • Obsidian 1.12+ (dla integracji CLI; wcześniejsze wersje działają w konfiguracjach wyłącznie z MCP)
  • Claude Code, Codex CLI lub Cursor

Krok 1: utworzenie magazynu

Należy pobrać Obsidian z obsidian.md i utworzyć nowy magazyn. Proszę wybrać lokalizację, którą łatwo będzie zapamiętać — serwer MCP wymaga ścieżki bezwzględnej.

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

Warto dodać kilka notatek, aby mechanizm wyszukiwania miał z czym pracować. Nawet 10-20 notatek wystarczy, aby zobaczyć wyniki. Każda notatka powinna być plikiem .md z sensownym tytułem i co najmniej jednym akapitem treści.

Krok 2: instalacja serwera MCP

Kilka społecznościowych serwerów MCP zapewnia natychmiastowy dostęp do magazynu. Ekosystem znacząco rozwinął się w latach 2025-2026. Do ważnych niedawnych aktualizacji należy MCPVault v0.11.0 (marzec 2026), który dodał list_all_tags do skanowania frontmatter i hashtagów wraz z licznikami, ulepszył obsługę folderów z kropkami w nazwach oraz dodał wsparcie dla plików .base i .canvas.13 Pakiet został też przemianowany w npm na @bitbonsai/mcpvault.

Zmiana z kwietnia 2026 — Obsidian CLI jako preferowany most: Obsidian 1.12.0 wprowadził pełnoprawny CLI, a publiczny instalator 1.12.7 (23 marca 2026) zawierał samodzielny plik binarny, TUI oraz ulepszenia pliku socket, które ułatwiły instalację i uruchamianie workflowów terminalowych.16 Narzędzia społecznościowe aktywnie migrują z pluginu Local REST API (który zasilał mcp-obsidian) do integracji opartej na CLI, ponieważ jest szybsza i stabilniejsza. Repozytorium MarkusPfundstein/mcp-obsidian nie miało commitów od czerwca 2025 i nigdy nie miało oznaczonych wydań — należy traktować je jako projekt w trybie utrzymania i preferować serwery oparte na CLI albo nowsze alternatywy społecznościowe wymienione poniżej.20 Zalecaną konfigurację opisuje sekcja „Obsidian CLI dla workflowów AI” w dalszej części tego przewodnika.

Serwer Autor Transport Wymaga pluginu Kluczowa funkcja
obsidian-mcp-server StevenStavrakis STDIO Nie Lekki, oparty na plikach
mcp-obsidian MarkusPfundstein STDIO Local REST API Pełny CRUD magazynu przez REST — tryb utrzymania, brak commitów od czerwca 202520
obsidian-mcp-tools jacksteamdev STDIO Tak (plugin) Wyszukiwanie semantyczne + Templater
obsidian-claude-code-mcp iansinnott WebSocket Tak (plugin) Automatyczne wykrywanie dla Claude Code
obsidian-mcp-server cyanheads STDIO Local REST API Tagi, zarządzanie frontmatter
Hybrid Search MCP społeczność STDIO Nie Serwer MCP z BM25 + wyszukiwaniem semantycznym + CLI. Nowy i aktywnie utrzymywany według stanu na kwiecień 2026.

W szybkim starcie najprostszą opcją jest serwer oparty na plikach, który odczytuje pliki .md bezpośrednio:

npm install -g obsidian-mcp-server

Krok 3: konfiguracja narzędzia AI

Claude Code — należy dodać do ~/.claude/settings.json:

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

Codex CLI — należy dodać do .codex/config.toml:

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

Cursor — należy dodać do .cursor/mcp.json:

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

Krok 4: uruchomienie pierwszego zapytania

Należy otworzyć narzędzie AI i zadać pytanie, na które mogą odpowiedzieć notatki z magazynu:

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

Narzędzie AI wywołuje serwer MCP, który przeszukuje magazyn i zwraca pasujące treści. Powinny pojawić się wyniki ze ścieżkami plików i odpowiednimi fragmentami.

Co właśnie zostało zbudowane

Lokalna baza wiedzy została połączona z narzędziem AI przez standardowy protokół. Serwer MCP odczytuje pliki magazynu, wykonuje podstawowe wyszukiwanie i zwraca wyniki. To minimalna wersja działającego rozwiązania.

Czego ten szybki start NIE zapewnia: - Hybrid retrieval (BM25 + wyszukiwanie wektorowe + RRF fusion) - Wyszukiwania semantycznego opartego na embeddings - Filtrowania poświadczeń - Indeksowania przyrostowego - Automatycznego wstrzykiwania kontekstu opartego na hookach

Pozostała część tego przewodnika omawia budowanie każdej z tych możliwości. Szybki start potwierdza koncepcję. Pełny pipeline zapewnia wyszukiwanie jakości produkcyjnej.


Obsidian CLI dla workflowów AI

Obsidian 1.12 (luty 2026) wprowadził wbudowany interfejs wiersza poleceń, który otwiera nową powierzchnię integracji dla workflowów AI.16 CLI działa jak zdalne sterowanie GUI Obsidian — Obsidian musi być uruchomiony (albo uruchomi się automatycznie przy pierwszym poleceniu). Należy włączyć go w Settings > General > Command line interface.

Dlaczego CLI ma znaczenie dla infrastruktury AI

CLI zapewnia programistyczny dostęp do natywnych operacji Obsidian, które wcześniej wymagały GUI lub pluginów API. Dla workflowów AI kluczowe są następujące możliwości:

  • Wyszukiwanie ze skryptów i hooków. obsidian search "query" oraz obsidian search:context "query" uruchamiają wyszukiwanie w magazynie z dowolnego skryptu shell, hooka lub pipeline’u automatyzacji. Wariant search:context zwraca pasujące wiersze wraz z otaczającym kontekstem, co przydaje się przy przekazywaniu wyników do promptów AI.
  • Automatyzacja notatek dziennych. obsidian daily otwiera lub tworzy dzisiejszą notatkę dzienną. W połączeniu ze skryptami shell umożliwia to zautomatyzowane workflowy codziennych briefingów — hook może dopisywać do notatki dziennej podsumowania wygenerowane przez AI.
  • Tworzenie notatek na podstawie szablonów. obsidian template list i obsidian template create generują notatki z szablonów Templater lub szablonów podstawowych, dzięki czemu agenci AI mogą tworzyć uporządkowane wpisy w magazynie bez bezpośredniego zapisywania plików markdown.
  • Zarządzanie właściwościami. obsidian property set i obsidian property get odczytują i zapisują właściwości frontmatter, umożliwiając aktualizacje metadanych ze skryptów bez parsowania YAML.
  • Kontrola pluginów. obsidian plugin enable/disable/list zarządza pluginami programistycznie, co jest przydatne przy przełączaniu pluginów indeksujących podczas operacji wsadowych.
  • Zarządzanie zadaniami. obsidian task list/add/complete zapewnia uporządkowany dostęp do zadań, przydatny dla agentów AI zarządzających elementami pracy w magazynie.

CLI vs MCP w dostępie AI

Serwery CLI i MCP pełnią różne role i wzajemnie się uzupełniają, zamiast konkurować:

Aspekt Obsidian CLI Serwer MCP
Wywołujący Skrypty shell, hooki, zadania cron Agenci AI (Claude Code, Codex, Cursor)
Protokół Proces POSIX (stdin/stdout/stderr) MCP (JSON-RPC przez STDIO lub HTTP)
Mocna strona Natywne operacje Obsidian (szablony, pluginy, właściwości) Niestandardowe wyszukiwanie (embeddings, BM25, RRF fusion)
Ograniczenie Brak wyszukiwania wektorowego, brak pipeline’u embeddings Brak dostępu do wewnętrznych operacji Obsidian
Najlepsze zastosowanie Skrypty automatyzacji, pipeline’y przyjmowania treści, działania hooków Zapytania agentów AI w czasie rzeczywistym podczas sesji

Rekomendacja: Warto używać CLI do automatyzacji przyjmowania treści (tworzenia notatek, zarządzania właściwościami, uruchamiania natywnego wyszukiwania Obsidian), a MCP do wyszukiwania (hybrid search z embeddings). Hook PreToolUse może wywołać obsidian search:context jako szybką kontrolę wstępną przed przejściem do pełnego retrievera MCP dla wyników rankingowych.

Przykład: hook przyjmowania treści oparty na 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}"

Wtyczki agentów w Obsidian

Rosnąca kategoria wtyczek Obsidian osadza agentów AI do kodowania bezpośrednio w interfejsie skarbca (vault), stanowiąc alternatywę dla zewnętrznej konfiguracji serwera MCP. Te wtyczki uruchamiają agenta AI w pasku bocznym Obsidian, zamiast łączyć się z narzędzia zewnętrznego.

Claudian

Claudian osadza Claude Code jako współpracownika AI w skarbcu. Katalog skarbca staje się katalogiem roboczym Claude, co daje pełne możliwości agentowe: odczyt i zapis plików, wyszukiwanie, polecenia bash oraz wieloetapowe przepływy pracy.17

Kluczowe funkcje dla infrastruktury AI: - Prompty świadome kontekstu. Automatycznie dołącza aktywną notatkę, obsługuje wzmianki o plikach @notename, wykluczanie na podstawie tagów oraz zaznaczenie w edytorze jako kontekst. - Obsługa obrazu. Analiza obrazów przez przeciągnięcie i upuszczenie, wklejenie lub ścieżkę pliku — przydatna do przetwarzania zrzutów ekranu i diagramów zapisanych w skarbcu. - Polecenia slash. Tworzenie wielokrotnego użytku szablonów promptów uruchamianych przez /command, co umożliwia standaryzację operacji na skarbcu. - Tryby uprawnień. Tryby YOLO (automatyczne zatwierdzanie), Safe (zatwierdzanie każdej akcji) i Plan (tylko planowanie), z blokadą bezpieczeństwa oraz ograniczeniem do skarbca.

Agent Client

Agent Client wprowadza Claude Code, Codex CLI i Gemini CLI do ujednoliconego paska bocznego Obsidian za pośrednictwem Agent Client Protocol (ACP).18

Kluczowe funkcje: - Przełączanie między wieloma agentami. Można rozmawiać z Claude Code, Codex lub Gemini CLI z tego samego panelu, przełączając agentów w zależności od potrzeb. - Wzmianki o notatkach. Użycie @notename pozwala uwzględnić treść notatki w promptach, podobnie jak w Claudian, ale niezależnie od agenta. - Wykonywanie poleceń shell. Polecenia terminala można wykonywać bezpośrednio w czacie — skrypty build, polecenia git lub dowolne operacje terminalowe bez opuszczania rozmowy. - Zatwierdzanie działań. Szczegółowa kontrola nad odczytem plików, edycjami i wykonywaniem poleceń.

Kiedy używać wtyczek agentów, a kiedy zewnętrznego MCP

Scenariusz Wtyczka agenta Zewnętrzny MCP
Pisanie i edytowanie notatek w skarbcu z pomocą AI Lepsze — agent widzi kontekst edytora Działa, ale bez świadomości edytora
Tworzenie kodu w wielu repozytoriach Ograniczone — zakres skarbca Lepsze — zakres projektu z pełnym systemem plików
Retrieval z dużego, zindeksowanego korpusu Tylko podstawowe wyszukiwanie Pełny pipeline hybrid retrieval
Szybkie pytania i odpowiedzi dotyczące skarbca podczas robienia notatek Idealne — bez przełączania kontekstu Wymaga przełączenia do terminala

Rekomendacja: Wtyczek agentów warto używać w przepływach pracy skupionych na skarbcu: pisaniu, porządkowaniu i streszczaniu notatek. Zewnętrzne serwery MCP sprawdzają się lepiej w przepływach deweloperskich, w których agent AI potrzebuje pełnego pipeline’u retrieval oraz dostępu do baz kodu poza skarbcem. Oba podejścia mogą współistnieć — Claudian może działać wewnątrz Obsidian do pracy z notatkami, a Claude Code z MCP zewnętrznie do developmentu.


Framework decyzyjny: Obsidian kontra alternatywy

Nie każdy przypadek użycia wymaga Obsidian. Ta sekcja pokazuje, kiedy Obsidian jest właściwą podstawą, kiedy jest rozwiązaniem nadmiarowym, a kiedy lepiej sprawdzi się coś innego.

Drzewo decyzyjne

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.

Macierz porównawcza

Kryterium Obsidian Notion Apple Notes Zwykły system plików CLAUDE.md
Local-first Tak Nie (chmura) Częściowo (iCloud) Tak Tak
Plaintext Tak (markdown) Nie (bloki) Nie (format własnościowy) Tak Tak
Struktura grafu Tak (wiki-links) Częściowo (wzmianki) Nie Nie Nie
Możliwość indeksowania przez AI Bezpośredni dostęp do plików Wymagany API Wymagany eksport Bezpośredni dostęp do plików Już w kontekście
Ekosystem wtyczek Ponad 2 500 wtyczek Integracje Brak N/A N/A
Praca offline Pełna Buforowane tylko do odczytu Częściowa Pełna Pełna
Skalowanie do 10K+ notatek Tak Tak (z API) Pogarsza się Tak Nie (pojedynczy plik)
Koszt Bezpłatny (rdzeń) Od 10 USD/mies. Bezpłatny Bezpłatny Bezpłatny

Kiedy Obsidian jest rozwiązaniem nadmiarowym

  • Kontekst jednego projektu. Jeśli AI potrzebuje tylko kontekstu bieżącej bazy kodu, należy umieścić go w CLAUDE.md, AGENTS.md albo dokumentacji na poziomie projektu. Te pliki podróżują razem z repozytorium i są ładowane automatycznie.
  • Dane strukturalne. Jeśli treść ma postać tabel, rekordów lub schematów, lepiej użyć bazy danych. Notatki Obsidian są przede wszystkim prozą. Dataview potrafi odpytywać pola frontmatter, ale prawdziwa baza danych lepiej obsługuje zapytania strukturalne.
  • Tymczasowy research. Jeśli notatki zostaną usunięte po zakończeniu projektu, prostszy będzie katalog roboczy z plikami markdown. Nie warto budować infrastruktury retrieval dla treści efemerycznych.

Kiedy Obsidian jest właściwym wyborem

  • Gromadzenie wiedzy przez miesiące lub lata. Wartość rośnie wraz z korpusem. Skarbiec z 200 notatkami odpytywany codziennie przez sześć miesięcy daje więcej wartości niż skarbiec z 5 000 notatkami odpytany raz.
  • Wiele domen w jednym korpusie. Skarbiec zawierający notatki o programowaniu, architekturze, bezpieczeństwie, projektowaniu i projektach osobistych korzysta z retrieval międzydomenowego, którego projektowy CLAUDE.md nie zapewni.
  • Treści wrażliwe prywatnościowo. Local-first oznacza, że pipeline retrieval nigdy nie wysyła treści do usług zewnętrznych. Skarbiec zawiera wszystko, co zostanie w nim umieszczone, także treści, których nie przesłano by do usługi chmurowej.

Model mentalny: trzy warstwy

System ma trzy warstwy, które działają niezależnie, ale po połączeniu wzajemnie wzmacniają swoją wartość. Każda warstwa odpowiada za inny aspekt i ma inny tryb awarii.

┌─────────────────────────────────────────────────────┐
                 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 określa, co trafia do skarbca. Bez kuracji skarbiec gromadzi szum: zrzuty ekranu tweetów, skopiowane artykuły bez adnotacji, niedokończone myśli bez kontekstu. Warstwa intake odpowiada za kontrolę jakości w punkcie wejścia. Pipeline scoringowy, konwencja tagowania albo ręczny proces przeglądu — dowolny mechanizm, który zapewnia, że skarbiec zawiera treści warte późniejszego wyszukania.

Retrieval sprawia, że skarbiec można odpytywać. To silnik: dzielenie notatek na jednostki wyszukiwania przez chunking, osadzanie chunków w przestrzeni wektorowej jako embeddings, indeksowanie pod kątem wyszukiwania słów kluczowych i semantycznego oraz łączenie wyników za pomocą RRF. Warstwa retrieval przekształca katalog plików w odpytywalną bazę wiedzy. Bez tej warstwy po skarbcu można poruszać się przez ręczne przeglądanie i podstawowe wyszukiwanie, ale nie jest on programowo dostępny dla narzędzi AI.

Integration łączy warstwę retrieval z narzędziami AI. Serwer MCP udostępnia retrieval jako wywoływalne narzędzie. Hooki automatycznie wstrzykują kontekst. Skills zapisują nową wiedzę z powrotem w skarbcu. Warstwa integration jest interfejsem między bazą wiedzy a agentami AI, które z niej korzystają.

Warstwy są celowo odsprzęgnięte. Pipeline scoringowy intake nie wie nic o embeddings. Retriever nie wie nic o regułach routingu sygnałów. Serwer MCP nie wie nic o tym, jak powstały notatki. To odsprzęgnięcie oznacza, że każdą warstwę można ulepszać niezależnie. Można wymienić model embeddingów bez zmiany pipeline’u intake. Dodać nową funkcję MCP bez modyfikowania retrievera. Zmienić heurystyki scoringu sygnałów bez dotykania indeksu.


Architektura magazynu na potrzeby AI

Magazyn zoptymalizowany pod kątem wyszukiwania przez AI rządzi się innymi konwencjami niż magazyn zoptymalizowany do osobistego przeglądania. Ta sekcja omawia strukturę folderów, schemat notatek, konwencje frontmatter oraz konkretne wzorce, które poprawiają jakość wyszukiwania.

Struktura folderów

W przypadku folderów najwyższego poziomu warto używać numerowanych prefiksów, aby utworzyć przewidywalną hierarchię organizacyjną. Numery nie oznaczają priorytetu — grupują powiązane domeny i sprawiają, że strukturę łatwiej przeskanować wzrokiem.

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

Foldery, które należy indeksować: Wszystko, co zawiera prozę w markdown — projekty, obszary, zasoby, sygnały, notatki dzienne.

Foldery, które należy wykluczyć z indeksowania: Szablony (zawierają zmienne zastępcze, a nie treść), załączniki (pliki binarne), konfigurację Obsidian oraz każdy folder zawierający treści poufne, których nie należy umieszczać w indeksie wyszukiwania.

Plik .indexignore

W katalogu głównym magazynu należy utworzyć plik .indexignore, aby jawnie wykluczyć ścieżki z indeksu wyszukiwania. Składnia odpowiada .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/

Indekser odczytuje ten plik przed skanowaniem i całkowicie pomija pasujące ścieżki. Pliki w wykluczonych ścieżkach nigdy nie są dzielone na chunks, nie otrzymują embeddings i nigdy nie pojawiają się w wynikach wyszukiwania.

Schemat notatek

Każda notatka powinna mieć frontmatter YAML. Retriever używa pól frontmatter do filtrowania i wzbogacania kontekstu:

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

Pola wymagane do wyszukiwania:

  • title — Używane w wyświetlaniu wyników wyszukiwania oraz w kontekście nagłówka dla BM25
  • type — Umożliwia zapytania filtrowane według typu („pokaż tylko MOC” albo „tylko sygnały”)
  • tags — Indeksowane w kontekście nagłówka FTS5 z wagą 0,3, zapewniając dopasowania słów kluczowych nawet wtedy, gdy treść używa innej terminologii

Pola opcjonalne, ale wartościowe:

  • domain — Umożliwia zapytania ograniczone do domeny („wyszukaj tylko notatki o bezpieczeństwie”)
  • source — Atrybucja przechwyconych treści; retriever może uwzględniać źródłowe URL-e w wynikach
  • status — Pozwala wykluczać z aktywnego wyszukiwania notatki zarchiwizowane lub robocze

Konwencje chunking

Retriever dzieli treść na chunks na granicach nagłówków H2 (##). Oznacza to, że struktura notatki bezpośrednio wpływa na szczegółowość wyszukiwania:

Dobre dla wyszukiwania:

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

Trzy sekcje H2 tworzą trzy niezależnie przeszukiwalne chunks. Każdy chunk ma wystarczający kontekst, aby embedding uchwycił jego znaczenie. Zapytanie o „obsługę wygasłych tokenów” dopasowuje konkretnie trzeci chunk.

Słabe dla wyszukiwania:

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

Jedna długa sekcja bez nagłówków H2 tworzy jeden duży chunk. Embedding uśrednia wszystkie tematy w sekcji. Zapytanie o dowolny podtemat dopasowuje całą notatkę w takim samym stopniu.

Praktyczna zasada: Jeśli sekcja obejmuje więcej niż jedno pojęcie, należy podzielić ją na podsekcje H2. Chunker zajmie się resztą.

Czego nie umieszczać w notatkach

Treści, które obniżają jakość wyszukiwania:

  • Surowe kopiuj-wklej całych artykułów bez adnotacji. Retriever indeksuje słowa kluczowe z oryginalnego artykułu, rozmywając magazyn treściami, których autor nie napisał. Zamiast tego warto dodać podsumowanie, wyodrębnić kluczowe punkty albo podać link do źródłowego URL-a.
  • Zrzuty ekranu bez opisu tekstowego. Retriever indeksuje tekst markdown. Obraz bez tekstu alternatywnego lub otaczającego opisu jest niewidoczny zarówno dla BM25, jak i wyszukiwania wektorowego.
  • Ciągi danych uwierzytelniających. Klucze API, tokeny, hasła, connection strings. Nawet przy filtrowaniu danych uwierzytelniających najbezpieczniej nigdy nie wklejać sekretów do notatek. Zamiast tego należy odwoływać się do nich nazwą („token Cloudflare API w ~/.env”).
  • Automatycznie generowane treści bez kuracji. Jeśli narzędzie generuje notatkę (transkrypt spotkania, wyróżnienia z Readwise, import RSS), należy ją przejrzeć i opatrzyć adnotacjami, zanim trafi do stałego magazynu. Nieselekcjonowane automatyczne importy zwiększają objętość, nie dodając wartości możliwej do wyszukania.

Ekosystem wtyczek dla przepływów pracy AI

Wtyczki Obsidian poprawiające jakość sejfu pod kątem wyszukiwania AI dzielą się na trzy kategorie: strukturalne (wymuszają spójność), zapytaniowe (ujawniają metadane) oraz synchronizacyjne (utrzymują sejf w aktualnym stanie).

Niezbędne wtyczki

Dataview. Przeszukuje sejf jak bazę danych, korzystając z pól frontmatter. Można tworzyć dynamiczne indeksy: „wszystkie notatki oznaczone tagiem security, zaktualizowane w ciągu ostatnich 30 dni” albo „wszystkie notatki projektowe ze statusem active”. Dataview nie wspiera bezpośrednio wyszukiwania, ale pomaga identyfikować luki w pokryciu sejfu i znajdować notatki wymagające aktualizacji.

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

Templater. Tworzy notatki z szablonów z polami dynamicznymi. Warto zadbać, aby każda nowa notatka zaczynała się od poprawnego frontmatter, używając szablonu, który wstępnie wypełnia pola created, type i domain. Spójny frontmatter usprawnia filtrowanie wyników wyszukiwania.

<%* /* 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. Wymusza reguły formatowania w całym sejfie. Spójna hierarchia nagłówków (H1 dla tytułu, H2 dla sekcji, H3 dla podsekcji) sprawia, że chunker daje przewidywalne wyniki. Reguły Lintera istotne dla wyszukiwania:

  • Przyrost nagłówków: wymuszanie kolejnych poziomów nagłówków (bez przeskakiwania z H1 do H3)
  • Tytuł YAML: zgodny z nazwą pliku
  • Końcowe spacje: usuwanie (zapobiega artefaktom tokenizacji FTS5)
  • Kolejne puste wiersze: ograniczenie do 1 (czystsze fragmenty)

Git integration. Kontrola wersji dla sejfu. Pozwala śledzić zmiany w czasie, synchronizować między komputerami i odzyskiwać przypadkowo usunięte treści. Git udostępnia też dane mtime, których indekser używa do przyrostowego wykrywania zmian.

Wtyczki wspierające indeksowanie

Smart Connections. Wtyczka Obsidian zapewniająca semantyczne wyszukiwanie oparte na AI bezpośrednio w Obsidian. Smart Connections v4 domyślnie tworzy lokalne embeddings — po zindeksowaniu sejfu połączenia semantyczne i wyszukiwanie działają całkowicie offline, bez wywołań API.11 v4.5.0 (5 maja 2026) przenosi połączenia w stopce do Smart Connections Core, dzięki czemu każda instalacja może pokazywać powiązane notatki w stopce bez otwierania panelu bocznego. Ostatnie wydania v4 dodały też widoki grafu dla list połączeń, konfigurowalne położenia dokowania, lepsze odzyskiwanie embeddings bloków po przerwanych przebiegach indeksowania oraz „Substrate”, środowisko międzywtyczkowe pozwalające Smart Connections, Smart Chat i Smart Composer współdzielić stan.21 Choć system wyszukiwania z tego przewodnika działa poza Obsidian (jako pipeline Python), Smart Connections przydaje się do odkrywania relacji semantycznych podczas pisania. Oba systemy indeksują te same treści, ale obsługują inne przypadki użycia: Smart Connections służy do odkrywania treści w edytorze, a zewnętrzny retriever do integracji z narzędziami AI przez MCP.

Wtyczki AI-native wydane w kwietniu 2026. Nowa fala wtyczek społecznościowych celuje bezpośrednio w przepływ pracy Claude Code / Codex / Gemini-CLI:

Wtyczka Wydana Co robi
Cortex 4 kwietnia Agent sejfu oparty na Claude Code — traktuje sejf jako przestrzeń roboczą agenta, a nie tylko magazyn notatek
VaultSearch 7 kwietnia Lokalne-first wyszukiwanie hybrydowe: BM25 + semantyczne + rozmyte (bezpośrednie pokrycie ze stosem wyszukiwania z tego przewodnika)
LLM Wiki 9 kwietnia Zamienia sejf w prywatnie odpytywalną bazę wiedzy
Drift 11 kwietnia Przeglądarka diffów w stylu VS Code do edycji Obsidian wspieranej przez AI; pozycjonowana pod przepływy pracy Claude Code
EngramQuest 11 kwietnia Generuje wyzwania pamięciowe z notatek; zawiera „AI Skills” dla Claude Code / Gemini CLI / Cursor
Hybrid Search MCP marzec (nadal nowe) Serwer MCP + CLI z BM25 + wyszukiwaniem semantycznym — zbudowany specjalnie dla asystentów AI

Należy traktować to jako dopiero wyłaniający się obszar — kilka z tych rozwiązań prawdopodobnie połączy się albo zostanie wchłoniętych przez Smart Connections / rdzeń Obsidian w ciągu kilku kolejnych kwartałów. Jeśli wybiera się dziś jedno narzędzie, VaultSearch i Hybrid Search MCP są filozoficznie najbliższe zewnętrznemu retrieverowi opisanemu w tym przewodniku.

Uwaga o Dataview: Dataview (od dawna istniejąca wtyczka zapytań dla Obsidian) ostatnio wydał wersję 0.5.70 w kwietniu 2025 roku i od tego czasu pozostaje zasadniczo nieaktywny. W przypadku nowych prac wbudowana funkcja Bases w Obsidian (1.9+) jest domyślnym następcą i zalecaną ścieżką.

Metadata Menu. Zapewnia strukturalną edycję frontmatter z autouzupełnianiem wartości pól. Ogranicza literówki w polach type, domain i tags. Spójne metadane zwiększają dokładność filtrowania wyników wyszukiwania.

Wtyczki utrudniające indeksowanie

Excalidraw. Przechowuje rysunki jako JSON osadzone w plikach markdown. JSON jest składniowo poprawnym markdown, ale po podziale na fragmenty i utworzeniu embeddings daje bezużyteczne wyniki. Pliki Excalidraw należy wykluczyć z indeksu przez .indexignore albo filtrować według rozszerzenia pliku.

Kanban. Przechowuje stan tablicy jako specjalnie sformatowany markdown. Format jest zaprojektowany pod renderowanie Kanban, a nie wyszukiwanie w prozie. Chunker tworzy fragmenty tytułów kart i metadanych, które słabo nadają się do embeddings. Tablice Kanban należy wykluczyć z indeksu.

Calendar. Tworzy notatki dzienne z minimalną zawartością (często tylko nagłówkiem daty). Puste lub prawie puste notatki tworzą fragmenty niskiej jakości. Jeśli używa się notatek dziennych, należy wpisywać w nich treściwe informacje albo wykluczyć folder notatek dziennych z indeksu.

Konfiguracja wtyczek, która ma znaczenie

File recovery → Enabled. Chroni przed przypadkowym usunięciem notatek. Nie jest bezpośrednio związane z wyszukiwaniem, ale ma krytyczne znaczenie dla bazy wiedzy, na której można polegać.

Strict line breaks → Disabled. Standardowe łamanie wierszy w Markdown (podwójny znak nowego wiersza dla akapitu) daje czystsze fragmenty niż tryb ścisły Obsidian (pojedynczy znak nowego wiersza dla <br>).

Default new file location → Designated folder. Nowe pliki należy kierować do 00-inbox/, aby nieskategoryzowane notatki nie zanieczyszczały folderów domenowych. Inbox jest obszarem przejściowym; po triage pliki przenosi się do folderów domenowych.

Wiki-link format → Shortest path when possible. Krótsze cele linków są łatwiejsze do rozwiązania przez retriever podczas indeksowania struktury linków.


Modele embeddings: wybór i konfiguracja

Model embeddingów przekształca fragmenty tekstu w wektory liczbowe na potrzeby wyszukiwania semantycznego. Wybór modelu decyduje o jakości wyszukiwania, rozmiarze indeksu, szybkości generowania embeddingów i zależnościach uruchomieniowych. W tej sekcji wyjaśniono, dlaczego Model2Vec potion-base-8M jest wyborem domyślnym i kiedy warto wybrać alternatywy.

Dlaczego Model2Vec potion-base-8M

Model: minishlab/potion-base-8M Parametry: 7,6 miliona Wymiary: 256 Rozmiar: ~30 MB Zależności: model2vec (tylko numpy, bez PyTorch) Inferencja: tylko CPU, statyczne embeddingi słów (bez warstw attention)

Model2Vec destyluje wiedzę transformera zdań do statycznych embeddingów tokenów. Zamiast uruchamiać warstwy attention na wejściu (jak robią to BERT, MiniLM i inne modele transformerowe), Model2Vec tworzy wektory przez ważone uśrednianie wcześniej obliczonych embeddingów tokenów.5 Praktyczny skutek: generowanie embeddingów jest 50-500 razy szybsze niż w modelach opartych na transformerach, ponieważ nie ma obliczeń sekwencyjnych.

Na aktualnej stronie wyników Model2Vec potion-base-8M osiąga około 92% wyniku all-MiniLM-L6-v2 dla wszystkich zadań (51,32 wobec 55,80), pozostając przy tym o rzędy wielkości szybszy.6 Pozostała różnica jakości to kompromis za przewagi szybkości i prostoty. W przypadku krótkich fragmentów markdown (średnio 200-400 słów w typowym vault) różnica jakości jest mniej wyraźna niż przy dłuższych dokumentach, ponieważ oba modele zbiegają się ku podobnym reprezentacjom krótkiego, skoncentrowanego tekstu.

Konfiguracja

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

Leniwe ładowanie. Model ładuje się przy pierwszym użyciu, a nie podczas importu. Import modułu embeddera nic nie kosztuje, gdy retriever działa w trybie awaryjnym wyłącznie BM25 (np. gdy venv dla embeddingów nie jest zainstalowany).

Izolowane środowisko wirtualne. Model działa w dedykowanym venv (np. ~/.claude/venvs/memory/), aby uniknąć konfliktów zależności z resztą toolchaina. Funkcja _activate_venv() dodaje site-packages z venv do sys.path w czasie działania.

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

Przetwarzanie wsadowe. Embedder przetwarza teksty w paczkach po 64, aby zamortyzować narzut Model2Vec. Indexer przekazuje fragmenty do embed_batch(), zamiast generować embedding dla każdego fragmentu osobno.

Kiedy wybrać alternatywy

Model Wym. Rozmiar Szybkość Jakość (MTEB) Najlepsze zastosowanie
potion-base-8M 256 30 MB 500x 51,32 Domyślnie: lokalnie, szybko, bez GPU
potion-base-32M 256 120 MB 400x 52,83 Wyższa jakość, nadal statyczny
potion-retrieval-32M 256 120 MB 400x 35,06 (retrieval) Statyczny, zoptymalizowany pod retrieval
potion-multilingual-128M 256 ~500 MB 300x Wielojęzyczne vaulty (101 języków)
all-MiniLM-L6-v2 384 80 MB 1x 55,80 Wyższa jakość, nadal lokalnie
nomic-embed-text-v1.5 768 270 MB 0,5x 62,28 Najlepsza jakość lokalna
text-embedding-3-small 1536 API N/A 62,30 Oparty na API, najwyższa jakość

Warto wybrać potion-base-32M, gdy potrzebna jest lepsza jakość niż potion-base-8M bez wychodzenia poza rodzinę statycznych embeddingów. Model używa większego słownika wydestylowanego z baai/bge-base-en-v1.5, osiągając wynik 52,83 dla wszystkich zadań (około 3% wyżej niż potion-base-8M), przy zachowaniu tego samego 256-wymiarowego wyjścia i zależności wyłącznie od numpy.8 Plik modelu większy 4 razy zwiększa zużycie pamięci, ale szybkość generowania embeddingów pozostaje o rzędy wielkości wyższa niż w modelach transformerowych.

Warto wybrać potion-retrieval-32M, gdy podstawowym przypadkiem użycia jest retrieval (a tym właśnie jest wyszukiwanie w vault). Ten wariant jest dostrajany na bazie potion-base-32M specjalnie pod zadania retrieval, osiągając 35,06 w tabeli benchmarków retrieval Model2Vec wobec 32,67 dla potion-base-32M.8 Kompromis polega na tym, że model jest zoptymalizowany pod retrieval, a nie pod ogólną jakość embeddingów.

Warto wybrać potion-multilingual-128M, gdy vault zawiera notatki w wielu językach. Ten 101-języczny model, wydany w maju 2025 roku, jest najlepiej działającym statycznym modelem embeddingów dla zadań wielojęzycznych: generuje embeddingi dla dowolnego tekstu w dowolnym języku, zachowując tę samą zależność wyłącznie od numpy co inne modele potion.12 Większy plik modelu (~500 MB) jest kompromisem za obsługę międzyjęzykową. Należy go używać, gdy obok treści angielskich występują notatki po japońsku, chińsku, niemiecku lub w innych językach nieangielskich.

Warto wybrać all-MiniLM-L6-v2, gdy jakość wyszukiwania jest ważniejsza niż szybkość i zainstalowany jest PyTorch. Wektory 384-wymiarowe zwiększają rozmiar bazy SQLite o ~50% względem wektorów 256-wymiarowych. Szybkość generowania embeddingów spada z <1 minuty do ~10 minut dla pełnego ponownego indeksowania 15 000 plików na sprzęcie M-series.

Warto wybrać nomic-embed-text-v1.5, gdy potrzebna jest najlepsza możliwa lokalna jakość retrieval i akceptowane jest wolniejsze indeksowanie. Wektory 768-wymiarowe w przybliżeniu potrajają rozmiar bazy danych. Wymaga PyTorch oraz nowoczesnego CPU lub GPU.

Warto wybrać text-embedding-3-small, gdy opóźnienia sieciowe i prywatność są akceptowalnymi kompromisami. API tworzy embeddingi najwyższej jakości, ale wprowadza zależność od chmury, koszt za token (0,02 USD / milion tokenów) i wysyła treści na serwery OpenAI.

Przy potion-base-8M warto pozostać we wszystkich pozostałych przypadkach. Przewaga szybkości jest kluczowa dla iteracyjnego indeksowania (ponowne indeksowanie podczas developmentu), zależność wyłącznie od numpy pozwala uniknąć złożoności instalacji PyTorch, a wektory 256-wymiarowe utrzymują kompaktowy rozmiar bazy danych.

Kwantyzacja i redukcja wymiarowości

Model2Vec v0.5.0+ obsługuje ładowanie modeli ze zmniejszoną precyzją i liczbą wymiarów.8 Przydaje się to przy wdrażaniu na ograniczonym sprzęcie lub zmniejszaniu rozmiaru bazy danych bez zmiany modelu:

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)

Modele skwantyzowane zachowują niemal identyczną jakość retrieval przy ułamku zapotrzebowania na pamięć. Redukcja wymiarowości działa jak przycinanie w stylu Matryoshka — pierwsze N wymiarów niesie najwięcej informacji. Zmniejszenie z 256 do 128 wymiarów obniża o połowę rozmiar przechowywania wektorów przy minimalnej utracie jakości w retrieval krótkich tekstów.

Model2Vec v0.8.x aktualizuje mechanizmy tokenizera i utrwalania, wycofuje obsługę Python 3.9 oraz odświeża opublikowane wyniki do nowszych tabel MTEB. Przed aktualizacją produkcyjnego indexera należy przypiąć lub przetestować model2vec, ponieważ aktualizacje biblioteki mogą zmienić ścieżki ładowania modelu nawet wtedy, gdy nazwa modelu embeddingów pozostaje taka sama.10

Fine-tuning embeddingów specyficznych dla vault

Model2Vec v0.4.0+ obsługuje trenowanie niestandardowych modeli klasyfikacyjnych na statycznych embeddingach, v0.7.0 dodaje kwantyzację słownika i konfigurowalne pooling dla destylacji, a v0.8.x refaktoryzuje zachowanie tokenizera i utrwalania.10 Ma to znaczenie w vaultach ze specjalistycznym słownictwem (notatki medyczne, odniesienia prawne, żargon domenowy), gdzie domyślne modele potion mogą nie uchwycić niuansów semantycznych:

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

W większości vaultów domyślny potion-base-8M zapewnia wystarczającą jakość retrieval. Fine-tuning ma sens tylko wtedy, gdy retrieval konsekwentnie pomija połączenia specyficzne dla domeny, których model ogólnego przeznaczenia nie potrafi uchwycić.

Śledzenie hash modelu

Indexer przechowuje hash wyprowadzony z nazwy modelu i rozmiaru słownika. Po zmianie modelu embeddingów indexer wykrywa niezgodność przy następnym przebiegu przyrostowym i automatycznie uruchamia pełne ponowne indeksowanie.

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]

Zapobiega to mieszaniu w tej samej bazie danych wektorów pochodzących z różnych modeli, co dawałoby bezsensowne wyniki cosine similarity.

Tryby awarii

Niepowodzenie pobierania modelu. Pierwsze uruchomienie pobiera model z Hugging Face. Jeśli pobieranie się nie powiedzie (problem z siecią, firmowy firewall), retriever przechodzi w tryb wyłącznie BM25. Po pierwszym pobraniu model jest przechowywany lokalnie w cache.

Niezgodność wymiarów. Jeśli model zostanie zmieniony bez wyczyszczenia bazy danych, zapisane wektory mają inny wymiar niż nowe embeddingi. Indexer wykrywa to za pomocą hash modelu i uruchamia pełne ponowne indeksowanie. Jeśli kontrola hash się nie powiedzie (niestandardowy model bez poprawnego hash), sqlite-vec zgłosi błąd przy zapytaniach KNN z niezgodnymi wymiarami.

Presja pamięci przy dużych vaultach. Generowanie embeddingów dla ponad 50 000 fragmentów w jednej paczce może zużyć znaczną ilość pamięci. Indexer przetwarza dane w paczkach po 64, aby ograniczyć szczytowe zużycie pamięci. Jeśli pamięć nadal stanowi problem, należy zmniejszyć rozmiar paczki.


Wyszukiwanie pełnotekstowe z FTS5

Rozszerzenie FTS5 w SQLite zapewnia wyszukiwanie pełnotekstowe z rankingiem BM25. FTS5 jest komponentem wyszukiwania po słowach kluczowych w potoku wyszukiwania hybrid retrieval. Ta sekcja omawia konfigurację FTS5, sytuacje, w których BM25 sprawdza się najlepiej, oraz jego konkretne tryby awarii.

Tabela wirtualna FTS5

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

Tryb synchronizacji treści. Parametr content=chunks informuje FTS5, aby odwoływał się bezpośrednio do tabeli chunks, zamiast przechowywać zduplikowaną kopię tekstu. Zmniejsza to wymagania dotyczące pamięci masowej o połowę, ale oznacza, że FTS5 trzeba synchronizować ręcznie, gdy fragmenty są wstawiane, aktualizowane lub usuwane.

Kolumny. Indeksowane są 3 kolumny: - chunk_text — główna treść każdego fragmentu (waga BM25: 1.0) - section — tekst nagłówka H2 (waga BM25: 0.5) - heading_context — tytuł notatki, tagi i metadane (waga BM25: 0.3)

Ranking BM25

BM25 szereguje dokumenty według częstotliwości termów, odwrotnej częstotliwości dokumentów oraz normalizacji długości dokumentu. Funkcja pomocnicza bm25() w FTS5 przyjmuje wagi dla poszczególnych kolumn:

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;

Wagi kolumn (1.0, 0.5, 0.3) oznaczają, że: - dopasowanie słowa kluczowego w chunk_text ma największy wpływ na wynik - dopasowanie w section (nagłówku) ma o połowę mniejszy wpływ - dopasowanie w heading_context (tytuł, tagi) ma 30% tego wpływu

Te wagi można dostrajać. Jeśli repozytorium Obsidian (vault) ma opisowe nagłówki, które silnie przewidują jakość treści, warto zwiększyć wagę section. Jeśli tagi są kompletne i trafne, warto zwiększyć wagę heading_context.

Kiedy BM25 wygrywa

BM25 świetnie sprawdza się przy zapytaniach zawierających dokładne identyfikatory:

  • Nazwy funkcji: _rrf_fuse, embed_batch, get_stale_files
  • Flagi CLI: --incremental, --vault, --model
  • Klucze konfiguracji: bm25_weight, max_tokens, batch_size
  • Komunikaty błędów: SQLITE_LOCKED, ConnectionRefusedError
  • Konkretne terminy specjalistyczne: PostToolUse, PreToolUse, AGENTS.md

Dla takich zapytań BM25 natychmiast znajduje dokładne dopasowanie. Wyszukiwanie wektorowe zwróciłoby treści powiązane semantycznie, ale mogłoby sklasyfikować dokładne dopasowanie niżej niż omówienie koncepcyjne.

Kiedy BM25 zawodzi

BM25 zawodzi przy zapytaniach, które używają innej terminologii niż przechowywana treść:

  • Zapytanie: „jak obsługiwać niepowodzenia uwierzytelniania” → Repozytorium zawiera notatki o „odzyskiwaniu po błędach logowania” i „obsłudze wygasania sesji”. BM25 nie dopasowuje wyników, ponieważ słowa kluczowe się różnią.
  • Zapytanie: „jaki jest najlepszy sposób zarządzania stanem” → Repozytorium zawiera notatki o „wzorcach Redux store” i „context providers”. BM25 ich nie znajduje, ponieważ „zarządzanie stanem” jest wyrażone przez nazwy konkretnych technologii.

BM25 zawodzi również przy kolizji słów kluczowych na dużą skalę. W repozytorium zawierającym 15 000 plików wyszukiwanie „configuration” dopasowuje setki notatek, ponieważ prawie każda notatka projektowa wspomina o konfiguracji. Wyniki są technicznie poprawne, ale praktycznie bezużyteczne — ranking nie jest w stanie określić, która notatka o „configuration” jest istotna dla bieżącego zapytania.

Tokenizer FTS5

FTS5 domyślnie używa tokenizera unicode61, który obsługuje tekst ASCII i Unicode. W przypadku repozytoriów ze znaczną ilością treści CJK (chińskiej, japońskiej, koreańskiej) warto rozważyć tokenizer trigram:

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

Domyślny tokenizer unicode61 dzieli tekst na granicach wyrazów, co słabo działa w językach bez spacji między słowami. Tokenizer trigram dzieli tekst co 3 znaki, umożliwiając dopasowywanie podłańcuchów kosztem rozmiaru indeksu (około 3 razy większego).

Utrzymanie

FTS5 wymaga jawnej synchronizacji, gdy bazowa tabela chunks się zmienia:

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

Polecenie rebuild rekonstruuje indeks FTS5 na podstawie tabeli treści. Należy uruchamiać je po operacjach wstawiania zbiorczego (pełne ponowne indeksowanie), ale nie po pojedynczych aktualizacjach przyrostowych — w ich przypadku należy używać INSERT INTO chunks_fts(rowid, chunk_text, section, heading_context), aby synchronizować pojedyncze wiersze.


Wyszukiwanie wektorowe z sqlite-vec

Rozszerzenie sqlite-vec wprowadza wyszukiwanie wektorowe KNN (K-Nearest Neighbors) do SQLite. Ta sekcja omawia konfigurację sqlite-vec, pipeline embeddingów od notatki do przeszukiwalnego wektora oraz konkretne wzorce zapytań.

Tabela wirtualna sqlite-vec

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

Moduł vec0 przechowuje 256-wymiarowe wektory float jako spakowane dane binarne. Kolumna id mapuje się 1:1 na tabelę chunks, umożliwiając złączenia między wynikami wektorowymi a metadanymi fragmentów.

Pipeline embeddingów

Pipeline prowadzi od notatki do przeszukiwalnego wektora:

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

Serializacja wektorów

Moduł struct w Python serializuje wektory float na potrzeby przechowywania w sqlite-vec:

import struct

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

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

Zapytanie KNN

Zapytanie wyszukiwania wektorowego tworzy embedding zapytania wejściowego, a następnie znajduje K najbliższych fragmentów według odległości cosinusowej:

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

Operator MATCH w sqlite-vec wykonuje przybliżone wyszukiwanie najbliższych sąsiadów. Parametr k kontroluje liczbę zwracanych wyników. Kolumna distance zawiera odległość cosinusową (0 = identyczne, 2 = przeciwne).

Paginacja KNN z ograniczeniami odległości

Od sqlite-vec v0.1.7 zapytania KNN obsługują ograniczenia WHERE distance < ?, umożliwiając paginację opartą na kursorze przez duże zestawy wyników bez ponownego skanowania wcześniejszych stron.14 Późniejsze stabilne wydania v0.1.8 i v0.1.9 to wydania dotyczące pakietowania oraz poprawek błędów DELETE, a nie nowe wydania modelu zapytań, dlatego v0.1.7 pozostaje granicą funkcji dla tego wzorca paginacji.23

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

Zastępuje to wcześniejszy wzorzec pobierania dużego k i wycinania wyników w Python, zmniejszając użycie pamięci przy eksploracyjnych zapytaniach w dużych vaultach.

Obsługa DELETE w tabelach vec0

sqlite-vec v0.1.7 dodał natywną obsługę DELETE dla tabel wirtualnych vec0, a v0.1.9 naprawił ścieżkę błędu DELETE związaną z tekstowymi kolumnami metadanych dłuższymi niż 12 znaków.1423 Wcześniej usuwanie wektorów wymagało porzucenia i ponownego utworzenia tabeli. Teraz ścieżka usuwania plików w indexerze może usuwać wektory bezpośrednio:

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

Upraszcza to przyrostowe ponowne indeksowanie, gdy notatki zostają usunięte lub przeniesione. Indexer nie musi już utrzymywać pomocniczej tabeli „aktywnych ID” ani wykonywać odbudowy wsadowej.

Kiedy wyszukiwanie wektorowe wygrywa

Wyszukiwanie wektorowe sprawdza się najlepiej w zapytaniach, w których pojęcie jest ważniejsze niż konkretne słowa:

  • Zapytanie: „how to handle authentication failures” → znajduje notatki o „login error recovery” (ta sama przestrzeń semantyczna, inne słowa kluczowe)
  • Zapytanie: „what patterns exist for caching” → znajduje notatki o „memoization”, „Redis TTL strategies” i „HTTP cache headers” (powiązane pojęcia, zróżnicowana terminologia)
  • Zapytanie: „approaches to testing asynchronous code” → znajduje notatki o „pytest-asyncio fixtures”, „mock event loops” i „async test patterns” (to samo pojęcie wyrażone przez szczegóły implementacji)

Kiedy wyszukiwanie wektorowe zawodzi

Wyszukiwanie wektorowe ma trudności z dokładnymi identyfikatorami:

  • Zapytanie: _rrf_fuse → zwraca notatki o „fusion algorithms” i „rank merging”, ale może umieścić właściwą definicję funkcji niżej niż omówienia koncepcyjne
  • Zapytanie: PostToolUse → zwraca notatki o „tool lifecycle hooks” i „post-execution handlers” zamiast konkretnej nazwy hooka

Wyszukiwanie wektorowe ma też trudności z danymi strukturalnymi. Pliki konfiguracyjne JSON, bloki YAML i fragmenty kodu generują embeddingi, które przechwytują wzorce strukturalne zamiast znaczenia semantycznego. Plik JSON z "review": true osadza się inaczej niż prozatorskie omówienie code review.

Łagodna degradacja

Jeśli sqlite-vec nie załaduje się (brakujące rozszerzenie, niezgodna platforma, uszkodzona biblioteka), retriever przechodzi awaryjnie na wyszukiwanie wyłącznie BM25:

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

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

Retriever sprawdza vec_available przed próbą wykonania zapytań wektorowych. Gdy funkcja jest wyłączona, wszystkie wyszukiwania używają wyłącznie BM25, a krok fuzji RRF jest pomijany.


Reciprocal Rank Fusion (RRF)

RRF scala dwie listy rankingowe bez konieczności kalibracji wyników. Ta sekcja omawia algorytm, prześledzone zapytanie, strojenie parametru k oraz powody wyboru RRF zamiast alternatyw. Interaktywny kalkulator z edytowalnymi rankingami, presetami scenariuszy i wizualnym eksploratorem architektury znajduje się w szczegółowym omówieniu mechanizmu wyszukiwania hybrid.

Algorytm

RRF przypisuje każdemu dokumentowi wynik wyłącznie na podstawie jego pozycji rankingowej na każdej liście:

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

Gdzie: - k to stała wygładzająca (60, zgodnie z Cormack et al.3) - rank_i to liczona od 1 pozycja dokumentu na liście wyników i - weight_i to opcjonalny mnożnik dla danej listy (domyślnie 1.0)

Dokumenty wysoko sklasyfikowane na wielu listach otrzymują wyższe wyniki po scaleniu. Dokumenty, które pojawiają się tylko na jednej liście, otrzymują wynik wyłącznie z tego jednego źródła.

Dlaczego RRF zamiast alternatyw

Ważona kombinacja liniowa wymaga kalibracji wyników BM25 względem odległości kosinusowych. Wyniki BM25 są nieograniczone i skalują się wraz z rozmiarem korpusu. Odległości kosinusowe są ograniczone do zakresu [0, 2]. Ich połączenie wymaga normalizacji, a parametry normalizacji zależą od zestawu danych. RRF używa wyłącznie pozycji rankingowych, które zawsze są liczbami całkowitymi zaczynającymi się od 1, niezależnie od metody punktacji.

Wyuczone modele fuzji wymagają oznaczonych danych treningowych — par zapytanie-dokument z oceną trafności. W przypadku osobistej bazy wiedzy takie dane treningowe nie istnieją. Trzeba byłoby ręcznie ocenić setki par zapytanie-dokument, aby wytrenować użyteczny model. RRF działa bez żadnych danych treningowych.

Metody głosowania Condorceta (Borda count, Schulze method) są teoretycznie eleganckie, ale bardziej złożone w implementacji i strojeniu. Oryginalna praca o RRF wykazała, że RRF przewyższa metody Condorceta na danych ewaluacyjnych TREC.3

Fuzja w praktyce

Zapytanie: „how does the review aggregator handle disagreements”

BM25 umieszcza review-aggregator.py na pozycji 3 (dokładne dopasowania słów kluczowych „review”, „aggregator”, „disagreements”), ale wyżej klasyfikuje dwa pliki konfiguracyjne (ponieważ słowo „review” występuje w nich bardziej eksponowanie). Wyszukiwanie wektorowe umieszcza ten sam chunk na pozycji 1 (semantyczne dopasowanie do rozwiązywania konfliktów). Po fuzji RRF:

Chunk BM25 Vec Wynik po scaleniu
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

Na szczyt trafiają chunki, które wysoko plasują się na obu listach. Chunki pojawiające się tylko na jednej liście dostają wynik z pojedynczego źródła i spadają poniżej wyników sklasyfikowanych podwójnie. Rzeczywista logika rozwiązywania niezgodności wygrywa, ponieważ znalazły ją obie metody — BM25 przez słowa kluczowe, a wyszukiwanie wektorowe przez semantykę.

Pełny ślad krok po kroku z obliczeniami RRF dla każdej pozycji rankingowej oraz różnymi wartościami k można sprawdzić w interaktywnym kalkulatorze RRF.

Implementacja

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

Strojenie k

Stała k kontroluje, jak dużą wagę otrzymują wyniki z najwyższych pozycji względem wyników z dalszych miejsc:

  • Niższe k (np. 10): Wyniki z najwyższych pozycji dominują. Pozycja 1 daje wynik 1/11 = 0,091, pozycja 10 daje 1/20 = 0,050 (różnica 1,8x). To dobre ustawienie, gdy ufa się poszczególnym rankerom, że poprawnie wybiorą najlepszy wynik.
  • Domyślne k (60): Zbalansowane. Pozycja 1 daje wynik 1/61 = 0,0164, pozycja 10 daje 1/70 = 0,0143 (różnica 1,15x). Różnice rankingowe są kompresowane, co zwiększa wagę obecności na wielu listach.
  • Wyższe k (np. 200): Obecność na obu listach ma znacznie większe znaczenie niż sama pozycja rankingowa. Pozycja 1 daje 1/201, pozycja 10 daje 1/210 — niemal identycznie. Warto użyć tego ustawienia, gdy poszczególne rankery generują zaszumione rankingi, ale zgodność między listami jest wiarygodna.

Proszę zacząć od k=60. Oryginalna praca o RRF uznała tę wartość za solidną w zróżnicowanych zestawach danych TREC. Strojenie warto przeprowadzać dopiero po zmierzeniu przypadków niepowodzeń na własnym rozkładzie zapytań.

Rozstrzyganie remisów

Gdy dwa chunki mają identyczne wyniki RRF (rzadkie, ale możliwe przy tej samej pozycji na jednej liście i braku obecności na drugiej), remisy należy rozstrzygać następująco:

  1. Preferować chunki, które pojawiają się na obu listach, względem chunków pojawiających się tylko na jednej
  2. Wśród chunków obecnych na obu listach preferować ten z niższą łączną pozycją
  3. Wśród chunków obecnych tylko na jednej liście preferować ten z niższą pozycją na tej liście

Pełny pipeline wyszukiwania

Ta sekcja prowadzi zapytanie od wejścia do wyjścia przez cały pipeline: wyszukiwanie BM25, wyszukiwanie wektorowe, fuzję RRF, przycinanie budżetu tokenów oraz składanie kontekstu.

Przepływ od początku do końca

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

Całkowite opóźnienie: ~23ms dla bazy danych obejmującej 49 746 fragmentów na sprzęcie Apple M3 Pro.

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

Przycinanie budżetu tokenów

Parametr max_tokens zapobiega zwracaniu przez retriever większego kontekstu, niż narzędzie AI może wykorzystać. Szacunek zakłada 4 znaki na token (rozsądne przybliżenie dla prozy angielskiej). Wyniki są przycinane zachłannie: dodawane są w kolejności rankingu, aż budżet zostanie wyczerpany.

To strategia konserwatywna. Bardziej zaawansowane podejście uwzględniałoby oceny jakości poszczególnych wyników i preferowało krótsze wyniki o wyższej jakości zamiast dłuższych wyników o niższej jakości. Podejście zachłanne jest prostsze i dobrze sprawdza się w praktyce, ponieważ ranking RRF już porządkuje wyniki według trafności.

Schemat bazy danych (pełny)

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

Ścieżka graceful degradation

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

Retriever sprawdza możliwości podczas inicjalizacji i dostosowuje strategię zapytań. Brakujący komponent obniża jakość, ale nie powoduje błędów. Jedyną twardą awarią jest brak pliku bazy danych.

Statystyki produkcyjne

Pomiar wykonany na vault Obsidian obejmującym 16 894 pliki, 49 746 fragmentów, bazę SQLite o rozmiarze 83 MB, Apple M3 Pro:

Metryka Wartość
Łączna liczba plików 16 894
Łączna liczba fragmentów 49 746
Rozmiar bazy danych 83 MB
Opóźnienie zapytania BM25 (p50) 12ms
Opóźnienie zapytania wektorowego (p50) 8ms
Opóźnienie fuzji RRF 3ms
Opóźnienie wyszukiwania od początku do końca (p50) 23ms
Czas pełnego ponownego indeksowania ~4 minuty
Czas przyrostowego ponownego indeksowania <10 sekund
Model embeddingów potion-base-8M (256-dim)
Pula kandydatów BM25 30
Pula kandydatów wektorowych 30
Domyślny limit wyników 10
Domyślny budżet tokenów 4 000 tokenów

Hashowanie treści i wykrywanie zmian

Indekser musi wiedzieć, które pliki zmieniły się od ostatniego uruchomienia indeksu. Ta sekcja omawia mechanizm wykrywania zmian oraz strategię hashów.

Porównanie czasu modyfikacji pliku

Indekser przechowuje mtime_ns (czas modyfikacji pliku w nanosekundach) dla każdego fragmentu w tabeli chunks. Podczas uruchomienia przyrostowego indekser:

  1. Skanuje vault Obsidian pod kątem wszystkich plików .md w dozwolonych folderach
  2. Odczytuje mtime_ns dla każdego pliku z systemu plików
  3. Porównuje go z mtime_ns zapisanym w bazie danych
  4. Identyfikuje 3 kategorie:
  5. Nowe pliki: ścieżka istnieje w systemie plików, ale nie w bazie danych
  6. Zmienione pliki: ścieżka istnieje w obu miejscach, ale mtime_ns jest inny
  7. Usunięte pliki: ścieżka istnieje w bazie danych, ale nie w systemie plików
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)

Dlaczego mtime, a nie hash treści

Hashowanie treści (SHA-256 zawartości pliku) byłoby bardziej niezawodne niż porównanie mtime — wykrywałoby przypadki, w których plik został dotknięty bez zmiany treści (np. git checkout przywracający pierwotny mtime). Hashowanie wymaga jednak odczytania każdego pliku przy każdym uruchomieniu przyrostowym. Dla 16 894 plików odczyt zawartości plików zajmuje 2-3 sekundy. Odczyt mtimes z systemu plików zajmuje <100ms.

Kompromis: porównanie mtime sporadycznie uruchamia niepotrzebne ponowne indeksowanie niezmienionych plików (wyniki fałszywie dodatnie), ale nigdy nie pomija rzeczywistych zmian. Wyniki fałszywie dodatnie kosztują kilka dodatkowych wywołań embeddingów na uruchomienie. Różnica szybkości (100ms kontra 3 sekundy) sprawia, że mtime jest pragmatycznym wyborem dla systemu uruchamianego przy każdej interakcji z AI.

Obsługa usunięć

Gdy plik zostaje usunięty z vault Obsidian, indekser usuwa wszystkie jego fragmenty z bazy danych:

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

Instrukcja DELETE FROM chunk_vecs działa natywnie od sqlite-vec v0.1.7, z poprawką błędu w v0.1.9 dla operacji DELETE na tabelach vec0 z dłuższymi kolumnami tekstu metadanych.1423 Wcześniejsze wersje wymagały obejść (usunięcia i ponownego utworzenia tabeli wirtualnej albo utrzymywania zewnętrznego zestawu „active IDs”). Jeśli używana jest wersja sprzed 0.1.9, należy wykonać upgrade przed poleganiem na bezpośrednich usunięciach w schematach intensywnie korzystających z metadanych.

Tabele synchronizacji treści FTS5 wymagają jawnego usunięcia przez INSERT INTO chunks_fts(chunks_fts, rowid, ...) VALUES('delete', ?, ...) dla każdego usuniętego wiersza. Indekser obsługuje to jako część procesu usuwania pliku.

Indeksowanie przyrostowe vs pełne ponowne indeksowanie

Indekser obsługuje 2 tryby: przyrostowy (szybki, do codziennego użycia) i pełny (wolny, okazjonalny). W tej sekcji omówiono, kiedy używać każdego z nich, gwarancje idempotencji oraz odzyskiwanie po uszkodzeniu danych.

Indeksowanie przyrostowe

Kiedy używać: Do codziennego indeksowania po edycji notatek. To tryb domyślny.

Co robi: 1. Skanuje magazyn notatek pod kątem zmian w plikach (porównanie mtime) 2. Usuwa fragmenty dla usuniętych plików 3. Ponownie dzieli na fragmenty i ponownie generuje embeddings dla zmienionych plików 4. Wstawia nowe fragmenty dla nowych plików 5. Synchronizuje indeks FTS5

Typowy czas trwania: <10 sekund dla dziennych zmian w magazynie z 16 000 plików.

python index_vault.py --incremental

Pełne ponowne indeksowanie

Kiedy używać: - Po zmianie modelu embeddings (wykryta niezgodność hasha modelu) - Po migracji schematu (nowe kolumny, zmienione indeksy) - Po uszkodzeniu bazy danych (kontrola integralności kończy się niepowodzeniem) - Gdy indeksowanie przyrostowe daje nieoczekiwane wyniki

Co robi: 1. Usuwa wszystkie istniejące dane (fragmenty, wektory, wpisy FTS5) 2. Skanuje cały magazyn notatek 3. Dzieli wszystkie pliki na fragmenty 4. Generuje embeddings dla wszystkich fragmentów 5. Buduje indeks FTS5 od zera

Typowy czas trwania: ~4 minuty dla 16 894 plików na Apple M3 Pro.

python index_vault.py --full

Idempotencja

Oba tryby są idempotentne: dwukrotne uruchomienie tego samego polecenia daje ten sam wynik. Indekser usuwa istniejące fragmenty dla pliku przed wstawieniem nowych, więc ponowne uruchomienie indeksowania przyrostowego na już aktualnej bazie danych nie wprowadza żadnych zmian. Ponowne uruchomienie pełnego indeksowania tworzy identyczną bazę danych.

Odzyskiwanie po uszkodzeniu danych

Jeśli baza SQLite zostanie uszkodzona (utrata zasilania podczas zapisu, błąd dysku, przerwany proces w trakcie transakcji):

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

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

Źródłem prawdy są zawsze pliki w magazynie notatek, nie baza danych. Baza danych jest artefaktem pochodnym, który można odbudować w dowolnym momencie. To kluczowa właściwość projektu: nie trzeba nigdy tworzyć kopii zapasowej bazy danych.

Flaga --incremental

Gdy indekser działa z --incremental:

  1. Sprawdzenie hasha modelu. Porównuje zapisany hash modelu z bieżącym modelem. Jeśli jest inny, automatycznie przełącza się w tryb pełnego ponownego indeksowania i ostrzega użytkownika.
  2. Skanowanie plików. Przechodzi przez dozwolone foldery, zbiera ścieżki plików i wartości mtime.
  3. Wykrywanie zmian. Porównuje je z zapisanymi danymi.
  4. Przetwarzanie wsadowe. Ponownie dzieli zmienione pliki na fragmenty i ponownie generuje embeddings w partiach po 64.
  5. Raportowanie postępu. Wypisuje liczbę przetworzonych plików i czas, który upłynął.
  6. Łagodne zamykanie. Obsługuje SIGINT, kończąc bieżący plik przed zatrzymaniem.

Filtrowanie poświadczeń i granice danych

Osobiste notatki zawierają sekrety: klucze API, bearer tokens, ciągi połączeń z bazą danych, klucze prywatne wklejone podczas sesji debugowania. Filtr poświadczeń zapobiega ich trafieniu do indeksu wyszukiwania.

Problem

Notatka o debugowaniu integracji OAuth może zawierać:

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

Bez filtrowania zarówno JWT, jak i klucz API zostałyby podzielone na fragmenty, przetworzone na embeddings i zapisane w bazie danych. Wyszukiwanie hasła „authentication” zwróciłoby fragment zawierający prawdziwe sekrety. Co gorsza, jeśli retriever przekaże wyniki do narzędzia AI przez MCP, sekrety pojawią się w oknie kontekstu AI i potencjalnie w logach narzędzia.

Filtrowanie oparte na wzorcach

Filtr poświadczeń uruchamia się dla każdego fragmentu przed zapisem, dopasowując 25 wzorców specyficznych dla dostawców oraz wzorce ogólne:

Wzorce specyficzne dla dostawców:

Wzorzec Przykład Regex
Klucz OpenAI API sk-... sk-[a-zA-Z0-9_-]{20,}
Klucz Anthropic API 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}
Klucz Stripe sk_live_... [sr]k_(live\|test)_[a-zA-Z0-9]{24,}
Token Cloudflare ... Różne wzorce

Wzorce ogólne:

Wzorzec Wykrywanie
Tokeny JWT eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+
Bearer tokens Bearer\s+[a-zA-Z0-9_\-\.]+
Klucze prywatne -----BEGIN (RSA\|EC\|OPENSSH) PRIVATE KEY-----
Base64 o wysokiej entropii Ciągi z entropią >4,5 bitu/znak, 40+ znaków
Przypisania haseł password\s*[:=]\s*["'][^"']+["']

Implementacja filtra

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

Kluczowe decyzje projektowe:

  1. Filtrowanie przed embeddings. Oczyszczony tekst jest tym, dla czego generowane są embeddings. Reprezentacja wektorowa nigdy nie koduje wzorców poświadczeń. Zapytanie o „klucz API” zwraca notatki omawiające zarządzanie kluczami API, a nie notatki zawierające rzeczywiste klucze.

  2. Zastępowanie, nie usuwanie. Token [REDACTED:pattern-name] zachowuje semantyczny kontekst otaczającego tekstu. Embedding uchwyci, że „było tu coś przypominającego poświadczenie”, bez kodowania samego poświadczenia.

  3. Logowanie wzorców, nie wartości. Filtr loguje, które wzorce zostały dopasowane (np. „Scrubbed 2 credential(s) from oauth-debug.md [jwt, bearer-token]”), ale nigdy nie loguje wartości poświadczenia.

Wykluczanie na podstawie ścieżki

Plik .indexignore zapewnia ogólne wykluczanie według ścieżki. Filtr poświadczeń zapewnia dokładne oczyszczanie wewnątrz indeksowanych plików. Oba mechanizmy są potrzebne:

  • .indexignore dla całych folderów, o których wiadomo, że zawierają wrażliwe treści (notatki zdrowotne, dokumenty finansowe, dokumenty zawodowe)
  • Filtr poświadczeń dla sekretów przypadkowo osadzonych w treści, która poza tym nadaje się do indeksowania

Klasyfikacja danych

W przypadku magazynów notatek zawierających zróżnicowane treści warto rozważyć klasyfikowanie notatek według wrażliwości:

Poziom Przykłady Indeksować? Filtrować?
Publiczne Szkice blogowe, notatki techniczne Tak Tak
Wewnętrzne Plany projektów, decyzje architektoniczne Tak Tak
Wrażliwe Dane o wynagrodzeniu, dokumentacja zdrowotna Nie (.indexignore) Nie dotyczy
Ograniczone Poświadczenia, klucze prywatne Nie (.indexignore) Nie dotyczy

Architektura serwera MCP

Serwery Model Context Protocol (MCP) udostępniają mechanizm wyszukiwania jako narzędzie, które mogą wywoływać agenci AI. Ta sekcja omawia projekt serwera, zakres funkcji oraz granice uprawnień.

Wybór protokołu: STDIO a HTTP

MCP obsługuje 2 tryby transportu:

STDIO — Narzędzie AI uruchamia serwer MCP jako proces podrzędny i komunikuje się z nim przez stdin/stdout. To standardowy tryb dla narzędzi lokalnych. Claude Code, Codex CLI i Cursor obsługują serwery MCP działające przez STDIO.

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

HTTP — Serwer MCP działa jako samodzielna usługa HTTP. Przydaje się przy dostępie zdalnym, konfiguracjach z wieloma klientami lub konfiguracjach zespołowych, w których vault znajduje się na współdzielonym serwerze.

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

Rekomendacja: W przypadku osobistych vaultów warto używać STDIO. Jest prostszy, bezpieczniejszy (brak ekspozycji sieciowej), a cyklem życia serwera zarządza narzędzie AI. HTTP należy używać tylko wtedy, gdy wiele narzędzi lub wiele maszyn potrzebuje jednoczesnego dostępu do tego samego vaultu.

Ewolucja specyfikacji MCP. Specyfikacja MCP z czerwca 2025 roku dodała autoryzację OAuth 2.1, ustrukturyzowane dane wyjściowe narzędzi (typowane schematy zwrotne) oraz elicitation (monity użytkownika inicjowane przez serwer). Wydanie z listopada 2025 roku wprowadziło Streamable HTTP jako pełnoprawny tryb transportu, wykrywanie URL-i .well-known do automatycznego przeglądania możliwości serwera, ustrukturyzowane adnotacje narzędzi deklarujące, czy narzędzie jest tylko do odczytu, czy modyfikuje dane, oraz system standaryzacji poziomów SDK.79 Następne wydanie specyfikacji (wstępnie planowane na połowę 2026 roku) proponuje operacje asynchroniczne dla długotrwałych zadań, branżowe rozszerzenia protokołu dla sektorów takich jak opieka zdrowotna i finanse oraz standardy komunikacji agent-to-agent dla przepływów pracy z wieloma agentami.9 W przypadku osobistych serwerów vaultów STDIO pozostaje najprostszą ścieżką. Transport Streamable HTTP oraz wykrywanie .well-known przynoszą korzyści głównie wdrożeniom korporacyjnym HTTP z routingiem wielodzierżawnym i równoważeniem obciążenia. Warto śledzić plan rozwoju MCP, aby zauważyć aktualizacje wpływające na wybór transportu.

Projektowanie możliwości

Serwer MCP powinien udostępniać minimalny zestaw narzędzi:

search — Główne narzędzie. Uruchamia hybrid retrieval i zwraca uszeregowane wyniki.

{
  "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 — Odczytuje pełną zawartość konkretnej notatki według ścieżki. Przydatne, gdy agent chce zobaczyć pełny kontekst wyniku wyszukiwania.

{
  "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 — Wyświetla notatki pasujące do filtra (według folderu, tagu, typu lub zakresu dat). Przydatne do eksploracji, gdy agent nie ma konkretnego zapytania.

{
  "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 — Narzędzie pomocnicze, które uruchamia wyszukiwanie i formatuje wyniki jako blok kontekstu odpowiedni do wstrzyknięcia do rozmowy.

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

Granice uprawnień

Serwer MCP powinien wymuszać ścisłe granice:

  1. Tylko do odczytu. Serwer odczytuje vault i bazę danych indeksu. Nie tworzy, nie modyfikuje ani nie usuwa notatek. Operacje zapisu (przechwytywanie nowych notatek) są obsługiwane przez osobne hooks lub skills, a nie przez serwer MCP.

  2. Ograniczony do vaultu. Serwer odczytuje wyłącznie pliki znajdujące się w skonfigurowanej ścieżce vaultu. Próby path traversal (../../etc/passwd) muszą być odrzucane.

  3. Dane wyjściowe filtrowane pod kątem poświadczeń. Nawet jeśli baza danych zawiera wstępnie przefiltrowaną treść, należy zastosować filtrowanie poświadczeń na wyjściu jako mechanizm defense-in-depth.

  4. Odpowiedzi ograniczone tokenami. Należy wymuszać max_tokens dla wszystkich odpowiedzi narzędzi, aby zapobiec otrzymywaniu przez narzędzie AI nadmiernie dużych bloków kontekstu.

Obsługa błędów

Narzędzia MCP powinny zwracać ustrukturyzowane komunikaty o błędach, które pomagają narzędziu AI odzyskać kontrolę po problemie:

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

Integracja Claude Code

Claude Code jest głównym konsumentem systemu wyszukiwania Obsidian. Ta sekcja omawia konfigurację MCP, integrację hooków oraz wzorzec obsidian_bridge.py.

Konfiguracja MCP

Dodać serwer MCP Obsidian do ~/.claude/settings.json:

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

Po dodaniu konfiguracji należy ponownie uruchomić Claude Code. Serwer MCP uruchomi się jako proces potomny. Aby sprawdzić, czy działa:

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

Claude Code powinien wyświetlić dostępne narzędzia (obsidian_search, obsidian_read_note itd.).

Integracja hooków

Hooki rozszerzają działanie Claude Code w określonych punktach cyklu życia. Dla integracji z Obsidian istotne są dwa hooki:

Hook PreToolUse — odpytuje skarbiec, zanim agent przetworzy wywołanie narzędzia. Automatycznie wstrzykuje odpowiedni kontekst.

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

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

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

Hook PostToolUse — zapisuje istotne wyniki działania narzędzi z powrotem do skarbca, aby można było je później odnaleźć.

#!/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

Wzorzec obsidian_bridge.py

Moduł pomostowy udostępnia Python API, który mogą wywoływać hooki i skills:

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

Skill /capture

Skill Claude Code do zapisywania spostrzeżeń z powrotem w skarbcu:

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

Skill tworzy nową notatkę w 00-inbox/ z poprawnym frontmatter i wyzwala przyrostowe ponowne indeksowanie, dzięki czemu nową notatkę można od razu wyszukać.

Wzorce niestandardowych poleceń

Skills Claude Code mogą opakowywać operacje na skarbcu w nazwane polecenia. Praktycy budowali biblioteki poleceń specyficznych dla Obsidian, które traktują skarbiec jednocześnie jako źródło odczytu i cel zapisu.

Skanowanie sygnałów. Polecenie /scan-intel odpytuje źródła zewnętrzne, ocenia znaleziska względem osobistych zainteresowań badawczych i zapisuje kwalifikujące się sygnały jako notatki w skarbcu z frontmatter:

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

Polecenie pobiera dane ze skonfigurowanych źródeł (arXiv, HN, RSS), stosuje model punktacji (trafność, możliwość działania, głębia, autorytet) i zapisuje sygnały spełniające kryteria w tematycznych folderach skarbca. Skarbiec staje się odbiorcą końcowym zautomatyzowanego potoku analitycznego.

Dziennik kapitana. Polecenie /captains-log agreguje dzienną aktywność git we wszystkich repozytoriach, zapisuje uporządkowany wpis dziennika w skarbcu i uwzględnia podjęte decyzje, odkrycia oraz otwarte wątki:

/captains-log

Polecenie pobiera historię commitów z GitHub, grupuje ją według repozytorium i formatuje jako narracyjny wpis dziennika. Z czasem dzienne logi tworzą przeszukiwalny zapis tego, co zostało dostarczone i dlaczego.

Przechwytywanie do Obsidian. Polecenie /obsidian-capture pobiera spostrzeżenie z bieżącej sesji Claude Code i zapisuje je bezpośrednio w skarbcu z poprawnymi metadanymi:

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

Ten wzorzec można rozszerzyć na dowolną operację na skarbcu: tworzenie MOCs, aktualizowanie notatek statusu projektu, łączenie powiązanych sygnałów czy generowanie tygodniowych podsumowań z nagromadzonych dziennych logów.

Przykłady społeczności. Praktycy publikują swoje biblioteki poleceń. Jeden deweloper udostępnił 22 niestandardowe polecenia Obsidian + Claude Code, obejmujące dzienne przeglądy, planowanie projektów, przechwytywanie badań i workflowy treści.1 Inny zbudował skill „Visual Explainer”, który generuje notatki z diagramami w skarbcu na podstawie analizy kodu.2 Polecenia się różnią, ale architektura pozostaje spójna: skills Claude Code jako interfejs, notatki w skarbcu jako warstwa przechowywania, a infrastruktura wyszukiwania jako silnik zapytań.

Zarządzanie oknem kontekstu

Integracja powinna uwzględniać okno kontekstu Claude Code:

  • Ograniczyć wstrzykiwany kontekst do 1 500-2 000 tokenów na zapytanie. Większa ilość konkuruje z pamięcią roboczą agenta.
  • Uwzględniać atrybucję źródła. Zawsze należy dołączyć ścieżkę pliku i nagłówek sekcji, aby agent mógł odwołać się do źródła.
  • Przycinać tekst chunków. Długie chunki należy skracać za pomocą ..., zamiast całkowicie je pomijać. Pierwsze 300-500 znaków zwykle zawiera kluczowe informacje.
  • Nie wstrzykiwać kontekstu przy każdym wywołaniu narzędzia. Hook PreToolUse powinien selektywnie wstrzykiwać kontekst na podstawie wywoływanego narzędzia. Operacje odczytu nie wymagają kontekstu skarbca. Operacje Write i Edit z niego korzystają.

Integracja Codex CLI

Codex CLI łączy się z serwerami MCP przez config.toml. Wzorzec integracji różni się od Claude Code składnią konfiguracji i sposobem przekazywania instrukcji.

Konfiguracja MCP

Dodać do .codex/config.toml lub ~/.codex/config.toml:

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

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

Wzorce AGENTS.md

Codex CLI odczytuje AGENTS.md w celu pobrania instrukcji na poziomie projektu. Należy uwzględnić wskazówki dotyczące przeszukiwania skarbca:

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

Różnice względem Claude Code

Funkcja Claude Code Codex CLI
Konfiguracja MCP settings.json config.toml
Hooki ~/.claude/hooks/ Nieobsługiwane
Skills ~/.claude/skills/ Nieobsługiwane
Plik instrukcji CLAUDE.md AGENTS.md
Tryby zatwierdzania --dangerously-skip-permissions suggest / auto-edit / full-auto

Kluczowa różnica: Codex CLI nie obsługuje hooków. Wzorzec automatycznego wstrzykiwania kontekstu (hook PreToolUse) nie jest dostępny. Zamiast tego należy umieścić w AGENTS.md jawne instrukcje nakazujące agentowi przeszukanie skarbca przed rozpoczęciem pracy.

Cursor i inne narzędzia

Cursor i inne narzędzia AI obsługujące MCP mogą łączyć się z tym samym serwerem MCP Obsidian. W tej sekcji omówiono konfigurację popularnych narzędzi.

Cursor

Do pliku .cursor/mcp.json w katalogu głównym projektu należy dodać:

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

Plik .cursorrules Cursor może zawierać instrukcje korzystania z magazynu:

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.

Macierz zgodności

Narzędzie Obsługa MCP Transport Lokalizacja konfiguracji
Claude Code Pełna STDIO ~/.claude/settings.json
Codex CLI Pełna STDIO .codex/config.toml
Cursor Pełna STDIO .cursor/mcp.json
Windsurf Pełna STDIO .windsurf/mcp.json
Continue.dev Częściowa HTTP ~/.continue/config.json
Zed W trakcie prac STDIO Interfejs ustawień
Claudian (plugin Obsidian) Nie dotyczy (wbudowane) Claude Code CLI Ustawienia pluginu Obsidian
Agent Client (plugin Obsidian) Nie dotyczy (wbudowane) ACP Ustawienia pluginu Obsidian

Rozwiązanie awaryjne dla narzędzi bez MCP

W przypadku narzędzi, które nie obsługują MCP, retriever można opakować jako CLI:

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

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

CLI zwraca uporządkowany tekst, który można ręcznie wkleić do wejścia dowolnego narzędzia AI. To mniej eleganckie niż integracja z MCP, ale działa uniwersalnie.


Prompt caching ze strukturyzowanych notatek

Strukturyzowane notatki w magazynie mogą służyć jako bloki kontekstu wielokrotnego użytku, które zmniejszają zużycie tokenów w interakcjach z AI. W tej sekcji omówiono projektowanie kluczy cache i zarządzanie budżetem tokenów.

Wzorzec

Zamiast wyszukiwać kontekst przy każdej interakcji, można wcześniej zbudować bloki kontekstu z dobrze uporządkowanych notatek w magazynie i zapisać je w cache:

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

Unieważnianie cache

Unieważnianie cache opiera się na dwóch sygnałach:

  1. Wygaśnięcie TTL. Każdy blok kontekstu ma określony czas życia. Po wygaśnięciu TTL blok jest odbudowywany przez ponowne zapytanie do magazynu.
  2. Wykrycie zmian w magazynie. Gdy indexer wykryje zmiany w plikach, które przyczyniły się do powstania zapisanego w cache bloku kontekstu, blok jest natychmiast unieważniany.

Zarządzanie budżetem tokenów

Sesja zaczyna się z łącznym budżetem kontekstu. Bloki zapisane w cache zużywają część tego budżetu:

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)

Bloki zapisane w cache są ładowane przy starcie sesji. Dynamiczne wyniki wyszukiwania wypełniają pozostały budżet osobno dla każdego zapytania. Takie hybrydowe podejście zapewnia agentowi bazowy zestaw często potrzebnego kontekstu, a jednocześnie zachowuje budżet na konkretne zapytania.

Zużycie tokenów przed i po

Bez cache: Każde istotne zapytanie uruchamia wyszukiwanie w magazynie i zwraca 1 500-2 000 tokenów kontekstu. Przy 10 zapytaniach w sesji agent zużywa 15 000-20 000 tokenów kontekstu z magazynu.

Z cache: Trzy wcześniej zbudowane bloki kontekstu zużywają łącznie 4 500 tokenów. Dodatkowe wyszukiwania dodają 1 500-2 000 tokenów na każde unikalne zapytanie. Przy 10 zapytaniach, z których 6 pokrywają bloki zapisane w cache, agent zużywa 4 500 + (4 * 1 500) = 10 500 tokenów, czyli mniej więcej połowę zużycia bez cache.


Hooki PostToolUse do kompresji kontekstu

Wyniki narzędzi mogą być obszerne: stack trace, listy plików, wyniki testów. Hook PostToolUse może skompresować te wyniki, zanim zajmą miejsce w oknie kontekstu.

Problem

Wywołanie narzędzia Bash, które uruchamia testy, może zwrócić:

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

Pełny wynik ma 5 000 tokenów, ale właściwy sygnał znajduje się w 2 wierszach: 200 zakończonych powodzeniem, 1 zakończony niepowodzeniem.

Implementacja hooka

#!/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

Zapobieganie rekurencyjnemu wyzwalaniu

Hook kompresujący, który emituje wynik, mógłby wyzwolić sam siebie, jeśli nie zostanie zabezpieczony:

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

Heurystyki kompresji

Typ wyniku Wykrywanie Strategia kompresji
Wyniki testów Słowa kluczowe PASSED / FAILED Policzyć sukcesy i niepowodzenia, pokazać tylko niepowodzenia
Listy plików ls lub find w poleceniu Skrócić do pierwszych 20 pozycji + liczba
Stack trace Słowo kluczowe Traceback Zachować pierwszą i ostatnią ramkę + komunikat błędu
Status Git modified: / new file: Podsumować liczby według statusu
Wynik budowania warning: / error: Usunąć wiersze informacyjne, zachować ostrzeżenia i błędy

Potok przyjmowania i selekcji sygnałów

Warstwa przyjmowania decyduje o tym, co trafia do skarbca. Bez kuracji skarbiec gromadzi szum. Ta sekcja omawia potok oceniania, który kieruje sygnały do folderów domenowych.

Źródła

Sygnały pochodzą z wielu kanałów:

  • Kanały RSS: blogi techniczne, biuletyny bezpieczeństwa, informacje o wydaniach
  • Zakładki przez Web Clipper: oficjalne rozszerzenie Obsidian Web Clipper (Chrome, Firefox, Safari) to ścieżka przyjmowania o najwyższej wierności do przechwytywania treści z poziomu przeglądarki. Cykl wydań z kwietnia 2026 roku sprawił, że stało się ono znacznie bardziej użyteczne w przepływach pracy AI:22
    • 1.4.0 (9 kwi): interaktywny interfejs transkrypcji YouTube — można przypiąć wideo, przewijać transkrypcję, automatycznie przewijać widok i podświetlać bieżącą pozycję. Do tego domyślna opcja „Open in Reader”, która jednym kliknięciem wysyła przechwycony materiał bezpośrednio do trybu Reader.
    • 1.5.0–1.5.1 (15 kwi): przeglądarka podświetleń — przeglądanie i wyszukiwanie przechwyconych podświetleń w całym skarbcu. Przejście fade-in do Reader. Płynniejsze odtwarzanie/wstrzymywanie YouTube. Wersja 1.5.1 naprawiła regresję kompilacji webpack.
    • 1.6.0–1.6.2 (21–23 kwi): przebudowa UX podświetlania z obsługą urządzeń mobilnych. Defuddle 0.18 dodaje ekstraktory specyficzne dla źródeł, takich jak LinkedIn, Threads, Bluesky, Discourse i Medium. Wersja 1.6.2 naprawia regresję schowka w trybie osadzonym Safari. Szablony należy konfigurować dla każdej domeny źródłowej, aby transkrypcje YouTube, pliki README GitHub i długie artykuły trafiały do sensownie nazwanych notatek z właściwym frontmatter dla poniższego potoku oceniania.
  • Newslettery: kluczowe fragmenty z newsletterów e-mailowych
  • Ręczne przechwytywanie: notatki tworzone podczas czytania, rozmów lub badań
  • Wyniki narzędzi: istotne wyniki narzędzi AI przechwycone przez hooks
  • Share Extension w iOS: aplikacja Obsidian na iOS (zaktualizowana na początku 2026 roku) zawiera Share Extension, które zapisuje treści z Safari, sieci społecznościowych i innych aplikacji bezpośrednio do skarbca, bez otwierania Obsidian.19 Tworzy to mało tarciową ścieżkę przyjmowania z urządzeń mobilnych — wystarczy udostępnić artykuł z Safari, a pojawi się on jako notatka w skarbcu, gotowa do oceny.
  • Obsidian CLI: skrypty powłoki i hooks mogą tworzyć notatki przez obsidian file create albo dopisywać treść do istniejących notatek przez obsidian file append, umożliwiając automatyczne potoki przyjmowania na komputerze.

Wymiary oceny

Każdy sygnał jest oceniany w czterech wymiarach (każdy od 0,0 do 1,0):

Wymiar Pytanie Niska ocena (0,0–0,3) Wysoka ocena (0,7–1,0)
Trafność Czy odnosi się to do moich aktywnych obszarów? Poboczne, poza zakresem Bezpośrednio związane z aktywną pracą
Możliwość działania Czy można wykorzystać tę informację? Czysta teoria, bez zastosowania Konkretna technika lub wzorzec do zastosowania
Głębia Jak merytoryczna jest treść? Nagłówki, płytkie streszczenie Szczegółowa analiza z przykładami
Autorytet Jak wiarygodne jest źródło? Anonimowy blog, brak weryfikacji Źródło pierwotne, recenzowane, uznany ekspert

Ocena złożona i routing

composite = (relevance * 0.35) + (actionability * 0.25) +
            (depth * 0.25) + (authority * 0.15)
Zakres oceny Działanie
0,55+ Automatyczne skierowanie do folderu domenowego
0,40 - 0,55 Kolejka do ręcznej weryfikacji
< 0,40 Odrzucenie (nie przechowywać)

Routing domenowy

Sygnały z oceną powyżej 0,55 trafiają do jednego z 12 folderów domenowych na podstawie dopasowania słów kluczowych i klasyfikacji tematu:

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

Statystyki produkcyjne

W ciągu 14 miesięcy działania:

Metryka Wartość
Łączna liczba przetworzonych sygnałów 7 771
Skierowane automatycznie (>0,55) 4 832 (62%)
W kolejce do weryfikacji (0,40–0,55) 1 543 (20%)
Odrzucone (<0,40) 1 396 (18%)
Aktywne foldery domenowe 12
Średnia liczba sygnałów dziennie ~18

Wzorce knowledge graph

Graf wiki-link w Obsidian koduje relacje między notatkami. Ta sekcja omawia semantykę linków, przechodzenie po grafie w celu rozszerzania kontekstu oraz antywzorce obniżające jakość grafu.

Każdy wiki-link tworzy w grafie krawędź skierowaną. Obsidian śledzi zarówno linki wychodzące, jak i backlinks:

  • Link wychodzący: notatka A zawiera [[Note B]] → A linkuje do B
  • Backlink: notatka B pokazuje, że notatka A się do niej odwołuje

Graf koduje różne typy relacji w zależności od kontekstu:

Wzorzec linku Semantyka Przykład
Link w treści „Jest powiązane z” „Zobacz [[OAuth Token Rotation]], aby poznać szczegóły”
Link nagłówkowy „Ma podtemat” „## Related\n- [[Token Rotation]]\n- [[Session Management]]”
Link podobny do tagu „Jest skategoryzowane jako” „[[type/reference]]”
Link MOC „Jest częścią” Notatka Map of Content z listą powiązanych notatek

Maps of Content (MOCs)

MOCs to notatki indeksowe, które porządkują powiązane notatki w strukturę możliwą do nawigowania:

---
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 wspierają retrieval na dwa sposoby:

  1. Bezpośrednie dopasowanie. Wyszukiwanie „authentication overview” dopasowuje sam MOC, dostarczając agentowi wyselekcjonowaną listę powiązanych notatek.
  2. Rozszerzanie kontekstu. Po znalezieniu konkretnej notatki retriever może sprawdzić, czy występuje ona w jakichkolwiek MOCs, i dołączyć strukturę MOC do wyników, dając agentowi mapę szerszego tematu.

Przechodzenie po grafie w celu rozszerzania kontekstu

Przyszłe usprawnienie retrievera: po znalezieniu najlepszych wyników można rozszerzyć kontekst przez podążanie za linkami:

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)

Nie jest to zaimplementowane w obecnym retrieverze, ale stanowi naturalne rozszerzenie struktury grafu.

Antywzorce

Osierocone klastry. Grupy notatek, które linkują do siebie nawzajem, ale nie mają połączeń z resztą skarbca. Panel grafu w Obsidian pokazuje je jako odłączone wyspy. Osierocone klastry wskazują na brakujące MOCs albo brakujące linki między domenami.

Rozrost tagów. Niespójne używanie tagów lub tworzenie zbyt wielu drobnoziarnistych tagów. Skarbiec z 500 unikalnymi tagami w 5 000 notatkach ma średnio 1 notatkę na 10 tagów — takie tagi nie są przydatne do filtrowania. Należy skonsolidować je do 20–50 tagów wysokiego poziomu, które odpowiadają folderom domenowym.

Notatki bogate w linki, ubogie w treść. Notatki składające się wyłącznie z wiki-link bez prozy. Takie notatki słabo się indeksują, ponieważ chunker nie ma tekstu do osadzenia. Warto dodać co najmniej jeden akapit kontekstu wyjaśniający, dlaczego linkowane notatki są ze sobą powiązane.

Dwukierunkowe linki do wszystkiego. Nie każde odwołanie musi być wiki-link. Przelotne wspomnienie „OAuth” nie wymaga [[OAuth 2.0 Overview]]. Wiki-link należy rezerwować dla intencjonalnych, możliwych do nawigowania relacji, w których kliknięcie linku dostarcza użytecznego kontekstu.

Przepisy dotyczące pracy deweloperskiej

Praktyczne przepływy pracy, które łączą wyszukiwanie w skarbcu z codziennymi zadaniami deweloperskimi.

Poranne ładowanie kontekstu

Dzień warto rozpocząć od załadowania odpowiedniego kontekstu:

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

Retriever zwraca najnowsze notatki dotyczące aktywnego projektu, co pozwala szybko przypomnieć sobie, gdzie praca została przerwana. To skuteczniejsze niż ponowne czytanie wczorajszych komunikatów commitów.

Przechwytywanie badań podczas kodowania

Podczas implementowania funkcji można zapisywać spostrzeżenia bez opuszczania edytora:

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

Zapisana obserwacja jest natychmiast indeksowana i dostępna do przyszłego wyszukiwania. W perspektywie miesięcy takie mikro-notatki budują korpus wiedzy specyficznej dla implementacji.

Rozpoczęcie projektu

Przy rozpoczynaniu nowego projektu lub funkcji:

  1. Przeszukaj skarbiec: „Co wiem o [technologia/wzorzec]?”
  2. Przejrzyj 5 najlepszych wyników pod kątem wcześniejszych decyzji i pułapek
  3. Sprawdź, czy istnieje MOC dla danej domeny; jeśli nie, utwórz go
  4. Wyszukaj tryby awarii: „problemy z [technologia]”

Debugowanie z wyszukiwaniem w skarbcu

Gdy pojawi się błąd lub nieoczekiwane zachowanie:

Search my vault for [error message or symptom]

Wcześniejsze notatki z debugowania często zawierają przyczynę źródłową i poprawkę. Jest to szczególnie cenne przy powtarzających się problemach w różnych projektach — skarbiec pamięta to, o czym łatwo zapomnieć.

Przygotowanie do przeglądu kodu

Przed przeglądem PR:

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

Skarbiec zwraca wcześniejsze decyzje, ograniczenia architektoniczne i standardy kodowania istotne dla przeglądanego kodu. Przegląd opiera się na wiedzy instytucjonalnej, a nie tylko na diffie.


Dostrajanie wydajności

Ta sekcja omawia strategie optymalizacji dla różnych rozmiarów skarbca i wzorców użycia.

Zarządzanie rozmiarem indeksu

Rozmiar skarbca Fragmenty Rozmiar DB Pełna reindeksacja Przyrostowo
500 notatek ~1 500 3 MB 15 sekund <1 sekunda
2 000 notatek ~6 000 12 MB 45 sekund 2 sekundy
5 000 notatek ~15 000 30 MB 2 minuty 4 sekundy
15 000 notatek ~50 000 83 MB 4 minuty <10 sekund
50 000 notatek ~150 000 250 MB 15 minut 30 sekund

Przy ponad 50 000 notatek warto rozważyć: - Zwiększenie rozmiaru batcha z 64 do 128, aby szybciej tworzyć embeddingi - Używanie trybu WAL (domyślnie) do równoległego dostępu - Uruchamianie pełnej reindeksacji poza godzinami pracy

Optymalizacja zapytań

Tryb WAL. Tryb Write-Ahead Logging w SQLite umożliwia równoległe odczyty podczas zapisu przez indekser:

db.execute("PRAGMA journal_mode=WAL")

Ma to krytyczne znaczenie, gdy serwer MCP obsługuje zapytania w czasie, gdy indekser wykonuje aktualizację przyrostową.

Connection pooling. Serwer MCP powinien ponownie wykorzystywać połączenia z bazą danych zamiast otwierać nowe połączenie dla każdego zapytania. Jedno długotrwałe połączenie z trybem WAL obsługuje równoległe odczyty.

# 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. Pragma mmap_size informuje SQLite, aby używać memory-mapped I/O dla pliku bazy danych. W przypadku bazy danych o rozmiarze 83 MB zmapowanie całego pliku w pamięci eliminuje większość odczytów z dysku.

Optymalizacja FTS5. Po pełnej reindeksacji uruchom:

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

Scali to wewnętrzne segmenty b-tree FTS5, zmniejszając opóźnienie zapytań dla kolejnych wyszukiwań.

Benchmarki skalowania

Pomiar wykonano na Apple M3 Pro, 36 GB RAM, NVMe SSD:

Operacja 500 notatek 5K notatek 15K notatek 50K notatek
Zapytanie BM25 2ms 5ms 12ms 25ms
Zapytanie wektorowe 1ms 3ms 8ms 20ms
Fuzja RRF <1ms <1ms 3ms 5ms
Pełne wyszukiwanie 3ms 8ms 23ms 50ms

Wszystkie benchmarki obejmują dostęp do bazy danych, wykonanie zapytania i formatowanie wyników. Opóźnienie sieciowe komunikacji MCP STDIO dodaje 1-2ms.


Rozwiązywanie problemów

Dryf indeksu

Objaw: Wyszukiwanie zwraca nieaktualne wyniki lub pomija niedawno dodane notatki.

Przyczyna: Indekser przyrostowy nie został uruchomiony po dodaniu notatek albo mtime pliku nie został zaktualizowany (np. po synchronizacji z innego komputera z zachowanymi znacznikami czasu).

Poprawka: Uruchom pełną reindeksację: python index_vault.py --full

Zmiana modelu embeddingów

Objaw: Po zmianie modelu embeddingów wyszukiwanie wektorowe zwraca bezsensowne wyniki.

Przyczyna: Stare wektory (z poprzedniego modelu) są porównywane z nowymi wektorami zapytania. Wymiary lub semantyka przestrzeni wektorowej są niezgodne.

Poprawka: Indekser powinien wykryć niezgodność hasha modelu i automatycznie uruchomić pełną reindeksację. Jeśli tak się nie stanie, należy ręcznie wyczyścić bazę danych i ponownie ją zindeksować:

rm vectors.db
python index_vault.py --full

Utrzymanie FTS5

Objaw: Zapytania FTS5 zwracają niepoprawne lub niepełne wyniki po wielu aktualizacjach przyrostowych.

Przyczyna: Wewnętrzne segmenty FTS5 mogą ulec fragmentacji po wielu małych aktualizacjach.

Poprawka: Odbuduj i zoptymalizuj:

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

Timeout MCP

Objaw: Narzędzie AI zgłasza, że serwer MCP przekroczył limit czasu.

Przyczyna: Pierwsze zapytanie uruchamia ładowanie modelu (lazy initialization), co trwa 2-5 sekund. Domyślny timeout MCP w narzędziu AI może być krótszy.

Poprawka: Wstępnie rozgrzej model przy starcie serwera:

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

Blokady plików SQLite

Objaw: Błędy SQLITE_BUSY lub SQLITE_LOCKED.

Przyczyna: Wiele procesów zapisuje jednocześnie do bazy danych. Tryb WAL pozwala na równoległe odczyty, ale tylko jednego zapisującego.

Poprawka: Upewnij się, że tylko jeden proces (indekser) zapisuje do bazy danych. Serwer MCP i hooks powinny wyłącznie odczytywać. Jeśli potrzebne są równoległe zapisy, użyj trybu WAL i ustaw busy timeout:

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

sqlite-vec się nie ładuje

Objaw: Wyszukiwanie wektorowe jest wyłączone; retriever działa w trybie tylko BM25.

Przyczyna: Rozszerzenie sqlite-vec nie jest zainstalowane, nie znajduje się w ścieżce bibliotek albo jest niezgodne z wersją SQLite.

Poprawka:

# Install via pip
pip install sqlite-vec

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

Sprawdź, czy rozszerzenie się ładuje:

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

Problemy z pamięcią w dużym skarbcu

Objaw: Błędy braku pamięci podczas pełnej reindeksacji dużego skarbca (ponad 50 000 notatek).

Przyczyna: Rozmiar batcha embeddingów jest zbyt duży albo zawartość wszystkich plików jest ładowana do pamięci jednocześnie.

Poprawka: Zmniejsz rozmiar batcha i przetwarzaj pliki przyrostowo:

BATCH_SIZE = 32  # Reduce from 64

Należy też upewnić się, że indekser przetwarza pliki pojedynczo (czytając, dzieląc na fragmenty i tworząc embeddingi dla każdego pliku przed przejściem do następnego), zamiast ładować wszystkie pliki do pamięci.


Przewodnik migracji

Z Apple Notes

  1. Wyeksportuj Apple Notes za pomocą opcji „Export All” (macOS) albo użyj narzędzia migracyjnego, takiego jak apple-notes-liberator
  2. Przekonwertuj eksporty HTML na markdown za pomocą markdownify lub pandoc
  3. Przenieś przekonwertowane pliki do folderu 00-inbox/ w swoim skarbcu
  4. Przejrzyj każdą notatkę i dodaj frontmatter
  5. Przenieś notatki do odpowiednich folderów domenowych

Z Notion

  1. Wyeksportuj z Notion: Settings → Export → Markdown & CSV
  2. Rozpakuj eksport do folderu 00-inbox/ w swoim skarbcu
  3. Popraw artefakty markdown specyficzne dla Notion:
  4. Notion używa - [ ] dla checklist — to standardowy markdown
  5. Notion uwzględnia tabele właściwości jako HTML — przekonwertuj je na frontmatter YAML
  6. Notion osadza obrazy jako ścieżki względne — skopiuj obrazy do folderu załączników
  7. Dodaj standardowy frontmatter (type, domain, tags)
  8. Zastąp linki stron Notion wiki-linkami Obsidian

Z Google Docs

  1. Użyj Google Takeout, aby wyeksportować wszystkie dokumenty
  2. Przekonwertuj pliki .docx na markdown: pandoc -f docx -t markdown input.docx -o output.md
  3. Wykonaj konwersję wsadową: for f in *.docx; do pandoc -f docx -t markdown "$f" -o "${f%.docx}.md"; done
  4. Przenieś do skarbca, dodaj frontmatter i uporządkuj w folderach

Ze zwykłego markdown (bez Obsidian)

Jeśli istnieje już katalog plików markdown:

  1. Otwórz katalog jako skarbiec Obsidian (Obsidian → Open Vault → Open folder)
  2. Dodaj .obsidian/ do .gitignore, jeśli katalog jest objęty kontrolą wersji
  3. Utwórz szablony frontmatter i zastosuj je do istniejących plików
  4. Zacznij łączyć notatki za pomocą [[wiki-links]] podczas czytania i porządkowania
  5. Uruchom indekser od razu — system wyszukiwania działa od pierwszego dnia

Z innego systemu wyszukiwania

Jeśli migracja odbywa się z innego systemu embeddingów/wyszukiwania:

  1. Nie próbuj migrować wektorów. Różne modele tworzą niezgodne przestrzenie wektorowe. Uruchom pełną reindeksację z nowym modelem.
  2. Migruj treść, nie indeks. Pliki skarbca są źródłem prawdy. Indeks jest artefaktem pochodnym.
  3. Zweryfikuj po migracji. Uruchom 10-20 zapytań, na które znasz odpowiedzi, i sprawdź, czy wyniki są zgodne z oczekiwaniami.

Dziennik zmian

Data Zmiana
2026-05-28 Wydano Obsidian 1.13.0 desktop + 1.13.0 mobile (Catalyst early-access). Desktop: przeprojektowany panel ustawień otwierany w osobnym oknie, z wbudowanym wyszukiwaniem i nawigacją klawiaturą; Obsidian URI wyświetlają teraz okno potwierdzenia przed uruchomieniem akcji; nowe ostrzeżenie przed ładowaniem zasobów HTML z dysków sieciowych; dodano wyszukiwanie do widoku Bookmarks; ulepszona obsługa obrazów w edytorze; usprawnienia File Explorer / Properties / Sync; liczne poprawki dla developer-API oraz poprawki błędów. Mobile: nowy iOS Share Sheet z konfigurowalnymi lokalizacjami docelowymi; zmiana kolejności kart z poziomu przełącznika kart; gesty naciśnięcia i przytrzymania na tabletach do zmiany rozmiaru podziałów i przypiętych paneli bocznych; Bases otrzymuje pozycję menu do zmiany rozmiaru kolumn w widokach tabel; poprawki błędów w iOS i wyszukiwaniu. Znaczenie dla przepływów pracy AI: okno potwierdzenia dla Obsidian URI dodaje świadomą bramkę do integracji MCP/agent opartych na URI; menu zmiany rozmiaru kolumn w Bases sprawia, że Bases lepiej nadaje się jako frontowy indeks magazynu, który odpytują agenci; konfigurowalny cel iOS Share Sheet przyspiesza konfigurację ścieżki przechwytywania z iPhone’a (już udokumentowanej jako główny kanał przyjmowania) dla potoków Claude/Codex.
2026-05-06 Odświeżenie aktualności zweryfikowanej źródłowo: Smart Connections v4.5.0 przeniósł połączenia stopki do Core; stabilne wydania sqlite-vec v0.1.8/v0.1.9 zaktualizowały pakowanie i zachowanie DELETE; Model2Vec v0.8.x zaktualizował wewnętrzne mechanizmy tokenizera/persistencji oraz tabele benchmarków; poprawiono chronologię Obsidian CLI z „1.12.7 wprowadził CLI” na „1.12.0 wprowadził CLI, 1.12.7 ulepszył instalację i pakowanie runtime”.
2026-04-27 Kwietniowy cykl Web Clipper: 1.4.0 (interaktywny interfejs transkrypcji YouTube + domyślne Open in Reader), 1.5.0 (przeglądarka Highlights), 1.6.0 (przebudowa UX Highlightera + ekstraktory źródeł Defuddle 0.18 dla LinkedIn/Threads/Bluesky/Discourse/Medium), 1.6.1 + 1.6.2 (poprawki Reader i Safari). Przedstawiono Web Clipper jako główną ścieżkę przyjmowania po stronie przeglądarki dla przepływów pracy AI, a nie tylko przelotną wzmiankę o zakładkach. W tym okresie brak wydań Obsidian desktop, Sync lub Bases.
2026-04-16 Smart Connections v4.3.0 (widok grafu, konfigurowalny dock, odzyskiwanie block-embedding, środowisko Substrate dla wielu wtyczek). Udokumentowano falę wtyczek AI-native z kwietnia 2026 (Cortex, VaultSearch, LLM Wiki, Drift, EngramQuest, Hybrid Search MCP). Oznaczono MarkusPfundstein/mcp-obsidian jako maintenance-mode (ostatni commit w czerwcu 2025). Dataview pozostaje uśpiony; Bases jest następcą dla nowych prac. Obsidian CLI 1.12.7 nadal jest preferowanym mostem dla asystentów AI.
2026-04-01 Dodano sekcję Obsidian CLI (polecenia v1.12 dla przepływów pracy AI). Dodano sekcję wtyczek agentowych (Claudian, Agent Client). Udokumentowano podstawową wtyczkę Bases do organizacji magazynu. Zaktualizowano liczbę wtyczek do 2500+. Dodano iOS Share Extension jako źródło przyjmowania. Zaktualizowano macierz zgodności z osadzonymi wtyczkami agentowymi.
2026-03-30 MCPVault v0.11.0: narzędzie list_all_tags, obsługa .base/.canvas, zmiana nazwy na @bitbonsai/mcpvault. Obsidian Desktop v1.12.7 zawiera binarium CLI dla szybszych interakcji terminalowych.
2026-03-23 Udokumentowano stabilne sqlite-vec v0.1.7: obsługa DELETE dla tabel vec0, ograniczenia dystansu KNN do paginacji. Zapowiedziano indeks DiskANN approximate nearest neighbor w nadchodzącym wydaniu.
2026-03-07 Dodano potion-multilingual-128M (101 języków, maj 2025) do porównania modeli embeddingowych. sqlite-vec w wersji v0.1.7-alpha.10 (poprawki CI/CD, bez zmian funkcjonalnych). Potwierdzono aktualność specyfikacji MCP i technik wyszukiwania.
2026-03-03 Zaktualizowano ewolucję specyfikacji MCP (wydanie z listopada 2025: Streamable HTTP, .well-known, adnotacje narzędzi). Dodano fine-tuning Model2Vec oraz obsługę tokenizera BPE/Unigram. Dodano tabelę porównawczą społecznościowych serwerów MCP. Zaktualizowano Smart Connections do v4.
2026-03-02 Dodano potion-base-32M i potion-retrieval-32M do porównania modeli. Dodano sekcję o kwantyzacji i redukcji wymiarowości. Dodano notatkę o ewolucji specyfikacji MCP.
2026-03-01 Pierwsze wydanie

Źródła


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

  2. Nicopreme, skill agenta „Visual Explainer” z poleceniami slash, x.com/nicopreme/status/2023495040258261460

  3. Cormack, G.V., Clarke, C.L.A. i Buettcher, S. Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods. SIGIR, 2009. Wprowadza RRF z k=60 jako metodę bezparametrową do łączenia list rankingowych. 

  4. OpenAI Embeddings Pricing. text-embedding-3-small: 0,02 USD za milion tokenów. Szacowany koszt pełnego ponownego indeksowania vault: ~0,30 USD. 

  5. van Dongen, T. et al. Model2Vec: Turn any Sentence Transformer into a Small Fast Model. arXiv, 2025. Opisuje podejście destylacyjne tworzące statyczne embeddings z sentence transformers. 

  6. potion-base-8M Model Card i Model2Vec results. Aktualne opublikowane tabele podają potion-base-8M na poziomie 51.32 Avg (All) / 51.08 Avg (MTEB), w porównaniu z all-MiniLM-L6-v2 na poziomie 55.80 Avg (All) / 55.93 Avg (MTEB), czyli około 92% zachowania wyniku dla wszystkich zadań. 

  7. Model Context Protocol Specification. Standard MCP do łączenia narzędzi AI ze źródłami danych. 

  8. Model2Vec Potion Models, potion-base-32M i potion-retrieval-32M. Aktualne karty modeli podają potion-base-32M na poziomie 52.83 Avg (All), a potion-retrieval-32M na poziomie 35.06 w tabeli retrieval. 

  9. Update on the Next MCP Protocol Release. Wydanie z listopada 2025 r. dostarczyło transport Streamable HTTP, wykrywanie adresów URL .well-known, strukturalne adnotacje narzędzi oraz standaryzację warstw SDK. Kolejne wydanie wstępnie planowane jest na połowę 2026 r. i ma obejmować operacje asynchroniczne, rozszerzenia dziedzinowe oraz komunikację agent-to-agent. 

  10. Model2Vec Releases. v0.4.0 (luty 2025): obsługa trenowania i fine-tuningu. v0.5.0 (kwiecień 2025): przepisanie backendu, kwantyzacja, redukcja wymiarowości. v0.7.0 (październik 2025): kwantyzacja słownika, obsługa tokenizera BPE/Unigram. v0.8.0/v0.8.1 (marzec 2026): refaktoryzacje tokenizera i utrwalania, wycofanie Python 3.9, aktualizacje wyników MTEB V2 oraz zgodność ze ścieżkami Windows. 

  11. Smart Connections for Obsidian. Smart Connections v4: lokalne AI embeddings, wyszukiwanie semantyczne działa offline po początkowym indeksowaniu. 

  12. potion-multilingual-128M. Minish Lab, maj 2025. Statyczny model embeddingów dla 101 języków, najlepsze wielojęzyczne statyczne embeddings. Ta sama zależność wyłącznie od numpy co w innych modelach potion. 

  13. MCPVault v0.11.0. Marzec 2026. Nowe narzędzie list_all_tags do skanowania frontmatter i hashtagów wraz z licznikami. Ulepszona obsługa folderów z kropkami oraz obsługa plików .base i .canvas. Pakiet zmienił nazwę na @bitbonsai/mcpvault w npm. 

  14. sqlite-vec v0.1.7 Release. 17 marca 2026 r. Stabilne wydanie: obsługa DELETE dla tabel wirtualnych vec0, ograniczenia odległości KNN dla paginacji, ulepszenia testów fuzz. Indeksowanie przybliżonego najbliższego sąsiada DiskANN zapowiedziano w przyszłym wydaniu. 

  15. Introduction to Bases. Podstawowa wtyczka Obsidian wprowadzona w v1.9.10. Widoki podobne do baz danych (tabele, galerie, kalendarze, tablice kanban) nad plikami vault z użyciem właściwości frontmatter jako pól. Pliki zapisywane są w formacie .base

  16. Obsidian Desktop v1.12.0 Changelog i Obsidian Desktop v1.12.7 Changelog. v1.12.0 wprowadziło CLI do terminalowej automatyzacji vault; v1.12.7 ulepszyło instalację i pakowanie środowiska uruchomieniowego dzięki samodzielnemu plikowi binarnemu, TUI oraz zachowaniu pliku socket. Zob. także dokumentację CLI

  17. Claudian. Wtyczka Obsidian, która osadza Claude Code jako współpracownika AI w vault. Zapewnia czat na pasku bocznym, prompty świadome kontekstu, obsługę wizji, slash commands i tryby uprawnień. 

  18. Agent Client. Wtyczka Obsidian zapewniająca ujednolicony interfejs dla Claude Code, Codex CLI i Gemini CLI przez Agent Client Protocol (ACP). Obsługuje wzmianki o notatkach, wykonywanie powłoki i zatwierdzanie działań. 

  19. Obsidian iOS Changelog. Aktualizacje z początku 2026 r. obejmują Share Extension do zapisywania treści z innych aplikacji bezpośrednio w vault, poprawki widżetów Daily Note i Bookmark oraz ulepszenia odświeżania widżetu View Note. 

  20. MarkusPfundstein/mcp-obsidian. Ostatni commit 28 czerwca 2025 r. Brak oznaczonych wydań. Dyskusje na forum (kwiecień 2026) wskazują migrację społeczności do integracji opartej na CLI, odkąd Obsidian 1.12.x dostarczył pełnoprawny CLI. Zachowane w tym przewodniku dla kontekstu historycznego i dla użytkowników z istniejącymi konfiguracjami, ale niezalecane dla nowych wdrożeń. 

  21. Smart Connections v4.5.0 Release. 5 maja 2026 r. Połączenia w stopce stały się funkcją Core; najnowsze wydania v4 obejmują też widoki grafu dla list połączeń, konfigurowalne lokalizacje panelu połączeń, ulepszone odzyskiwanie block-embedding, stan Substrate między wtyczkami, poprawki fallbacku transformera oraz ograniczenie zduplikowanych obliczeń połączeń. 

  22. obsidianmd/obsidian-clipper releases — główne źródło mapowania wersji Web Clipper na funkcje. Cykl z kwietnia 2026 r.: 1.4.0 (9 kwietnia, interfejs transkrypcji YouTube + domyślne Open in Reader), 1.5.0 (15 kwietnia, przeglądarka Highlights + pojawianie się Reader), 1.5.1 (15 kwietnia, poprawka kompilacji webpack), 1.6.0 (21 kwietnia, UX Highlighter + Defuddle 0.18 z ekstraktorami LinkedIn/Threads/Bluesky/Discourse/Medium), 1.6.1 (22 kwietnia, poprawki konspektu Reader + wyszukiwanie highlights), 1.6.2 (23 kwietnia, poprawka schowka w trybie osadzonym Safari). Wpisane także w Mozilla Add-ons store i Chrome Web Store

  23. sqlite-vec v0.1.8, sqlite-vec v0.1.9 i sqlite-vec v0.1.10-alpha.3. v0.1.8 naprawiło pakowanie npm; v0.1.9 naprawiło błąd DELETE dla tekstowych kolumn metadanych dłuższych niż 12 znaków; v0.1.10-alpha.3 dodaje poprawną obsługę INSERT OR REPLACE INTO, ale jest wersją prerelease. 

VAULT obsidian.md INDEXED