Obsidian MCP+混合檢索:2026參考指南
# 透過MCP將Obsidian串接至Claude與其他代理:伺服器設定、BM25+向量混合檢索,以及為含有16,894個檔案的知識庫建立索引,並提供可用設定。
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。grep、ripgrep、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帶來的三項能力:
-
雙向連結。Obsidian會自動追蹤backlink。當您從筆記A連結至筆記B時,筆記B會顯示筆記A曾參照它。圖譜面板可視覺化連結群集。這種雙向感知屬於原始檔案系統無法提供的中繼資料。
-
具備外掛渲染的即時預覽。Dataview查詢、Mermaid圖表與callout區塊都能即時渲染。在儲存格式仍為純文字的前提下,寫作體驗比文字編輯器更加豐富。您可在豐富的環境中撰寫與組織內容;擷取系統則索引原始markdown。
-
社群基礎設施。包括外掛探索、主題市集、同步服務(選用)、發佈服務(選用)及文件生態系。您可以用獨立工具重現任何單一功能,但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_tag與get_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_tag/get_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_KEY/OBSIDIAN_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_search/search |
找出符合查詢的筆記,並回傳附有檔案路徑與來源歸屬的排序摘錄 |
| 讀取完整筆記 | obsidian_read_note/read_note |
當搜尋摘錄不足時,擷取完整筆記內容 |
| 列出與瀏覽 | obsidian_list_notes/list_notes |
在沒有特定查詢時,依資料夾、標籤或日期範圍探索筆記 |
| 取得格式化脈絡 | obsidian_get_context |
回傳符合主題的脈絡區塊,大小符合token預算,可直接注入對話 |
實務上,Claude可根據您的筆記回答問題並標示來源、將過往決策與參考資料帶入程式設計工作階段,也能在不將整個檔案載入脈絡的情況下探索vault結構。部分社群伺服器還提供寫入操作(建立、附加、標籤與frontmatter管理);本指南稍後建置的自訂伺服器刻意維持唯讀,改由hooks處理筆記建立。
深入說明:MCP Server Architecture介紹工具與權限設計,Claude Code Integration介紹hooks與橋接模式,Codex CLI Integration及Cursor 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 list與obsidian template create可從Templater或核心範本產生筆記,讓AI agent無須直接寫入markdown檔案,也能建立結構化vault項目。 - 屬性管理。
obsidian property set與obsidian 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.md、AGENTS.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 可以在結果中包含來源 URLstatus— 可將封存或草稿筆記排除於 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。透過具備動態欄位的範本建立筆記。使用預先填入 created、type 和 domain 欄位的範本,確保每則新筆記一開始就具備正確的 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 編輯,並為欄位值提供自動完成。可減少 type、domain 和 tags 欄位中的錯字。一致的 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_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 會失效:
- 查詢:「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 Search
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分數時(少見,但若它們在某一個清單中排名相同,且未出現在另一個清單中,就可能發生),請依序用以下規則打破平手:
- 優先選擇同時出現在兩個清單中的chunk,而非只出現在單一清單中的chunk
- 在同時出現在兩個清單中的chunk之間,優先選擇合併排名較低者
- 在只出現在單一清單中的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 會:
- 掃描 vault 中允許資料夾內的所有
.md檔案 - 從檔案系統讀取每個檔案的
mtime_ns - 與資料庫中儲存的
mtime_ns比較 - 識別 3 種類別:
- 新檔案:路徑存在於檔案系統,但不存在於資料庫
- 已變更檔案:路徑同時存在於兩者,但
mtime_ns不同 - 已刪除檔案:路徑存在於資料庫,但不存在於檔案系統
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 執行時:
- Model hash 檢查。將已儲存的 model hash 與目前模型比較。若不同,會自動切換為完整重新索引模式,並警告使用者。
- 檔案掃描。走訪允許的資料夾,收集檔案路徑與 mtimes。
- 變更偵測。與已儲存資料比較。
- 批次處理。以每批 64 個檔案重新 chunk 並重新 embed 變更檔案。
- 進度回報。列印已處理檔案數與經過時間。
- 優雅關閉。處理 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
關鍵設計選擇:
-
先過濾再 embedding。清理後的文字才會被 embed。vector representation 永遠不會編碼 credential patterns。查詢「API key」會傳回討論 API key 管理的筆記,而不是含有實際 keys 的筆記。
-
替換,而非移除。
[REDACTED:pattern-name]token 會保留周邊文字的語意脈絡。embedding 會捕捉「這裡曾有類似 credential 的內容」,但不會編碼 credential 本身。 -
記錄 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-knownURL探索機制、可宣告工具為唯讀或會變更資料的結構化工具註解,以及SDK分層標準化系統。79下一次修訂現已具體成形:2026-07-28規格於2026年5月21日進入Release Candidate,是MCP自推出以來規模最大的修訂。其主要變更包括無狀態協定核心(移除initialize交握與Mcp-Session-Id標頭,因此伺服器不再追蹤每條連線的工作階段狀態)、MCP Apps(伺服器可回傳在沙箱化用戶端iframe中顯示、由伺服器渲染的HTML)、Tasks從實驗性核心升格為正式擴充功能(供長時間執行作業使用的tasks/get、tasks/update、tasks/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伺服器應強制執行嚴格邊界:
-
唯讀。伺服器會讀取vault與索引資料庫,不會建立、修改或刪除筆記。寫入作業(擷取新筆記)由獨立的hooks或skills處理,而非由MCP伺服器處理。
-
限定vault範圍。伺服器只會讀取已設定vault路徑內的檔案。必須拒絕路徑穿越嘗試(
../../etc/passwd)。 -
憑證過濾輸出。即使資料庫包含已預先過濾的內容,仍應在輸出時套用憑證過濾,作為縱深防禦措施。
-
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_search、obsidian_read_note等)。
Hook整合
Hook會在定義好的生命週期節點擴充Claude Code的行為。Obsidian整合會用到兩種hook:
Hook會在設定中註冊(於~/.claude/settings.json的hooks鍵下,指定事件名稱與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 | 核准政策untrusted/on-request/never×sandbox read-only/workspace-write/danger-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.yaml(mcpServers) |
| Zed | 完整(context servers) | STDIO | settings.json(context_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
},
}
快取失效
快取失效依據兩項訊號:
- TTL到期。每個內容區塊都有存活時間。TTL到期後,系統會重新查詢vault以重建區塊。
- 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本身的寫入不會再次觸發它,匯出的變數也不會延續到下一次呼叫。
壓縮啟發式規則
| 輸出類型 | 偵測方式 | 壓縮策略 |
|---|---|---|
| 測試結果 | PASSED/FAILED關鍵字 |
統計通過/失敗數量,只顯示失敗項目 |
| 檔案清單 | 指令中含有ls或find |
截斷至前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 圖譜會編碼筆記之間的關係。本節介紹連結語意、用於擴充脈絡的圖譜走訪方式,以及會降低圖譜品質的反模式。
Backlink 語意
每個 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 能從兩個方面改善檢索:
- 直接比對。搜尋「authentication overview」會比對到 MOC 本身,向代理提供精心整理的相關筆記清單。
- 脈絡擴充。找到特定筆記後,檢索器可檢查該筆記是否出現在任何 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
擷取到的心得會立即建立索引,日後可供擷取使用。幾個月下來,這些微型擷取會累積成一套與實作細節密切相關的知識語料庫。
專案啟動
開始新專案或新功能時:
- 搜尋知識庫:「我對 [technology/pattern] 知道什麼?」
- 檢視前 5 筆結果,找出過去的決策與注意事項
- 檢查該領域是否已有 MOC;若沒有,建立一個
- 搜尋失敗模式:「[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_BUSY 或 SQLITE_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 遷移
- 透過「Export All」選項(macOS)匯出 Apple Notes,或使用
apple-notes-liberator之類的遷移工具 - 使用
markdownify或pandoc將 HTML 匯出內容轉換為 markdown - 將轉換後的檔案移至知識庫的
00-inbox/資料夾 - 檢查並為每則筆記加入 frontmatter
- 將筆記移至適當的領域資料夾
從 Notion 遷移
- 從 Notion 匯出:Settings → Export → Markdown & CSV
- 將匯出檔解壓縮到知識庫的
00-inbox/資料夾 - 修正 Notion 特有的 markdown 產物:
- Notion 使用
- [ ]作為檢查清單——這是標準 markdown - Notion 會將 property tables 納入 HTML——請轉換為 YAML frontmatter
- Notion 會以相對路徑嵌入圖片——請將圖片複製到 attachments 資料夾
- 加入標準 frontmatter(
type、domain、tags) - 將 Notion 頁面連結替換為 Obsidian wiki-links
從 Google Docs 遷移
- 使用 Google Takeout 匯出所有文件
- 將
.docx檔案轉換為 markdown:pandoc -f docx -t markdown input.docx -o output.md - 批次轉換:
for f in *.docx; do pandoc -f docx -t markdown "$f" -o "${f%.docx}.md"; done - 移至知識庫、加入 frontmatter,並整理到資料夾中
從純 Markdown 遷移(未使用 Obsidian)
如果您已經有一個 markdown 檔案目錄:
- 將該目錄開啟為 Obsidian vault(Obsidian → Open Vault → Open folder)
- 若該目錄有版本控管,請將
.obsidian/加入.gitignore - 建立 frontmatter templates,並套用到既有檔案
- 閱讀與整理時,開始使用
[[wiki-links]]連結筆記 - 立即執行索引器——擷取系統從第 1 天起即可運作
從其他擷取系統遷移
如果您正從不同的 embedding/搜尋系統遷移:
- 不要嘗試遷移向量。不同模型會產生不相容的向量空間。請使用新模型執行完整重新索引。
- 遷移內容,而不是索引。知識庫檔案才是真實來源。索引是衍生產物。
- 遷移後進行驗證。執行 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.json 的 latestVersion 為 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 | 初次發布 |
參考資料
-
Internet Vin,「22 commands I use with Obsidian and Claude Code,」2026年3月,x.com/internetvin/status/2026461256677245131。 ↩
-
Nicopreme,「Visual Explainer」agent skill with slash commands,x.com/nicopreme/status/2023495040258261460。 ↩
-
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 作為免調參的排序清單整合方法。 ↩↩↩
-
OpenAI Embeddings Pricing。text-embedding-3-small:每百萬 tokens 為 $0.02。完整重新建立索引的預估 vault 成本:約 $0.30。 ↩
-
van Dongen, T. et al. Model2Vec: Turn any Sentence Transformer into a Small Fast Model。arXiv,2025年。說明從 sentence transformers 產生靜態 embeddings 的蒸餾方法。 ↩
-
potion-base-8M Model Card與Model2Vec 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%。 ↩
-
Model Context Protocol Specification。用於將 AI 工具連接至資料來源的 MCP 標準。 ↩
-
Model2Vec Potion Models、potion-base-32M與potion-retrieval-32M。目前 model cards 顯示 potion-base-32M 的 Avg(All)為 52.83,而 potion-retrieval-32M 在 retrieval 表格中的分數為 35.06。 ↩↩↩
-
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)。 ↩↩↩
-
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 權重處理修正。 ↩↩↩
-
Smart Connections for Obsidian。Smart Connections v4:local-first AI embeddings;完成初始索引後,semantic search 可離線運作。 ↩
-
potion-multilingual-128M。Minish Lab,2025年5月。支援 101 種語言的靜態 embedding 模型,為效能最佳的多語言靜態 embeddings。與其他 potion 模型同樣僅依賴 numpy。 ↩
-
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.5 與 0.11.4——兩者均早於 0.12.0,因此包括 0.12.1 在內的所有 0.12.x 版本均已修補。Advisory 範圍與 npm 時間戳記已於 2026-08-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 預告將於未來版本推出。 ↩↩↩
-
Introduction to Bases。Obsidian core plugin 於 v1.9.10 推出。使用 frontmatter properties 作為欄位,在 vault 檔案之上建立類似資料庫的 views(tables、galleries、calendars、kanban boards)。檔案以
.base格式儲存。 ↩ -
Obsidian Desktop v1.12.0 Changelog與Obsidian Desktop v1.12.7 Changelog。v1.12.0 推出用於以 terminal 為基礎進行 vault automation 的 CLI;v1.12.7 透過 standalone binary、TUI 與 socket-file 行為改善安裝/runtime packaging。另請參閱CLI 文件。 ↩↩
-
Claudian。將 Claude Code 嵌入 vault 作為 AI 協作者的 Obsidian plugin。提供 sidebar chat、context-aware prompts、vision support、slash commands 與 permission modes。 ↩
-
Agent Client。Obsidian plugin,透過 Agent Client Protocol(ACP)為 Claude Code、Codex CLI 與 Gemini CLI 提供統一介面。支援 note mentions、shell execution 與 action approval。 ↩
-
Obsidian iOS Changelog。2026年初的更新包含 Share Extension,可將其他 app 的內容直接儲存至 vault,以及 Daily Note 與 Bookmark widget 修正,並改善 View Note widget 重新整理。 ↩
-
MarkusPfundstein/mcp-obsidian。持續維護中——commit 延續至 2026年5月15日,近期工作新增
search_by_tag與get_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 而言仍是可用且持續更新的選項。 ↩↩ -
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。 ↩
-
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 store與Chrome Web Store。 ↩
-
sqlite-vec v0.1.8、sqlite-vec v0.1.9、sqlite-vec v0.1.10-alpha.3與sqlite-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 的vec0tables 在執行ALTER TABLE RENAME時失敗,以及 DiskANN 中 cached-statement cleanup bug 的問題。0.1.10 系列仍為 prerelease。 ↩↩↩↩↩ -
MCP 2026-07-28 Specification Release Candidate。於 2026年5月21日宣布;最終規格於 2026年7月28日發布。自推出以來最大規模的 MCP 修訂:stateless protocol core(移除
initializehandshake 與Mcp-Session-Idheader)、MCP Apps(在 sandboxed client iframes 中 server-rendered HTML)、Tasks 從 experimental core 升格為正式 extension(tasks/get、tasks/update、tasks/cancel)、OAuth 2.0/OIDC authorization 強化,以及 12 個月的 feature-deprecation lifecycle policy。 ↩↩↩↩↩ -
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。 ↩↩↩
-
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)列出公開
latestVersion1.12.7,beta channel 則為 1.13.2;已於 2026-07-21 驗證。於 2026-07-27 再次驗證:manifest 仍回報latestVersion1.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-releasesGitHub release list 相符。於 2026-08-07 再次驗證:manifest 現回報latestVersion1.13.4(於 2026年7月30日公開推送),beta.latestVersion為 1.13.6——1.13 系列已正式普及,而上述歷史列在各自日期時,對 Catalyst-only 期間的描述均屬準確。於 2026-08-14 再次驗證:manifest 回報latestVersion1.13.7,beta.latestVersion亦為 1.13.7——stable 與 beta 已趨於一致。 ↩↩↩↩↩↩↩↩↩