obsidian:~/vault$ search --hybrid obsidian

Obsidian MCP+混合檢索:2026參考指南

# 透過MCP將Obsidian串接至Claude與其他代理:伺服器設定、BM25+向量混合檢索,以及為含有16,894個檔案的知識庫建立索引,並提供可用設定。

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

Obsidian不是筆記應用程式。它是本機優先、純文字、圖狀結構的markdown語料庫;加入檢索基礎架構後,就會成為AI脈絡資源池。16,894個檔案。49,746個片段。23ms查詢。0次API呼叫。1個83 MB SQLite檔案。本指南涵蓋完整系統:從知識庫架構,到hybrid檢索,再到MCP整合與營運工作流程。


重點摘要

這是情境工程,不只是記筆記。Obsidian vault對AI的價值不在筆記本身,而在讓筆記可被查詢的擷取層。沒有擷取能力的16,000個檔案vault,只是一個只能寫入的資料庫;擁有hybrid搜尋與MCP整合的200個檔案vault,則是AI知識庫。擷取基礎設施才是產品,筆記則是原始素材。

Hybrid擷取優於純關鍵字或純語意搜尋。BM25能找出精確識別碼與函式名稱;向量搜尋則能跨越不同術語,找出同義詞與概念相符的結果。Reciprocal Rank Fusion(RRF)無須校準分數,即可合併兩者。單一方法都無法涵蓋這兩種失敗模式。MS MARCO段落排序研究也證實了這個模式:hybrid擷取的表現持續優於任一單獨方法。3hybrid retriever深入解析涵蓋RRF數學原理、使用真實數字的實作範例、失敗模式分析,以及互動式融合計算器。

MCP讓AI工具能直接存取vault。Model Context Protocol(MCP)伺服器會將retriever公開為工具,供Claude Code、Codex CLI、Cursor及其他AI工具直接呼叫。代理程式查詢vault後,會收到附帶來源歸屬的排序結果,並能使用這些情境,而無須載入整份檔案。MCP伺服器只是擷取引擎的一層輕量包裝。

Local-first代表零API成本與完整隱私。整套技術堆疊都在單一機器上執行:SQLite負責儲存、Model2Vec負責embeddings、FTS5負責關鍵字搜尋、sqlite-vec負責向量KNN。沒有雲端服務、沒有API呼叫,也沒有網路相依性。個人筆記永遠不會離開機器。為49,746個區塊完整重新建立embeddings,按OpenAI API價格計算約需$0.30;但真正的成本在於延遲、隱私曝露,以及一套本應能離線運作的系統卻得依賴網路。4

增量索引可在10秒內讓系統保持最新。系統會比較檔案修改時間以偵測變更,只會重新chunking並重新建立已修改檔案的embeddings。在Apple M系列硬體上,完整重新建立索引約需4分鐘。一般一天的編輯所觸發的增量更新,能在10秒內完成。系統無須人工介入即可保持最新狀態。

此架構可從200則筆記擴展至20,000+則。相同的三層設計(輸入、擷取、整合)適用於任何vault規模。可先在小型vault上使用僅BM25的搜尋;當關鍵字衝突成為問題時再加入向量搜尋;需要同時支援精確與語意匹配時,再加入RRF融合。每一層都能獨立發揮效用,也能獨立移除。


如何使用本指南

本指南涵蓋完整系統。您的起點取決於目前所處階段:

您的情況 從這裡開始 接著探索
剛接觸Obsidian+AI 為何選擇Obsidian作為AI基礎設施Obsidian MCP設定 Vault架構MCP伺服器架構
已有vault,想讓AI存取 MCP伺服器架構Claude Code整合 Embedding模型使用FTS5的全文搜尋
正在建立擷取系統 完整擷取管線Reciprocal Rank Fusion 效能調校疑難排解
團隊或企業情境 決策框架知識圖譜模式 開發者工作流程配方遷移指南

標示為Contract的章節包含實作細節、設定區塊與失敗模式。標示為Narrative的章節著重於概念、架構決策與設計選擇背後的推理。標示為Recipe的章節提供逐步工作流程。


為何選擇Obsidian作為AI基礎設施

本指南的核心論點是:Obsidian vault是個人AI知識庫的最佳基底,因為它以local-first為核心、採用純文字、具備圖譜結構,且使用者能掌控技術堆疊的每一層。

Obsidian提供其他替代方案無法給AI的能力

純文字markdown檔案。每則筆記都是檔案系統中的.md檔案。沒有專有格式、不需匯出資料庫,也不需要API即可讀取內容。任何能讀取檔案的工具都能讀取您的vault。grepripgrep、Python的pathlib、SQLite FTS5——它們都能直接處理來源檔案。建立擷取系統時,索引的是檔案,而不是API回應。由於來源就是檔案系統,索引會始終與來源一致。

Local-first架構。vault儲存在您的機器上。沒有伺服器、沒有雲端同步相依性、沒有API速率限制,也沒有規範您如何處理自身內容的服務條款。您可以在不使用任何外部服務的情況下,為筆記建立embeddings、索引、chunking與搜尋。這對AI基礎設施至關重要,因為擷取管線的速度取決於磁碟,而非API端點回應的速度。隱私同樣重要:含有憑證、健康資料、財務資訊與私人感想的個人筆記,永遠不會離開您的機器。

透過wiki-links建立的圖譜結構。Obsidian的[[wiki-link]]語法會在筆記間建立有向圖譜。一則關於OAuth實作的筆記,可能連結至token輪替、session管理與API安全性等筆記。圖譜結構編碼了人在思考主題時親自整理的概念關係。向量embeddings可捕捉語意相似性,但wiki-links記錄的是作者有意建立的連結。這種圖譜訊號無法由embeddings重現。

外掛生態系。Obsidian擁有2,500+個社群外掛(數量於2026年3月突破2,500個,高於2025年中期的1,800+個)。Dataview能像查詢資料庫般查詢您的vault。Templater可使用JavaScript邏輯,從範本產生筆記。Git整合可將vault同步至儲存庫。Linter可強制維持格式一致性。Bases核心外掛(於v1.9.10推出)會使用frontmatter屬性作為欄位,為vault檔案提供類似資料庫的檢視——表格、圖庫、行事曆與kanban看板,並儲存為.base檔案。15這些外掛會為vault增添結構,卻不改變底層純文字格式。擷取系統索引的是這些外掛產生的內容,而非外掛本身。

500萬+使用者。Obsidian擁有龐大且活躍的社群,持續產出範本、工作流程、外掛與文件。當您遇到vault組織或外掛設定問題時,很可能已有其他人記錄了解決方案。社群也開發Obsidian周邊工具:MCP伺服器、索引指令碼、發佈管線及API包裝工具。

單靠檔案系統無法提供的能力

一個markdown檔案目錄具備純文字優勢,但缺少Obsidian帶來的三項能力:

  1. 雙向連結。Obsidian會自動追蹤backlink。當您從筆記A連結至筆記B時,筆記B會顯示筆記A曾參照它。圖譜面板可視覺化連結群集。這種雙向感知屬於原始檔案系統無法提供的中繼資料。

  2. 具備外掛渲染的即時預覽。Dataview查詢、Mermaid圖表與callout區塊都能即時渲染。在儲存格式仍為純文字的前提下,寫作體驗比文字編輯器更加豐富。您可在豐富的環境中撰寫與組織內容;擷取系統則索引原始markdown。

  3. 社群基礎設施。包括外掛探索、主題市集、同步服務(選用)、發佈服務(選用)及文件生態系。您可以用獨立工具重現任何單一功能,但Obsidian將它們整合成連貫的工作流程。

Obsidian不做什麼(以及您要自行建立的內容)

Obsidian不包含擷取基礎設施。它提供基本搜尋功能(全文、檔名、標籤),但沒有embedding管線、向量搜尋、融合排序、MCP伺服器、憑證過濾、chunking策略,以及供外部AI工具使用的整合hooks。本指南涵蓋您在Obsidian之上建立的基礎設施。vault是基底;擷取管線、MCP伺服器與整合hooks才是基礎設施。

此處描述的架構是markdown-first,而非Obsidian專屬。若您使用Logseq、Foam、Dendron,或純markdown檔案目錄,擷取管線的運作方式完全相同。chunker會讀取.md檔案;embedder處理文字字串;indexer寫入SQLite。這些元件都不依賴Obsidian專屬功能。Obsidian的價值在於提供撰寫與組織環境,產生供retriever建立索引的markdown檔案。


Obsidian MCP 設定

Model Context Protocol(MCP)是標準介面,讓Claude Code、Codex CLI、Cursor及其他AI工具可直接存取Obsidian vault。本節可在5分鐘內將vault連接至AI工具。您將安裝Obsidian、建立vault、安裝MCP伺服器,並執行第一個查詢。快速入門使用社群MCP伺服器,立即取得結果。後續章節將介紹如何建置適合正式環境使用的自訂檢索管線。

先決條件

  • macOS、Linux或Windows
  • Node.js 18+(供MCP伺服器使用)
  • Obsidian 1.12+(用於CLI整合;1.13.7是目前公開桌面版發行版本——穩定版與beta版已趨於一致,1.13分支於2026年7月30日離開Catalyst;較早版本仍適用於僅使用MCP的設定)
  • 已安裝Claude Code、Codex CLI或Cursor

步驟1:建立vault

obsidian.md下載Obsidian,並建立新的vault。請選擇一個您記得住的位置——MCP伺服器需要絕對路徑。

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

新增幾則筆記,讓檢索器有內容可處理。即使只有10至20則筆記,也足以看出結果。每則筆記都應是具有明確標題、且至少包含一個段落內容的.md檔案。

步驟2:安裝MCP伺服器

有數個社群MCP伺服器可立即存取vault。整個生態系在2025至2026年間大幅成長。其中值得注意的是MCPVault(npm @bitbonsai/mcpvault,儲存庫bitbonsai/mcpvault),目前為v0.15.0(已於2026年8月14日根據npm驗證)——它與下方的MarkusPfundstein/mcp-obsidian是不同專案,並非後者改名而來。其v0.11.0(2026年3月)新增list_all_tags,可掃描frontmatter與hashtag並統計數量,也改善了含點資料夾的處理,以及.base.canvas支援。值得採用的是2026年7月23日同日發布的3個修補版本:v0.12.3新增wiki_link工具,可解析[[Document Name]][[Name|Display]]、表格逸出的[[Name\|Display]]#fragment形式,回傳筆記內容、解析後的路徑與任何含糊的替代結果——這項檢索基礎功能讓agent可沿著vault自身的連結圖譜,而不必再次搜尋——並透過預設路徑篩選器,讓所有工具都排除.trash/;v0.12.4將wiki_link延伸至如[[folder/Note]]的限定路徑連結;v0.12.2避免patch_note因包含$取代模式的插入內容而毀損,並正規化意外帶有vault前綴的路徑。其路徑篩選受限目錄拒絕清單曾揭露兩項中度嚴重性公告(GHSA-9c83-rr99-vfwj及GHSA-j99q-93c9-h869);兩者均早在0.12分支之前,於0.11.4與0.11.5修正,因此所有0.12.x版本都不受影響。13

2026年4月的轉變——以Obsidian CLI作為首選橋接方式:Obsidian 1.12.0導入一級支援的CLI,而公開的1.12.7安裝程式(2026年3月23日)整合獨立二進位檔、TUI與socket檔案改良,使終端機工作流程更易於安裝與執行。16 1.13分支於2026年7月30日以1.13.4進入公開頻道——這是設定、影像與URI安全性更新,除了1.12.x的CLI介面外,沒有新增AI或自動化功能(請參閱變更記錄列,了解其實際變更內容)。2526 社群工具正積極從Local REST API外掛(mcp-obsidian使用的外掛)遷移至以CLI為基礎的整合方式,因其更快速且更穩定。MarkusPfundstein/mcp-obsidian儲存庫仍持續維護——截至2026年5月的提交新增了search_by_tagget_frontmatter等工具——但未發布帶標籤的版本(請從固定的commit安裝)。它仍以Local-REST-API為基礎;若是新設定,CLI橋接方式通常更快、更穩定,因此建議優先使用它或下列較新的社群替代方案。20 請參閱本指南稍後的「Obsidian CLI for AI Workflows」章節,以取得建議設定方式。

伺服器 作者 傳輸方式 需要外掛 主要功能
obsidian-mcp(npm obsidian-mcp StevenStavrakis STDIO 輕量級、以檔案為基礎
mcp-obsidian MarkusPfundstein STDIO Local REST API 透過REST提供完整vault CRUD,另有search_by_tagget_frontmatter——持續維護中(提交至2026年5月);沒有帶標籤的版本,請固定commit20
obsidian-mcp-tools jacksteamdev STDIO 是(外掛) 語意搜尋+Templater
obsidian-claude-code-mcp iansinnott WebSocket 是(外掛) 為Claude Code自動探索
obsidian-mcp-server(npm obsidian-mcp-server cyanheads STDIO Local REST API 標籤、frontmatter管理——透過OBSIDIAN_API_KEYOBSIDIAN_BASE_URL設定,而非CLI旗標
Hybrid Search MCP community STDIO BM25+語意搜尋MCP伺服器+CLI。由社群維護;採用前請確認最近的提交。

對於快速入門,最簡單的選項是直接讀取.md檔案的檔案型伺服器。請留意npm名稱衝突:檔案型伺服器的npm名稱是obsidian-mcp(StevenStavrakis);npm obsidian-mcp-server則是cyanheads以REST-API為後端的伺服器,需要Local REST API外掛與API金鑰——這是常見混淆,會讓讀者安裝到無法啟動的伺服器:

npm install -g obsidian-mcp

步驟3:設定您的AI工具

Claude Code——使用claude mcp add註冊伺服器(Claude Code將使用者範圍的MCP伺服器儲存在~/.claude.json,或儲存在專案的.mcp.json——不是~/.claude/settings.json;後者的mcpServers區塊會被靜默忽略):

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

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

Codex CLI——新增至~/.codex/config.toml

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

Cursor——新增至.cursor/mcp.json

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

步驟4:執行第一個查詢

開啟AI工具,提出一個vault筆記能回答的問題:

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

AI工具會呼叫MCP伺服器,搜尋您的vault並回傳相符內容。您應會看到包含檔案路徑與相關摘錄的結果。

連線後Claude能做什麼

實際工具名稱會依伺服器而異,但各實作的核心功能範圍一致:

功能 常見工具 agent如何使用
搜尋vault obsidian_searchsearch 找出符合查詢的筆記,並回傳附有檔案路徑與來源歸屬的排序摘錄
讀取完整筆記 obsidian_read_noteread_note 當搜尋摘錄不足時,擷取完整筆記內容
列出與瀏覽 obsidian_list_noteslist_notes 在沒有特定查詢時,依資料夾、標籤或日期範圍探索筆記
取得格式化脈絡 obsidian_get_context 回傳符合主題的脈絡區塊,大小符合token預算,可直接注入對話

實務上,Claude可根據您的筆記回答問題並標示來源、將過往決策與參考資料帶入程式設計工作階段,也能在不將整個檔案載入脈絡的情況下探索vault結構。部分社群伺服器還提供寫入操作(建立、附加、標籤與frontmatter管理);本指南稍後建置的自訂伺服器刻意維持唯讀,改由hooks處理筆記建立。

深入說明:MCP Server Architecture介紹工具與權限設計,Claude Code Integration介紹hooks與橋接模式,Codex CLI IntegrationCursor and Other Tools則涵蓋其他agent。

您剛剛建置了什麼

您已透過標準通訊協定,將本機知識庫連接至AI工具。MCP伺服器讀取vault檔案、執行基本搜尋,並回傳結果。這是最小可行版本。

此快速入門未提供: - 混合檢索(BM25+向量搜尋+RRF融合) - 以Embedding為基礎的語意搜尋 - 憑證篩選 - 增量索引 - 以Hook為基礎的自動脈絡注入

本指南其餘內容將介紹如何建置上述每項能力。快速入門用以驗證概念;完整管線則提供正式環境等級的檢索能力。


AI工作流程的Obsidian CLI

Obsidian 1.12(2026年2月)導入內建命令列介面,為AI工作流程開闢新的整合介面;截至1.13.7仍維持最新狀態(1.13系列於2026年7月30日進入公開頻道;此後未新增CLI功能)。162526 CLI可作為Obsidian GUI的遙控器——Obsidian必須正在執行(或會在首次執行命令時自動啟動)。請在「設定」>「一般」>「命令列介面」中啟用。

CLI為何對AI基礎設施至關重要

CLI讓您能以程式方式存取原生Obsidian操作;過去這些操作必須透過GUI或plugin API執行。對AI工作流程而言,主要功能包括:

  • 從指令碼與hook搜尋。 obsidian search "query"obsidian search:context "query"可從任何shell指令碼、hook或自動化管線執行vault搜尋。search:context變體會回傳符合項目及其周邊內容,適合將結果提供給AI提示。
  • 每日筆記自動化。 obsidian daily會開啟或建立今天的每日筆記。搭配shell指令碼,即可建立自動化每日簡報工作流程——hook可將AI產生的摘要附加至每日筆記。
  • 以範本建立筆記。 obsidian template listobsidian template create可從Templater或核心範本產生筆記,讓AI agent無須直接寫入markdown檔案,也能建立結構化vault項目。
  • 屬性管理。 obsidian property setobsidian property get可讀寫frontmatter屬性,讓指令碼無須剖析YAML即可更新中繼資料。
  • Plugin控制。 obsidian plugin enable/disable/list可透過程式管理plugin,適合在批次作業期間切換索引plugin。
  • 任務管理。 obsidian task list/add/complete提供結構化任務存取,適合讓AI agent管理vault中的工作項目。

用於AI存取的CLI與MCP比較

CLI與MCP伺服器各司其職,彼此互補而非競爭:

面向 Obsidian CLI MCP伺服器
呼叫端 Shell指令碼、hook、cron工作 AI agent(Claude Code、Codex、Cursor)
協定 POSIX程序(stdin/stdout/stderr) MCP(透過STDIO或HTTP的JSON-RPC)
優勢 Obsidian原生操作(範本、plugin、屬性) 自訂檢索(embeddings、BM25、RRF融合)
限制 沒有向量搜尋,也沒有embedding管線 無法存取Obsidian內部操作
最適用於 自動化指令碼、匯入管線、hook動作 工作階段期間的即時AI agent查詢

建議:將CLI用於匯入自動化(建立筆記、管理屬性、執行Obsidian原生搜尋),並將MCP用於檢索(使用embeddings的hybrid搜尋)。UserPromptSubmithook可在較繁重的hybrid檢索執行前,呼叫obsidian search:context作為快速預先檢查(tool範圍的hook事件無法注入——其stdout永遠不會傳送至模型)。

範例:由CLI驅動的匯入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 Plugins

日益增加的一類Obsidian plugin會將AI coding agent直接嵌入vault UI,提供外部MCP伺服器設定以外的替代方案。這些plugin會讓AI agent在Obsidian側邊欄中執行,而非從外部工具連線。

Claudian

Claudian將Claude Code作為AI協作者嵌入vault中。vault目錄會成為Claude的工作目錄,讓它具備完整的agent能力:檔案讀寫、搜尋、bash命令與多步驟工作流程。17

AI基礎設施的主要功能: - 情境感知提示。自動附加目前聚焦的筆記,支援@notename檔案提及、以tag排除內容,以及將編輯器選取範圍作為情境。 - 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。 - 筆記提及。使用@notename將筆記內容納入提示;與Claudian類似,但不受特定agent限制。 - Shell執行。可在對話中內嵌執行終端機命令——建立指令碼、執行git命令或任何終端機操作,無須離開對話。 - 動作核准。可細緻控制檔案讀取、編輯及命令執行。

何時使用agent plugin或外部MCP

情境 Agent plugin 外部MCP
使用AI協助撰寫與編輯vault筆記 較佳——agent可看見編輯器情境 可行,但無法掌握編輯器狀態
跨多個repo進行程式開發 有限——僅限vault範圍 較佳——以專案為範圍,具備完整檔案系統存取
從大型已索引語料庫進行檢索 僅提供基本搜尋 完整hybrid檢索管線
筆記期間快速進行vault問答 理想——無須切換情境 需要切換至終端機

建議:將agent plugin用於以vault為中心的工作流程(撰寫、整理、摘要筆記)。在AI agent需要完整檢索管線,以及存取vault外程式碼庫的開發工作流程中,則使用外部MCP伺服器。兩種方式可以並存——在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 Plain Filesystem CLAUDE.md
Local-first 否(雲端) 部分(iCloud)
Plaintext 是(markdown) 否(blocks) 否(專有格式)
圖狀結構 是(wiki-links) 部分(mentions)
AI可索引 直接存取檔案 需要API 需要匯出 直接存取檔案 已在context中
Plugin生態系 2,500多個plugins Integrations N/A N/A
離線能力 完整 快取唯讀 部分 完整 完整
可擴展至10K+筆記 是(搭配API) 效能下降 否(單一檔案)
成本 免費(核心功能) $10/月以上 免費 免費 免費

何時Obsidian顯得大材小用

  • 單一專案context。如果AI只需要目前程式碼庫的context,請放在CLAUDE.mdAGENTS.md或專案層級文件中。這些檔案會隨repo一起移動,並自動載入。
  • 結構化資料。如果內容是表格、記錄或schema,請使用資料庫。Obsidian筆記以 prose 為優先。Dataview可以查詢frontmatter欄位,但真正的資料庫更擅長處理結構化查詢。
  • 暫時性研究。如果筆記會在專案結束後丟棄,用一個放markdown檔案的scratch目錄會更簡單。不要為短暫內容建置retrieval基礎設施。

何時Obsidian是正確選擇

  • 累積數月或數年的知識。隨著語料庫成長,價值會持續複利。一個每天查詢、持續6個月的200則筆記vault,會比只查詢一次的5,000則筆記vault更有價值。
  • 單一語料庫涵蓋多個領域。包含程式設計、架構、安全、設計與個人專案筆記的vault,能受益於跨領域retrieval;這是專案專屬CLAUDE.md無法提供的。
  • 重視隱私的內容。Local-first表示retrieval pipeline永遠不會把內容傳送到外部服務。vault會包含您放入其中的任何內容,包括您不會上傳到雲端服務的資料。

心智模型:三個層次

此系統有三個彼此獨立運作、但結合後相輔相成的層次。每個層次關注的問題不同,失效模式也不同。

┌─────────────────────────────────────────────────────┐
                 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。若缺乏策展,vault會累積雜訊:推文截圖、沒有註解的複製貼上文章、缺少context的半成品想法。intake層負責在入口處進行品質控管。無論是評分pipeline、tagging慣例,或人工審查流程,目的都是確保vault包含值得retrieving的內容。

Retrieval讓vault可被查詢。這是引擎:將筆記chunking成搜尋單元、把chunks embedding到向量空間、建立關鍵字與語意搜尋索引,並用RRF融合結果。retrieval層會把一個檔案目錄轉換成可查詢的知識庫。沒有這一層,vault仍可透過手動瀏覽與基本搜尋來導覽,但AI tools無法以程式化方式存取。

Integration將retrieval層連接到AI tools。MCP伺服器會將retrieval公開為可呼叫的tool。Hooks會自動注入context。Skills會把新知識擷取回vault。integration層是知識庫與消費它的AI agents之間的介面。

這些層次在設計上彼此解耦。intake評分pipeline不了解embeddings。retriever不了解signal routing規則。MCP伺服器不了解筆記是如何建立的。這種解耦代表您可以獨立改善任何一層。更換embedding模型,不必變更intake pipeline。新增MCP能力,不必修改retriever。調整signal scoring heuristics,不必碰觸index。


供 AI 取用的 Vault 架構

為 AI 檢索最佳化的 vault,遵循的慣例不同於為個人瀏覽最佳化的 vault。本節說明資料夾結構、筆記 schema、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(內含 placeholder 變數,而非內容)、attachments(二進位檔案)、Obsidian 設定,以及任何含有敏感內容、不希望進入檢索索引的資料夾。

.indexignore 檔案

在 vault 根目錄建立 .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/

indexer 會在掃描前讀取此檔案,並完全略過相符的路徑。被排除路徑中的檔案不會被 chunking、不會產生 embeddings,也不會出現在搜尋結果中。

筆記 Schema

每則筆記都應該有 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 — 啟用依類型篩選的查詢(「只顯示 MOC」或「只顯示 signals」)
  • tags — 以 0.3 權重索引到 FTS5 標題脈絡中,即使正文使用不同術語,也能提供關鍵字比對

選用但很有價值的欄位:

  • domain — 啟用依領域限定範圍的查詢(「只搜尋 security 筆記」)
  • source — 標示擷取內容的來源;retriever 可以在結果中包含來源 URL
  • status — 可將封存或草稿筆記排除於 active search 之外

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 個可獨立搜尋的 chunks。每個 chunk 都有足夠脈絡,讓 embedding 捕捉其意義。關於「expired token handling」的查詢會精準比對到第 3 個 chunk。

不利於檢索:

# 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 標題的長區段會產生一個大型 chunk。embedding 會在該區段的所有主題之間取平均。查詢任何子主題時,都會同等比對到整則筆記。

經驗法則:如果一個區段涵蓋超過一個概念,請拆成 H2 子區段。chunker 會處理其餘部分。

不應放進筆記的內容

會降低檢索品質的內容:

  • 未加註解就完整複製貼上的整篇文章。retriever 會索引原文的關鍵字,讓您的 vault 被非您撰寫的內容稀釋。請改為加入摘要、摘錄重點,或連結到來源 URL。
  • 沒有文字說明的截圖。retriever 索引的是 markdown 文字。沒有 alt text 或周邊描述的圖片,對 BM25 與 vector search 都是不可見的。
  • credential 字串。API keys、tokens、passwords、connection strings。即使有 credential filtering,最安全的做法仍是永遠不要把 secrets 貼進筆記。請改用名稱參照(例如「~/.env 中的 Cloudflare API token」)。
  • 未經整理的自動產生內容。如果工具產生筆記(meeting transcript、Readwise highlights、RSS import),請先審閱並加註後,再放入永久 vault。未整理的自動匯入只會增加數量,卻不會增加可檢索價值。

AI Workflows 的 Plugin 生態系

能提升 AI 檢索用 vault 品質的 Obsidian plugins,可分為 3 類:結構型(強制一致性)、查詢型(公開 metadata),以及同步型(讓 vault 保持最新)。

必備 Plugins

Dataview。使用 frontmatter 欄位,像查詢資料庫一樣查詢您的 vault。可建立動態索引,例如:「過去 30 天內更新、標記為 security 的所有筆記」,或「狀態為 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 artifact)
  • 連續空白行:限制為 1 行(產生更乾淨的 chunks)

Git integration。為您的 vault 提供版本控制。可追蹤隨時間變化的修改、在多台機器間同步,並從意外刪除中復原。Git 也提供 mtime 資料,indexer 會用它進行增量變更偵測。

有助於 Indexing 的 Plugins

Smart Connections。這是一個 Obsidian plugin,可在 Obsidian 內提供 AI 驅動的語意搜尋。Smart Connections v4 預設會建立本機 embeddings;一旦 vault 完成索引,語意連結與查找即可完全離線運作,不需要 API 呼叫。11 v4.5.0(2026年5月5日)將頁尾連結納入 Smart Connections Core,因此每個安裝都能在頁尾顯示相關筆記連結,不必開啟側邊面板。近期 v4 版本也加入了連結清單的圖形檢視、可設定的 dock 位置、索引中斷後更完善的 block-embedding 復原,以及「Substrate」:一個跨 plugin 環境,讓 Smart Connections、Smart Chat 和 Smart Composer 能共享狀態。21 本指南中的檢索系統位於 Obsidian 外部(作為 Python pipeline 執行),但 Smart Connections 對寫作時探索語意關係很有幫助。兩套系統索引相同內容,但服務不同情境:Smart Connections 用於編輯器內探索;外部 retriever 則透過 MCP 與 AI tool 整合。

2026年4月推出的 AI-native plugins。一波新的社群 plugins 直接鎖定 Claude Code / Codex / Gemini-CLI workflow:

Plugin 發布時間 功能
Cortex 4月4日 由 Claude Code 驅動的 vault agent:將 vault 視為 agent 工作區,而不只是筆記儲存處
VaultSearch 4月7日 Local-first hybrid 搜尋:BM25 + 語意 + 模糊搜尋(與本指南的檢索堆疊直接重疊)
LLM Wiki 4月9日 將您的 vault 轉為可私下查詢的知識庫
Drift 4月11日 用於 AI 驅動 Obsidian 編輯的 VS Code 風格 diff 檢視器;定位於 Claude Code workflows
EngramQuest 4月11日 從筆記產生記憶挑戰;提供適用於 Claude Code / Gemini CLI / Cursor 的「AI Skills」
Hybrid Search MCP 3月(仍屬新項目) MCP server + CLI,搭配 BM25 + 語意搜尋,專為 AI assistants 打造

可將這視為正在浮現的應用表面:其中幾個很可能在接下來幾季整併,或被 Smart Connections / Obsidian core 吸收。如果今天要選一個,VaultSearch 和 Hybrid Search MCP 在理念上最接近本指南的外部 retriever。

Dataview note:Dataview(長期存在的 Obsidian 查詢 plugin)最後一次發布是 2025年4月的 0.5.70,之後實質上已停滯。對於新工作,Obsidian 內建的 Bases 功能(1.9+)是隱含的後繼者,也是建議採用的路徑。

Metadata Menu。提供結構化 frontmatter 編輯,並為欄位值提供自動完成。可減少 typedomaintags 欄位中的錯字。一致的 metadata 能提升檢索篩選準確度。

會傷害 Indexing 的 Plugins

Excalidraw。將繪圖以嵌入於 markdown 檔案中的 JSON 形式儲存。這些 JSON 在語法上是有效的 markdown,但在 chunking 和 embedding 時會產生雜訊。請透過 .indexignore 將 Excalidraw 檔案排除在索引之外,或依副檔名篩選。

Kanban。以特殊格式的 markdown 儲存看板狀態。此格式是為 Kanban 呈現而設計,不適合 prose retrieval。chunker 會產生卡片標題與 metadata 的片段,embedding 效果不佳。請將 Kanban boards 排除在索引之外。

Calendar。建立內容極少的每日筆記(通常只有日期標題)。空白或近乎空白的筆記會產生低品質 chunks。若使用每日筆記,請在其中撰寫實質內容,或將每日筆記資料夾排除在索引之外。

重要的 Plugin 設定

File recovery → Enabled。防止意外刪除筆記。這與檢索沒有直接關係,但對您所依賴的知識庫至關重要。

Strict line breaks → Disabled。Markdown 標準換行(以雙換行分隔段落)比 Obsidian strict mode(以單一換行產生 <br>)能產生更乾淨的 chunks。

Default new file location → Designated folder。將新檔案導向 00-inbox/,避免未分類筆記污染 domain folders。inbox 是暫存區;檔案會在 triage 後移至 domain folders。

Wiki-link format → Shortest path when possible。較短的 link targets 讓 retriever 在索引 link structure 時更容易解析。


Embedding Models:選擇與設定

embedding模型會將文字chunk轉換成語意搜尋使用的數值向量。模型選擇會決定擷取品質、索引大小、embedding速度,以及執行階段相依套件。本節說明為何Model2Vec的potion-base-8M是預設選擇,以及何時該選用替代方案。

為何選擇Model2Vec potion-base-8M

Model: minishlab/potion-base-8M Parameters: 760萬 Dimensions: 256 Size: 約30 MB Dependencies: model2vec(僅numpy,無PyTorch) Inference: 僅CPU、靜態word embeddings(無attention layers)

Model2Vec會將sentence transformer的知識蒸餾成靜態token embeddings。Model2Vec不像BERT、MiniLM與其他transformer模型那樣在輸入上執行attention layers,而是透過預先計算的token embeddings加權平均來產生向量。5實務上的結果是:embedding速度比transformer-based模型快50到500倍,因為沒有序列運算。

在目前的Model2Vec結果頁面中,potion-base-8M達到all-MiniLM-L6-v2全任務分數約92%(51.32對55.80),同時速度仍快上數個數量級。6剩餘的品質差距,是換取速度與簡潔性的取捨。對於較短的markdown chunk(典型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的fallback模式運作時(例如embedding venv尚未安裝),匯入embedder模組不會產生成本。

隔離的虛擬環境。模型會在專用venv中執行(例如~/.claude/venvs/memory/),避免與其餘toolchain發生相依套件衝突。_activate_venv()函式會在執行階段將venv的site-packages加入sys.path

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

批次處理。embedder會以64筆為一批處理文字,以攤平Model2Vec的額外成本。indexer會將chunk送入embed_batch(),而不是一次只embedding一個chunk。

何時選擇替代方案

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 較高品質,仍為靜態
potion-retrieval-32M 256 120 MB 400x 35.06(retrieval) 針對retrieval最佳化的靜態模型
potion-multilingual-128M 256 約500 MB 300x 多語言vault(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-8M更好的品質,又不離開靜態embedding系列,請選擇potion-base-32M。它使用從baai/bge-base-en-v1.5蒸餾而來的較大詞彙表,達到52.83全任務分數(約比potion-base-8M高3%),同時維持相同的256維輸出與僅numpy相依。8模型檔案增為4倍會提高記憶體用量,但embedding速度仍比transformer模型快上數個數量級。

若主要使用案例是retrieval(vault搜尋正是如此),請選擇potion-retrieval-32M。此變體是從potion-base-32M針對retrieval任務微調而來,在Model2Vec的retrieval benchmark表中取得35.06分,高於potion-base-32M的32.67分。8取捨在於它是為retrieval最佳化,而不是一般用途的embedding品質。

若vault包含多種語言的筆記,請選擇potion-multilingual-128M。這個101語言模型於2025年5月發布,是多語言任務中表現最佳的靜態embedding模型,可為任何語言的任何文字產生embeddings,同時維持與其他potion模型相同的僅numpy相依。12較大的模型檔案(約500 MB)是換取跨語言能力的代價。若有日文、中文、德文或其他非英文筆記與英文內容並存,請使用此模型。

若retrieval品質比速度更重要,且已安裝PyTorch,請選擇all-MiniLM-L6-v2。384維向量會讓SQLite資料庫大小比256維向量增加約50%。在M系列硬體上,對15,000個檔案進行完整重新索引時,embedding速度會從少於1分鐘降至約10分鐘。

若需要最佳的本機retrieval品質,並能接受較慢的索引速度,請選擇nomic-embed-text-v1.5。768維向量大約會使資料庫大小變為3倍。需要PyTorch與現代CPU或GPU。

若網路延遲與隱私是可接受的取捨,請選擇text-embedding-3-small。API會產生最高品質的embeddings,但會引入雲端相依、按token計費(每百萬token 0.02美元),並將內容傳送到OpenAI的伺服器。

其他所有情況都維持使用potion-base-8M。速度優勢對反覆索引至關重要(開發期間重新索引),僅numpy相依可避開PyTorch安裝複雜度,而256維向量能讓資料庫保持精簡。

Quantization與維度縮減

Model2Vec v0.5.0+支援以降低精度與維度載入模型。8這對受限硬體部署,或在不切換模型的情況下降低資料庫大小很有幫助:

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模型能以一小部分記憶體占用,保留幾乎相同的retrieval品質。維度縮減採Matryoshka式截斷,前N個維度承載最多資訊。從256維降到128維,可將向量儲存空間減半,且在短文字retrieval上品質損失極小。

Model2Vec v0.8.x更新tokenizer與persistence內部實作、棄用Python 3.9支援,並將發布結果更新到較新的MTEB表。升級production indexer前,請先釘選或測試model2vec,因為即使embedding模型名稱維持不變,函式庫升級仍可能改變模型載入路徑。10

針對Vault特定Embeddings進行微調

Model2Vec v0.4.0+支援在靜態embeddings之上訓練自訂分類模型,v0.7.0加入詞彙量化與可設定pooling以進行蒸餾,v0.8.x則重構tokenizer與persistence行為。10這對具備專門詞彙的vault很有關聯(醫療筆記、法律參照、領域專用術語),因為預設potion模型可能無法捕捉語意細微差異:

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

對大多數vault而言,預設potion-base-8M已能產生足夠的retrieval品質。只有當retrieval持續漏掉一般用途模型無法捕捉的領域特定連結時,微調才值得投入。

Model Hash追蹤

indexer會儲存由模型名稱與詞彙表大小衍生的hash。若更換embedding模型,indexer會在下一次incremental run偵測到不一致,並自動觸發完整重新索引。

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]

這可避免在同一個資料庫中混用不同模型產生的向量,否則會產生毫無意義的cosine similarity分數。

失敗模式

模型下載失敗。首次執行會從Hugging Face下載模型。若下載失敗(網路問題、企業防火牆),retriever會fallback到僅BM25模式。第一次下載後,模型會快取到本機。

維度不一致。若未清除資料庫就切換模型,已儲存向量會與新的embeddings維度不同。indexer會透過model hash偵測此狀況,並觸發完整重新索引。若hash檢查失敗(自訂模型沒有正確hash),sqlite-vec會在維度不一致的KNN查詢上報錯。

大型vault的記憶體壓力。單一批次embedding 50,000個以上chunk可能消耗大量記憶體。indexer會以64筆為一批處理,以限制尖峰記憶體用量。若記憶體仍有問題,請降低batch size。


使用 FTS5 進行全文搜尋

SQLite 的 FTS5 擴充功能提供具備 BM25 排名的全文搜尋。FTS5 是 hybrid 檢索管線中的關鍵字搜尋元件。本節說明 FTS5 設定、BM25 擅長的情境,以及其特定失效模式。

FTS5 Virtual Table

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

內容同步模式。content=chunks參數會告訴 FTS5 直接參照chunks資料表,而不是儲存一份重複的文字副本。這能將儲存需求減半,但也表示當 chunk 被插入、更新或刪除時,必須手動同步 FTS5。

欄位。索引包含3個欄位: - chunk_text—每個 chunk 的主要內容(BM25 權重:1.0) - section—H2 標題文字(BM25 權重:0.5) - heading_context—筆記標題、標籤與 metadata(BM25 權重:0.3)

BM25 排名

BM25 會依據詞彙頻率、反向文件頻率,以及文件長度正規化來排列文件。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%

這些權重可以調整。如果您的 vault 中有描述性強、能高度預測內容品質的標題,請提高section權重。如果標籤完整且準確,請提高heading_context權重。

BM25 何時勝出

BM25 擅長處理包含精確識別碼的查詢:

  • 函式名稱:_rrf_fuseembed_batchget_stale_files
  • CLI 旗標:--incremental--vault--model
  • 設定鍵:bm25_weightmax_tokensbatch_size
  • 錯誤訊息:SQLITE_LOCKEDConnectionRefusedError
  • 特定術語:PostToolUsePreToolUseAGENTS.md

對這些查詢而言,BM25 會立即找到精確符合項目。向量搜尋會回傳語意相關的內容,但可能把精確符合項目排在概念性討論之後。

BM25 何時失效

當查詢使用的術語與儲存內容不同時,BM25 會失效:

  • 查詢:「how to handle authentication failures」→ Vault 中包含關於「login error recovery」與「session expiration handling」的筆記。BM25 不會符合,因為關鍵字不同。
  • 查詢:「what is the best way to manage state」→ Vault 中包含關於「Redux store patterns」與「context providers」的筆記。BM25 會漏掉,因為「state management」是透過特定技術名稱來表達。

BM25 在規模變大時也會因為關鍵字碰撞而失效。在15,000個檔案的 vault 中,搜尋「configuration」會符合數百則筆記,因為幾乎每個專案筆記都會提到 configuration。結果在技術上正確,實務上卻難以使用——排名無法判斷哪一則「configuration」筆記與目前查詢相關。

FTS5 Tokenizer

FTS5 預設使用unicode61 tokenizer,可處理 ASCII 與 Unicode 文字。若 vault 含有大量 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命令會從內容資料表重建 FTS5 索引。大量插入後(完整重新索引)執行此命令,但不要在個別增量更新後執行;針對這類情境,請使用INSERT INTO chunks_fts(rowid, chunk_text, section, heading_context)來同步個別資料列。


sqlite-vec 擴充功能將 vector KNN(K-Nearest Neighbors)搜尋帶入 SQLite。本節說明 sqlite-vec 設定、從筆記到可搜尋 vector 的 embedding pipeline,以及具體的查詢模式。

sqlite-vec Virtual Table

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

vec0 模組會將 256 維浮點 vector 儲存為封裝後的二進位資料。id 欄位與 chunks 資料表形成 1:1 對應,因此可在 vector 結果與 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 模組會將浮點 vector 序列化,以便存入 sqlite-vec:

import struct

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

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

KNN Query

vector search query 會先將輸入查詢轉成 embedding,接著依 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 運算子會執行 approximate nearest neighbor search。k 參數控制要回傳多少結果。distance 欄位包含 cosine distance(0 = 完全相同,2 = 完全相反)。

使用 Distance Constraints 進行 KNN Pagination

自 sqlite-vec v0.1.7 起,KNN queries 支援 WHERE distance < ? constraints,可在大型結果集上進行 cursor-based pagination,且不必重新掃描先前頁面。14 後續 v0.1.8 與 v0.1.9 stable releases 主要是 packaging 與 DELETE bug-fix releases,而不是新的 query-model releases,因此 v0.1.7 仍是此 pagination pattern 的功能分界。23

接下來的 v0.1.10-alpha 系列(2026年3月31日至5月18日)是 sqlite-vec 首次超越 brute-force KNN 的版本:它引入 approximate-nearest-neighbor index types,包括 rescore、實驗性的 ivf(inverted-file)index(預設未啟用),以及適用於 vector 太大、無法常駐記憶體的大型 vault 的 disk-based DiskANN index。23 這些功能會改變超大型 vault 的擴展性敘事,但 0.1.10 系列仍是 pre-release (alpha)。請將 ANN indexing 視為實驗性功能;在 stable 0.1.10 發布前,production vaults 仍建議持續建立在 stable v0.1.9 brute-force KNN 路徑上。

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 中 slicing 的模式,降低在大型 vault 上執行探索式查詢時的記憶體用量。

vec0 Tables 中的 DELETE Support

sqlite-vec v0.1.7 為 vec0 virtual tables 加入原生 DELETE support,而 v0.1.9 修正了涉及長度超過 12 個字元的 metadata text columns 時的 DELETE error path。1423 先前若要移除 vectors,必須 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」資料表,也不需要進行 batch rebuilds。

Vector Search 何時勝出

當概念比特定文字更重要時,vector search 表現尤其出色:

  • Query: “how to handle authentication failures” → 找到關於 “login error recovery” 的筆記(相同語意空間,不同關鍵字)
  • Query: “what patterns exist for caching” → 找到關於 “memoization,” “Redis TTL strategies,” 以及 “HTTP cache headers” 的筆記(相關概念,多樣術語)
  • Query: “approaches to testing asynchronous code” → 找到關於 “pytest-asyncio fixtures,” “mock event loops,” 以及 “async test patterns” 的筆記(同一概念透過實作細節表達)

Vector Search 何時失準

vector search 不擅長處理精確識別符:

  • Query: _rrf_fuse → 會回傳關於 “fusion algorithms” 與 “rank merging” 的筆記,但實際函式定義的排序可能低於概念討論
  • Query: PostToolUse → 會回傳關於 “tool lifecycle hooks” 與 “post-execution handlers” 的筆記,而不是特定 hook 名稱

vector search 也不擅長處理結構化資料。JSON 設定檔、YAML blocks,以及程式碼片段產生的 embeddings,往往捕捉的是結構模式,而非語意意義。含有 "review": true 的 JSON 檔案,embedding 結果會不同於一段討論 code review 的散文。

Graceful Degradation

如果 sqlite-vec 載入失敗(缺少 extension、平台不相容、library 損毀),retriever 會 fallback 到僅使用 BM25 的搜尋:

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

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

retriever 會在嘗試 vector queries 前檢查 vec_available。停用時,所有搜尋都只使用 BM25,並略過 RRF fusion 步驟。


Reciprocal Rank Fusion(RRF)

RRF會合併兩個已排序清單,而不需要校準分數。本節涵蓋演算法、實際查詢追蹤、k參數調校,以及為何選擇RRF而非其他替代方案。若想使用可編輯排名、情境預設與視覺化架構探索器的互動式計算器,請參閱hybrid retriever深度解析

演算法

RRF只根據文件在各清單中的排名位置來分配分數:

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

其中: - k是平滑常數(60,依循Cormack等人3) - rank_i是文件在結果清單i中的1起始排名 - weight_i是選用的各清單乘數(預設為1.0)

在多個清單中排名良好的文件,會取得較高的融合分數。只出現在單一清單中的文件,則會取得來自該單一來源的分數。

為何選擇RRF而非其他方案

加權線性組合需要校準BM25分數與cosine distances。BM25分數沒有上限,並會隨語料庫大小縮放。Cosine distances則限制在[0, 2]。若要合併兩者,就必須進行正規化,而正規化參數會依資料集而異。RRF只使用排名位置;無論評分方法為何,排名位置永遠是從1開始的整數。

學習式融合模型需要有標記的訓練資料,也就是查詢與文件的相關性配對。對個人知識庫而言,這種訓練資料並不存在。若要訓練出可用模型,您必須手動評判數百組查詢與文件配對。RRF不需要任何訓練資料即可運作。

Condorcet voting方法(Borda count、Schulze method)在理論上相當優雅,但實作與調校更為複雜。原始RRF論文證明,RRF在TREC評估資料上的表現優於Condorcet方法。3

實務中的融合

查詢:「how does the review aggregator handle disagreements」

BM25將review-aggregator.py排在第3名(精確關鍵字符合「review」、「aggregator」、「disagreements」),但把兩個設定檔排得更高(它們更醒目地符合「review」)。Vector search將同一個chunk排在第1名(語意上符合衝突解決)。經過RRF融合後:

Chunk BM25 Vec Fused Score
review-aggregator.py “Disagreement Resolution” #3 #1 0.0323
code-review-patterns.md “Multi-Reviewer” #4 #2 0.0317
deliberation-config.json “Review Weights” #1 0.0164

兩個清單中排名都好的chunk會浮上最前面。只出現在單一清單中的chunk會得到單一來源分數,並落到雙清單排名結果之後。實際的歧見解決邏輯會勝出,因為兩種方法都找到了它: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資料集上都很穩健。只有在量測您自己的查詢分布中的失敗案例後,才進一步調校。

平手處理

當兩個chunk具有相同RRF分數時(少見,但若它們在某一個清單中排名相同,且未出現在另一個清單中,就可能發生),請依序用以下規則打破平手:

  1. 優先選擇同時出現在兩個清單中的chunk,而非只出現在單一清單中的chunk
  2. 在同時出現在兩個清單中的chunk之間,優先選擇合併排名較低者
  3. 在只出現在單一清單中的chunk之間,優先選擇在該清單中排名較低者

完整的 Retrieval Pipeline

本節會追蹤一個查詢如何從輸入一路通過整個 pipeline 產生輸出:BM25 搜尋、向量搜尋、RRF fusion、token budget 截斷,以及內容脈絡組裝。

端到端流程

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 個 chunk 資料庫。

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 參數可避免 retriever 回傳超出 AI 工具可使用範圍的內容脈絡。估算方式採用每個 token 4 個字元(對英文散文而言是合理近似值)。結果會以貪婪方式截斷:依排名順序加入結果,直到 budget 用盡為止。

這是一種保守策略。更精細的做法會考量每筆結果的品質分數,並偏好較短且品質較高的結果,而不是較長且品質較低的結果。貪婪方法更簡單,實務上也運作良好,因為 RRF 排名已經按照相關性排序結果。

資料庫 Schema(完整)

-- 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 會在初始化時檢查能力,並調整其查詢策略。缺少某個元件會降低品質,但不會造成錯誤。唯一的硬性失敗是找不到資料庫檔案。

Production 統計

以下是在包含 16,894 個檔案、49,746 個 chunks、83 MB SQLite 資料庫的 vault 上測得,硬體為 Apple M3 Pro:

指標 數值
檔案總數 16,894
chunks 總數 49,746
資料庫大小 83 MB
BM25 查詢延遲(p50) 12ms
向量查詢延遲(p50) 8ms
RRF fusion 延遲 3ms
端到端搜尋延遲(p50) 23ms
完整重新索引時間 約 4 分鐘
增量重新索引時間 <10 秒
Embedding 模型 potion-base-8M(256-dim)
BM25 候選池 30
向量候選池 30
預設結果限制 10
預設 token budget 4,000 tokens

內容 Hashing 與變更偵測

indexer 需要知道哪些檔案自上次索引執行後已經變更。本節說明變更偵測機制與 hashing 策略。

檔案修改時間比較

indexer 會在 chunks table 中為每個 chunk 儲存 mtime_ns(以奈秒表示的檔案修改時間)。在增量執行時,indexer 會:

  1. 掃描 vault 中允許資料夾內的所有 .md 檔案
  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)

為什麼使用 mtime,而不是內容 Hash

內容 hashing(檔案內容的 SHA-256)會比 mtime 比較更可靠,因為它能偵測檔案被碰觸但內容未變的情況(例如 git checkout 還原原本的 mtime)。不過,hashing 需要在每次增量執行時讀取每個檔案。對 16,894 個檔案而言,讀取檔案內容需要 2 到 3 秒。從檔案系統讀取 mtimes 則少於 100ms。

取捨在於:mtime 比較偶爾會觸發對未變更檔案的不必要重新索引(false positives),但不會漏掉實際變更。False positives 的成本只是每次執行多幾次 embedding 呼叫。速度差異(100ms 對 3 秒)讓 mtime 成為這套會在每次 AI 互動時執行的系統中務實的選擇。

處理刪除

當檔案從 vault 刪除時,indexer 會從資料庫移除該檔案的所有 chunks:

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 修正了針對 metadata 文字欄位較長的 vec0 table 執行 DELETE 操作的 bug。1423 較早版本需要採用 workaround(刪除並重建 virtual table,或維護外部的「active IDs」集合)。如果正在執行 pre-0.1.9 版本,請先升級,再依賴 metadata-heavy schema 中的直接刪除。

FTS5 content-sync tables 需要針對每個移除的 row,透過 INSERT INTO chunks_fts(chunks_fts, rowid, ...) VALUES('delete', ?, ...) 明確刪除。indexer 會在檔案移除流程中處理這件事。

增量與完整重新索引

索引器支援兩種模式:增量(快速,日常使用)與完整(較慢,偶爾使用)。本節說明各自的使用時機、冪等性保證,以及毀損復原。

增量重新索引

使用時機:編輯筆記後的日常索引。這是預設模式。

執行內容: 1. 掃描 vault 中的檔案變更(比較 mtime) 2. 刪除已刪除檔案的 chunks 3. 重新 chunk 並重新 embed 已變更的檔案 4. 為新檔案插入新的 chunks 5. 同步 FTS5 索引

典型耗時:在含 16,000 個檔案的 vault 中,處理一天的編輯通常少於 10 秒。

python index_vault.py --incremental

完整重新索引

使用時機: - 變更 embedding model 之後(偵測到 model hash 不相符) - schema migration 之後(新增欄位、變更索引) - 資料庫毀損之後(integrity check 失敗) - 增量索引產生非預期結果時

執行內容: 1. 刪除所有既有資料(chunks、vectors、FTS5 entries) 2. 掃描整個 vault 3. 對所有檔案進行 chunk 4. 對所有 chunks 產生 embeddings 5. 從零開始建立 FTS5 索引

典型耗時:在 Apple M3 Pro 上處理 16,894 個檔案約需 4 分鐘。

python index_vault.py --full

冪等性

兩種模式都是冪等的:執行同一個命令兩次會產生相同結果。索引器會先刪除檔案既有的 chunks,再插入新的 chunks,因此在已是最新狀態的資料庫上重新執行增量索引,會產生零變更。重新執行完整索引則會產生相同的資料庫。

毀損復原

如果 SQLite 資料庫毀損(寫入期間斷電、磁碟錯誤、交易中途程序被終止):

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

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

真實來源永遠是 vault 檔案,而不是資料庫。資料庫是衍生產物,可隨時重建。這是關鍵的設計特性:您永遠不需要備份資料庫。

--incremental 旗標

索引器以 --incremental 執行時:

  1. Model hash 檢查。將已儲存的 model hash 與目前模型比較。若不同,會自動切換為完整重新索引模式,並警告使用者。
  2. 檔案掃描。走訪允許的資料夾,收集檔案路徑與 mtimes。
  3. 變更偵測。與已儲存資料比較。
  4. 批次處理。以每批 64 個檔案重新 chunk 並重新 embed 變更檔案。
  5. 進度回報。列印已處理檔案數與經過時間。
  6. 優雅關閉。處理 SIGINT 時,會先完成目前檔案再停止。

Credential Filtering 與資料邊界

個人筆記含有機密:API keys、bearer tokens、資料庫連線字串,以及除錯期間貼上的 private keys。credential filter 會防止這些內容進入 retrieval index。

問題

一則關於除錯 OAuth 整合的筆記可能包含:

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

若未過濾,JWT 與 API key 都會被 chunk、embed,並儲存在資料庫中。搜尋「authentication」會傳回含有真實機密的 chunk。更糟的是,如果 retriever 透過 MCP 將結果提供給 AI 工具,這些機密會出現在 AI 的 context window 中,甚至可能進入工具記錄。

以模式為基礎的過濾

credential filter 會在每個 chunk 儲存前執行,匹配 25 種 vendor-specific patterns,加上通用 patterns:

Vendor-Specific Patterns:

Pattern Example 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 ... Various 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/char entropy、40+ chars 的字串
Password assignments password\s*[:=]\s*["'][^"']+["']

Filter 實作

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。清理後的文字才會被 embed。vector representation 永遠不會編碼 credential patterns。查詢「API key」會傳回討論 API key 管理的筆記,而不是含有實際 keys 的筆記。

  2. 替換,而非移除。[REDACTED:pattern-name] token 會保留周邊文字的語意脈絡。embedding 會捕捉「這裡曾有類似 credential 的內容」,但不會編碼 credential 本身。

  3. 記錄 patterns,不記錄 values。filter 會記錄哪些 patterns 命中(例如「Scrubbed 2 credential(s) from oauth-debug.md [jwt, bearer-token]」),但絕不記錄 credential value。

以路徑為基礎的排除

.indexignore 檔案提供以路徑為單位的粗粒度排除。credential filter 則在已索引檔案中提供細粒度清理。兩者缺一不可:

  • .indexignore 用於您明知含有敏感內容的整個資料夾(健康筆記、財務紀錄、職涯文件)
  • Credential filter 用於意外嵌入在原本可索引內容中的機密

資料分類

對於包含多樣內容的 vault,可考慮依敏感度分類筆記:

Level Examples Index? Filter?
Public 部落格草稿、技術筆記 Yes Yes
Internal 專案計畫、架構決策 Yes Yes
Sensitive 薪資資料、健康紀錄 No (.indexignore) N/A
Restricted Credentials、private keys No (.indexignore) N/A

MCP Server架構

Model Context Protocol(MCP)伺服器會將檢索器公開為AI代理可呼叫的工具。本節介紹伺服器設計、功能範圍與權限邊界。

協定選擇:STDIO與HTTP

MCP支援兩種傳輸模式:

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授權、結構化工具輸出(具型別的回傳schema),以及elicitation(由伺服器發起的使用者提示)。2025年11月的版本推出Streamable HTTP作為一級傳輸模式、用於自動瀏覽伺服器功能的.well-known URL探索機制、可宣告工具為唯讀或會變更資料的結構化工具註解,以及SDK分層標準化系統。79下一次修訂現已具體成形:2026-07-28規格於2026年5月21日進入Release Candidate,是MCP自推出以來規模最大的修訂。其主要變更包括無狀態協定核心(移除initialize交握與Mcp-Session-Id標頭,因此伺服器不再追蹤每條連線的工作階段狀態)、MCP Apps(伺服器可回傳在沙箱化用戶端iframe中顯示、由伺服器渲染的HTML)、Tasks從實驗性核心升格為正式擴充功能(供長時間執行作業使用的tasks/gettasks/updatetasks/cancel)、強化的OAuth 2.0/OIDC授權,以及12個月功能淘汰生命週期政策。它已如期於2026年7月28日以該次修訂發布,現為Current規格(已於2026年8月14日驗證)。24對個人vault伺服器而言,STDIO仍是最簡單的途徑,而無狀態核心使單一使用者的STDIO伺服器更加精簡。Streamable HTTP傳輸、.well-known探索與MCP Apps,主要有利於具備多租戶路由與負載平衡的企業HTTP部署。請關注MCP roadmap,以掌握會影響傳輸方式選擇的更新。

功能設計

MCP伺服器應公開最精簡的一組工具:

search — 主要工具。執行hybrid檢索並回傳排序後的結果。

{
  "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 — 便利工具,會執行搜尋並將結果格式化為適合注入對話的內容區塊。

{
  "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與索引資料庫,不會建立、修改或刪除筆記。寫入作業(擷取新筆記)由獨立的hooks或skills處理,而非由MCP伺服器處理。

  2. 限定vault範圍。伺服器只會讀取已設定vault路徑內的檔案。必須拒絕路徑穿越嘗試(../../etc/passwd)。

  3. 憑證過濾輸出。即使資料庫包含已預先過濾的內容,仍應在輸出時套用憑證過濾,作為縱深防禦措施。

  4. Token受限回應。對所有工具回應強制套用max_tokens,避免AI工具收到過大的內容區塊。

錯誤處理

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

使用claude mcp add註冊自訂伺服器(使用者範圍會寫入~/.claude.json-s project會寫入可共用的.mcp.json——~/.claude/settings.json不是MCP設定介面):

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

若偏好手動撰寫,對應的.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"
      }
    }
  }
}

加入設定後,請重新啟動Claude Code。MCP伺服器會以子程序啟動。請確認它正在執行:

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

Claude Code應會列出可用工具(obsidian_searchobsidian_read_note等)。

Hook整合

Hook會在定義好的生命週期節點擴充Claude Code的行為。Obsidian整合會用到兩種hook:

Hook會在設定中註冊(於~/.claude/settings.jsonhooks鍵下,指定事件名稱與matcher),並透過stdin接收JSON payload——不存在Claude Code會自動探索的hooks資料夾,工具詳細資料也不會以$1/$2引數傳入。

UserPromptSubmit hook——提交提示時查詢vault並注入相關脈絡(此事件的stdout會加入對話):

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

PostToolUse hook——將重要工具輸出擷取回vault,供後續檢索使用(透過matcher註冊,因此只會針對您關心的工具觸發):

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

obsidian_bridge.py模式

橋接模組提供一個可供hook與skill呼叫的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會在00-inbox/建立一則具備適當frontmatter的新筆記,並觸發增量重新索引,讓新筆記立即可供搜尋。

自訂命令模式

Claude Code skills可將vault操作包裝成具名命令。實務使用者已建立Obsidian專屬命令庫,將vault同時視為讀取來源與寫入目標。

訊號掃描。/scan-intel命令會查詢外部來源,依個人研究興趣為發現結果評分,並將符合條件的訊號以含frontmatter的vault筆記寫入:

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

此命令會從已設定來源(arXiv、HN、RSS)擷取資料,套用評分模型(相關性、可行動性、深度、權威性),並將通過的訊號寫入特定主題的vault資料夾。vault成為自動化情報管線的下游使用端。

Captain’s log。/captains-log命令會彙整所有repository的每日git活動,將結構化日誌項目寫入vault,並包含已做出的決策、領悟與待解事項:

/captains-log

此命令會從GitHub擷取commit歷程、依repository分組,並格式化為敘事式日誌項目。隨著時間推進,每日日誌會形成可搜尋的交付內容與決策緣由紀錄。

Obsidian擷取。/obsidian-capture命令會取得目前Claude Code工作階段中的洞見,並以適當中繼資料直接寫入vault:

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

此模式可延伸至任何vault操作:建立MOC、更新專案狀態筆記、連結相關訊號,或從累積的每日日誌產生每週摘要。

社群範例。實務使用者正陸續發布自己的命令庫。有位開發者分享了22個自訂Obsidian+Claude Code命令,涵蓋每日回顧、專案規劃、研究擷取與內容工作流程。1另一位則建立了「Visual Explainer」skill,可根據程式碼分析在vault中產生圖解筆記。2命令各有不同,但架構始終一致:以Claude Code skills作為介面、vault筆記作為儲存層,以及檢索基礎架構作為查詢引擎。

Context Window管理

整合時應留意Claude Code的context window:

  • 每次查詢注入的脈絡限制在1,500至2,000 tokens。超過此範圍會與agent的工作記憶競爭。
  • 包含來源歸屬資訊。務必附上檔案路徑與章節標題,讓agent能參照來源。
  • 截斷chunk文字。較長的chunk應以...截斷,而非完全省略。前300至500個字元通常已包含關鍵資訊。
  • 不要在每個提示都注入。注入會透過UserPromptSubmit執行(其stdout會送達模型的事件),因此應在此處控管預算:略過簡短的對話式提示,僅在提示提及程式碼、檔案或過去決策時注入,並限制注入區塊大小。像PreToolUse這類工具範圍事件可用於控管或記錄,但其stdout永遠不會送達模型。

Codex CLI整合

Codex CLI透過config.toml連線至MCP伺服器。此整合模式與Claude Code在設定語法及指令傳遞方式上有所不同。

MCP設定

加入至~/.codex/config.toml(Codex會讀取$CODEX_HOME/config.toml;專案層級指示應放在AGENTS.md,而非專案設定檔):

[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的差異

功能 Claude Code Codex CLI
MCP設定 claude mcp add~/.claude.json/專案.mcp.json ~/.codex/config.toml
Hooks 於設定中註冊、31個生命週期事件、stdin JSON 支援(穩定介面;具備自己的事件集)
Skills ~/.claude/skills/ ~/.codex/skills/(穩定)
指示檔 CLAUDE.md AGENTS.md
權限介面 模式:Manual/acceptEdits/auto(自2026年8月14日起,Pro/Max/Team預設)/plan/bypassPermissions 核准政策untrustedon-requestnever×sandbox read-onlyworkspace-writedanger-full-access--full-auto已於v0.147.0移除)

關鍵差異:兩種工具現在都支援hooks與skills;差異在於形式。Codex會將核准政策與OS層級sandbox模式搭配使用,而非採用Claude Code的權限模式,其hook事件也不同——請移植模式(工作前查詢vault、完成後擷取),而非設定。AGENTS.md仍是Codex中放置「先搜尋vault」常設指示的正確位置。

Cursor與其他工具

支援MCP的Cursor與其他AI工具可連線至相同的ObsidianMCP伺服器。本節說明常見工具的設定方式。

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檔案可加入使用vault的指示:

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

相容性矩陣

工具 MCP支援 傳輸方式 設定位置
Claude Code 完整 STDIO claude mcp add~/.claude.json/專案.mcp.json
Codex CLI 完整 STDIO ~/.codex/config.toml
Cursor 完整 STDIO .cursor/mcp.json
Windsurf 完整 STDIO ~/.codeium/windsurf/mcp_config.json
Continue.dev 完整 STDIO + HTTP ~/.continue/config.yamlmcpServers
Zed 完整(context servers) STDIO settings.jsoncontext_servers
Claudian(Obsidian外掛) 不適用(內嵌) Claude Code CLI Obsidian外掛設定
Agent Client(Obsidian外掛) 不適用(內嵌) ACP Obsidian外掛設定

不支援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整合優雅,但通用性十足。


從結構化筆記進行Prompt快取

vault中的結構化筆記可作為可重複使用的內容區塊,在多次AI互動中降低token用量。本節說明快取金鑰設計與token預算管理。

模式

與其在每次互動時搜尋內容,不如從結構完善的vault筆記預先建立內容區塊並加以快取:

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

快取失效

快取失效依據兩項訊號:

  1. TTL到期。每個內容區塊都有存活時間。TTL到期後,系統會重新查詢vault以重建區塊。
  2. vault變更偵測。當indexer偵測到曾用於建立快取內容區塊的檔案有所變更時,該區塊會立即失效。

Token預算管理

工作階段一開始會有總內容預算。快取區塊會占用其中一部分:

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具備常用內容的基礎脈絡,同時保留預算供特定查詢使用。

快取前後的Token用量

未使用快取:每次相關查詢都會觸發vault搜尋,回傳1,500至2,000 tokens的內容。在一個工作階段中進行10次查詢,agent會消耗15,000至20,000 tokens的vault內容。

使用快取:3個預先建立的內容區塊共消耗4,500 tokens。每個不重複查詢的額外搜尋會再增加1,500至2,000 tokens。在10次查詢中,若有6次由快取區塊涵蓋,agent消耗的token為4,500 + (4 * 1,500) = 10,500 tokens——約為未快取用量的一半。


擷取冗長輸出的壓縮摘要

工具輸出可能十分冗長:stack trace、檔案清單、測試結果。hook無法縮減模型看見的內容——PostToolUse觸發時,完整輸出早已進入context window,且hook輸出的任何內容都無法取代它。不過,hook可以將壓縮摘要寫入vault,讓後續工作階段擷取兩行結論,而無須重新執行或重讀5,000-token的原始內容。應將此視為跨工作階段記憶的擷取模式,而非工作階段內的內容節省工具(在工作階段內,真正有效的方式是/compact、限定範圍的prompt,以及要求較精簡的輸出)。

問題

執行測試的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 tokens,但關鍵資訊只在2行:200項通過、1項失敗。

Hook實作

PostToolUse上以Bashmatcher註冊(由settings註冊、stdin JSON——請參閱上方的Hook Integration):

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

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

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

每次hook呼叫都是全新的process,因此不需要遞迴防護——hook本身的寫入不會再次觸發它,匯出的變數也不會延續到下一次呼叫。

壓縮啟發式規則

輸出類型 偵測方式 壓縮策略
測試結果 PASSEDFAILED關鍵字 統計通過/失敗數量,只顯示失敗項目
檔案清單 指令中含有lsfind 截斷至前20個項目+總數
Stack trace Traceback關鍵字 保留第一個與最後一個frame+錯誤訊息
Git狀態 modified:new file: 依狀態彙總數量
建置輸出 warning:error: 移除資訊行,保留警告/錯誤

訊號接收與分流管線

接收層決定哪些內容會進入知識庫。若缺乏篩選,知識庫便會累積雜訊。本節介紹依分數將訊號導向各領域資料夾的管線。

來源

訊號來自多個管道:

  • RSS feeds:技術部落格、安全性公告、版本資訊
  • 透過 Web Clipper 的書籤:官方 Obsidian Web Clipper 擴充功能(Chrome、Firefox、Safari)是從瀏覽器端擷取內容時保真度最高的接收途徑。2026年4月的發布週期使其對 AI 工作流程格外實用:22
    • 1.4.0(4月9日):互動式 YouTube 逐字稿 UI——可釘選影片、在逐字稿中拖曳瀏覽、自動捲動,並標示目前位置。此外,「Open in Reader」預設選項可將一鍵擷取直接送至 Reader 模式。
    • 1.5.0–1.5.1(4月15日):重點標示檢視器——可瀏覽及搜尋整個知識庫中擷取的重點標示。淡入轉場進入 Reader。更流暢的 YouTube 播放/暫停操作。1.5.1 修正了 webpack 編譯回歸問題。
    • 1.6.0–1.6.2(4月21日至23日):全面改造 Highlighter UX,並支援行動裝置。Defuddle 0.18 為 LinkedIn、Threads、Bluesky、Discourse 與 Medium 新增來源專用擷取器。1.6.2 修正 Safari 內嵌模式的剪貼簿回歸問題。 請依來源網域設定範本,讓 YouTube 逐字稿、GitHub README 與長篇文章,各自以合理命名的筆記落地,並具備下方評分管線所需的正確 frontmatter。
  • 電子報:從電子郵件電子報擷取的關鍵摘要
  • 手動擷取:閱讀、對談或研究期間撰寫的筆記
  • 工具輸出:透過 hooks 擷取的重要 AI 工具輸出
  • iOS Share Extension:Obsidian 的 iOS 應用程式(於2026年初更新)包含 Share Extension,可將 Safari、社群網路及其他應用程式的內容直接儲存至知識庫,無須開啟 Obsidian;1.13 系列新增可設定的 Share Sheet 目標與範本變數——包括 url,因此擷取的網頁會自動將來源連結記錄至 frontmatter。19這提供了低摩擦的行動接收途徑——從 Safari 分享文章後,它便會成為可供評分的知識庫筆記。
  • Obsidian CLI:Shell scripts 與 hooks 可透過 obsidian file create 建立筆記,或透過 obsidian file append 附加至既有筆記,讓桌面端可建立自動化接收管線。

評分面向

每個訊號依四個面向評分(各為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
每日平均訊號數 ~18

知識圖譜模式

Obsidian 的 wiki-link 圖譜會編碼筆記之間的關係。本節介紹連結語意、用於擴充脈絡的圖譜走訪方式,以及會降低圖譜品質的反模式。

每個 wiki-link 都會在圖譜中建立一條有向邊。Obsidian 同時追蹤正向連結與 backlinks:

  • 正向連結:筆記 A 包含 [[Note B]] → A 連結至 B
  • Backlink:筆記 B 顯示筆記 A 曾參照它

圖譜會依脈絡編碼不同類型的關係:

連結模式 語意 範例
行內連結 「與此相關」 「詳情請參閱 [[OAuth Token Rotation]]」
標題連結 「具有子主題」 「## Related\n- [[Token Rotation]]\n- [[Session Management]]」
類似標籤的連結 「歸類為」 「[[type/reference]]」
MOC 連結 「屬於其中一部分」 列出相關筆記的 Map of Content 筆記

Maps of Content(MOCs)

MOC 是索引筆記,可將相關筆記組織為可瀏覽的結構:

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

MOC 能從兩個方面改善檢索:

  1. 直接比對。搜尋「authentication overview」會比對到 MOC 本身,向代理提供精心整理的相關筆記清單。
  2. 脈絡擴充。找到特定筆記後,檢索器可檢查該筆記是否出現在任何 MOC 中,並將 MOC 的結構納入結果,為代理提供更廣泛主題的地圖。

用於脈絡擴充的圖譜走訪

檢索器未來可新增的功能:在找到頂尖結果後,透過追蹤連結擴充脈絡:

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)

這尚未在目前的檢索器中實作,但它是圖譜結構順理成章的延伸。

反模式

孤立叢集。一組彼此相連、卻未與知識庫其餘部分建立連結的筆記。Obsidian 的圖譜面板會將它們顯示為彼此斷開的島嶼。孤立叢集表示缺少 MOC 或跨領域連結。

標籤蔓延。標籤使用方式不一致,或建立過多過於細緻的標籤。若知識庫在5,000則筆記中有500個唯一標籤,平均每10個標籤只有1則筆記——這些標籤無法有效篩選。應整併為20至50個對應領域資料夾的高階標籤。

連結多、內容少的筆記。整則筆記完全由 wiki-link 組成,沒有任何散文內容。這類筆記的索引效果不佳,因為 chunker 沒有文字可產生 embeddings。至少加入一段脈絡,說明這些連結筆記為何相關。

凡事都建立雙向連結。不是每個參照都需要 wiki-link。順帶提及「OAuth」不代表必須建立 [[OAuth 2.0 Overview]]。請將 wiki-link 保留給有意建立、可供瀏覽的關係,也就是點擊連結確實能提供有用脈絡的情況。


開發者工作流程範例

結合知識庫擷取與日常開發任務的實用工作流程。

早晨載入脈絡

一天開始時,先載入相關脈絡:

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

擷取器會回傳與目前專案相關的近期筆記,讓您快速回想上次停在哪裡。這比重新閱讀昨天的 commit 訊息更有效。

編碼期間擷取研究心得

實作功能時,不必離開編輯器也能擷取心得:

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

擷取到的心得會立即建立索引,日後可供擷取使用。幾個月下來,這些微型擷取會累積成一套與實作細節密切相關的知識語料庫。

專案啟動

開始新專案或新功能時:

  1. 搜尋知識庫:「我對 [technology/pattern] 知道什麼?」
  2. 檢視前 5 筆結果,找出過去的決策與注意事項
  3. 檢查該領域是否已有 MOC;若沒有,建立一個
  4. 搜尋失敗模式:「[technology] 的問題」

使用知識庫搜尋進行除錯

遇到錯誤或非預期行為時:

Search my vault for [error message or symptom]

過去的除錯筆記通常包含根本原因與修正方式。對於跨專案反覆出現的問題,這特別有價值——知識庫會記住您忘記的事。

Code Review 準備

審查 PR 前:

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

知識庫會回傳與待審查程式碼相關的既有決策、架構限制與程式碼標準。這讓審查能以組織知識為依據,而不只是看 diff。


效能調校

本節涵蓋針對不同知識庫大小與使用模式的最佳化策略。

索引大小管理

知識庫大小 Chunks DB 大小 完整重新索引 增量
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 則以上筆記時,建議考慮: - 將 batch size 從 64 提高到 128,以加快 embedding - 使用 WAL 模式(預設)支援並行存取 - 在離峰時段執行完整重新索引

查詢最佳化

WAL 模式。 SQLite 的 Write-Ahead Logging 模式可讓索引器寫入時仍能並行讀取:

db.execute("PRAGMA journal_mode=WAL")

當 MCP 伺服器在索引器執行增量更新期間處理查詢時,這一點至關重要。

連線池。 MCP 伺服器應重複使用資料庫連線,而不是每次查詢都開啟新連線。搭配 WAL 模式的單一長期連線即可支援並行讀取。

# 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 會告訴 SQLite 對資料庫檔案使用 memory-mapped I/O。對於 83 MB 的資料庫,將整個檔案映射到記憶體可消除大多數磁碟讀取。

FTS5 最佳化。 完整重新索引後,請執行:

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

這會合併 FTS5 內部的 b-tree segments,降低後續搜尋的查詢延遲。

擴充基準測試

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


疑難排解

索引漂移

症狀: 搜尋回傳過期結果,或找不到最近新增的筆記。

原因: 新增筆記後未執行增量索引器,或檔案的 mtime 未更新(例如從另一台機器同步且保留時間戳記)。

修正: 執行完整重新索引:python index_vault.py --full

更換 Embedding 模型

症狀: 變更 embedding 模型後,向量搜尋回傳不合理的結果。

原因: 舊向量(來自先前模型)正在與新的查詢向量比較。其維度或向量空間語意不相容。

修正: 索引器應偵測模型 hash 不相符,並自動觸發完整重新索引。若未自動執行,請手動清除資料庫並重新索引:

rm vectors.db
python index_vault.py --full

FTS5 維護

症狀: 多次增量更新後,FTS5 查詢回傳錯誤或不完整的結果。

原因: FTS5 內部 segments 可能在多次小型更新後變得碎片化。

修正: 重建並最佳化:

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

MCP 逾時

症狀: AI 工具回報 MCP 伺服器逾時。

原因: 第一次查詢會觸發模型載入(lazy initialization),需花費 2-5 秒。AI 工具預設的 MCP 逾時時間可能更短。

修正: 在伺服器啟動時預先暖機模型:

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

SQLite 檔案鎖定

症狀: 出現 SQLITE_BUSYSQLITE_LOCKED 錯誤。

原因: 多個程序同時寫入資料庫。WAL 模式允許並行讀取,但同一時間只能有一個寫入者。

修正: 確保只有一個程序(索引器)寫入資料庫。MCP 伺服器與 hooks 應只讀取。若需要並行寫入,請使用 WAL 模式並設定 busy timeout:

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

sqlite-vec 無法載入

症狀: 向量搜尋被停用;擷取器以僅 BM25 模式執行。

原因: sqlite-vec extension 未安裝、在 library path 中找不到,或與 SQLite 版本不相容。

修正:

# Install via pip
pip install sqlite-vec

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

確認 extension 可載入:

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

大型知識庫記憶體問題

症狀: 對大型知識庫(50,000 則以上筆記)執行完整重新索引時出現記憶體不足錯誤。

原因: Embedding batch size 過大,或一次將所有檔案內容載入記憶體。

修正: 降低 batch size,並以增量方式處理檔案:

BATCH_SIZE = 32  # Reduce from 64

同時請確保索引器一次處理一個檔案(先讀取、chunking,並對每個檔案進行 embedding 後,再移至下一個),而不是將所有檔案載入記憶體。


遷移指南

從 Apple Notes 遷移

  1. 透過「Export All」選項(macOS)匯出 Apple Notes,或使用 apple-notes-liberator 之類的遷移工具
  2. 使用 markdownifypandoc 將 HTML 匯出內容轉換為 markdown
  3. 將轉換後的檔案移至知識庫的 00-inbox/ 資料夾
  4. 檢查並為每則筆記加入 frontmatter
  5. 將筆記移至適當的領域資料夾

從 Notion 遷移

  1. 從 Notion 匯出:Settings → Export → Markdown & CSV
  2. 將匯出檔解壓縮到知識庫的 00-inbox/ 資料夾
  3. 修正 Notion 特有的 markdown 產物:
  4. Notion 使用 - [ ] 作為檢查清單——這是標準 markdown
  5. Notion 會將 property tables 納入 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. 移至知識庫、加入 frontmatter,並整理到資料夾中

從純 Markdown 遷移(未使用 Obsidian)

如果您已經有一個 markdown 檔案目錄:

  1. 將該目錄開啟為 Obsidian vault(Obsidian → Open Vault → Open folder)
  2. 若該目錄有版本控管,請將 .obsidian/ 加入 .gitignore
  3. 建立 frontmatter templates,並套用到既有檔案
  4. 閱讀與整理時,開始使用 [[wiki-links]] 連結筆記
  5. 立即執行索引器——擷取系統從第 1 天起即可運作

從其他擷取系統遷移

如果您正從不同的 embedding/搜尋系統遷移:

  1. 不要嘗試遷移向量。不同模型會產生不相容的向量空間。請使用新模型執行完整重新索引。
  2. 遷移內容,而不是索引。知識庫檔案才是真實來源。索引是衍生產物。
  3. 遷移後進行驗證。執行 10-20 個您知道答案的查詢,並確認結果符合預期。

變更紀錄

日期 變更 來源
2026-08-14 首次整體閘門稽核——完整指南評估器通讀;R1 獲得 8.29 分,發現 3 項 CRITICAL 與 5 項 MAJOR 問題,均已在此列修復。CRITICAL 問題會傷害讀者:快速入門將 npm obsidian-mcp-server 安裝為「最簡單的檔案型選項」——該套件是 cyanheads 以 REST-API 為後端的伺服器(需要 Local REST API plugin 與 OBSIDIAN_API_KEY;沒有 --vault 旗標),而檔案型伺服器其實是 npm obsidian-mcp(StevenStavrakis)——伺服器表格也有相同的名稱衝突,現已透過明確 npm 名稱修正;兩個 Claude Code MCP 設定區塊都教導在 ~/.claude/settings.json 中使用 mcpServers,但 Claude Code 會直接忽略它——改寫為 claude mcp add(使用者範圍 → ~/.claude.json),並加入 .mcp.json 專案範圍變體,同時修正相容性矩陣儲存格;hook 範例使用位置式 $1/$2 引數與 ~/.claude/hooks/pre-tool-use/ 自動探索資料夾——這是 Claude Code 從未提供過的介面——已改寫為在 settings 註冊、透過 jq 讀取 stdin JSON 的 hooks(內容注入移至 UserPromptSubmit,其 stdout 才會實際加入內容),而「PostToolUse 內容壓縮」段落的前提(一個 hook 縮減模型所見內容)不可能成立——改為將壓縮摘要擷取至 vault,以供跨工作階段重複使用,並移除不必要的遞迴防護(每次 hook 呼叫都是新的程序)。MAJOR 問題:1.13.4 → 1.13.7(依 manifest 驗證,stable 與 beta 已收斂);MCP 2026-07-28 規格附註在規格作為 Current 修訂版發布 17 天後,仍寫著「最終規格將於 7 月 28 日發布」(已改為過去式;9 改寫為歷史內容,指向 24);Codex 比較教導已移除的 suggest/auto-edit/full-auto 核准模式,並稱「不支援 hooks/skills」——兩者自 2026 年中起都是穩定的 Codex 介面,表格與段落已重建(CC 儲存格現列出實際權限模式,包括 8 月 14 日的自動預設值);Zed/Continue/Windsurf 矩陣列已更新。次要問題:移除 .codex/config.toml 專案變體(僅限 $CODEX_HOME)、mcpvault 0.12.4 → 0.15.0、將過期的「截至」錨點改為絕對表述,並在擷取段落納入原先承諾的 1.13 iOS Share Sheet url 變數。R2 驗證確認修復,但在邊緣發現殘留問題,已於第二輪修正:快速入門的 Codex/Cursor 區塊仍呼叫衝突的二進位檔(現三項工具皆使用 npx -y obsidian-mcp@2 serve,符合已安裝套件的 v2 語法)、改寫 hook 段落下方仍殘留一句 PreToolUse 注入內容的描述(注入指引現一致改由 UserPromptSubmit 處理),以及 4 個單行問題(不平衡的括號、過時的 1.13.4 參考、13 的版本、9 殘留的路線圖句子)。 24 26
2026-08-07 Obsidian 1.13 已進入公開頻道:1.13.4 於 2026 年 7 月 30 日升版(依 manifest 驗證:desktop-releases.jsonlatestVersion 為 1.13.4,beta.latestVersion 為 1.13.6)。本文中 3 處提及「公開頻道仍為 1.12.7」的內容已更新。既然 1.13 系列已普遍可用,其所提供的功能包括:設定介面全面改版(獨立視窗、可依名稱/說明搜尋、鍵盤與 Vim 導覽)、具備逐檔導覽和 Live Preview 調整大小控制的全螢幕圖片檢視器、可搜尋的 Bookmarks、Sync 多重選取,以及——與本指南讀者最密切相關的是——Obsidian URI 安全性:除非列入允許清單,obsidian:// 動作現在需要確認對話框。本指南的自動化流程透過 MCP 與 CLI 進行,不受影響;但凡是透過 URI 操作 Obsidian 的工作流程(Shortcuts、指令碼、其他啟動器),現在都必須先將動作加入允許清單,否則每次都會提示。面向開發者的變更包括:新的 Settings API 與遷移指南、破壞性的 --callout-color 變更(需要有效的 CSS 顏色,不再接受 RGB 三元組——themes 與 snippets 必須更新)、Electron 43.1.1,以及 CodeMirror 和 Mermaid 11.13.0 升級。沒有 AI、MCP 或 CLI 變更。Catalyst 追蹤版本移至 1.13.6。 26
2026-07-27 發布掃描與一項公告修正。MCPVault 在 7 月 23 日同日發布的 3 個修補版本中,從 0.12.1 升至 0.12.4;由於這些版本在 7 月 22 日掃描後隔日才推出,因此全數漏列。v0.12.3 新增 wiki_link 工具——解析 [[Document Name]][[Name\|Display]]、表格跳脫與 #fragment 格式,回傳內容、解析後的路徑與模糊匹配替代項目——並透過預設路徑篩選器,讓所有工具排除 .trash/;v0.12.4 將其擴充至路徑限定的 [[folder/Note]] 連結;v0.12.2 修正 patch_note 破壞 $ 模式插入的問題、正規化帶有 vault 前綴的路徑,並清除 npm audit 的高嚴重性問題。MCP-server 段落與 [^24] 現已說明三者。修正:2026-07-07 列稱 v0.12.1「帶有兩項中等嚴重性的路徑篩選公告」。事實並非如此。GitHub Advisory API 指出 GHSA-9c83-rr99-vfwj 的受影響版本範圍為 < 0.11.5,GHSA-j99q-93c9-h869 為 < 0.11.4——兩者都在 0.12 系列開始前修補完成,因此撰寫該列時 0.12.1 已沒有風險。本文與註腳現改為說明最先修補的版本,不再讓「執行目前版本」暗示仍存在未處理的曝露。此外:Obsidian 1.13.4 桌面版與行動版(7 月 27 日)屬於 Catalyst 搶先體驗;desktop-releases.json manifest 仍顯示 latestVersion 1.12.7 與 beta.latestVersion 1.13.4,因此公開頻道未變,本指南中的版本參考仍然有效。內容屬 UX 層級(lightbox 檔名顯示、Live Preview 圖片對齊與內距、卡住檔案的儲存競態、設定版面),沒有 AI、MCP 或 CLI 變更。 13 26
2026-07-22 發布掃描,沒有工作流程變更。Obsidian 1.13.3 桌面版與行動版(7 月 21 日)僅屬 Catalyst 搶先體驗——依 manifest 驗證,公開頻道仍為 1.12.7;內容屬 UX 層級(圖片嵌入 lightbox/縮放、Live Preview 行高修正、File Recovery 方向鍵、unique URI paneType 修正),沒有 AI/MCP/CLI 變更。Catalyst 追蹤從 1.13.2 升至 1.13.3。註:1.13.3 於 7 月 21 日稍晚、在當日掃描結束後發布——前一列的「沒有新版本」在撰寫當時是正確的。Web Clipper 1.7.1(7 月 22 日,GitHub 發布):匯入重點標示、{{model}}/{{modelId}}/{{modelProvider}} Interpreter 範本變數、更新的提供者預設集、Defuddle 0.19.2、針對近期 Anthropic models 的 Interpreter 修正、原生 Gemini API keys、DeepSeek 與 Azure OpenAI 處理;商店推出時間可能晚於 GitHub 日期。沒有官方 MCP server 新聞;無狀態規格仍預定於 7 月 28 日推出。 26
2026-07-21 準確性修正:公開桌面版頻道為 1.12.7,而非 1.13.1。2026-06-10 的項目(及其後本文參考)將 1.13.1 視為公開頻道版本;1.13.1 changelog 頁面標示為 Early access,官方自動更新 manifest(obsidianmd/obsidian-releases、desktop-releases.json)則列出公開 latestVersion 為 1.12.7,beta 頻道為 1.13.2——整個 1.13.x 系列都僅限 Catalyst。本文參考與 26 已修正。2026-07-17 → 2026-07-21 的發布掃描未發現新版本:core 仍為 1.13.2 Catalyst、Clipper 1.7.0,沒有官方 MCP server 新聞,MCP 無狀態規格仍預定於 7 月 28 日推出。 26
2026-07-17 發布掃描,沒有工作流程變更。Obsidian 1.13.2(7 月 14 日)僅屬 Catalyst 搶先體驗——公開頻道仍為 1.13.1,因此本文版本參考維持最新;唯一與本指南相關的項目是 iOS Share Sheet 範本新增 url 變數(將分享連結插入筆記),待 1.13.2 進入公開頻道後,將納入擷取路徑段落。Web Clipper 1.7.0(6 月 16 日,先前未列出):Defuddle 0.19.0 升級、{{content}} 現可保留 ==highlight== 標記,且重點標示會在即時頁面與 Reader 檢視之間持續保留。尚未宣布官方 Obsidian MCP server 或 AI 整合;MCP 規格的無狀態發布仍預定於 7 月 28 日。已依 obsidian.md/changelog、github.com/obsidianmd/obsidian-clipper releases 與 blog.modelcontextprotocol.io 驗證。
2026-07-07 準確性修正。MCPVault 已明確說明為獨立專案(npm @bitbonsai/mcpvault、repo bitbonsai/mcpvault),目前為 v0.12.1,帶有兩項中等嚴重性的路徑篩選公告(GHSA-9c83-rr99-vfwj、GHSA-j99q-93c9-h869)——先前的 [^24] 連結指向錯誤 repo(MarkusPfundstein/mcp-obsidian)。已修正 MarkusPfundstein/mcp-obsidian 的狀態:它是積極維護中(截至 2026 年 5 月 15 日仍有 commits,新增 search_by_tag/get_frontmatter),而非「自 2025 年 6 月起停滯」;它仍未發布任何標記版本。已依 GitHub commit history、GitHub Security Advisories 與 npm 驗證。
2026-07-06 為提升可發現性進行編輯重構:將「Quick Start: First AI-Connected Vault」重新命名為 Obsidian MCP Setup(錨點 #obsidian-mcp-setup),並加入「連線後 Claude 可以做什麼」功能摘要(搜尋、讀取、列出、格式化內容;唯讀邊界,寫入由 hooks 處理),內容整合自 MCP Server Architecture 段落。沒有新事實;已更新內部連結。
2026-06-10 版本時效性更新。Obsidian 1.13.1 desktop 已進入公開頻道(2026 年 6 月 9 日)——相較 1.13.0 為設定 UX 與 CodeMirror 升級,沒有重大 AI/自動化變更。本文目前版本參考從 1.13.0 移至 1.13.1(公開版,2026 年 6 月 9 日)。 26
2026-06-09 生態系統更新。MCP 2026-07-28 規格進入 Release Candidate(2026 年 5 月 21 日宣布)——這是 MCP 自推出以來最大修訂:無狀態協定核心(移除 initialize handshake 與 Mcp-Session-Id)、MCP Apps(在 sandboxed iframes 中呈現的 server-rendered HTML)、Tasks 從 experimental core 畢業為官方 extension、OAuth 2.0/OIDC 強化,以及 12 個月的棄用生命週期政策(最終規格於 2026 年 7 月 28 日發布);以具體 RC 取代 MCP Spec Evolution 附註中推測性的「暫定 2026 年中」路線圖說法。sqlite-vec v0.1.10-alpha(2026 年 3 月 31 日至 5 月 18 日)在暴力 KNN 之外新增近似最近鄰索引類型(rescore、experimental ivf、以磁碟為基礎的 DiskANN)——由於 0.1.10 系列仍為 pre-release,因此標記為即將推出/experimental。Obsidian 1.13.0 desktop(2026 年 5 月 28 日,搶先體驗)已在本文參考中更新為目前版本;這是 UX/安全性/開發工具版本,沒有新的 AI/自動化功能。 24 23 25
2026-06-08 維護檢查。Model2Vec v0.8.2(2026 年 5 月 29 日)發布:此維護版本新增訓練的 frozen-weights 選項,以及 multiword-token 修正、訓練重構與非量化權重處理修正;註腳已更新。沒有比既有基準更新的其他內容:Obsidian 最新版本仍為 1.13.0(5 月 28 日,已於下方記錄)、sqlite-vec stable 仍為 v0.1.9(v0.1.10 仍為 alpha),而 MCP 規格仍為 2025-11-25 修訂版。除 Model2Vec 版本附註外,本文沒有變更。 10
2026-05-28 Obsidian 1.13.0 desktop 與 1.13.0 mobile(Catalyst 搶先體驗)發布。Desktop:改版的 Settings 面板,可在獨立視窗開啟,內建搜尋與鍵盤導覽;Obsidian URIs 現在會在觸發動作前顯示確認對話框;從網路磁碟載入 HTML resources 前新增警告;Bookmarks 檢視新增 Search;強化 editor 圖片處理;File Explorer/Properties/Sync 改進;眾多 developer-API 與 bug 修正。Mobile:具可設定目標位置的新 iOS Share Sheet;可從 tab switcher 重新排序分頁;平板裝置支援按住手勢以調整分割區與釘選側邊欄大小;Bases 在表格檢視中新增可調整欄寬的選單項目;iOS 與搜尋 bug 修正。對 AI 工作流程的影響:Obsidian URIs 的確認對話框,為以 URI 驅動的 MCP/agent 整合加入刻意設置的閘門;Bases 欄寬調整選單讓 Bases 更適合作為 agents 查詢的 vault 前端索引;iOS Share Sheet 的可設定目標,讓 iPhone 擷取路徑(已記錄為主要 intake)更容易連接至 Claude/Codex pipelines。
2026-05-06 更新依來源驗證的時效性:Smart Connections v4.5.0 將 footer connections 移入 Core;sqlite-vec v0.1.8/v0.1.9 stable releases 更新 packaging 與 DELETE 行為;Model2Vec v0.8.x 更新 tokenizer/persistence internals 與 benchmark tables;將 Obsidian CLI 時序從「1.12.7 導入 CLI」修正為「1.12.0 導入 CLI,1.12.7 改善安裝/runtime packaging」。
2026-04-27 Web Clipper 4 月週期:1.4.0(互動式 YouTube transcript UI + Open in Reader 預設)、1.5.0(Highlights viewer)、1.6.0(Highlighter UX 全面改版 + Defuddle 0.18 針對 LinkedIn/Threads/Bluesky/Discourse/Medium 的 source extractors)、1.6.1 + 1.6.2(Reader 與 Safari 修正)。將 Web Clipper 重新定位為 AI workflows 的主要 browser-side intake path,而非一筆帶過的 bookmark 提及。此期間沒有 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 浪潮(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 的首選橋接方式。
2026-04-01 新增 Obsidian CLI 段落(適用於 AI workflows 的 v1.12 commands)。新增 agent plugin 段落(Claudian、Agent Client)。記錄用於 vault organization 的 Bases core plugin。將 plugin 數量更新為 2,500+。新增 iOS Share Extension 作為 intake source。以 embedded agent plugins 更新 compatibility matrix。
2026-03-30 MCPVault v0.11.0:list_all_tags 工具、.base/.canvas 支援,重新命名為 @bitbonsai/mcpvault。Obsidian Desktop v1.12.7 內含 CLI binary,以加快 terminal interactions。
2026-03-23 記錄 sqlite-vec v0.1.7 stable:支援 vec0 tables 的 DELETE、適用於 pagination 的 KNN distance constraints。宣布 DiskANN approximate nearest neighbor index 將在即將推出的版本中提供。
2026-03-07 在 embedding model comparison 中新增 potion-multilingual-128M(101 種語言,2025 年 5 月)。sqlite-vec 為 v0.1.7-alpha.10(CI/CD 修正,沒有功能變更)。確認 MCP spec 與 retrieval techniques 仍為最新。
2026-03-03 更新 MCP spec evolution(2025 年 11 月已發布:Streamable HTTP、.well-known、tool annotations)。新增 Model2Vec fine-tuning 與 BPE/Unigram tokenizer 支援。新增 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 附註。
2026-03-01 初次發布

參考資料


  1. Internet Vin,「22 commands I use with Obsidian and Claude Code,」2026年3月,x.com/internetvin/status/2026461256677245131。 

  2. Nicopreme,「Visual Explainer」agent skill with slash commands,x.com/nicopreme/status/2023495040258261460。 

  3. Cormack, G.V., Clarke, C.L.A., and Buettcher, S. Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods。SIGIR,2009年。介紹 RRF,並以 k=60 作為免調參的排序清單整合方法。 

  4. OpenAI Embeddings Pricing。text-embedding-3-small:每百萬 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 transformers 產生靜態 embeddings 的蒸餾方法。 

  6. potion-base-8M Model CardModel2Vec results。目前公開表格顯示,potion-base-8M 的 Avg(All)為 51.32、Avg(MTEB)為 51.08;相較之下,all-MiniLM-L6-v2 的 Avg(All)為 55.80、Avg(MTEB)為 55.93,亦即在全任務分數上約保留 92%。 

  7. Model Context Protocol Specification。用於將 AI 工具連接至資料來源的 MCP 標準。 

  8. Model2Vec Potion Modelspotion-base-32Mpotion-retrieval-32M。目前 model cards 顯示 potion-base-32M 的 Avg(All)為 52.83,而 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 標準化。其預告的發布週期最終以 2026年7月28日修訂版告終——即目前規格(請參閱 24)。 

  10. Model2Vec Releases。v0.4.0(2025年2月):支援訓練/微調。v0.5.0(2025年4月):後端重寫、quantization、dimensionality reduction。v0.7.0(2025年10月):vocabulary quantization、BPE/Unigram tokenizer 支援。v0.8.0/v0.8.1(2026年3月):tokenizer 與 persistence 重構、Python 3.9 棄用、MTEB V2 結果更新,以及 Windows 路徑相容性。v0.8.2(2026年5月29日):維護版本,新增訓練時的 frozen-weights 選項,以及 multiword-token 修正、訓練重構與非 quantized 權重處理修正。 

  11. Smart Connections for Obsidian。Smart Connections v4:local-first AI embeddings;完成初始索引後,semantic search 可離線運作。 

  12. potion-multilingual-128M。Minish Lab,2025年5月。支援 101 種語言的靜態 embedding 模型,為效能最佳的多語言靜態 embeddings。與其他 potion 模型同樣僅依賴 numpy。 

  13. MCPVault — bitbonsai/mcpvault。npm @bitbonsai/mcpvault,最新版本為 v0.15.0(發布於 2026-08-09);0.12.2–0.12.4 均於 2026-07-23 發布(0.12.2 於 09:51、0.12.4 於 10:10——0.12.3 雖出現在兩者之間的 repo changelog 中,但從未發布至 npm);此專案不同於 MarkusPfundstein/mcp-obsidian,並非其更名版本。v0.11.0(2026年3月)新增 list_all_tags 工具,可掃描 frontmatter 與 hashtags 並統計數量,同時改善 dotted-folder 處理,並支援 .base.canvas 檔案。0.12.2–0.12.4 的內容來自 repository CHANGELOG.md,這是唯一的發布紀錄——此 repo 的 GitHub releases endpoint 回傳空白清單,因此 npm 發布時間與 changelog 是主要來源。0.12.2:patch_note 會將 newString 原樣插入,不再展開 $'$&$`$$(issue #149/PR #153);以 vault 為前綴的絕對路徑或 ~/ 樣式路徑會正規化為 vault-relative(issue #122/PR #151);僅透過 lockfile 更新即清除 npm audit 的高嚴重性發現項目(PR #154)。0.12.3:新增 wiki_link 工具(PR #101),並透過預設路徑篩選器,讓所有工具排除 .trash/。0.12.4:wiki_link 會依完整 vault-relative path,而非 basename,解析如 [[folder/Note]] 的含路徑連結。其 path filter 受到兩個中等嚴重性 GitHub Security Advisories 影響:GHSA-9c83-rr99-vfwj(受限制資料夾僅在 vault root 遭拒絕,巢狀位置則否)與GHSA-j99q-93c9-h869(可透過大小寫及結尾點號/空白等價性繞過 deny-list)。依 GitHub Advisory API 所述,兩者受影響範圍分別為 < 0.11.5< 0.11.4,首個已修補版本分別為 0.11.50.11.4——兩者均早於 0.12.0,因此包括 0.12.1 在內的所有 0.12.x 版本均已修補。Advisory 範圍與 npm 時間戳記已於 2026-08-14 再次驗證。 

  14. sqlite-vec v0.1.7 Release。2026年3月17日。穩定版本:支援 vec0 virtual tables 的 DELETE、用於 pagination 的 KNN distance constraints,以及 fuzz testing 改善。DiskANN approximate nearest neighbor indexing 預告將於未來版本推出。 

  15. Introduction to Bases。Obsidian core plugin 於 v1.9.10 推出。使用 frontmatter properties 作為欄位,在 vault 檔案之上建立類似資料庫的 views(tables、galleries、calendars、kanban boards)。檔案以 .base 格式儲存。 

  16. Obsidian Desktop v1.12.0 ChangelogObsidian Desktop v1.12.7 Changelog。v1.12.0 推出用於以 terminal 為基礎進行 vault automation 的 CLI;v1.12.7 透過 standalone binary、TUI 與 socket-file 行為改善安裝/runtime packaging。另請參閱CLI 文件。 

  17. Claudian。將 Claude Code 嵌入 vault 作為 AI 協作者的 Obsidian plugin。提供 sidebar chat、context-aware prompts、vision support、slash commands 與 permission modes。 

  18. Agent Client。Obsidian plugin,透過 Agent Client Protocol(ACP)為 Claude Code、Codex CLI 與 Gemini CLI 提供統一介面。支援 note mentions、shell execution 與 action approval。 

  19. Obsidian iOS Changelog。2026年初的更新包含 Share Extension,可將其他 app 的內容直接儲存至 vault,以及 Daily Note 與 Bookmark widget 修正,並改善 View Note widget 重新整理。 

  20. MarkusPfundstein/mcp-obsidian。持續維護中——commit 延續至 2026年5月15日,近期工作新增 search_by_tagget_frontmatter 等工具,並擴充測試覆蓋率(已依 repository 的 commit history 與 tools.py 驗證)。目前仍未提供 tagged releases,因此請從已釘選的 commit 安裝。基於 Local-REST-API;forum discussions(2026年4月)指出,社群在新建設定時正逐步轉向一級支援的 Obsidian CLI bridge(1.12.x),但 mcp-obsidian 對既有 REST-API deployments 而言仍是可用且持續更新的選項。 

  21. Smart Connections v4.5.0 Release。2026年5月5日。Footer connections 成為 Core 功能;近期 v4 版本亦包含 connection lists 的 graph views、可設定的 connection-panel 位置、改進的 block-embedding recovery、Substrate cross-plugin state、transformer fallback 修正,以及減少重複的 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 預設)、1.5.0(4月15日,Highlights viewer + Reader fade-in)、1.5.1(4月15日,webpack compilation 修正)、1.6.0(4月21日,Highlighter UX + Defuddle 0.18,包含 LinkedIn/Threads/Bluesky/Discourse/Medium extractors)、1.6.1(4月22日,Reader outline 修正 + highlights search)、1.6.2(4月23日,Safari embedded-mode clipboard 修正)。亦列於Mozilla Add-ons storeChrome Web Store。 

  23. sqlite-vec v0.1.8sqlite-vec v0.1.9sqlite-vec v0.1.10-alpha.3sqlite-vec v0.1.10-alpha.4。v0.1.8 修正 npm packaging;v0.1.9 修正 metadata text columns 長度超過 12 個字元時的 DELETE bug;v0.1.10-alpha.3 新增正確的 INSERT OR REPLACE INTO 支援;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日宣布;最終規格於 2026年7月28日發布。自推出以來最大規模的 MCP 修訂:stateless protocol core(移除 initialize handshake 與 Mcp-Session-Id header)、MCP Apps(在 sandboxed client iframes 中 server-rendered HTML)、Tasks 從 experimental core 升格為正式 extension(tasks/gettasks/updatetasks/cancel)、OAuth 2.0/OIDC authorization 強化,以及 12 個月的 feature-deprecation lifecycle policy。 

  25. Obsidian Desktop v1.13.0 Changelog。Early access,2026年5月28日。UX/security/developer-tooling 版本:重新設計的 Settings panel 會在獨立視窗中開啟,提供 search 與 keyboard navigation;Obsidian URIs 執行前會顯示 confirmation dialogs;新增供 plugin developers 使用的 Settings API;並修正 flatpak installs 的 CLI 問題。除了 1.12.x CLI surface 之外,未新增重大 AI/automation capabilities。 

  26. Obsidian Changelog。Obsidian 1.13.1 desktop 於 2026年6月9日以 Catalyst early-access release 形式推出——相較 1.13.0,主要為 settings-UX refinement 與 CodeMirror upgrade,未增加新的 AI/automation capability。1.13.1 changelog page 本身標示為「Early access」,官方 auto-update manifest(obsidianmd/obsidian-releases,desktop-releases.json)列出公開 latestVersion 1.12.7,beta channel 則為 1.13.2;已於 2026-07-21 驗證。於 2026-07-27 再次驗證:manifest 仍回報 latestVersion 1.12.7,而 beta.latestVersion 已為 1.13.4。obsidian.md/changelog.xml 的 Atom feed 將每個 1.13.x 項目——1.13.1 至 1.13.4——都標示為「(Early access)」;最新標題為「(Public)」的項目仍是 1.12.7,日期為 2026-03-23,與 obsidian-releases GitHub release list 相符。於 2026-08-07 再次驗證:manifest 現回報 latestVersion 1.13.4(於 2026年7月30日公開推送),beta.latestVersion 為 1.13.6——1.13 系列已正式普及,而上述歷史列在各自日期時,對 Catalyst-only 期間的描述均屬準確。於 2026-08-14 再次驗證:manifest 回報 latestVersion 1.13.7beta.latestVersion 亦為 1.13.7——stable 與 beta 已趨於一致。 

VAULT obsidian.md INDEXED