obsidian:~/vault$ search --hybrid obsidian

Obsidian MCP + ハイブリッド検索:2026年版リファレンス

# アプリの基本は公式Obsidianドキュメントを参照し、MCP、ハイブリッド検索、16,894ファイルのAI vaultのインデックス作成にはBlakeのリファレンスを活用します。

words: 4091 read_time: 59m updated: 2026-06-11 12:56
$ retriever search --hybrid obsidian

Obsidianは単なるノートアプリではありません。ローカルファーストのプレーンテキストで、グラフ構造を持つMarkdownコーパスです。検索基盤を加えることで、AIコンテキストの貯水池になります。 16,894ファイル。49,746チャンク。23msのクエリ。API呼び出しはゼロ。1つの83 MB SQLiteファイル。このガイドでは、vaultアーキテクチャからhybrid検索、MCP連携、運用ワークフローまで、システム全体を扱います。


重要ポイント

メモ取りではなく、Context engineeringです。 AIにとってObsidian vault(保管庫)の価値は、メモそのものではありません。メモを検索可能にするretrieval層にあります。retrievalなしの16,000ファイルのvaultは、書き込み専用データベースです。hybrid検索とMCP連携を備えた200ファイルのvaultは、AI知識ベースになります。retrieval基盤こそがプロダクトです。メモはその原材料です。

Hybrid retrievalは、純粋なキーワード検索や純粋なsemantic searchより優れています。 BM25は、正確な識別子や関数名を捉えます。Vector searchは、用語が違っても同義語や概念的な一致を捉えます。Reciprocal Rank Fusion (RRF)は、スコア調整を必要とせずに両方を統合します。どちらか一方だけでは、両方の失敗パターンをカバーできません。MS MARCOのpassage rankingに関する研究でも、この傾向が確認されています。hybrid retrievalは、単独の手法より一貫して高い性能を示します。3 hybrid retrieverの詳細解説では、RRFの数式、実際の数値を使った例、失敗パターンの分析、対話型のfusion計算機を扱っています。

MCPにより、AIツールがvaultへ直接アクセスできます。 Model Context Protocol (MCP)サーバーは、retrieverをツールとして公開します。Claude Code、Codex CLI、Cursor、その他のAIツールが、そのツールを直接呼び出せます。エージェントはvaultにクエリを投げ、出典付きのランキング結果を受け取り、ファイル全体を読み込まずにコンテキストを利用します。MCPサーバーは、retrieval engineを包む薄いラッパーです。

Local-firstなら、APIコストはゼロで、プライバシーも完全に保てます。 スタック全体は1台のマシン上で動作します。ストレージにはSQLite、embeddingsにはModel2Vec、キーワード検索にはFTS5、vector KNNにはsqlite-vecを使います。クラウドサービスも、API呼び出しも、ネットワーク依存もありません。個人メモがマシンの外へ出ることはありません。49,746チャンクをすべて再embedしても、OpenAI APIの価格ではおよそ$0.30です。しかし本当のコストは、レイテンシー、プライバシーの露出、そして本来オフラインで動くべきシステムがネットワークに依存することです。4

Incremental indexingにより、10秒未満でシステムを最新に保てます。 ファイルの更新時刻を比較して変更を検出します。変更されたファイルだけを再chunkingし、再embeddingします。Apple M-seriesハードウェアでは、完全なreindexに約4分かかります。一般的な1日の編集量であれば、incremental updateは10秒未満で完了します。手動操作なしで、システムを最新状態に保てます。

このアーキテクチャは、200件のメモから20,000件超のメモまでスケールします。 同じ3層設計(intake、retrieval、integration)は、どの規模のvaultでも機能します。小規模なvaultでは、BM25のみの検索から始めます。キーワードの衝突が問題になったらvector searchを追加します。正確な一致とsemanticな一致の両方が必要になったら、RRF fusionを追加します。各層は単独でも有用で、単独で取り外すこともできます。


このガイドの使い方

このガイドでは、システム全体を扱います。どこから始めるべきかは、現在の状況によって異なります。

該当する状況 ここから開始 次に読む内容
Obsidian + AIが初めて AI InfrastructureにObsidianを使う理由, Quick Start Vault Architecture, MCP Server Architecture
既存のvaultがあり、AIアクセスを追加したい MCP Server Architecture, Claude Code Integration Embedding Models, Full-Text Search
retrieval systemを構築している The Complete Retrieval Pipeline, Reciprocal Rank Fusion Performance Tuning, Troubleshooting
チームまたはenterprise環境で使う Decision Framework, Knowledge Graph Patterns Developer Workflow Recipes, Migration Guide

Contractと記されたセクションには、実装の詳細、設定ブロック、失敗パターンが含まれます。Narrativeと記されたセクションでは、概念、アーキテクチャ上の判断、デザイン選択の背景にある考え方に焦点を当てます。Recipeと記されたセクションでは、ステップごとのワークフローを示します。


AI InfrastructureにObsidianを使う理由

このガイドの主張は次のとおりです。Obsidian vaultは、個人向けAI知識ベースの土台として最適です。local-firstで、plaintextで、グラフ構造を持ち、ユーザーがスタックのすべての層を制御できるからです。

Obsidianが他の選択肢にはない形でAIに与えるもの

Plaintext markdownファイル。 すべてのメモは、ファイルシステム上の.mdファイルです。独自形式も、データベースエクスポートも、内容を読むためのAPIも必要ありません。ファイルを読めるツールなら、どれでもvaultを読めます。grepripgrep、Pythonのpathlib、SQLite FTS5。これらはすべて、ソースファイルに直接作用します。retrieval systemを構築するときにindexingするのは、API responsesではなくファイルです。ソースはファイルシステムなので、indexは常にソースと整合します。

Local-first architecture。 vaultは自分のマシン上にあります。サーバーも、クラウド同期への依存も、APIのレート制限も、自分のコンテンツ処理方法を制限する利用規約もありません。外部サービスなしで、メモをembed、index、chunk、searchできます。これはAI infrastructureにとって重要です。retrieval pipelineの速度は、API endpointの応答速度ではなく、ディスクの速度で決まるからです。プライバシーの面でも重要です。認証情報、健康データ、金融情報、個人的な考察を含むメモが、マシンの外へ出ることはありません。

wiki-linkによるグラフ構造。 Obsidianの[[wiki-link]]構文は、メモ間に有向グラフを作ります。OAuth実装に関するメモは、token rotation、session management、API securityに関するメモへリンクします。グラフ構造には、概念間の関係を人間が整理した結果がエンコードされています。Vector embeddingsはsemanticな類似性を捉えますが、wiki-linksは著者がそのトピックについて考えながら作った意図的なつながりを捉えます。このグラフは、embeddingsでは再現できないシグナルです。

Plugin ecosystem。 Obsidianには2,500以上のcommunity pluginsがあります(2026年3月時点。2025年半ばの1,800以上から増加)。Dataviewは、vaultをデータベースのようにクエリします。Templaterは、JavaScriptロジックを使ってテンプレートからメモを生成します。Git integrationは、vaultをリポジトリへ同期します。Linterは、フォーマットの一貫性を強制します。Bases core plugin(v1.9.10で導入)は、frontmatter propertiesをフィールドとして使い、vaultファイル上にデータベースのようなビュー(テーブル、ギャラリー、カレンダー、kanban boards)を追加します。保存形式は.baseファイルです。15 これらのpluginは、基盤となるplaintext形式を変えずにvaultへ構造を追加します。retrieval systemがindexingするのは、pluginそのものではなく、これらのpluginの出力です。

500万以上のユーザー。 Obsidianには、テンプレート、ワークフロー、plugin、ドキュメントを生み出す大規模で活発なコミュニティがあります。vaultの整理やplugin設定で問題に出会ったとき、誰かがすでに解決策を文書化している可能性が高いです。コミュニティはObsidian周辺ツールも生み出しています。MCP servers、indexing scripts、publishing pipelines、API wrappersなどです。

ファイルシステムだけでは得られないもの

markdownファイルのディレクトリにはplaintextの利点がありますが、Obsidianが追加する次の3つがありません。

  1. 双方向リンク。 Obsidianはbacklinksを自動で追跡します。Note AからNote Bへリンクすると、Note BにはNote Aが参照元として表示されます。グラフパネルでは、接続クラスターを可視化できます。この双方向の把握は、素のファイルシステムにはないメタデータです。

  2. plugin rendering付きのlive preview。 Dataviewクエリ、Mermaid図、callout blocksはリアルタイムにレンダリングされます。保存形式はplaintextのまま、テキストエディタより豊かな執筆体験を得られます。豊かな環境で書き、整理し、retrieval systemは生のmarkdownをindexingします。

  3. Community infrastructure。 Plugin discovery、theme marketplace、sync service(任意)、publish service(任意)、ドキュメントエコシステムがあります。個々の機能はスタンドアロンツールでも再現できますが、Obsidianはそれらを一貫したワークフローとしてまとめています。

Obsidianがしないこと(そして構築するもの)

Obsidianにはretrieval infrastructureは含まれていません。基本的な検索(full-text、filename、tag)はありますが、embedding pipeline、vector search、fusion ranking、MCP server、credential filtering、chunking strategy、外部AIツール向けのintegration hooksはありません。このガイドでは、Obsidianの上に構築するinfrastructureを扱います。 vaultは土台です。retrieval pipeline、MCP server、integration hooksがinfrastructureです。

ここで説明するアーキテクチャは、markdown-firstであり、Obsidian専用ではありません。 Logseq、Foam、Dendron、またはmarkdownファイルだけのプレーンなディレクトリを使っている場合でも、retrieval pipelineは同じように機能します。chunkerは.mdファイルを読みます。embedderはテキスト文字列を処理します。indexerはSQLiteへ書き込みます。これらのコンポーネントはいずれもObsidian固有の機能に依存しません。Obsidianの役割は、retrieverがindexingするmarkdownファイルを生み出すための執筆・整理環境を提供することです。


クイックスタート: 初めての AI 接続 Vault

このセクションでは、5分で vault を AI ツールに接続します。Obsidian をインストールし、vault を作成し、MCP server をインストールして、最初のクエリを実行します。このクイックスタートでは、すぐに結果を得るためにコミュニティ製の MCP server を使います。本番用途向けのカスタム検索パイプラインの構築については、後のセクションで扱います。

前提条件

  • macOS、Linux、または Windows
  • Node.js 18+(MCP server 用)
  • Obsidian 1.12+(CLI 連携用。1.13.1 が現在の公開デスクトップリリースです。MCP のみの構成では、以前のバージョンでも動作します)
  • Claude Code、Codex CLI、または Cursor がインストール済みであること

ステップ 1: vault を作成する

obsidian.md から Obsidian をダウンロードし、新しい vault を作成します。覚えやすい場所を選んでください。MCP server には絶対パスが必要です。

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

retriever が処理できるように、いくつかノートを追加します。10〜20件のノートでも結果を確認するには十分です。各ノートは、意味のあるタイトルと少なくとも1段落の本文を含む .md ファイルにしてください。

ステップ 2: MCP server をインストールする

すぐに vault へアクセスできるコミュニティ製 MCP server は複数あります。このエコシステムは 2025〜2026年にかけて大きく成長しました。最近の注目すべき更新として、MCPVault v0.11.0(2026年3月)では、frontmatter と hashtags を件数付きでスキャンする list_all_tags が追加され、ドットを含むフォルダーの扱いが改善され、.base.canvas ファイルがサポートされました。13 このパッケージは npm 上で @bitbonsai/mcpvault にもリネームされています。

2026年4月の変化 — 推奨ブリッジとしての Obsidian CLI: Obsidian 1.12.0 でファーストクラスの CLI が導入され、公開版 1.12.7 インストーラー(2026年3月23日)には、スタンドアロンバイナリ、TUI、socket-file の改善が含まれ、ターミナルワークフローのインストールと実行が容易になりました。16 現在の公開デスクトップリリースである 1.13.1(公開チャンネル、2026年6月9日)は、1.13.0 からのバージョン更新であり、設定 UX の改善と CodeMirror のアップグレードが中心です。1.12.x の CLI surface を超える新しい AI/自動化機能はありません。2526 mcp-obsidian を支えていた Local REST API plugin から、CLI ベースの連携へコミュニティツールは積極的に移行しています。より高速で安定しているためです。MarkusPfundstein/mcp-obsidian repo は 2025年6月以降コミットがなく、タグ付きリリースも一度もありません。maintenance mode と見なし、CLI ベースの server、または以下に挙げる新しいコミュニティ代替を優先してください。20 推奨セットアップについては、このガイド後半の「AI Workflows 向け Obsidian CLI」セクションをご覧ください。

Server Author Transport Requires Plugin Key Feature
obsidian-mcp-server StevenStavrakis STDIO No 軽量、ファイルベース
mcp-obsidian MarkusPfundstein STDIO Local REST API REST 経由の完全な vault CRUD — maintenance mode、2025年6月以降コミットなし20
obsidian-mcp-tools jacksteamdev STDIO Yes(plugin) セマンティック検索 + Templater
obsidian-claude-code-mcp iansinnott WebSocket Yes(plugin) Claude Code 向け自動検出
obsidian-mcp-server cyanheads STDIO Local REST API tags、frontmatter 管理
Hybrid Search MCP community STDIO No BM25 + セマンティック検索 MCP server + CLI。2026年4月時点で新しく、活発にメンテナンスされています。

クイックスタートでは、.md ファイルを直接読み取るファイルベースの server が最も簡単です。

npm install -g obsidian-mcp-server

ステップ 3: AI ツールを設定する

Claude Code~/.claude/settings.json に追加します。

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

Codex CLI.codex/config.toml に追加します。

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

Cursor.cursor/mcp.json に追加します。

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

ステップ 4: 最初のクエリを実行する

AI ツールを開き、vault のノートで答えられる質問をします。

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

AI ツールが MCP server を呼び出し、vault を検索して一致する内容を返します。ファイルパスと関連する抜粋を含む結果が表示されるはずです。

ここまでで構築したもの

標準プロトコルを通じて、ローカルのナレッジベースを AI ツールに接続しました。MCP server は vault ファイルを読み取り、基本的な検索を実行し、結果を返します。これは最小限の実用バージョンです。

このクイックスタートで得られないもの: - Hybrid retrieval(BM25 + ベクトル検索 + RRF fusion) - embeddings ベースのセマンティック検索 - credential filtering - インクリメンタル indexing - hook ベースの自動コンテキスト注入

このガイドの残りでは、これらの機能を1つずつ構築していきます。クイックスタートは概念実証です。完全なパイプラインでは、本番品質の検索を実現します。


AI Workflows 向け Obsidian CLI

Obsidian 1.12(2026年2月)では、AI ワークフロー向けの新しい連携 surface を開く組み込みコマンドラインインターフェースが導入されました。これは現在の 1.13.1 公開デスクトップリリース(公開チャンネル、2026年6月9日)でも有効です。同リリースは設定 UX と CodeMirror のバージョン更新であり、新しい CLI 機能は追加されていません。162526 CLI は Obsidian GUI のリモートコントロールとして機能します。Obsidian が起動している必要があります(または最初のコマンド実行時に自動起動します)。Settings > General > Command line interface で有効化してください。

AI インフラにとって CLI が重要な理由

CLI は、これまで GUI または plugin APIs が必要だった Obsidian ネイティブ操作へのプログラム的アクセスを提供します。AI ワークフローにおける主な機能は次のとおりです。

  • スクリプトや hooks から検索する。 obsidian search "query"obsidian search:context "query" により、任意のシェルスクリプト、hook、自動化パイプラインから vault 検索を実行できます。search:context バリアントは、一致した行とその周辺コンテキストを返すため、AI prompts に結果を渡す用途に便利です。
  • daily notes の自動化。 obsidian daily は今日の daily note を開く、または作成します。シェルスクリプトと組み合わせることで、自動化された daily briefing ワークフローを実現できます。たとえば hook が AI 生成の要約を daily note に追記できます。
  • template ベースのノート作成。 obsidian template listobsidian template create は、Templater または core templates からノートを生成します。AI agents が markdown ファイルを直接書き込まずに、構造化された vault entries を作成できます。
  • property 管理。 obsidian property setobsidian property get は frontmatter properties を読み書きします。YAML を解析せずに、スクリプトからメタデータを更新できます。
  • plugin 制御。 obsidian plugin enable/disable/list は plugin をプログラムで管理します。バッチ処理中に indexing plugins を切り替える用途に便利です。
  • task 管理。 obsidian task list/add/complete は構造化された task アクセスを提供します。vault 内の作業項目を管理する AI agents に役立ちます。

AI アクセスにおける CLI と MCP の違い

CLI と MCP servers は役割が異なり、競合ではなく補完関係にあります。

Aspect Obsidian CLI MCP Server
Caller シェルスクリプト、hooks、cron jobs AI agents(Claude Code、Codex、Cursor)
Protocol POSIX process(stdin/stdout/stderr) MCP(STDIO または HTTP 上の JSON-RPC)
Strength Obsidian ネイティブ操作(templates、plugins、properties) カスタム検索(embeddings、BM25、RRF fusion)
Limitation ベクトル検索なし、embedding pipeline なし Obsidian 内部操作へアクセス不可
Best for 自動化スクリプト、intake pipelines、hook actions セッション中のリアルタイム AI agent queries

推奨: intake automation(ノート作成、properties 管理、Obsidian ネイティブ検索の実行)には CLI を使い、retrieval(embeddings を使った hybrid search)には MCP を使ってください。PreToolUse hook では、ランク付けされた結果を得るために完全な MCP retriever へフォールバックする前の高速な事前確認として、obsidian search:context を呼び出せます。

例: CLI を使った intake hook

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

Obsidian Agentプラグイン

Obsidianプラグインの中で、AI coding agentをvault(Obsidianの保管庫)UIに直接組み込むカテゴリが広がっています。外部のMCPサーバー設定の代替となるものです。これらのプラグインは、外部ツールから接続するのではなく、Obsidianのサイドバー内でAI agentを実行します。

Claudian

Claudianは、Claude CodeをAIコラボレーターとしてvaultに組み込みます。vaultディレクトリがClaudeの作業ディレクトリになり、ファイルの読み書き、検索、bashコマンド、複数ステップのワークフローといった、完全なagentic capabilitiesを利用できます。17

AIインフラ向けの主な機能: - コンテキスト対応プロンプト。 フォーカス中のノートを自動で添付し、@notenameによるファイル参照、タグベースの除外、エディタ上の選択範囲をコンテキストとしてサポートします。 - Visionサポート。 ドラッグ&ドロップ、貼り付け、ファイルパス経由で画像を分析できます。vaultに保存したスクリーンショットや図を処理する場合に便利です。 - Slash commands。 /commandで呼び出せる再利用可能なプロンプトテンプレートを作成し、標準化されたvault操作を実行できます。 - 権限モード。 YOLO(自動承認)、Safe(各アクションを承認)、Plan(計画のみ)モードがあり、安全用のブロックリストとvault内への制限を備えています。

Agent Client

Agent Clientは、Agent Client Protocol(ACP)を通じて、Claude Code、Codex CLI、Gemini CLIを統合されたObsidianサイドバーに取り込みます。18

主な機能: - 複数agentの切り替え。 同じパネルからClaude Code、Codex、Gemini CLIとチャットでき、必要に応じてagentを切り替えられます。 - ノート参照。 Claudianと同様に、@notenameでノートの内容をプロンプトに含められますが、特定のagentに依存しません。 - Shell実行。 チャット内でターミナルコマンドをインライン実行できます。ビルドスクリプト、gitコマンド、その他のターミナル操作を会話から離れずに実行できます。 - アクション承認。 ファイル読み取り、編集、コマンド実行を細かく制御できます。

agentプラグインと外部MCPの使い分け

シナリオ agentプラグイン 外部MCP
AI支援でvaultノートを書いたり編集したりする より適しています。agentがエディタのコンテキストを把握できます 動作しますが、エディタの認識はありません
複数repoにまたがるコード開発 限定的です。vaultスコープになります より適しています。プロジェクトスコープでfilesystem全体を扱えます
大規模なindex済みcorpusからの検索 基本検索のみです 完全なhybrid retrieval pipelineを利用できます
ノート作成中のすばやいvault Q&A 理想的です。コンテキスト切り替えが不要です ターミナルへ切り替える必要があります

推奨: ノートの作成、整理、要約など、vault中心のワークフローにはagentプラグインを使います。AI agentが完全なretrieval pipelineとvault外のcodebaseへのアクセスを必要とする開発ワークフローには、外部MCPサーバーを使います。2つのアプローチは共存できます。ノート作業にはObsidian内でClaudianを実行し、開発には外部でClaude CodeとMCPを使えます。


判断フレームワーク: Obsidianと代替ツール

すべてのユースケースにObsidianが必要なわけではありません。このセクションでは、Obsidianが適した基盤になる場合、過剰になる場合、そして別のものがより合う場合を整理します。

判断ツリー

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.

比較マトリクス

基準 Obsidian Notion Apple Notes プレーンなFilesystem CLAUDE.md
Local-first はい いいえ(cloud) 一部(iCloud) はい はい
Plaintext はい(markdown) いいえ(blocks) いいえ(独自形式) はい はい
Graph構造 はい(wiki-links) 一部(mentions) いいえ いいえ いいえ
AIでindex可能 直接ファイルアクセス APIが必要 exportが必要 直接ファイルアクセス すでにコンテキスト内
プラグインエコシステム 2,500以上のプラグイン 連携機能 なし N/A N/A
Offline対応 完全対応 キャッシュ済みの読み取りのみ 一部対応 完全対応 完全対応
10K以上のノートへのスケール はい はい(API使用時) 劣化します はい いいえ(単一ファイル)
コスト 無料(core) $10/月以上 無料 無料 無料

Obsidianが過剰になる場合

  • 単一プロジェクトのコンテキスト。 AIが現在のcodebaseについてのコンテキストだけを必要とするなら、CLAUDE.mdAGENTS.md、またはプロジェクトレベルのドキュメントに入れます。これらのファイルはrepoと一緒に移動し、自動で読み込まれます。
  • 構造化データ。 内容がテーブル、レコード、schemaである場合はdatabaseを使います。Obsidianのノートはprose-firstです。Dataviewでfrontmatterフィールドをqueryできますが、構造化queryは本物のdatabaseのほうが適しています。
  • 一時的なリサーチ。 プロジェクト終了後にノートを破棄するなら、markdownファイルを置いたscratchディレクトリのほうがシンプルです。一時的なコンテンツのためにretrieval infrastructureを構築する必要はありません。

Obsidianが適している場合

  • 数か月から数年にわたって知識を蓄積する。 corpusが成長するほど価値が積み上がります。毎日6か月queryされる200ノートのvaultは、一度しかqueryされない5,000ノートのvaultよりも価値があります。
  • 複数ドメインを1つのcorpusにまとめる。 programming、architecture、security、デザイン、個人プロジェクトのノートを含むvaultでは、プロジェクト固有のCLAUDE.mdでは得られないcross-domain retrievalの恩恵があります。
  • Privacy-sensitiveなコンテンツ。 Local-firstであれば、retrieval pipelineがコンテンツを外部サービスへ送ることはありません。vaultには、cloudサービスへアップロードしたくない内容も含めて、入れたものがそのまま保存されます。

メンタルモデル: 3つのレイヤー

このシステムには、独立して動作しながら、組み合わせることで効果が積み上がる3つのレイヤーがあります。各レイヤーは関心ごとが異なり、失敗モードも異なります。

┌─────────────────────────────────────────────────────┐
                 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は、何がvaultに入るかを決めます。curationがなければ、vaultにはノイズが蓄積します。tweetのスクリーンショット、注釈のないコピー&ペースト記事、コンテキストのない書きかけの思考などです。Intakeレイヤーは、入口の時点で品質管理を担います。スコアリングpipeline、タグ付け規約、手動レビューprocessなど、vaultにretrievalする価値のあるコンテンツが含まれるようにする仕組みです。

Retrievalは、vaultをquery可能にします。これがエンジンです。ノートを検索単位にchunkingし、chunkをvector spaceにembeddingsし、keyword検索とsemantic検索用にindexし、RRFで結果を統合します。Retrievalレイヤーは、ファイルのディレクトリをquery可能なknowledge baseに変換します。このレイヤーがなければ、vaultは手動ブラウズと基本検索では移動できますが、AIツールからprogrammaticallyにはアクセスできません。

Integrationは、retrievalレイヤーをAIツールにつなぎます。MCPサーバーは、retrievalを呼び出し可能なツールとして公開します。hooksはコンテキストを自動で注入します。Skillsは新しい知識をvaultへ戻して記録します。Integrationレイヤーは、knowledge baseと、それを利用するAI agentsの間にあるインターフェースです。

これらのレイヤーは、意図的にdecoupledされています。Intakeのスコアリングpipelineは、embeddingsについて何も知りません。Retrieverは、signal routing rulesについて何も知りません。MCPサーバーは、ノートがどのように作成されたかを知りません。このdecouplingにより、どのレイヤーも独立して改善できます。Intake pipelineを変えずにembedding modelを置き換えられます。Retrieverを修正せずに新しいMCP機能を追加できます。Indexに触れずにsignal scoring heuristicsを変更できます。


AIが利用しやすいVaultアーキテクチャ

AI検索に最適化した保管庫(Obsidianのvault)は、個人が閲覧しやすい保管庫とは異なる慣例に従います。このセクションでは、フォルダー構造、ノートスキーマ、frontmatterの慣例、検索品質を高める具体的なパターンを扱います。

フォルダー構造

トップレベルのフォルダーには番号付きプレフィックスを使い、予測しやすい整理階層を作ります。この番号は優先度を示すものではありません。関連する領域をまとめ、構造を見渡しやすくするためのものです。

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

インデックス対象にすべきフォルダー: Markdownの本文を含むものすべてです。projects、areas、resources、signals、daily notesなどが該当します。

インデックス対象から除外すべきフォルダー: Templates(コンテンツではなくプレースホルダー変数を含むため)、attachments(バイナリファイル)、Obsidian設定、そして検索インデックスに入れたくない機密コンテンツを含むフォルダーです。

.indexignoreファイル

保管庫のルートに.indexignoreファイルを作成し、検索インデックスから除外するパスを明示します。構文は.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/

インデクサーはスキャン前にこのファイルを読み込み、一致するパスを完全にスキップします。除外パス内のファイルは、chunkingされることも、embeddings化されることも、検索結果に表示されることもありません。

ノートスキーマ

すべてのノートにはYAML frontmatterを持たせるべきです。retrieverはfrontmatterフィールドを、フィルタリングとコンテキスト強化に使用します。

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

検索に必須のフィールド:

  • title — 検索結果の表示と、BM25向けの見出しコンテキストに使われます
  • type — typeで絞り込んだクエリを可能にします(「MOCだけ表示」「signalsだけ表示」など)
  • tags — FTS5の見出しコンテキストに0.3の重みでインデックスされるため、本文で別の用語を使っていてもキーワード一致を得られます

任意ですが価値の高いフィールド:

  • domain — domain単位のクエリを可能にします(「securityノートだけ検索」など)
  • source — 取り込んだコンテンツの出典です。retrieverが結果にソースURLを含められます
  • status — archivedやdraftのノートをアクティブな検索から除外できます

Chunkingの慣例

retrieverはH2(##)見出しの境界でchunkingします。つまり、ノート構造が検索の粒度に直接影響します。

検索に適した構造:

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

3つのH2セクションから、独立して検索できる3つのチャンクが作られます。各チャンクには、embeddingが意味を捉えるのに十分なコンテキストがあります。「expired token handling」に関するクエリは、特に3つ目のチャンクに一致します。

検索に適さない構造:

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

H2見出しのない長いセクションが1つだけあると、1つの大きなチャンクになります。embeddingはセクション内のすべてのトピックを平均化します。そのため、どのサブトピックに関するクエリでも、ノート全体に同じように一致してしまいます。

経験則: 1つのセクションで複数の概念を扱う場合は、H2サブセクションに分割しましょう。残りはchunkerが処理します。

ノートに入れるべきでないもの

検索品質を下げるコンテンツは次のとおりです。

  • 記事全文を注釈なしでそのままコピー&ペーストしたもの。 retrieverは元記事のキーワードをインデックスするため、自分で書いていないコンテンツで保管庫が薄まってしまいます。代わりに、要約を追加する、要点を抽出する、またはソースURLにリンクしてください。
  • テキスト説明のないスクリーンショット。 retrieverがインデックスするのはMarkdownテキストです。altテキストや周辺の説明がない画像は、BM25にもvector searchにも見えません。
  • 認証情報の文字列。 APIキー、トークン、パスワード、接続文字列です。credential filteringがあっても、最も安全なのは秘密情報をノートに貼り付けないことです。代わりに、名前で参照してください(「~/.envにあるCloudflare APIトークン」など)。
  • キュレーションされていない自動生成コンテンツ。 ツールがノートを生成する場合(会議の文字起こし、Readwiseのハイライト、RSSインポートなど)、恒久的な保管庫に入れる前に確認し、注釈を加えてください。未整理の自動インポートは量を増やすだけで、検索できる価値は増やしません。

AIワークフロー向けプラグインエコシステム

AI検索のためにvaultの品質を高めるObsidianプラグインは、構造(整合性を強制する)、クエリ(metadataを可視化する)、sync(vaultを最新に保つ)の3つに分類できます。

必須プラグイン

Dataview。 frontmatterフィールドを使って、vaultをデータベースのようにクエリできます。「過去30日以内に更新されたsecurityタグ付きの全ノート」や「statusがactiveの全プロジェクトノート」といった動的インデックスを作成できます。Dataviewは検索そのものを直接改善するわけではありませんが、vaultのカバレッジの穴を見つけたり、更新が必要なノートを特定したりするのに役立ちます。

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

Templater。 動的フィールドを含むテンプレートからノートを作成します。createdtypedomainフィールドを事前入力するテンプレートを使えば、新しいノートが常に正しいfrontmatterから始まるようにできます。一貫したfrontmatterは、検索フィルタリングの精度を高めます。

<%* /* 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。 vault全体にフォーマットルールを適用します。一貫した見出し階層(タイトルにH1、セクションにH2、サブセクションにH3)があると、chunkerが予測しやすい結果を生成できます。検索に関係するLinterルールは次のとおりです。

  • 見出しの段階: 見出しレベルを順番どおりにする(H1からH3へ飛ばない)
  • YAMLタイトル: ファイル名と一致させる
  • 行末スペース: 削除する(FTS5のtokenizationアーティファクトを避ける)
  • 連続する空行: 1つまでに制限する(chunkがきれいになる)

Git integration。 vaultのバージョン管理です。変更を時系列で追跡し、マシン間で同期し、誤削除から復旧できます。Gitは、indexerが増分変更検出に使うmtimeデータも提供します。

インデックス作成に役立つプラグイン

Smart Connections。 Obsidian内でAIによるセマンティック検索を提供するObsidianプラグインです。Smart Connections v4はデフォルトでローカルembeddingsを作成します。vaultのインデックス作成が終われば、semantic connectionsと検索はAPI callsなしで完全にオフライン動作します。11 v4.5.0(2026年5月5日)では、footer connectionsがSmart Connections Coreの一部になりました。そのため、どのインストールでもサイドパネルを開かずに、関連ノートのつながりをフッターに表示できます。最近のv4リリースでは、connection list向けのgraph view、設定可能なdock locations、中断されたインデックス作成後のblock-embedding復旧改善、そしてSmart Connections、Smart Chat、Smart Composerが状態を共有できるクロスプラグイン環境「Substrate」も追加されています。21 このガイドの検索システムはObsidian外部で動作します(Python pipelineとして実行)。それでもSmart Connectionsは、執筆中にセマンティックな関係を探索するうえで有用です。2つのシステムは同じコンテンツをインデックス化しますが、用途が異なります。Smart Connectionsはエディタ内での発見に、外部retrieverはMCP経由のAIツール統合に使います。

2026年4月に登場したAI-nativeプラグイン。 新しいコミュニティプラグインの波が、Claude Code / Codex / Gemini-CLIワークフローを直接ターゲットにしています。

プラグイン リリース 機能
Cortex 4月4日 Claude Codeで動くvault agent。vaultを単なるノート保管庫ではなく、agentワークスペースとして扱います
VaultSearch 4月7日 ローカルファーストのhybrid検索: BM25 + semantic + fuzzy(このガイドの検索スタックと直接重なります)
LLM Wiki 4月9日 vaultをプライベートにクエリ可能なナレッジベースに変えます
Drift 4月11日 AIによるObsidian編集向けのVS Code風diffビューア。Claude Codeワークフロー向けに位置づけられています
EngramQuest 4月11日 ノートから記憶チャレンジを生成します。Claude Code / Gemini CLI / Cursor向けの「AI Skills」も同梱されています
Hybrid Search MCP 3月(まだ新しい) BM25 + semantic検索を備えたMCP server + CLI。AIアシスタント向けに作られています

これは新しく現れつつある領域として扱いましょう。今後数四半期で、これらのいくつかは統合されるか、Smart Connections / Obsidian coreに吸収される可能性があります。今日1つ選ぶなら、VaultSearchとHybrid Search MCPが、このガイドの外部retrieverに最も近い思想を持っています。

Dataviewメモ: Dataview(長く使われているObsidianクエリプラグイン)は、2025年4月に0.5.70を最後にリリースして以降、実質的に休止状態です。新しい作業では、Obsidian組み込みのBases機能(1.9+)が暗黙の後継であり、推奨される道筋です。

Metadata Menu。 フィールド値のautocomplete付きで、構造化されたfrontmatter編集を提供します。typedomaintagsフィールドでの入力ミスを減らせます。一貫したmetadataは、検索フィルタリングの精度を高めます。

インデックス作成に悪影響を与えるプラグイン

Excalidraw。 図面をmarkdownファイル内のJSONとして保存します。JSONは構文上は有効なmarkdownですが、chunk化してembeddingするとノイズになります。.indexignoreを使うか、ファイル拡張子でフィルタリングして、Excalidrawファイルをインデックスから除外してください。

Kanban。 ボード状態を特殊なフォーマットのmarkdownとして保存します。この形式はKanban表示のために設計されており、文章検索向けではありません。chunkerはカードタイトルやmetadataの断片を生成しますが、うまくembeddingされません。Kanbanボードはインデックスから除外してください。

Calendar。 最小限の内容の日次ノートを作成します(多くの場合、日付の見出しだけです)。空またはほぼ空のノートは、低品質なchunkを生みます。日次ノートを使う場合は、実質的な内容を書くか、日次ノートフォルダをインデックスから除外してください。

重要なプラグイン設定

ファイル復元 → 有効。 誤ってノートを削除した場合に備えます。検索とは直接関係ありませんが、依存しているナレッジベースにとっては重要です。

Strict line breaks → 無効。 Markdown標準の改行(段落には空行を2つ)を使うほうが、Obsidianのstrict mode(<br>に単一改行)よりもきれいなchunkを生成できます。

Default new file location → 指定フォルダ。 新規ファイルを00-inbox/に送ることで、未分類ノートがdomainフォルダを汚さないようにします。inboxはステージング領域です。ファイルはトリアージ後にdomainフォルダへ移動します。

Wiki-link format → 可能な場合は最短パス。 リンク先が短いほど、link structureをインデックス化するときにretrieverが解決しやすくなります。


Embedding Models:選び方と設定

embedding modelは、テキストのチャンクをセマンティック検索用の数値ベクトルに変換します。どのモデルを選ぶかによって、検索品質、インデックスサイズ、embedding速度、実行時の依存関係が決まります。このセクションでは、Model2Vecのpotion-base-8Mをデフォルトにしている理由と、代替モデルを選ぶべき場面を説明します。

Model2Vec potion-base-8Mを選ぶ理由

Model: minishlab/potion-base-8M Parameters: 7.6 million Dimensions: 256 Size: ~30 MB Dependencies: model2vec(numpyのみ、PyTorch不要) Inference: CPUのみ、静的な単語embeddings(attention layersなし)

Model2Vecは、sentence transformerの知識を静的なtoken embeddingsへ蒸留します。BERT、MiniLM、その他のtransformer modelsのように入力に対してattention layersを実行するのではなく、Model2Vecは事前計算済みtoken embeddingsの重み付き平均でベクトルを生成します。5 実用上の結果として、逐次計算がないため、embedding速度はtransformer-based modelsより50〜500倍高速です。

現在のModel2Vec results pageでは、potion-base-8Mはall-MiniLM-L6-v2のall-task scoreの約92%(51.32対55.80)に達しながら、桁違いに高速です。6 残る品質差は、速度とシンプルさを得るためのトレードオフです。短いmarkdownチャンク(一般的な保管庫(Obsidianのvault)では平均200〜400語)では、長い文書ほど品質差は目立ちません。短く焦点の定まったテキストでは、どちらのモデルも似た表現に収束するためです。

設定

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

遅延読み込み。 モデルはimport時ではなく、初回使用時に読み込まれます。retrieverがBM25-only fallback modeで動作する場合(たとえばembedding venvがインストールされていない場合)、embedder moduleをimportしてもコストはかかりません。

分離されたvirtual environment。 依存関係がtoolchainの他の部分と衝突しないよう、モデルは専用のvenv(例:~/.claude/venvs/memory/)で実行します。_activate_venv()関数は、実行時にvenvのsite-packagessys.pathへ追加します。

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

バッチ処理。 embedderはModel2Vecのオーバーヘッドをならすため、64件ずつテキストを処理します。indexerは、チャンクを1件ずつembeddingするのではなく、embed_batch()へ渡します。

代替モデルを選ぶタイミング

Model Dim Size Speed Quality (MTEB) 最適な用途
potion-base-8M 256 30 MB 500x 51.32 デフォルト:ローカル、高速、GPU不要
potion-base-32M 256 120 MB 400x 52.83 より高品質、引き続きstatic
potion-retrieval-32M 256 120 MB 400x 35.06 (retrieval) Retrieval向けに最適化されたstatic
potion-multilingual-128M 256 ~500 MB 300x 多言語の保管庫(101言語)
all-MiniLM-L6-v2 384 80 MB 1x 55.80 より高品質、引き続きローカル
nomic-embed-text-v1.5 768 270 MB 0.5x 62.28 最高のローカル品質
text-embedding-3-small 1536 API N/A 62.30 APIベース、最高品質

potion-base-32Mを選ぶのは、静的embeddingファミリーのまま、potion-base-8Mより高い品質が必要な場合です。baai/bge-base-en-v1.5から蒸留されたより大きな語彙を使い、同じ256次元の出力とnumpyのみの依存関係を保ったまま、52.83のall-task score(potion-base-8Mより約3%高い)を達成します。8 モデルファイルが4倍大きくなるためメモリ使用量は増えますが、embedding速度はtransformer modelsより桁違いに高速なままです。

potion-retrieval-32Mを選ぶのは、主な用途がretrieval(保管庫検索がまさにこれです)の場合です。このvariantはpotion-base-32Mからretrieval tasks向けにfine-tunedされており、Model2Vecのretrieval benchmark tableで35.06を記録しています。potion-base-32Mは32.67です。8 トレードオフとして、汎用的なembedding品質ではなくretrievalに最適化されています。

potion-multilingual-128Mを選ぶのは、保管庫に複数言語のノートが含まれる場合です。2025年5月にリリースされたこの101言語対応モデルは、多言語タスク向けの静的embedding modelとして最高性能で、他のpotion modelsと同じnumpyのみの依存関係を保ちながら、あらゆる言語のテキストに対してembeddingsを生成します。12 より大きなモデルファイル(約500 MB)は、cross-lingual capabilityのためのトレードオフです。英語コンテンツに加えて、日本語、中国語、ドイツ語、その他の非英語ノートがある場合に使います。

all-MiniLM-L6-v2を選ぶのは、速度よりretrieval品質が重要で、PyTorchがインストール済みの場合です。384次元ベクトルにより、256次元ベクトルと比べてSQLite database sizeは約50%増えます。M-series hardwareで15,000ファイルをfull reindexする場合、embedding速度は1分未満から約10分へ低下します。

nomic-embed-text-v1.5を選ぶのは、可能な限り最高のローカルretrieval品質が必要で、indexingが遅くなることを許容できる場合です。768次元ベクトルにより、database sizeはおおむね3倍になります。PyTorchと、modern CPUまたはGPUが必要です。

text-embedding-3-smallを選ぶのは、network latencyとprivacyを許容できるトレードオフとして扱える場合です。APIは最高品質のembeddingsを生成しますが、cloud dependency、tokenごとのコスト($0.02/million tokens)、そしてコンテンツがOpenAIのserversへ送信されることを伴います。

それ以外のすべてのケースではpotion-base-8Mのままにします。 反復的なindexing(開発中のreindex)では速度面の利点が重要で、numpyのみの依存関係によりPyTorchインストールの複雑さを避けられ、256次元ベクトルによってdatabaseをコンパクトに保てます。

Quantizationと次元削減

Model2Vec v0.5.0+は、精度と次元を削減したモデルの読み込みをサポートしています。8 制約のあるhardwareへdeploymentする場合や、モデルを切り替えずにdatabase sizeを減らしたい場合に便利です。

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)

Quantized modelsは、メモリフットプリントを大幅に削減しながら、ほぼ同等のretrieval品質を維持します。次元削減はMatryoshka-style truncationに従い、最初のN次元に最も多くの情報が含まれます。256次元から128次元へ減らすと、短文retrievalでは品質低下を最小限に抑えつつ、vector storageを半分にできます。

Model2Vec v0.8.xでは、tokenizer/persistence internalsが更新され、Python 3.9 supportがdeprecateされ、公開結果が新しいMTEB tablesに更新されています。本番indexerをupgradeする前にmodel2vecをpinまたはtestしてください。embedding model nameが同じでも、library upgradesによってmodel-loading pathsが変わることがあるためです。10

保管庫固有のEmbeddings向けFine-Tuning

Model2Vec v0.4.0+は、静的embeddingsの上にcustom classification modelsをtrainingする機能をサポートしています。v0.7.0ではvocabulary quantizationとdistillation用のconfigurable poolingが追加され、v0.8.xではtokenizerとpersistence behaviorがrefactorされています。10 これは、専門用語を含む保管庫(医療ノート、法的参照、domain-specific jargonなど)で関連します。こうした保管庫では、デフォルトのpotion modelsがsemantic nuancesを十分に捉えられない場合があります。

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

ほとんどの保管庫では、デフォルトのpotion-base-8Mで十分なretrieval品質が得られます。Fine-tuningに価値があるのは、general-purpose modelでは捉えられないdomain-specific connectionsをretrievalが一貫して見逃す場合だけです。

Model Hash Tracking

indexerは、model nameとvocabulary sizeから導出したhashを保存します。embedding modelを変更すると、次回のincremental runでindexerが不一致を検出し、自動的にfull reindexを開始します。

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]

これにより、異なるモデル由来のベクトルが同じdatabase内で混在することを防げます。混在すると、cosine similarity scoresは意味をなさなくなります。

Failure Modes

Model download failure。 初回実行時に、モデルはHugging Faceからdownloadされます。downloadが失敗した場合(network issue、corporate firewallなど)、retrieverはBM25-only modeへfallbackします。初回download後、モデルはローカルにcacheされます。

Dimension mismatch。 databaseをclearせずにモデルを切り替えると、保存済みベクトルの次元が新しいembeddingsと異なります。indexerはmodel hashを使ってこれを検出し、full reindexを開始します。hash checkが失敗した場合(proper hashのないcustom modelなど)、sqlite-vecは次元不一致のKNN queriesでerrorになります。

大規模な保管庫でのmemory pressure。 50,000件以上のチャンクを単一batchでembeddingすると、かなりのメモリを消費する可能性があります。indexerはpeak memory usageを抑えるため、64件ずつbatch処理します。それでもメモリが問題になる場合は、batch sizeを減らしてください。


FTS5による全文検索

SQLiteのFTS5拡張は、BM25ランキングを使った全文検索を提供します。FTS5は、hybrid retrievalパイプラインにおけるキーワード検索のコンポーネントです。このセクションでは、FTS5の設定、BM25が強い場面、そして具体的な失敗パターンを扱います。

FTS5 Virtual Table

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

content-syncモード。 content=chunksパラメータは、テキストの重複コピーを保存するのではなく、FTS5にchunksテーブルを直接参照させます。これにより保存容量は半分になりますが、チャンクの挿入、更新、削除時にはFTS5を手動で同期する必要があります。

カラム。 3つのカラムをインデックス化します。 - chunk_text:各チャンクの主要コンテンツ(BM25 weight: 1.0) - section:H2見出しのテキスト(BM25 weight: 0.5) - heading_context:ノートのタイトル、タグ、メタデータ(BM25 weight: 0.3)

BM25ランキング

BM25は、term frequency、inverse document frequency、document length normalizationに基づいてドキュメントをランク付けします。FTS5のbm25()補助関数は、カラムごとの重みを受け取れます。

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;

カラムの重み(1.0、0.5、0.3)は、次の意味です。 - chunk_textでのキーワード一致がスコアに最も大きく寄与します - section(見出し)での一致は、その半分の寄与になります - heading_context(タイトル、タグ)での一致は、30%の寄与になります

これらの重みは調整できます。保管庫の見出しが説明的で、コンテンツ品質を強く予測できる場合は、sectionの重みを上げます。タグが網羅的かつ正確な場合は、heading_contextの重みを上げてください。

BM25が勝つ場面

BM25は、正確な識別子を含むクエリで力を発揮します。

  • 関数名: _rrf_fuse, embed_batch, get_stale_files
  • CLIフラグ: --incremental, --vault, --model
  • 設定キー: bm25_weight, max_tokens, batch_size
  • エラーメッセージ: SQLITE_LOCKED, ConnectionRefusedError
  • 特定の専門用語: PostToolUse, PreToolUse, AGENTS.md

これらのクエリでは、BM25は完全一致をすぐに見つけます。ベクトル検索では意味的に関連するコンテンツは返せますが、概念的な説明よりも完全一致の順位が低くなる可能性があります。

BM25が失敗する場面

BM25は、保存されているコンテンツと異なる用語を使ったクエリで失敗します。

  • Query: “how to handle authentication failures” → 保管庫には「login error recovery」や「session expiration handling」に関するノートがあります。キーワードが異なるため、BM25は一致させられません。
  • Query: “what is the best way to manage state” → 保管庫には「Redux store patterns」や「context providers」に関するノートがあります。「state management」が特定の技術名で表現されているため、BM25は取りこぼします。

BM25は、大規模になるとキーワード衝突でも失敗します。15,000ファイルの保管庫で「configuration」を検索すると、ほぼすべてのプロジェクトノートが設定に触れているため、数百件のノートに一致します。結果は技術的には正しいものの、実用上は役に立ちません。ランキングでは、どの「configuration」ノートが現在のクエリに関連しているかを判定できないためです。

FTS5 Tokenizer

FTS5はデフォルトでunicode61 tokenizerを使用し、ASCIIとUnicodeテキストを処理します。CJK(中国語、日本語、韓国語)コンテンツが多い保管庫では、trigram tokenizerを検討してください。

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

デフォルトのunicode61 tokenizerは単語境界で分割しますが、単語間にスペースがない言語ではうまく機能しません。trigram tokenizerは3文字ごとに分割するため、インデックスサイズが大きくなる(おおよそ3倍)代わりに、部分文字列のマッチングが可能になります。

メンテナンス

基盤となるchunksテーブルが変更された場合、FTS5は明示的な同期を必要とします。

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

rebuildコマンドは、content tableからFTS5インデックスを再構築します。一括挿入(フル再インデックス)の後に実行してください。ただし、個別の差分更新の後には使いません。その場合は、INSERT INTO chunks_fts(rowid, chunk_text, section, heading_context)を使って個別行を同期します。


sqlite-vec拡張は、vector KNN(K-Nearest Neighbors)検索をSQLiteに持ち込みます。このセクションでは、sqlite-vecの設定、ノートから検索可能なvectorまでのembedding pipeline、そして具体的なquery patternを扱います。

sqlite-vec Virtual Table

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

vec0 moduleは、256次元のfloat vectorをpacked binary dataとして保存します。id列はchunks tableと1:1で対応し、vector resultsとchunk metadataをjoinできるようにします。

Embedding Pipeline

pipelineは、ノートから検索可能なvectorへ次のように流れます。

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

Vector Serialization

Pythonのstruct moduleは、sqlite-vec storage向けにfloat vectorをserializeします。

import struct

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

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

KNN Query

vector search queryでは、入力queryをembedし、cosine distanceで最も近いK個のchunksを見つけます。

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

sqlite-vecのMATCH operatorは、approximate nearest neighbor searchを実行します。k parameterで返すresults数を制御します。distance列にはcosine distance(0 = identical、2 = opposite)が入ります。

Distance制約付きKNN Pagination

sqlite-vec v0.1.7以降、KNN queriesはWHERE distance < ?制約をサポートしています。これにより、大きなresult setでも前のページを再スキャンせずにcursor-based paginationができます。14 その後のv0.1.8とv0.1.9 stable releasesは、新しいquery modelではなくpackagingとDELETE bug fixのreleaseです。そのため、このpagination patternのfeature boundaryはv0.1.7のままです。23

今後については、v0.1.10-alpha line(2026年3月31日〜5月18日)が、sqlite-vecをbrute-force KNNの先へ進める最初のlineです。approximate-nearest-neighbor index typesとして、rescoredefaultでは有効化されていないexperimentalなivf(inverted-file)index、そしてvectorをmemory内に常駐させるには大きすぎるvault向けのdisk-based DiskANN indexが導入されます。23 これらは非常に大きなvaultのscaling storyを変える可能性がありますが、0.1.10 lineはまだpre-release(alpha)です。ANN indexingはexperimentalとして扱い、stable 0.1.10が出荷されるまでは、production vaultではstable v0.1.9のbrute-force KNN pathを土台にし続けてください。

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

これは、大きなkを取得してPython側でsliceする従来のpatternを置き換えるものです。大規模vaultに対する探索的なqueriesで、memory使用量を削減できます。

vec0 TablesでのDELETE Support

sqlite-vec v0.1.7ではvec0 virtual tables向けのnative DELETE supportが追加され、v0.1.9では12文字を超えるmetadata text columnsに関係するDELETE error pathが修正されました。1423 以前は、vectorsを削除するにはtableをdropして再作成する必要がありました。現在は、indexerのfile-removal pathからvectorsを直接削除できます。

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

これにより、ノートが削除または移動されたときのincremental reindexingが簡単になります。indexerはshadowの「active IDs」tableを維持したり、batch rebuildsを行ったりする必要がなくなります。

Vector Searchが強い場面

Vector searchは、特定の単語よりも概念が重要なqueryで力を発揮します。

  • Query: “how to handle authentication failures” → “login error recovery”に関するノートを見つけます(同じsemantic space、異なるkeywords)
  • Query: “what patterns exist for caching” → “memoization,”、”Redis TTL strategies,”、”HTTP cache headers”に関するノートを見つけます(関連するconcepts、多様なterminology)
  • Query: “approaches to testing asynchronous code” → “pytest-asyncio fixtures,”、”mock event loops,”、”async test patterns”に関するノートを見つけます(同じconceptがimplementation detailsを通じて表現されています)

Vector Searchが失敗しやすい場面

Vector searchは、exact identifiersが苦手です。

  • Query: _rrf_fuse → “fusion algorithms”や”rank merging”に関するノートを返しますが、実際のfunction definitionはconceptual discussionsより低くrankされる場合があります
  • Query: PostToolUse → specific hook nameではなく、”tool lifecycle hooks”や”post-execution handlers”に関するノートを返します

Vector searchはstructured dataも苦手です。JSON configuration files、YAML blocks、code snippetsでは、semantic meaningではなくstructural patternsを捉えたembeddingsが生成されます。"review": trueを含むJSON fileは、code reviewについてのprose discussionとは異なるembeddingになります。

Graceful Degradation

sqlite-vecのloadに失敗した場合(missing extension、incompatible platform、corrupted library)、retrieverはBM25-only searchにfallbackします。

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はvector queriesを試す前にvec_availableを確認します。無効な場合、すべてのsearchesはBM25のみを使用し、RRF fusion stepはskipされます。


Reciprocal Rank Fusion (RRF)

RRF は、スコアの較正を必要とせずに、2つのランク付きリストを統合します。このセクションでは、アルゴリズム、実際のクエリトレース、k パラメータの調整、そして他の手法ではなく RRF を選ぶ理由を扱います。ランクを編集できるインタラクティブな計算ツール、シナリオプリセット、視覚的なアーキテクチャ探索については、hybrid retriever の詳細解説をご覧ください。

アルゴリズム

RRF は、各リスト内でのランク位置だけに基づいて、各ドキュメントにスコアを割り当てます。

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

ここで: - k は平滑化定数です(Cormack らに従い 603) - rank_i は、結果リスト i におけるドキュメントの1始まりのランクです - weight_i は任意のリスト別の倍率です(デフォルトは 1.0)

複数のリストで上位にランクされるドキュメントほど、統合後のスコアが高くなります。1つのリストにしか現れないドキュメントは、その単一ソースからのスコアだけを受け取ります。

代替手法ではなく RRF を使う理由

重み付き線形結合では、BM25 スコアと cosine distances を較正する必要があります。BM25 スコアには上限がなく、コーパスサイズに応じてスケールします。cosine distances は [0, 2] の範囲に収まります。両者を組み合わせるには正規化が必要であり、その正規化パラメータはデータセットに依存します。RRF はランク位置だけを使います。ランク位置は、スコアリング手法に関係なく、常に 1 から始まる整数です。

学習済みの融合モデルには、ラベル付きの訓練データ、つまりクエリとドキュメントの関連性ペアが必要です。個人のナレッジベースでは、この訓練データは存在しません。有用なモデルを訓練するには、数百件のクエリとドキュメントのペアを手作業で評価する必要があります。RRF は訓練データなしで機能します。

Condorcet voting 手法(Borda count、Schulze method)は理論的には洗練されていますが、実装と調整がより複雑です。元の RRF 論文では、TREC 評価データにおいて RRF が Condorcet 手法を上回ることが示されています。3

実践での融合

クエリ: “how does the review aggregator handle disagreements”

BM25 は review-aggregator.py を3位にランクします(”review,” “aggregator,” “disagreements” の完全なキーワード一致)が、2つの設定ファイルをそれより上位に置きます(それらは “review” により目立って一致するためです)。Vector search は同じチャンクを1位にランクします(conflict resolution の意味的な一致)。RRF で融合した後は次のようになります。

チャンク BM25 Vec 融合スコア
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

両方のリストで上位に入るチャンクが先頭に浮上します。1つのリストにしか現れないチャンクは単一ソースのスコアだけになり、両方でランクされた結果より下に落ちます。実際の disagreement resolution logic が勝つのは、BM25 がキーワードを通じて、vector search が意味を通じて、どちらの手法もそれを見つけたためです。

ランクごとの RRF 計算を含む完全なステップごとのトレースは、インタラクティブな RRF 計算ツールで k の値を変えながら試せます。

実装

RRF_K = 60

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

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

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

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

k の調整

k 定数は、上位ランクの結果と下位ランクの結果にどれだけ重みを与えるかを制御します。

  • 低い k(例: 10): 上位ランクの結果が支配的になります。ランク1は 1/11 = 0.091、ランク10は 1/20 = 0.050 です(1.8倍の差)。個々のランカーが最上位の結果を正しく出せると信頼できる場合に適しています。
  • デフォルトの k(60): バランス型です。ランク1は 1/61 = 0.0164、ランク10は 1/70 = 0.0143 です(1.15倍の差)。ランク差が圧縮されるため、複数のリストに現れることの重みが増します。
  • 高い k(例: 200): ランク位置よりも、両方のリストに現れることがはるかに重要になります。ランク1は 1/201、ランク10は 1/210 で、ほぼ同じです。個々のランカーの順位付けにノイズがある一方で、リスト間の一致は信頼できる場合に使います。

まずは k=60 から始めましょう。 元の RRF 論文では、この値が多様な TREC データセット全体で堅牢であることが示されています。調整は、自分のクエリ分布で失敗例を測定した後に行ってください。

タイブレーク

2つのチャンクの RRF スコアが同一になる場合(まれですが、片方のリストで同じランクにあり、もう一方には現れない場合に起こり得ます)、次の順でタイを解消します。

  1. 1つのリストにしか現れないチャンクよりも、両方のリストに現れるチャンクを優先します
  2. 両方のリストに現れるチャンク同士では、合計ランクが低いものを優先します
  3. 1つのリストにしか現れないチャンク同士では、そのリスト内でランクが低いものを優先します

完全な検索パイプライン

このセクションでは、クエリが入力から出力まで、BM25検索、ベクトル検索、RRF融合、token budgetの切り詰め、コンテキスト組み立てというパイプライン全体を通る流れを追います。

End-to-Endの流れ

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

合計レイテンシ: 約23ms。Apple M3 Proハードウェア上の49,746チャンクのデータベースでの値です。

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

Token Budgetの切り詰め

max_tokensパラメータは、AIツールが利用できる量を超えるコンテキストをretrieverが返さないようにします。推定には、1 tokenあたり4文字を使います(英語の文章では妥当な近似です)。結果は貪欲法で切り詰められます。つまり、予算が尽きるまで、ランキング順に結果を追加していきます。

これは保守的な戦略です。より高度な方法では、結果ごとの品質スコアを考慮し、長くて品質の低い結果よりも、短くて品質の高い結果を優先できます。貪欲法はより単純で、実運用でもうまく機能します。RRFランキングがすでに関連性の高い順に結果を並べているためです。

データベーススキーマ(完全版)

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

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

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

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

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

Graceful Degradationの経路

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は初期化時に機能を確認し、クエリ戦略を適応させます。コンポーネントが欠けている場合は品質が下がりますが、エラーにはなりません。唯一のハードフェイルは、データベースファイルが存在しない場合です。

本番環境での統計

16,894ファイル、49,746チャンク、83 MB SQLiteデータベース、Apple M3 Proのvaultで測定した結果です。

指標
総ファイル数 16,894
総チャンク数 49,746
データベースサイズ 83 MB
BM25クエリレイテンシ(p50) 12ms
ベクトルクエリレイテンシ(p50) 8ms
RRF融合レイテンシ 3ms
End-to-end検索レイテンシ(p50) 23ms
フル再index時間 約4分
インクリメンタル再index時間 <10秒
Embeddingモデル potion-base-8M (256-dim)
BM25候補プール 30
ベクトル候補プール 30
デフォルトの結果上限 10
デフォルトのtoken budget 4,000 tokens

コンテンツHashingと変更検出

indexerは、前回のindex実行以降にどのファイルが変更されたかを把握する必要があります。このセクションでは、変更検出の仕組みとhashing戦略を扱います。

ファイル変更時刻の比較

indexerは、すべてのチャンクについてchunksテーブルにmtime_ns(ナノ秒単位のファイル変更時刻)を保存します。インクリメンタル実行では、indexerは次の処理を行います。

  1. 許可されたフォルダー内のすべての.mdファイルをvaultからスキャンします
  2. ファイルシステムから各ファイルのmtime_nsを読み取ります
  3. データベースに保存されているmtime_nsと比較します
  4. 3つのカテゴリを特定します。
  5. 新規ファイル: パスはファイルシステムに存在するが、データベースには存在しない
  6. 変更ファイル: パスは両方に存在するが、mtime_nsが異なる
  7. 削除ファイル: パスはデータベースに存在するが、ファイルシステムには存在しない
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)

Content Hashではなくmtimeを使う理由

Content hashing(ファイル内容のSHA-256)は、mtime比較よりも信頼性が高くなります。たとえば、ファイルが触られたものの内容は変わっていない場合(git checkoutで元のmtimeに戻る場合など)も検出できます。ただし、hashingではインクリメンタル実行のたびに全ファイルを読む必要があります。16,894ファイルでは、ファイル内容の読み取りに2〜3秒かかります。ファイルシステムからmtimeを読むだけなら<100msです。

トレードオフはこうです。mtime比較では、変更されていないファイルを不要に再indexすることがたまにあります(false positive)が、実際の変更を見逃すことはありません。false positiveのコストは、実行ごとに追加のembedding呼び出しが数回発生する程度です。速度差(100ms対3秒)を考えると、AIとのやり取りごとに動くシステムでは、mtimeが現実的な選択です。

削除の処理

vaultからファイルが削除されると、indexerはそのファイルのすべてのチャンクをデータベースから削除します。

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

DELETE FROM chunk_vecs文は、sqlite-vec v0.1.7以降ではネイティブに動作します。v0.1.9では、長いメタデータテキスト列を持つvec0テーブルに対するDELETE操作のバグ修正も入っています。1423 それ以前のバージョンでは、回避策(仮想テーブルを削除して再作成する、または外部の「active IDs」セットを維持する)が必要でした。pre-0.1.9版を実行している場合は、メタデータが多いスキーマで直接削除に依存する前にアップグレードしてください。

FTS5のcontent-syncテーブルでは、削除された各行に対してINSERT INTO chunks_fts(chunks_fts, rowid, ...) VALUES('delete', ?, ...)による明示的な削除が必要です。indexerは、ファイル削除プロセスの一部としてこれを処理します。


Incremental Reindex と Full Reindex

インデクサーは、incremental(高速で日常利用向け)と full(低速で必要時のみ)の2つのモードに対応しています。このセクションでは、それぞれを使うタイミング、冪等性の保証、破損時の復旧について説明します。

Incremental Reindex

使うタイミング: ノートを編集した後の日次インデックス作成に使います。デフォルトのモードです。

実行内容: 1. ファイル変更を検出するためにvaultをスキャンします(mtime比較) 2. 削除されたファイルのchunksを削除します 3. 変更されたファイルを再chunkingし、再embedします 4. 新しいファイルの新規chunksを挿入します 5. FTS5 indexを同期します

通常の所要時間: 16,000ファイルのvaultで1日分の編集なら10秒未満です。

python index_vault.py --incremental

Full Reindex

使うタイミング: - embedding modelを変更した後(model hashの不一致を検出した場合) - schema migrationの後(新しい列、変更されたindexes) - database corruptionの後(integrity checkが失敗した場合) - incremental indexingで予期しない結果が出る場合

実行内容: 1. 既存データをすべて削除します(chunks、vectors、FTS5 entries) 2. vault全体をスキャンします 3. すべてのファイルをchunkingします 4. すべてのchunksをembedします 5. FTS5 indexをゼロから構築します

通常の所要時間: Apple M3 Proで16,894ファイルなら約4分です。

python index_vault.py --full

冪等性

どちらのモードも冪等です。同じコマンドを2回実行しても、結果は同じになります。インデクサーは新しいchunksを挿入する前に、そのファイルの既存chunksを削除します。そのため、すでに最新のdatabaseに対してincremental indexingを再実行しても、変更は0件です。full indexingを再実行した場合も、同一のdatabaseが生成されます。

破損からの復旧

SQLite databaseが破損した場合(書き込み中の電源断、ディスクエラー、トランザクション中にプロセスがkillされた場合):

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

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

常に信頼すべき元データはdatabaseではなくvaultファイルです。databaseはいつでも再構築できる派生成果物にすぎません。これは重要な設計特性です。databaseをバックアップする必要はありません。

--incremental Flag

インデクサーを--incremental付きで実行すると、次の処理が行われます。

  1. Model hash check。 保存済みのmodel hashを現在のmodelと比較します。異なる場合は、自動的にfull reindex modeへ切り替え、ユーザーに警告します。
  2. File scan。 許可されたフォルダーを走査し、file pathsとmtimesを収集します。
  3. Change detection。 保存済みデータと比較します。
  4. Batch processing。 変更されたファイルを64件ずつのbatchで再chunkingし、再embedします。
  5. Progress reporting。 処理済みファイル数と経過時間を表示します。
  6. Graceful shutdown。 SIGINTを受け取った場合、現在のファイル処理を終えてから停止します。

Credential Filtering と Data Boundaries

個人ノートにはsecretが含まれます。API keys、bearer tokens、database connection strings、debugging session中に貼り付けたprivate keysなどです。credential filterは、これらがretrieval indexに入るのを防ぎます。

問題

OAuth 連携のdebuggingに関するノートには、次のような内容が含まれることがあります。

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

filteringしない場合、JWTとAPI keyの両方がchunkingされ、embedされ、databaseに保存されます。”authentication”で検索すると、本物のsecretを含むchunkが返されます。さらに悪いことに、retrieverがMCP経由で結果をAI toolへ渡す場合、そのsecretはAIのcontext windowに入り、場合によってはtoolのlogsにも残ります。

Pattern-Based Filtering

credential filterは保存前にすべてのchunkで実行され、25個のvendor-specific patternsとgeneric patternsに一致するかを確認します。

Vendor-Specific Patterns:

Pattern Regex
OpenAI API key sk-... sk-[a-zA-Z0-9_-]{20,}
Anthropic API key sk-ant-api03-... sk-ant-api\d{2}-[a-zA-Z0-9_-]{20,}
GitHub PAT ghp_... gh[ps]_[a-zA-Z0-9]{36,}
AWS Access Key AKIA... AKIA[0-9A-Z]{16}
Stripe key sk_live_... [sr]k_(live\|test)_[a-zA-Z0-9]{24,}
Cloudflare token ... さまざまなpatterns

Generic Patterns:

Pattern Detection
JWT tokens eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+
Bearer tokens Bearer\s+[a-zA-Z0-9_\-\.]+
Private keys -----BEGIN (RSA\|EC\|OPENSSH) PRIVATE KEY-----
高エントロピーbase64 文字あたり>4.5 bitsのエントロピー、40文字以上のstrings
Password assignments password\s*[:=]\s*["'][^"']+["']

Filter Implementation

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

主な設計判断:

  1. embeddingの前にfilterします。 embedされるのはcleaned textです。vector表現にcredential patternsがエンコードされることはありません。”API key”でqueryして返るのはAPI key管理について論じたノートであり、実際のkeysを含むノートではありません。

  2. 削除ではなく置換します。 [REDACTED:pattern-name] tokenにより、周囲のtextのsemantic contextが保たれます。embeddingは、credentialらしき何かがそこにあったことを捉えますが、credentialそのものはエンコードしません。

  3. valuesではなくpatternsをlogします。 filterは一致したpatternsをlogします(例: “Scrubbed 2 credential(s) from oauth-debug.md [jwt, bearer-token]”)。ただし、credential valueは決してlogしません。

Path-Based Exclusion

.indexignoreファイルは、path単位の粗い除外を提供します。credential filterは、indexed files内で細かなscrubbingを行います。どちらも必要です。

  • .indexignore は、sensitive contentを含むことが分かっているフォルダー全体に使います(health notes、financial records、career documents)
  • Credential filter は、通常はindex対象にできるcontentへ偶発的に埋め込まれたsecretsに使います

Data Classification

多様なcontentを含むvaultでは、sensitivityに応じてノートを分類することを検討してください。

Level Index? Filter?
Public Blog drafts、technical notes Yes Yes
Internal Project plans、architecture decisions Yes Yes
Sensitive Salary data、health records No (.indexignore) N/A
Restricted Credentials、private keys No (.indexignore) N/A

MCPサーバーアーキテクチャ

Model Context Protocol(MCP)サーバーは、AIエージェントが呼び出せるツールとして retriever を公開します。このセクションでは、サーバー設計、機能の範囲、権限の境界について説明します。

プロトコルの選択: STDIO vs HTTP

MCP は2つの transport mode をサポートしています。

STDIO — AIツールが MCP サーバーを子プロセスとして起動し、stdin/stdout 経由で通信します。これはローカルツール向けの標準モードです。Claude Code、Codex CLI、Cursor はいずれも STDIO MCP サーバーをサポートしています。

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

HTTP — MCP サーバーをスタンドアロンの HTTP サービスとして実行します。リモートアクセス、複数クライアント構成、または vault が共有サーバー上にあるチーム設定で役立ちます。

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

推奨: 個人用 vault には STDIO を使用してください。よりシンプルで、ネットワークに公開されないため安全性が高く、サーバーのライフサイクルも AIツールによって管理されます。同じ vault に複数のツールや複数のマシンから同時アクセスする必要がある場合にのみ HTTP を使用してください。

MCP仕様の進化。 2025年6月の MCP仕様では、OAuth 2.1 authorization、構造化されたツール出力(型付き return schema)、elicitation(サーバー起点のユーザープロンプト)が追加されました。2025年11月のリリースでは、Streamable HTTP が first-class の transport mode として提供され、自動的なサーバー機能ブラウズのための .well-known URL discovery、ツールが read-only か mutating かを宣言する構造化 tool annotations、そして SDK tier standardization system が導入されました。79 次の改訂はすでに具体化しています。2026-07-28 specification は2026年5月21日に Release Candidate に入り、ローンチ以来最大の MCP改訂となります。主な変更点は、stateless protocol coreinitialize handshake と Mcp-Session-Id header が削除され、サーバーは接続ごとの session state を追跡しなくなります)、MCP Apps(サーバーが server-rendered HTML を返し、sandboxed client iframe 内に表示できます)、Tasks が experimental core から公式 extension に昇格(長時間実行される操作向けの tasks/gettasks/updatetasks/cancel)、強化された OAuth 2.0 / OIDC authorization、そして 12か月の feature-deprecation lifecycle policy です。最終仕様は2026年7月28日に公開されます。24 個人用 vault サーバーでは、STDIO が引き続き最もシンプルな道筋です。stateless core によって、単一ユーザー向け STDIO サーバーはさらに薄くなります。Streamable HTTP transport、.well-known discovery、MCP Apps は、主に multi-tenant routing と load balancing を備えた enterprise HTTP deployments にメリットがあります。transport の選択に影響する更新については、MCP roadmap を確認してください。

機能設計

MCP サーバーが公開するツールは最小限にするべきです。

search — 主要なツールです。hybrid retrieval を実行し、ランク付けされた結果を返します。

{
  "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 — パスを指定して特定のノートの全文を読み取ります。エージェントが検索結果の完全な文脈を確認したい場合に役立ちます。

{
  "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 — フィルター(フォルダー、タグ、種類、日付範囲)に一致するノートを一覧表示します。エージェントに具体的なクエリがなく、探索したい場合に便利です。

{
  "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 — 検索を実行し、会話に挿入しやすい context block として結果を整形する便利なツールです。

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

権限の境界

MCP サーバーは厳格な境界を適用するべきです。

  1. 読み取り専用。 サーバーは vault と index database を読み取ります。ノートの作成、変更、削除は行いません。書き込み操作(新しいノートの取り込み)は、MCP サーバーではなく、別の hook や skill で処理します。

  2. Vault に限定。 サーバーは設定された vault path 内のファイルだけを読み取ります。Path traversal の試行(../../etc/passwd)は拒否しなければなりません。

  3. Credential-filtered output。 database に事前フィルター済みの内容が含まれている場合でも、多層防御として出力時に credential filtering を適用します。

  4. Token-limited responses。 AIツールが過度に大きな context block を受け取らないように、すべてのツール応答で max_tokens を適用します。

エラーハンドリング

MCP ツールは、AIツールが復旧しやすい構造化エラーメッセージを返すべきです。

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

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

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

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

Claude Code 連携

Claude Code は Obsidian 検索システムの主な利用先です。このセクションでは、MCP の設定、hook 連携、obsidian_bridge.py パターンについて説明します。

MCP 設定

Obsidian MCP サーバーを ~/.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"
      }
    }
  }
}

設定を追加したら、Claude Code を再起動します。MCP サーバーは子プロセスとして起動します。実行中であることを確認してください。

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

Claude Code には、利用可能なツール(obsidian_searchobsidian_read_note など)が表示されるはずです。

Hook 連携

Hooks は、定義されたライフサイクルの各時点で Claude Code の動作を拡張します。Obsidian 連携に関係する hook は2つあります。

PreToolUse hook — agent がツール呼び出しを処理する前に、vault をクエリします。関連するコンテキストを自動的に注入します。

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

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

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

PostToolUse hook — 重要なツール出力を vault に取り込み、今後の検索に使えるようにします。

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

obsidian_bridge.py パターン

ブリッジモジュールは、hooks や skills から呼び出せる Python API を提供します。

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

/capture Skill

得られた知見を vault に取り込むための Claude Code skill です。

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

この skill は、適切な frontmatter 付きの新しいノートを 00-inbox/ に作成し、増分再インデックスを実行します。そのため、新しいノートはすぐに検索可能になります。

Custom Command パターン

Claude Code skills を使うと、vault 操作を名前付きコマンドとしてまとめられます。実践者は、vault を読み取り元としても書き込み先としても扱う、Obsidian 専用コマンドのライブラリを構築しています。

シグナルスキャン。 /scan-intel コマンドは外部ソースをクエリし、個人のリサーチ関心に照らして発見事項をスコアリングし、条件を満たしたシグナルを frontmatter 付きの vault ノートとして書き込みます。

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

このコマンドは、設定済みソース(arXiv、HN、RSS)から取得し、スコアリングモデル(関連性、実行可能性、深さ、権威性)を適用して、基準を満たすシグナルをトピック別の vault フォルダに書き込みます。vault は、自動化されたインテリジェンスパイプラインの下流の受け皿になります。

Captain’s log。 /captains-log コマンドは、すべてのリポジトリの日次 git activity を集約し、構造化されたジャーナルエントリとして vault に書き込みます。そこには、下した意思決定、気づき、未解決の論点も含まれます。

/captains-log

このコマンドは GitHub からコミット履歴を取得し、リポジトリごとにグループ化して、物語形式のジャーナルエントリとして整形します。時間が経つにつれて、日次ログは「何を出荷したのか」と「なぜそうしたのか」を検索できる記録になります。

Obsidian capture。 /obsidian-capture コマンドは、現在の Claude Code セッションで得た知見を取得し、適切なメタデータ付きで vault に直接書き込みます。

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

このパターンは、どのような vault 操作にも拡張できます。MOCs の作成、プロジェクト状況ノートの更新、関連シグナルのリンク、蓄積された日次ログからの週次ダイジェスト生成などです。

コミュニティ例。 実践者は、自身のコマンドライブラリを公開しています。ある開発者は、日次レビュー、プロジェクト計画、リサーチ記録、コンテンツワークフローを対象とする、Obsidian + Claude Code のカスタムコマンド22個を共有しました。1 別の開発者は、コード分析から vault 内に図解ノートを生成する「Visual Explainer」skill を構築しました。2 コマンドの内容はさまざまですが、アーキテクチャは一貫しています。インターフェースとしての Claude Code skills、ストレージ層としての vault ノート、クエリエンジンとしての検索インフラです。

Context Window 管理

連携では、Claude Code の context window に注意する必要があります。

  • 注入するコンテキストは、クエリごとに1,500〜2,000トークンまでに制限します。 これを超えると、agent の作業記憶と競合します。
  • ソース帰属を含めます。 agent がソースを参照できるように、必ずファイルパスとセクション見出しを含めてください。
  • chunk text を切り詰めます。 長い chunk は完全に省略するのではなく、... を使って切り詰めます。通常、最初の300〜500文字に重要な情報が含まれます。
  • すべてのツール呼び出しで注入しないでください。 PreToolUse hook は、呼び出されるツールに応じて選択的にコンテキストを注入するべきです。読み取り操作には vault のコンテキストは不要です。Write や Edit 操作では役立ちます。

Codex CLI 連携

Codex CLI は、config.toml を通じて MCP サーバーに接続します。設定構文と指示の渡し方が、Claude Code とは異なります。

MCP 設定

.codex/config.toml または ~/.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"

AGENTS.md パターン

Codex CLI は、プロジェクトレベルの指示として AGENTS.md を読み取ります。vault 検索に関するガイダンスを含めてください。

## Available Tools

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

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

Claude Code との違い

Feature Claude Code Codex CLI
MCP config settings.json config.toml
Hooks ~/.claude/hooks/ 非対応
Skills ~/.claude/skills/ 非対応
Instruction file CLAUDE.md AGENTS.md
Approval modes --dangerously-skip-permissions suggest / auto-edit / full-auto

主な違い: Codex CLI は hooks に対応していません。自動コンテキスト注入パターン(PreToolUse hook)は利用できません。代わりに、作業を始める前に vault を検索するよう agent に伝える明示的な指示を AGENTS.md に含めてください。

Cursorとその他のツール

MCPをサポートするCursorやその他のAIツールは、同じObsidian MCPサーバーに接続できます。このセクションでは、一般的なツールの設定を扱います。

Cursor

プロジェクトルートの.cursor/mcp.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"
      }
    }
  }
}

Cursorの.cursorrulesファイルには、保管庫を使うための指示を含められます。

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.

互換性マトリクス

ツール MCPサポート 転送方式 設定場所
Claude Code 完全 STDIO ~/.claude/settings.json
Codex CLI 完全 STDIO .codex/config.toml
Cursor 完全 STDIO .cursor/mcp.json
Windsurf 完全 STDIO .windsurf/mcp.json
Continue.dev 部分的 HTTP ~/.continue/config.json
Zed 開発中 STDIO 設定UI
Claudian(Obsidian plugin) N/A(組み込み) Claude Code CLI Obsidian plugin設定
Agent Client(Obsidian plugin) N/A(組み込み) ACP Obsidian plugin設定

非MCPツール向けのフォールバック

MCPをサポートしていないツールでは、retrieverを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は構造化されたテキストを出力し、任意のAIツールの入力へ手動で貼り付けられます。MCP統合ほど洗練されてはいませんが、どこでも使える方法です。


構造化ノートによるプロンプトキャッシュ

保管庫内の構造化ノートは、AIとのやり取り全体でトークン使用量を減らす再利用可能なコンテキストブロックとして使えます。このセクションでは、キャッシュキー設計とトークン予算管理を扱います。

パターン

やり取りのたびにコンテキストを検索する代わりに、よく構造化された保管庫ノートからコンテキストブロックを事前に作成し、キャッシュします。

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

キャッシュの無効化

キャッシュの無効化は、2つのシグナルに基づきます。

  1. TTLの期限切れ。 各コンテキストブロックには有効期間があります。TTLが切れると、保管庫を再クエリしてブロックを再構築します。
  2. 保管庫の変更検出。 indexerがキャッシュ済みコンテキストブロックに寄与したファイルの変更を検出すると、そのブロックはただちに無効化されます。

トークン予算管理

セッションは、合計コンテキスト予算から始まります。キャッシュ済みブロックは、その予算の一部を消費します。

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)

キャッシュ済みブロックはセッション開始時に読み込まれます。動的な検索結果は、クエリごとに残りの予算を使って埋めます。このhybridアプローチにより、agentには頻繁に必要になるコンテキストの基礎が与えられつつ、特定のクエリ向けの予算も確保できます。

トークン使用量のBefore/After

キャッシュなし: 関連するクエリごとに保管庫検索が実行され、1,500〜2,000トークンのコンテキストが返ります。1セッションで10件のクエリがある場合、agentは15,000〜20,000トークンの保管庫コンテキストを消費します。

キャッシュあり: 事前作成された3つのコンテキストブロックが合計4,500トークンを消費します。追加検索では、ユニークなクエリごとに1,500〜2,000トークンが加わります。10件のクエリのうち6件がキャッシュ済みブロックでカバーされる場合、agentの消費量は4,500 + (4 * 1,500) = 10,500トークンとなり、キャッシュなしの場合のおよそ半分です。


コンテキスト圧縮のためのPostToolUse Hooks

ツール出力は冗長になりがちです。たとえば、スタックトレース、ファイル一覧、テスト結果などです。PostToolUse hookを使うと、これらの出力がコンテキストウィンドウの領域を消費する前に圧縮できます。

問題

テストを実行するBashツール呼び出しでは、次のような結果が返ることがあります。

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

完全な出力は5,000トークンありますが、重要なシグナルは2行にあります。200件成功、1件失敗です。

Hookの実装

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

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

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

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

再帰的トリガーの防止

圧縮hookが出力を発すると、ガードしない限り自分自身をトリガーしてしまう可能性があります。

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

圧縮ヒューリスティック

出力タイプ 検出 圧縮戦略
テスト結果 PASSED / FAILEDキーワード 成功/失敗を数え、失敗のみを表示
ファイル一覧 command内のlsまたはfind 先頭20件 + 件数に切り詰め
スタックトレース Tracebackキーワード 最初と最後のフレーム + エラーメッセージを保持
Git status modified: / new file: status別に件数を要約
ビルド出力 warning: / error: 情報行を削除し、警告/エラーを保持

シグナル取り込みとトリアージのパイプライン

取り込みレイヤーは、何を vault に入れるかを決めます。キュレーションがなければ、vault にはノイズが蓄積していきます。このセクションでは、シグナルをドメインフォルダへ振り分けるスコアリングパイプラインを扱います。

ソース

シグナルは複数のチャネルから入ってきます。

  • RSS フィード: 技術ブログ、セキュリティ勧告、リリースノート
  • Web Clipper 経由のブックマーク: 公式の Obsidian Web Clipper 拡張機能(Chrome、Firefox、Safari)は、ブラウザ側のキャプチャとして最も忠実度の高い取り込み経路です。2026年4月のリリースサイクルにより、AI ワークフローで実用性が大きく向上しました:22
    • 1.4.0(4月9日): インタラクティブな YouTube transcript UI。動画を固定し、transcript をスクラブし、自動スクロールし、現在位置をハイライトできます。さらに、ワンクリックのキャプチャを Reader モードへ直接送る「Open in Reader」デフォルトも追加されました。
    • 1.5.0–1.5.1(4月15日): Highlights viewer。vault 全体のキャプチャ済みハイライトを閲覧・検索できます。Reader へのフェードイン遷移、より滑らかな YouTube の再生/一時停止も追加されました。1.5.1 では webpack compilation regression が修正されています。
    • 1.6.0–1.6.2(4月21–23日): モバイル対応を含む Highlighter UX の全面見直し。Defuddle 0.18 では LinkedIn、Threads、Bluesky、Discourse、Medium 向けのソース別 extractor が追加されました。1.6.2 では Safari embedded-mode clipboard regression が修正されています。 ソースドメインごとにテンプレートを設定し、YouTube transcripts、GitHub READMEs、長文記事が、それぞれ下のスコアリングパイプラインに適した frontmatter を持つ、わかりやすい名前のノートに入るようにします。
  • ニュースレター: メールニュースレターからの重要な抜粋
  • 手動キャプチャ: 読書中、会話中、調査中に書いたノート
  • ツール出力: hooks 経由でキャプチャされた重要な AI ツール出力
  • iOS Share Extension: Obsidian の iOS アプリ(2026年初頭に更新)には Share Extension が含まれており、Safari、ソーシャルネットワーク、その他のアプリからのコンテンツを、Obsidian を開かずに vault へ直接保存できます。19 これにより、モバイルで摩擦の少ない取り込み経路ができます。Safari から記事を共有すると、スコアリング可能な vault ノートとして届きます。
  • Obsidian CLI: Shell scripts と hooks は、obsidian file create でノートを作成したり、obsidian file append で既存ノートに追記したりできます。これにより、デスクトップ上で自動取り込みパイプラインを構築できます。

スコアリングの軸

各シグナルは、4つの軸でスコアリングされます(それぞれ 0.0 から 1.0)。

問い 低スコア(0.0-0.3) 高スコア(0.7-1.0)
関連性 自分のアクティブなドメインに関係しているか? 周辺的、スコープ外 現在の作業に直接関係する
実行可能性 この情報を使えるか? 純粋な理論で、応用がない 適用できる具体的な技法やパターンがある
深さ コンテンツにどれだけ実質があるか? 見出し、浅い要約 例を含む詳細な分析
権威性 ソースはどれだけ信頼できるか? 匿名ブログ、未検証 一次ソース、査読済み、認知された専門家

複合スコアとルーティング

composite = (relevance * 0.35) + (actionability * 0.25) +
            (depth * 0.25) + (authority * 0.15)
スコア範囲 アクション
0.55+ ドメインフォルダへ自動ルーティング
0.40 - 0.55 手動レビューのキューへ送る
< 0.40 破棄(保存しない)

ドメインルーティング

0.55 を超えたシグナルは、キーワード照合とトピック分類に基づいて、12個のドメインフォルダのいずれかへルーティングされます。

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

本番運用の統計

14か月の運用結果です。

指標
処理したシグナル総数 7,771
自動ルーティング(>0.55) 4,832(62%)
レビュー待ち(0.40-0.55) 1,543(20%)
破棄(<0.40) 1,396(18%)
アクティブなドメインフォルダ 12
1日あたりの平均シグナル数 約18

Knowledge Graph パターン

Obsidian の wiki-link graph は、ノート間の関係をエンコードします。このセクションでは、リンクのセマンティクス、コンテキスト拡張のためのグラフ走査、そしてグラフ品質を下げるアンチパターンを扱います。

すべての wiki-link は、グラフ内に有向エッジを作ります。Obsidian は forward links と backlinks の両方を追跡します。

  • Forward link: Note A contains [[Note B]] → A links to B
  • Backlink: Note B shows that Note A references it

グラフは、文脈に応じて異なる種類の関係をエンコードします。

リンクパターン セマンティクス
インラインリンク 「関連している」 “See [[OAuth Token Rotation]] for details”
見出しリンク 「サブトピックを持つ」 ”## Related\n- [[Token Rotation]]\n- [[Session Management]]”
タグ風リンク 「分類されている」 ”[[type/reference]]”
MOC link 「一部である」 関連ノートを一覧化した Maps of Content ノート

Maps of Content(MOCs)

MOCs は、関連ノートを移動しやすい構造へ整理するインデックスノートです。

---
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 は、retrieval に2つの形で役立ちます。

  1. 直接一致。 「authentication overview」を検索すると MOC 自体が一致し、agent に関連ノートのキュレーション済みリストを渡せます。
  2. コンテキスト拡張。 特定のノートが見つかった後、retriever はそのノートが MOCs に含まれているかを確認し、MOC の構造を結果に含められます。これにより、agent はより広いトピックの地図を得られます。

コンテキスト拡張のためのグラフ走査

retriever の今後の拡張案です。上位結果を見つけた後、リンクをたどってコンテキストを広げます。

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)

これは現在の retriever には実装されていませんが、グラフ構造の自然な拡張です。

アンチパターン

孤立クラスタ。 互いにリンクしているものの、vault の他の部分とつながっていないノート群です。Obsidian のグラフパネルでは、こうしたクラスタが切り離された島として表示されます。孤立クラスタは、MOCs が不足しているか、ドメイン横断リンクが不足していることを示します。

タグの乱立。 タグを一貫性なく使ったり、細かすぎるタグを作りすぎたりすることです。5,000件のノートに 500個のユニークタグがある vault では、平均すると 10タグあたり 1ノートになります。これではタグはフィルタリングに役立ちません。ドメインフォルダに対応する 20〜50個の高レベルタグへ統合しましょう。

リンクは多いが内容が薄いノート。 prose がなく、wiki-links だけで構成されているノートです。この種のノートは、chunker が embedding するテキストを持たないため、インデックス品質が下がります。リンク先のノートがなぜ関連しているのかを説明する文脈を、少なくとも1段落追加してください。

あらゆるものへの双方向リンク。 すべての参照を wiki-link にする必要はありません。「OAuth」に軽く触れただけなら、[[OAuth 2.0 Overview]] は不要です。wiki-links は、クリックすると有用な文脈が得られる、意図的で移動可能な関係に限定しましょう。


開発者ワークフローのレシピ

vault(Obsidianの保管庫)検索と日々の開発タスクを組み合わせる実践的なワークフローです。

朝のコンテキスト読み込み

関連するコンテキストを読み込んで1日を始めます。

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

retrieverは、作業中のプロジェクトに関する最近のノートを返します。前回どこまで進めたかをすばやく思い出せます。昨日のコミットメッセージを読み返すより効果的です。

コーディング中のリサーチ記録

機能を実装している途中でも、エディタを離れずに気づきを記録できます。

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

記録した気づきはすぐにindexされ、今後の検索で利用できるようになります。数か月かけて、こうした小さな記録が実装固有の知識コーパスを形成します。

プロジェクト開始

新しいプロジェクトや機能に着手するときは、次のように進めます。

  1. vaultを検索します: 「[technology/pattern]について何を知っているか?」
  2. 上位5件の結果を確認し、過去の判断や注意点を把握します
  3. その領域のMOCがあるか確認します。なければ作成します
  4. 失敗パターンを検索します: 「[technology]の問題」

Vault Searchでデバッグする

エラーや予期しない挙動に遭遇したときは、次のようにします。

Search my vault for [error message or symptom]

過去のデバッグノートには、根本原因と修正方法が含まれていることがよくあります。これは複数プロジェクトで繰り返し発生する問題に特に有効です。vaultは、忘れてしまうことを覚えていてくれます。

コードレビューの準備

PRをレビューする前に、次のようにします。

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

vaultは、レビュー対象のコードに関連する過去の判断、アーキテクチャ上の制約、コーディング標準を返します。レビューはdiffだけでなく、組織的な知識に基づいたものになります。


パフォーマンスチューニング

このセクションでは、vaultのサイズや利用パターンに応じた最適化戦略を扱います。

Indexサイズの管理

Vaultサイズ チャンク数 DBサイズ フルreindex 差分
500件のノート ~1,500 3 MB 15秒 <1秒
2,000件のノート ~6,000 12 MB 45秒 2秒
5,000件のノート ~15,000 30 MB 2分 4秒
15,000件のノート ~50,000 83 MB 4分 <10秒
50,000件のノート ~150,000 250 MB 15分 30秒

50,000件以上のノートでは、次を検討してください。 - embeddingを高速化するため、batch_sizeを64から128に増やす - 同時アクセスのためにWAL mode(デフォルト)を使用する - フルreindexは利用の少ない時間帯に実行する

Query最適化

WAL mode。 SQLiteのWrite-Ahead Logging modeでは、indexerが書き込み中でも並行して読み取りできます。

db.execute("PRAGMA journal_mode=WAL")

これは、indexerが差分更新を実行している間にMCPサーバーがクエリを処理する場合に重要です。

Connection pooling。 MCPサーバーは、クエリごとに新しい接続を開くのではなく、データベース接続を再利用するべきです。WAL modeの単一の長寿命接続で、並行読み取りをサポートできます。

# 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。 mmap_size pragmaは、データベースファイルにmemory-mapped I/Oを使うようSQLiteに指示します。83 MBのデータベースであれば、ファイル全体をメモリにマッピングすることで、ほとんどのディスク読み取りをなくせます。

FTS5最適化。 フルreindexの後に、次を実行します。

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

これによりFTS5内部のb-treeセグメントがマージされ、その後の検索でクエリレイテンシが低下します。

スケーリングベンチマーク

Apple M3 Pro、36 GB RAM、NVMe SSDで測定しました。

操作 500件のノート 5K件のノート 15K件のノート 50K件のノート
BM25 query 2ms 5ms 12ms 25ms
Vector query 1ms 3ms 8ms 20ms
RRF fusion <1ms <1ms 3ms 5ms
Full search 3ms 8ms 23ms 50ms

すべてのベンチマークには、データベースアクセス、クエリ実行、結果フォーマットを含みます。MCP STDIO通信のネットワークレイテンシにより、1〜2msが追加されます。


トラブルシューティング

Index Drift

症状: 検索で古い結果が返る、または最近追加したノートが見つかりません。

原因: ノート追加後に差分indexerが実行されていないか、ファイルのmtimeが更新されていません(例: タイムスタンプを保持したまま別のマシンから同期された場合)。

修正: フルreindexを実行します: python index_vault.py --full

Embeddingモデルの切り替え

症状: embeddingモデルを変更した後、ベクトル検索が意味不明な結果を返します。

原因: 古いベクトル(以前のモデル由来)が、新しいクエリベクトルと比較されています。次元数またはベクトル空間の意味が互換性を持ちません。

修正: indexerがモデルハッシュの不一致を検出し、自動的にフルreindexをトリガーするべきです。そうならない場合は、手動でデータベースをクリアしてreindexします。

rm vectors.db
python index_vault.py --full

FTS5メンテナンス

症状: 多数の差分更新後に、FTS5クエリが不正確または不完全な結果を返します。

原因: 小さな更新を多数行ったことで、FTS5内部セグメントが断片化している可能性があります。

修正: rebuildとoptimizeを実行します。

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

MCP Timeout

症状: AIツールが、MCPサーバーがタイムアウトしたと報告します。

原因: 最初のクエリでモデルの読み込み(遅延初期化)が発生し、2〜5秒かかります。AIツールのデフォルトのMCPタイムアウトがそれより短い可能性があります。

修正: サーバー起動時にモデルを事前にwarm upします。

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

SQLite File Locks

症状: SQLITE_BUSYまたはSQLITE_LOCKEDエラーが発生します。

原因: 複数のプロセスが同時にデータベースへ書き込んでいます。WAL modeは並行読み取りを可能にしますが、writerは1つだけです。

修正: データベースへ書き込むプロセスは1つ(indexer)だけにしてください。MCPサーバーとhooksは読み取り専用にします。同時書き込みが必要な場合は、WAL modeを使用し、busy timeoutを設定します。

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

sqlite-vecが読み込まれない

症状: ベクトル検索が無効化され、retrieverがBM25-only modeで動作します。

原因: sqlite-vec拡張がインストールされていない、ライブラリパス上で見つからない、またはSQLiteのバージョンと互換性がありません。

修正:

# Install via pip
pip install sqlite-vec

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

拡張が読み込めることを確認します。

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

大規模Vaultのメモリ問題

症状: 大規模vault(50,000件以上のノート)のフルreindex中にout-of-memoryエラーが発生します。

原因: embeddingのbatch_sizeが大きすぎるか、すべてのファイル内容を同時にメモリへ読み込んでいます。

修正: batch_sizeを下げ、ファイルを差分的に処理します。

BATCH_SIZE = 32  # Reduce from 64

また、indexerがすべてのファイルをメモリに読み込むのではなく、1ファイルずつ処理していることも確認してください。各ファイルを読み込み、chunkingし、embeddingしてから次のファイルへ進む形です。


移行ガイド

Apple Notesから

  1. Apple Notesを「Export All」オプション(macOS)でエクスポートするか、apple-notes-liberatorのような移行ツールを使用します
  2. markdownifyまたはpandocを使って、HTMLエクスポートをmarkdownに変換します
  3. 変換したファイルをvaultの00-inbox/フォルダへ移動します
  4. 各ノートを確認し、frontmatterを追加します
  5. ノートを適切なドメインフォルダへ移動します

Notionから

  1. Notionからエクスポートします: Settings → Export → Markdown & CSV
  2. エクスポートを解凍し、vaultの00-inbox/フォルダに配置します
  3. Notion固有のmarkdown生成物を修正します。
  4. Notionはチェックリストに- [ ]を使用します。これは標準のmarkdownです
  5. NotionはプロパティテーブルをHTMLとして含めます。YAML frontmatterに変換します
  6. Notionは画像を相対パスとして埋め込みます。画像をattachmentsフォルダへコピーします
  7. 標準frontmatter(typedomaintags)を追加します
  8. NotionページリンクをObsidian wiki-linksに置き換えます

Google Docsから

  1. Google Takeoutを使ってすべてのドキュメントをエクスポートします
  2. .docxファイルをmarkdownに変換します: pandoc -f docx -t markdown input.docx -o output.md
  3. 一括変換します: for f in *.docx; do pandoc -f docx -t markdown "$f" -o "${f%.docx}.md"; done
  4. vaultへ移動し、frontmatterを追加して、フォルダに整理します

プレーンMarkdownから(Obsidianなし)

すでにmarkdownファイルのディレクトリがある場合は、次のようにします。

  1. そのディレクトリをObsidian vaultとして開きます(Obsidian → Open Vault → Open folder)
  2. ディレクトリをバージョン管理している場合は、.obsidian/.gitignoreに追加します
  3. frontmatterテンプレートを作成し、既存ファイルへ適用します
  4. 読みながら整理しつつ、[[wiki-links]]でノートをリンクし始めます
  5. すぐにindexerを実行します。検索システムは初日から機能します

別の検索システムから

別のembedding/searchシステムから移行する場合は、次のようにします。

  1. ベクトルを移行しようとしないでください。 モデルが異なると、互換性のないベクトル空間が生成されます。新しいモデルでフルreindexを実行してください。
  2. indexではなく、コンテンツを移行してください。 vaultファイルがsource of truthです。indexは派生物にすぎません。
  3. 移行後に検証してください。 答えが分かっているクエリを10〜20件実行し、結果が期待どおりか確認します。

変更履歴

日付 変更
2026-06-10 バージョンの最新性を更新しました。Obsidian 1.13.1 desktop が public channel に到達しました(2026年6月9日)— 1.13.0 から設定 UX と CodeMirror がアップグレードされていますが、AI/automation に関する大きな変更はありません。本文中の現行バージョン参照を 1.13.0 から 1.13.1(public、2026年6月9日)へ移しました。
2026-06-09 エコシステムを更新しました。MCP 2026-07-28 specification が Release Candidate に入りました(2026年5月21日発表)— ローンチ以来最大の MCP 改訂です。ステートレスな protocol core(initialize handshake と Mcp-Session-Id を削除)、MCP Apps(sandboxed iframes 内の server-rendered HTML)、Tasks の experimental core から official extension への昇格、OAuth 2.0/OIDC の強化、12か月の deprecation-lifecycle policy(final spec は 2026年7月28日)が含まれます。MCP Spec Evolution の注記にあった推測的な「tentatively mid-2026」という roadmap 表現を、具体的な RC に置き換えました。sqlite-vec v0.1.10-alpha(2026年3月31日〜5月18日)は、brute-force KNN を超える approximate-nearest-neighbor index types(rescore、experimental ivf、disk-based DiskANN)を追加しました。ただし 0.1.10 系はまだ pre-release のため、on-the-horizon/experimental として扱っています。Obsidian 1.13.0 desktop(early access、2026年5月28日)を本文全体の現行バージョンとして更新しました。UX/security/dev-tooling のリリースであり、新しい AI/automation 機能はありません。
2026-06-08 メンテナンス確認を行いました。Model2Vec v0.8.2(2026年5月29日)がリリースされました。トレーニング用の frozen-weights オプションに加え、multiword-token の修正、トレーニングのリファクタリング、non-quantized weight-handling の修正を含むメンテナンスリリースです。脚注を更新しました。既存のベースラインより新しいものは他にありません。Obsidian の最新は引き続き 1.13.0(5月28日、下記で既に記載済み)、sqlite-vec stable は引き続き v0.1.9(v0.1.10 はまだ alpha)、MCP specification は引き続き 2025-11-25 revision です。Model2Vec のバージョン注記以外、本文の変更はありません。
2026-05-28 Obsidian 1.13.0 desktop + 1.13.0 mobile(Catalyst early-access)がリリースされました。Desktop: 設定パネルが刷新され、独立したウィンドウで開き、組み込み検索とキーボードナビゲーションに対応しました。Obsidian URIs は action を実行する前に確認ダイアログを表示するようになりました。network drives から HTML resources を読み込む前の新しい警告、Bookmarks view への Search 追加、editor image handling の強化、File Explorer / Properties / Sync の改善、多数の developer-API とバグ修正も含まれます。Mobile: 設定可能な target locations を備えた新しい iOS Share Sheet、tab switcher からのタブ並べ替え、tablet で split と pinned sidebars をリサイズする press-and-hold gestures、Bases の table views で columns をリサイズする menu item、iOS と search のバグ修正が入りました。AI workflows への影響として、Obsidian URIs の確認ダイアログは URI-driven MCP/agent integrations に明示的なゲートを追加します。Bases の column-resize menu により、agents が query する vault-front index として Bases を使いやすくなります。iOS Share Sheet の設定可能な target は、主要な intake として既に記載している iPhone capture path を Claude/Codex pipelines へより素早く接続できるようにします。
2026-05-06 source-verified currentness を更新しました。Smart Connections v4.5.0 は footer connections を Core に移しました。sqlite-vec v0.1.8/v0.1.9 stable releases は packaging と DELETE behavior を更新しました。Model2Vec v0.8.x は tokenizer/persistence internals と benchmark tables を更新しました。Obsidian CLI の chronology を「1.12.7 introduced CLI」から「1.12.0 introduced CLI, 1.12.7 improved installation/runtime packaging」へ修正しました。
2026-04-27 Web Clipper の4月サイクルです。1.4.0(interactive YouTube transcript UI + Open in Reader default)、1.5.0(Highlights viewer)、1.6.0(Highlighter UX overhaul + Defuddle 0.18 source extractors for LinkedIn/Threads/Bluesky/Discourse/Medium)、1.6.1 + 1.6.2(Reader と Safari の修正)。Web Clipper を単なる bookmark への言及ではなく、AI workflows における主要な browser-side intake path として再位置づけしました。この期間に Obsidian desktop、Sync、Bases のリリースはありません。
2026-04-16 Smart Connections v4.3.0(graph view、configurable dock、block-embedding recovery、Substrate cross-plugin env)。2026年4月の AI-native plugin wave(Cortex、VaultSearch、LLM Wiki、Drift、EngramQuest、Hybrid Search MCP)を記載しました。MarkusPfundstein/mcp-obsidian は maintenance-mode(最終 commit は 2025年6月)として明示しました。Dataview は休眠状態で、新規作業では Bases が後継です。Obsidian CLI 1.12.7 は、AI assistants 向けの推奨 bridge であり続けています。
2026-04-01 Obsidian CLI セクション(AI workflows 向け v1.12 commands)を追加しました。agent plugin セクション(Claudian、Agent Client)を追加しました。vault organization 向けの Bases core plugin を記載しました。plugin 数を 2,500+ に更新しました。intake source として iOS Share Extension を追加しました。embedded agent plugins を含めて compatibility matrix を更新しました。
2026-03-30 MCPVault v0.11.0: list_all_tags tool、.base/.canvas support、@bitbonsai/mcpvault への rename。Obsidian Desktop v1.12.7 は、より高速な terminal interactions のために CLI binary を同梱しています。
2026-03-23 sqlite-vec v0.1.7 stable を記載しました。vec0 tables の DELETE support、pagination 向けの KNN distance constraints です。DiskANN approximate nearest neighbor index が今後のリリース向けに発表されました。
2026-03-07 embedding model comparison に potion-multilingual-128M(101 languages、2025年5月)を追加しました。sqlite-vec は v0.1.7-alpha.10(CI/CD fixes、feature changes なし)。MCP spec と retrieval techniques が現行であることを確認しました。
2026-03-03 MCP spec evolution を更新しました(2025年11月に shipped: Streamable HTTP、.well-known、tool annotations)。Model2Vec fine-tuning と BPE/Unigram tokenizer support を追加しました。community MCP server comparison table を追加しました。Smart Connections を v4 に更新しました。
2026-03-02 model comparison に potion-base-32M と potion-retrieval-32M を追加しました。quantization/dimensionality reduction セクションを追加しました。MCP spec evolution note を追加しました。
2026-03-01 初回リリース

参照


  1. Internet Vin, “Obsidian と Claude Code で使っている22個のコマンド,” 2026年3月, x.com/internetvin/status/2026461256677245131

  2. Nicopreme, slash commands 付きの「Visual Explainer」agent skill, x.com/nicopreme/status/2023495040258261460

  3. Cormack, G.V., Clarke, C.L.A., and Buettcher, S. Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods. SIGIR, 2009. 順位付きリストを組み合わせるためのパラメーター不要の手法として、k=60 の RRF を導入しています。 

  4. OpenAI Embeddings Pricing. text-embedding-3-small: 100万 tokens あたり $0.02。vault 全体をフル再インデックスする推定コストは約 $0.30 です。 

  5. van Dongen, T. et al. Model2Vec: Turn any Sentence Transformer into a Small Fast Model. arXiv, 2025. sentence transformer から静的 embeddings を生成する蒸留アプローチを説明しています。 

  6. potion-base-8M Model Card および Model2Vec results。現在公開されている表では、potion-base-8M は 51.32 Avg (All) / 51.08 Avg (MTEB) と報告されています。all-MiniLM-L6-v2 は 55.80 Avg (All) / 55.93 Avg (MTEB) で、全タスクスコアではおよそ 92% の維持率です。 

  7. Model Context Protocol Specification。AI ツールをデータソースに接続するための MCP 標準です。 

  8. Model2Vec Potion Modelspotion-base-32M、および potion-retrieval-32M。現在の model card では、potion-base-32M は 52.83 Avg (All)、potion-retrieval-32M は retrieval 表で 35.06 と報告されています。 

  9. Update on the Next MCP Protocol Release。2025年11月リリースでは、Streamable HTTP transport、.well-known URL discovery、structured tool annotations、SDK tier standardization が提供されました。次のリリースは暫定的に2026年半ばで、async operations、domain-specific extensions、agent-to-agent communication が予定されています。 

  10. Model2Vec Releases。v0.4.0(2025年2月): training/fine-tuning support。v0.5.0(2025年4月): backend rewrite、quantization、dimensionality reduction。v0.7.0(2025年10月): vocabulary quantization、BPE/Unigram tokenizer support。v0.8.0/v0.8.1(2026年3月): tokenizer と persistence のリファクタリング、Python 3.9 deprecation、MTEB V2 result updates、Windows path compatibility。v0.8.2(2026年5月29日): training 用の frozen-weights option を追加したメンテナンスリリースで、multiword-token fixes、training refactor、non-quantized weight-handling fixes も含まれます。 

  11. Smart Connections for Obsidian。Smart Connections v4: local-first AI embeddings。初回インデックス後は semantic search がオフラインで動作します。 

  12. potion-multilingual-128M。Minish Lab、2025年5月。101言語対応の静的 embedding model で、multilingual static embeddings として最高性能です。他の potion models と同じく numpy-only dependency です。 

  13. MCPVault v0.11.0。2026年3月。frontmatter と hashtags を件数付きでスキャンする新しい list_all_tags ツール。dotted folder handling、.base.canvas ファイル対応が改善されました。npm ではパッケージ名が @bitbonsai/mcpvault に変更されています。 

  14. sqlite-vec v0.1.7 Release。2026年3月17日。安定版リリース: vec0 virtual tables の DELETE 対応、pagination 用の KNN distance constraints、fuzz testing improvements。DiskANN approximate nearest neighbor indexing は今後のリリース向けに発表されています。 

  15. Introduction to Bases。Obsidian core plugin として v1.9.10 で導入されました。vault ファイル上で、frontmatter properties を fields として使うデータベース風ビュー(tables、galleries、calendars、kanban boards)を提供します。ファイルは .base 形式で保存されます。 

  16. Obsidian Desktop v1.12.0 Changelog および Obsidian Desktop v1.12.7 Changelog。v1.12.0 では、terminal-based vault automation のための CLI が導入されました。v1.12.7 では standalone binary、TUI、socket-file behavior により、installation/runtime packaging が改善されています。CLI documentation も参照してください。 

  17. Claudian。Claude Code を vault 内の AI collaborator として埋め込む Obsidian plugin です。sidebar chat、context-aware prompts、vision support、slash commands、permission modes を提供します。 

  18. Agent Client。Agent Client Protocol (ACP) 経由で、Claude Code、Codex CLI、Gemini CLI の統一インターフェースを提供する Obsidian plugin です。note mentions、shell execution、action approval に対応しています。 

  19. Obsidian iOS Changelog。2026年初頭の更新には、他のアプリから vault へ直接コンテンツを保存する Share Extension、Daily Note と Bookmark widget の修正、View Note widget の更新改善が含まれます。 

  20. MarkusPfundstein/mcp-obsidian。最終コミットは2025年6月28日。tagged release はありません。フォーラムでの議論(2026年4月)では、Obsidian 1.12.x が first-class CLI を提供したため、コミュニティは CLI ベースの integration へ移行していると報告されています。このガイドでは、歴史的文脈と既存 setup のユーザー向けに残していますが、新規デプロイには推奨しません。 

  21. Smart Connections v4.5.0 Release。2026年5月5日。Footer connections が Core feature になりました。最近の v4 release には、connection lists の graph views、設定可能な connection-panel locations、改善された block-embedding recovery、Substrate cross-plugin state、transformer fallback fixes、duplicate connection calculations の削減も含まれています。 

  22. obsidianmd/obsidian-clipper releases — Web Clipper の version-feature mapping に関する一次情報源です。2026年4月サイクル: 1.4.0(4月9日、YouTube transcript UI + Open in Reader default)、1.5.0(4月15日、Highlights viewer + Reader fade-in)、1.5.1(4月15日、webpack compilation fix)、1.6.0(4月21日、Highlighter UX + Defuddle 0.18 with LinkedIn/Threads/Bluesky/Discourse/Medium extractors)、1.6.1(4月22日、Reader outline fixes + highlights search)、1.6.2(4月23日、Safari embedded-mode clipboard fix)。Mozilla Add-ons storeChrome Web Store にも掲載されています。 

  23. sqlite-vec v0.1.8sqlite-vec v0.1.9sqlite-vec v0.1.10-alpha.3、および sqlite-vec v0.1.10-alpha.4。v0.1.8 では npm packaging が修正されました。v0.1.9 では 12 文字を超える metadata text columns に対する DELETE bug が修正されました。v0.1.10-alpha.3 では適切な INSERT OR REPLACE INTO support が追加されています。v0.1.10-alpha.4(2026年5月18日)では、新しい ivf/diskann features を使う vec0 tables で ALTER TABLE RENAME が失敗する問題と、DiskANN の cached-statement cleanup bug が修正されています。0.1.10 系はまだ prerelease です。 

  24. MCP 2026-07-28 Specification Release Candidate。2026年5月21日に発表され、final spec は2026年7月28日に公開されます。ローンチ以来最大の MCP 改訂です。stateless protocol core(initialize handshake と Mcp-Session-Id header を削除)、MCP Apps(sandboxed client iframes 内の server-rendered HTML)、Tasks の experimental core から official extension への昇格(tasks/gettasks/updatetasks/cancel)、OAuth 2.0 / OIDC authorization hardening、12か月の feature-deprecation lifecycle policy が含まれます。 

  25. Obsidian Desktop v1.13.0 Changelog。Early access、2026年5月28日。UX/security/developer-tooling release です。検索と keyboard navigation に対応し、独立ウィンドウで開く刷新された Settings panel、Obsidian URIs 実行前の confirmation dialogs、plugin developers 向けの新しい Settings API、flatpak installs 向けの CLI fix が含まれています。1.12.x の CLI surface を超える大きな新規 AI/automation capabilities はありません。 

  26. Obsidian Changelog。Obsidian 1.13.1 desktop は2026年6月9日に public channel に到達しました。1.13.0 から settings-UX refinement と CodeMirror upgrade が行われていますが、新しい AI/automation capability はありません。 

VAULT obsidian.md INDEXED