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知识库对AI的价值不在于笔记本身,而在于让笔记可被查询的检索层。没有检索能力的16,000个文件知识库,不过是一个只写不读的数据库。拥有hybrid搜索和MCP集成的200个文件知识库,才是AI知识库。检索基础设施才是产品,笔记则是原材料。
hybrid检索优于纯关键词或纯语义搜索。BM25擅长捕捉精确标识符和函数名称。向量搜索能够跨越不同术语捕捉同义词和概念匹配。Reciprocal Rank Fusion(RRF)无需进行分数校准即可合并两者。任何单一方法都无法同时覆盖这两类失效模式。关于MS MARCO段落排序的研究证实了这一规律:hybrid检索的表现始终优于单独使用任一方法。3《hybrid retriever深度解析》涵盖RRF数学原理、包含真实数值的示例、失效模式分析,以及交互式融合计算器。
MCP让AI工具直接访问知识库。Model Context Protocol(MCP)服务器将检索器作为工具公开,供Claude Code、Codex CLI、Cursor及其他AI工具直接调用。代理会查询知识库,获得带来源归属的排序结果,并在无需加载完整文件的情况下使用上下文。MCP服务器只是检索引擎的一层轻量封装。
本地优先意味着零API成本和完整隐私保护。整套技术栈在一台机器上运行:SQLite负责存储,Model2Vec负责embeddings,FTS5负责关键词搜索,sqlite-vec负责向量KNN。无需云服务、无需API调用,也不依赖网络。个人笔记永远不会离开本机。以OpenAI API价格计算,完整重新嵌入49,746个文本块的成本约为$0.30;但真正的成本在于延迟、隐私暴露,以及一个本应离线运行的系统对网络的依赖。4
增量索引让系统在10秒内保持最新。通过比较文件修改时间来检测变更。只有已修改的文件会被重新chunking和重新嵌入。在Apple M系列硬件上,完整重新索引约需4分钟。典型一天的编辑所触发的增量更新可在10秒内完成。系统无需人工干预即可保持最新状态。
该架构可从200条笔记扩展至20,000+条。相同的三层设计(采集、检索、集成)适用于任何规模的知识库。对于小型知识库,可从仅使用BM25搜索开始。当关键词冲突成为问题时,再添加向量搜索。当您同时需要精确匹配和语义匹配时,加入RRF融合。每一层都可独立发挥价值,也可独立移除。
如何使用本指南
本指南涵盖完整系统。您的起点取决于当前所处阶段:
| 您是…… | 从这里开始 | 然后探索 |
|---|---|---|
| 刚接触Obsidian+AI | 为何选择Obsidian作为AI基础设施、Obsidian MCP设置 | 知识库架构、MCP服务器架构 |
| 已有知识库,希望获得AI访问能力 | MCP服务器架构、Claude Code集成 | 嵌入模型、全文搜索 |
| 正在构建检索系统 | 完整检索管道、Reciprocal Rank Fusion | 性能调优、故障排除 |
| 团队或企业环境 | 决策框架、知识图谱模式 | 开发者工作流方案、迁移指南 |
标记为Contract的章节包含实现细节、配置块和失效模式。标记为Narrative的章节侧重概念、架构决策及其设计考量。标记为Recipe的章节提供分步工作流。
为何选择Obsidian作为AI基础设施
本指南的核心观点是:Obsidian知识库是个人AI知识库的最佳基础,因为它本地优先、采用纯文本、具备图谱结构,并且用户可控制技术栈的每一层。
Obsidian为AI提供了哪些替代方案所没有的能力
纯文本markdown文件。每条笔记都是文件系统中的.md文件。没有专有格式,无需导出数据库,也无需API即可读取内容。任何能够读取文件的工具都可以读取您的知识库。grep、ripgrep、Python的pathlib、SQLite FTS5——它们都能直接处理源文件。构建检索系统时,您索引的是文件,而不是API响应。由于源头就是文件系统,索引始终与源内容保持一致。
本地优先架构。知识库存放在您的机器上。没有服务器、没有云同步依赖、没有API速率限制,也没有约束您如何处理自有内容的服务条款。无需任何外部服务,即可对笔记进行嵌入、索引、chunking和搜索。对于AI基础设施而言,这一点很重要:检索管道的运行速度取决于磁盘速度,而非API端点的响应速度。隐私同样如此:包含凭据、健康数据、财务信息和私人感想的个人笔记永远不会离开您的机器。
通过wiki-links构建的图谱结构。Obsidian的[[wiki-link]]语法会在笔记之间创建有向图。一条关于OAuth实现的笔记,可以链接到令牌轮换、会话管理和API安全相关笔记。图谱结构编码了作者在思考主题时人工整理的概念关系。向量embeddings能够捕捉语义相似性,但wiki-links捕捉的是作者有意建立的连接。这种信号是embeddings无法复制的。
插件生态系统。Obsidian拥有2,500+个社区插件(截至2026年3月,数量已突破2,500个,高于2025年年中时的1,800+个)。Dataview可像查询数据库一样查询您的知识库。Templater可通过JavaScript逻辑根据模板生成笔记。Git集成可将知识库同步到代码仓库。Linter可强制保持格式一致。Bases核心插件(在v1.9.10中引入)使用frontmatter属性作为字段,在知识库文件之上提供类似数据库的视图——表格、画廊、日历和看板,并保存为.base文件。15这些插件在不改变底层纯文本格式的前提下,为知识库增添结构。检索系统索引的是这些插件的输出,而非插件本身。
500万+用户。Obsidian拥有庞大且活跃的社区,持续产出模板、工作流、插件和文档。当您遇到知识库组织或插件配置问题时,很可能已经有人记录了解决方案。社区还开发了Obsidian周边工具:MCP服务器、索引脚本、发布管道和API封装器。
仅有文件系统无法提供什么
markdown文件目录具有纯文本优势,但缺少Obsidian带来的三项能力:
-
双向链接。Obsidian会自动跟踪backlinks。当您从笔记A链接到笔记B时,笔记B会显示笔记A引用了它。图谱面板会将连接集群可视化。这种双向感知是原始文件系统无法提供的元数据。
-
带插件渲染的实时预览。Dataview查询、Mermaid图表和callout块会实时渲染。在存储格式仍为纯文本的同时,写作体验比文本编辑器更丰富。您在丰富的环境中撰写和组织内容;检索系统则索引原始markdown。
-
社区基础设施。包括插件发现、主题市场、同步服务(可选)、发布服务(可选)和文档生态系统。您可以使用独立工具复刻任何单项功能,但Obsidian将它们整合为连贯的工作流。
Obsidian不提供什么(以及您需要构建什么)
Obsidian不包含检索基础设施。它具备基础搜索能力(全文、文件名、标签),但没有嵌入管道、向量搜索、融合排序、MCP服务器、凭据过滤、chunking策略,也没有面向外部AI工具的集成钩子。本指南介绍如何在Obsidian之上构建这些基础设施。知识库是基础。检索管道、MCP服务器和集成钩子才是基础设施。
本文所述架构是markdown优先,而非Obsidian专属。如果您使用Logseq、Foam、Dendron,或一个普通的markdown文件目录,检索管道的工作方式完全相同。chunker读取.md文件。embedder处理文本字符串。indexer写入SQLite。这些组件均不依赖Obsidian特有功能。Obsidian的贡献在于提供写作和组织环境,产出供检索器索引的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 前缀的路径。其路径过滤器的受限目录拒绝列表曾披露 2 个中等严重性公告(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等工具——但未发布带标签的版本(请从固定的提交安装)。它仍基于 Local-REST-API;对于新设置,CLI 桥接通常更快、更稳定,因此应优先选择它或下文列出的较新社区替代方案。20 有关推荐设置,请参阅本指南后文的“面向 AI 工作流的 Obsidian CLI”章节。
| 服务器 | 作者 | 传输方式 | 需要插件 | 核心功能 |
|---|---|---|---|---|
obsidian-mcp(npm obsidian-mcp) |
StevenStavrakis | STDIO | 否 | 轻量级、基于文件 |
| mcp-obsidian | MarkusPfundstein | STDIO | Local REST API | 通过 REST 完整 CRUD vault,另提供 search_by_tag/get_frontmatter——仍在积极维护(提交截至 2026年5月);无带标签版本,请固定提交20 |
| 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 服务器架构了解工具与权限设计;Claude Code 集成了解 hooks 与桥接模式;Codex CLI 集成和 Cursor 及其他工具了解其他 agent。
您刚刚构建了什么
您通过标准协议将本地知识库连接到了 AI 工具。MCP 服务器读取 vault 文件,执行基础搜索并返回结果。这是最小可行版本。
此快速入门不提供以下能力: - Hybrid 检索(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 为此前必须通过 GUI 或插件APIs才能完成的 Obsidian 原生操作提供了编程访问能力。对于 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 即可更新元数据。 - 插件控制。
obsidian plugin enable/disable/list可通过编程方式管理插件,适合在批处理期间切换索引插件。 - 任务管理。
obsidian task list/add/complete提供结构化任务访问,适合由 AI agent 管理 vault 中的工作项。
面向 AI 访问的 CLI 与 MCP
CLI 和 MCP 服务器承担不同角色,彼此互补而非竞争:
| 方面 | Obsidian CLI | MCP Server |
|---|---|---|
| 调用方 | Shell 脚本、hook、cron 任务 | AI agent(Claude Code、Codex、Cursor) |
| 协议 | POSIX 进程(stdin/stdout/stderr) | MCP(通过 STDIO 或 HTTP 的 JSON-RPC) |
| 优势 | Obsidian 原生操作(模板、插件、属性) | 自定义检索(embeddings、BM25、RRF 融合) |
| 局限 | 不支持向量搜索和 embedding 流水线 | 无法访问 Obsidian 内部操作 |
| 最适合 | 自动化脚本、接入流水线、hook 操作 | 会话期间的实时 AI agent 查询 |
建议:使用 CLI 处理接入自动化(创建笔记、管理属性、运行 Obsidian 原生搜索),使用 MCP 进行检索(结合 embeddings 的 hybrid 搜索)。UserPromptSubmit hook 可以在更耗资源的 hybrid 检索运行前调用 obsidian search:context 进行快速预检(限定工具范围的 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 插件
日益壮大的 Obsidian 插件类别正在将 AI 编程 agent 直接嵌入 vault UI,为外部 MCP server 配置提供了替代方案。这些插件让 AI agent 在 Obsidian 的侧边栏中运行,而非从外部工具连接。
Claudian
Claudian 将 Claude Code 作为 AI 协作者嵌入 vault。vault 目录会成为 Claude 的工作目录,使其具备完整的 agent 能力:文件读写、搜索、bash 命令以及多步骤工作流。17
面向 AI 基础设施的主要功能:
- 上下文感知提示词。 自动附加当前聚焦的笔记,支持使用 @notename 提及文件、基于标签排除内容,并将编辑器选区作为上下文。
- 视觉支持。 通过拖放、粘贴或文件路径分析图像——适合处理 vault 中保存的截图和图表。
- 斜杠命令。 创建由 /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 插件,何时使用外部 MCP
| 场景 | Agent 插件 | 外部 MCP |
|---|---|---|
| 借助 AI 编写和编辑 vault 笔记 | 更好——agent 能感知编辑器上下文 | 可用,但不具备编辑器感知能力 |
| 跨多个 repo 进行代码开发 | 有限——仅限 vault 范围 | 更好——以项目为范围并可访问完整文件系统 |
| 从大型已索引语料库中检索 | 仅提供基础搜索 | 提供完整 hybrid 检索流水线 |
| 记笔记期间快速进行 vault 问答 | 理想——无需切换上下文 | 需要切换到终端 |
建议:将 agent 插件用于以 vault 为中心的工作流(编写、整理、总结笔记)。对于 AI agent 需要完整检索流水线且需要访问 vault 外代码库的开发工作流,请使用外部 MCP 服务器。两种方式可以并存——在 Obsidian 内运行 Claudian 处理笔记工作,同时在外部运行带有 MCP 的 Claude Code 进行开发。
决策框架: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 | 普通文件系统 | CLAUDE.md |
|---|---|---|---|---|---|
| Local-first | 是 | 否(云端) | 部分支持(iCloud) | 是 | 是 |
| 纯文本 | 是(markdown) | 否(blocks) | 否(专有格式) | 是 | 是 |
| 图结构 | 是(wiki-links) | 部分支持(mentions) | 否 | 否 | 否 |
| AI可索引 | 直接文件访问 | 需要API | 需要导出 | 直接文件访问 | 已在上下文中 |
| Plugin生态 | 2,500多个plugins | Integrations | 无 | N/A | N/A |
| 离线可用 | 完整支持 | 只读缓存 | 部分支持 | 完整支持 | 完整支持 |
| 可扩展到10K+笔记 | 是 | 是(借助API) | 性能下降 | 是 | 否(单个文件) |
| 成本 | 免费(核心功能) | $10/月起 | 免费 | 免费 | 免费 |
什么时候Obsidian显得过度
- 单项目上下文。 如果AI只需要当前代码库的上下文,请放入
CLAUDE.md、AGENTS.md或项目级文档。这些文件会随repo一起移动,并自动加载。 - 结构化数据。 如果内容是表格、记录或schemas,请使用数据库。Obsidian笔记以 prose 为主。Dataview可以查询frontmatter字段,但真正的数据库更适合处理结构化查询。
- 临时研究。 如果笔记会在项目结束后丢弃,使用包含markdown文件的草稿目录更简单。不要为短期内容构建检索基础设施。
什么时候Obsidian是正确选择
- 跨数月或数年积累知识。 随着语料库增长,价值会不断复利。一个每天查询、持续使用6个月的200条笔记vault,比只查询一次的5,000条笔记vault更有价值。
- 一个语料库覆盖多个领域。 包含编程、架构、安全、设计和个人项目笔记的vault,可以受益于跨领域检索,这是项目专属
CLAUDE.md无法提供的。 - 隐私敏感内容。 Local-first意味着检索流水线绝不会把内容发送到外部服务。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 │
└─────────────────────────────────────────────────────┘
摄取决定什么内容进入vault。如果没有筛选,vault会积累噪声:推文截图、没有注释的复制粘贴文章、缺少上下文的半成品想法。摄取层负责在入口处进行质量控制。它可以是评分流水线、标签约定或人工审核流程,也可以是任何确保vault包含值得检索内容的机制。
检索让vault可查询。这是系统的引擎:将笔记chunking(分块)成搜索单元,把chunks转换为embeddings(嵌入)并放入向量空间,为关键词和语义搜索建立索引,再用RRF融合结果。检索层把一个文件目录转化为可查询的知识库。没有这一层,vault只能通过手动浏览和基础搜索来导航,而无法被AI工具以编程方式访问。
集成将检索层连接到AI工具。MCP服务器将检索暴露为可调用工具。Hooks会自动注入上下文。Skills会把新知识捕获回vault。集成层是知识库与消费它的AI agents之间的接口。
这些层在设计上彼此解耦。摄取评分流水线不了解embeddings。检索器不了解信号路由规则。MCP服务器不了解笔记是如何创建的。这种解耦意味着您可以独立改进任何一层。替换embedding模型,而无需更改摄取流水线。新增MCP能力,而无需修改检索器。调整信号评分启发式规则,而无需触碰索引。
面向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正文的内容——项目、领域、资源、信号、每日笔记。
应当从索引中排除的文件夹:模板(其中包含占位变量,而非内容)、附件(二进制文件)、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/
索引器会在扫描前读取此文件,并完全跳过匹配的路径。被排除路径中的文件不会被chunking,不会生成embeddings,也不会出现在搜索结果中。
笔记Schema
每篇笔记都应包含YAML frontmatter。检索器会使用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”或“只显示信号”)tags——以0.3权重索引到FTS5标题上下文中,即使正文使用不同术语,也能提供关键词匹配
可选但很有价值的字段:
domain——支持按领域限定的查询(“只搜索安全笔记”)source——为捕获内容提供出处;检索器可以在结果中包含来源URLstatus——允许从活跃搜索中排除已归档或草稿笔记
Chunking约定
检索器会在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个可独立搜索的chunk。每个chunk都有足够上下文,便于embedding捕捉其含义。关于“过期token处理”的查询会精确匹配第三个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处理。
不应放入笔记的内容
会降低检索质量的内容:
- 未加注释地原样复制整篇文章。检索器会索引原文关键词,用并非您撰写的内容稀释vault。建议改为添加摘要、提取要点,或链接到来源URL。
- 没有文字说明的截图。检索器索引的是markdown文本。没有alt文本或周边说明的图片,对BM25和向量搜索都是不可见的。
- 凭据字符串。API密钥、token、密码、连接字符串。即使有凭据过滤,最安全的做法仍然是永远不要把密钥粘贴到笔记中。请改用名称引用(例如“
~/.env中的Cloudflare API token”)。 - 未经整理的自动生成内容。如果某个工具生成了一篇笔记(会议转录、Readwise高亮、RSS导入),请在其进入永久vault前进行审阅和批注。未经整理的自动导入只会增加体量,而不会增加可检索价值。
AI Workflows的插件生态
能够提升AI检索库质量的Obsidian插件可分为三类:结构类(强制一致性)、查询类(暴露元数据)和同步类(保持库内容最新)。
必备插件
Dataview。 使用frontmatter字段像查询数据库一样查询您的库。创建动态索引,例如:“过去30天内更新、标记为security的所有笔记”,或“状态为active的所有项目笔记”。Dataview不会直接帮助检索,但能帮助您发现库覆盖范围中的缺口,并找出需要更新的笔记。
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。 在整个库中强制执行格式规则。一致的标题层级(H1用于标题,H2用于章节,H3用于小节)可确保chunker生成可预测的结果。对检索重要的Linter规则包括:
- 标题递增:强制标题层级按顺序递增(不要从H1跳到H3)
- YAML标题:与文件名匹配
- 行尾空格:删除(避免FTS5分词伪影)
- 连续空行:限制为1行(生成更干净的chunks)
Git集成。 为您的库提供版本控制。跟踪随时间发生的变更,在多台机器之间同步,并从误删中恢复。Git还提供索引器用于增量变更检测的mtime数据。
有助于索引的插件
Smart Connections。 这是一个Obsidian插件,可在Obsidian内部提供AI驱动的语义搜索。Smart Connections v4默认创建本地embeddings(嵌入)——库完成索引后,语义连接和查找可完全离线运行,无需任何API调用。11 v4.5.0(2026年5月5日) 将页脚连接纳入Smart Connections Core,因此每次安装都可以在页脚显示相关笔记连接,而无需打开侧边面板。近期v4版本还为连接列表添加了图视图、可配置的停靠位置、索引运行中断后的块嵌入恢复改进,以及“Substrate”:一种跨插件环境,让Smart Connections、Smart Chat和Smart Composer共享状态。21 虽然本指南中的检索系统位于Obsidian外部(作为Python pipeline运行),但Smart Connections有助于在写作时探索语义关系。这两个系统索引相同内容,但服务于不同用例:Smart Connections用于编辑器内发现,外部retriever则通过MCP集成AI工具。
2026年4月发布的AI原生插件。 一批新的社区插件直接面向Claude Code / Codex / Gemini-CLI工作流:
| Plugin | 发布时间 | 功能 |
|---|---|---|
| Cortex | 4月4日 | 由Claude Code驱动的库代理——将库视为代理工作区,而不仅是笔记存储 |
| VaultSearch | 4月7日 | 本地优先的hybrid搜索:BM25 + 语义 + 模糊(与本指南的检索栈直接重叠) |
| LLM Wiki | 4月9日 | 将您的库转换为可私密查询的知识库 |
| Drift | 4月11日 | 面向AI驱动Obsidian编辑的VS Code风格diff查看器;定位于Claude Code工作流 |
| EngramQuest | 4月11日 | 从笔记生成记忆挑战;随附面向Claude Code / Gemini CLI / Cursor的“AI Skills” |
| Hybrid Search MCP | 3月(仍属新品) | MCP服务器 + CLI,支持BM25 + 语义搜索——专为AI助手构建 |
请将其视为正在涌现的功能版图——未来几个季度,其中若干插件很可能会整合,或被Smart Connections / Obsidian core吸收。如果今天要选择一个,VaultSearch和Hybrid Search MCP在理念上最接近本指南的外部retriever。
Dataview说明: Dataview(长期存在的Obsidian查询插件)最后一次发布是2025年4月的0.5.70,此后实际上已处于停滞状态。对于新工作,Obsidian内置的Bases功能(1.9+)是隐含的继任者,也是推荐路径。
Metadata Menu。 提供结构化frontmatter编辑,并为字段值提供自动补全。减少type、domain和tags字段中的拼写错误。一致的元数据可提升检索过滤准确性。
不利于索引的插件
Excalidraw。 将绘图作为嵌入在markdown文件中的JSON保存。该JSON在语法上是有效的markdown,但在chunking(分块)和嵌入后会产生无用内容。请通过.indexignore从索引中排除Excalidraw文件,或按文件扩展名过滤。
Kanban。 将看板状态存储为特殊格式的markdown。该格式面向Kanban渲染设计,而不是面向散文检索。chunker会生成卡片标题和元数据的碎片,这些内容不适合嵌入。请从索引中排除Kanban看板。
Calendar。 创建内容极少的每日笔记(通常只有日期标题)。空笔记或近乎空白的笔记会产生低质量chunks。如果使用每日笔记,请在其中写入实质性内容,或从索引中排除每日笔记文件夹。
关键插件配置
文件恢复 → 已启用。 防止意外删除笔记。它与检索没有直接关系,但对于您所依赖的知识库至关重要。
严格换行 → 已禁用。 相比Obsidian严格模式(单换行表示<br>),Markdown标准换行(双换行表示段落)会生成更干净的chunks。
默认新文件位置 → 指定文件夹。 将新文件路由到00-inbox/,避免未分类笔记污染领域文件夹。收件箱是暂存区;文件会在分拣后移动到领域文件夹。
Wiki-link格式 → 尽可能使用最短路径。 更短的链接目标更便于retriever在索引链接结构时解析。
Embedding Models:选择与配置
embedding模型会将文本chunk转换为用于语义搜索的数值向量。模型选择会决定检索质量、索引大小、embedding速度和运行时依赖。本节说明为什么默认选择Model2Vec的potion-base-8M,以及何时应选择其他方案。
为什么选择Model2Vec potion-base-8M
模型:minishlab/potion-base-8M
参数量:760万
维度:256
大小:约30 MB
依赖:model2vec(仅numpy,无需PyTorch)
推理:仅CPU,静态词embedding(无attention层)
Model2Vec会将sentence transformer的知识蒸馏到静态token embedding中。它不像BERT、MiniLM和其他transformer模型那样对输入运行attention层,而是通过对预先计算的token embedding进行加权平均来生成向量。5实际效果是:由于没有顺序计算,embedding速度比基于transformer的模型快50到500倍。
在当前Model2Vec结果页面上,potion-base-8M达到all-MiniLM-L6-v2全任务分数约92%的水平(51.32对55.80),同时速度快出数个数量级。6剩余的质量差距,是换取速度和简单性优势的取舍。对于较短的markdown chunk(典型知识库中平均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]
懒加载。模型在首次使用时加载,而不是在导入时加载。当retriever以仅BM25的回退模式运行时(例如embedding venv未安装),导入embedder模块不会产生额外成本。
隔离的虚拟环境。模型在专用venv中运行(例如~/.claude/venvs/memory/),以避免与工具链其他部分发生依赖冲突。_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(),而不是一次只为一个chunk生成embedding。
何时选择其他方案
| 模型 | 维度 | 大小 | 速度 | 质量(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(检索) | 面向检索优化的静态模型 |
| potion-multilingual-128M | 256 | 约500 MB | 300x | — | 多语言知识库(101种语言) |
| all-MiniLM-L6-v2 | 384 | 80 MB | 1x | 55.80 | 更高质量,仍可本地运行 |
| nomic-embed-text-v1.5 | 768 | 270 MB | 0.5x | 62.28 | 最佳本地质量 |
| text-embedding-3-small | 1536 | API | N/A | 62.30 | 基于API,质量最高 |
当您希望获得比potion-base-8M更好的质量,同时仍留在静态embedding系列中时,选择potion-base-32M。它使用从baai/bge-base-en-v1.5蒸馏而来的更大词汇表,达到52.83的全任务分数(比potion-base-8M高约3%),同时保持相同的256维输出和仅numpy依赖。8模型文件大4倍,会增加内存占用,但embedding速度仍比transformer模型快数个数量级。
当主要用例是检索时(知识库搜索正是如此),选择potion-retrieval-32M。这个变体专门针对检索任务从potion-base-32M微调而来,在Model2Vec检索基准表中得分为35.06,高于potion-base-32M的32.67。8取舍在于,它针对检索而非通用embedding质量进行优化。
当您的知识库包含多种语言的笔记时,选择potion-multilingual-128M。该模型于2025年5月发布,支持101种语言,是多语言任务中表现最好的静态embedding模型。它可以为任意语言的文本生成embedding,同时保持与其他potion模型相同的仅numpy依赖。12较大的模型文件(约500 MB)是获得跨语言能力的代价。如果您的笔记中既有英文内容,也有日语、中文、德语或其他非英文语言内容,请使用它。
当检索质量比速度更重要,并且已经安装PyTorch时,选择all-MiniLM-L6-v2。与256维向量相比,384维向量会让SQLite数据库大小增加约50%。在M系列硬件上,对15,000个文件进行完整重建索引时,embedding速度会从不到1分钟降至约10分钟。
当需要尽可能好的本地检索质量,并且可以接受较慢的索引速度时,选择nomic-embed-text-v1.5。768维向量会让数据库大小大约增加到3倍。它需要PyTorch以及现代CPU或GPU。
当网络延迟和隐私可以接受作为取舍时,选择text-embedding-3-small。API会生成最高质量的embedding,但也会引入云端依赖、按token计费的成本(每百万token 0.02美元),并将您的内容发送到OpenAI服务器。
其他所有情况下都继续使用potion-base-8M。速度优势对迭代式索引非常关键(开发期间反复重建索引),仅numpy依赖避免了PyTorch安装复杂度,256维向量也能让数据库保持紧凑。
量化与降维
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)
量化模型能以更小的内存占用保留几乎相同的检索质量。降维遵循Matryoshka式截断,即前N个维度承载最多信息。对于短文本检索,将维度从256降到128,可以让向量存储减半,同时质量损失很小。
Model2Vec v0.8.x更新了tokenizer和持久化内部机制,弃用Python 3.9支持,并将已发布结果刷新到较新的MTEB表。升级生产indexer前,请固定或测试model2vec版本,因为即使embedding模型名称保持不变,库升级也可能改变模型加载路径。10
针对知识库特定embedding进行微调
Model2Vec v0.4.0+支持在静态embedding之上训练自定义分类模型,v0.7.0加入了词汇表量化和用于蒸馏的可配置pooling,v0.8.x则重构了tokenizer和持久化行为。10这对包含专业词汇的知识库很有意义,例如医学笔记、法律参考、领域专用术语。在这些场景中,默认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")
对于大多数知识库,默认potion-base-8M已经能提供足够的检索质量。只有当检索持续漏掉通用模型无法捕捉的领域特定关联时,微调才值得投入。
模型哈希跟踪
indexer会存储一个由模型名称和词汇表大小派生出的哈希。如果更换embedding模型,indexer会在下一次增量运行时检测到不匹配,并自动触发完整重建索引。
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会回退到仅BM25模式。首次下载后,模型会缓存在本地。
维度不匹配。如果在未清空数据库的情况下切换模型,已存储向量的维度会与新的embedding不同。indexer会通过模型哈希检测到这一点,并触发完整重建索引。如果哈希检查失败(自定义模型没有正确哈希),sqlite-vec会在维度不匹配的KNN查询上报错。
大型知识库的内存压力。在单个批次中为50,000多个chunk生成embedding可能消耗大量内存。indexer会以64条为一批处理,以限制峰值内存占用。如果内存仍然紧张,请减小批次大小。
使用FTS5进行全文搜索
SQLite的FTS5扩展提供带BM25排序的全文搜索。FTS5是hybrid检索流水线中的关键词搜索组件。本节介绍FTS5配置、BM25擅长的场景,以及它的具体失效模式。
FTS5虚拟表
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——笔记标题、标签和元数据(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”笔记与当前查询相关。
FTS5分词器
FTS5默认使用unicode61分词器,可处理ASCII和Unicode文本。对于包含大量CJK(中文、日文、韩文)内容的vault,可以考虑使用trigram分词器:
-- For CJK-heavy vaults
CREATE VIRTUAL TABLE chunks_fts USING fts5(
chunk_text, section, heading_context,
content=chunks, content_rowid=id,
tokenize='trigram'
);
默认的unicode61分词器按词边界切分,这对词与词之间没有空格的语言效果较差。trigram分词器每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 扩展将向量 KNN(K-Nearest Neighbors)搜索引入 SQLite。本节介绍 sqlite-vec 配置、从笔记到可搜索向量的 embedding 流水线,以及具体的查询模式。
sqlite-vec 虚拟表
CREATE VIRTUAL TABLE chunk_vecs USING vec0(
id INTEGER PRIMARY KEY,
embedding float[256]
);
vec0 模块将 256 维浮点向量存储为打包的二进制数据。id 列与 chunks 表建立 1:1 映射,从而支持在向量结果与 chunk 元数据之间进行 join。
Embedding 流水线
流水线从笔记流向可搜索向量:
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
向量序列化
Python 的 struct 模块会为 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 查询
向量搜索查询会先对输入查询生成 embedding,然后按 cosine distance 查找 K 个最近的 chunk:
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 运算符执行近似最近邻搜索。k 参数控制返回的结果数量。distance 列包含 cosine distance(0=相同,2=相反)。
带 Distance 约束的 KNN 分页
从 sqlite-vec v0.1.7 开始,KNN 查询支持 WHERE distance < ? 约束,可在大型结果集中进行基于游标的分页,而无需重新扫描前面的页面。14 后续的 v0.1.8 和 v0.1.9 稳定版本主要是打包和 DELETE bug 修复版本,并非新的查询模型版本,因此 v0.1.7 仍是此分页模式的功能边界。23
展望后续,v0.1.10-alpha 版本线(2026年3月31日至5月18日)首次让 sqlite-vec 超越暴力 KNN:它引入了近似最近邻索引类型,包括 rescore、实验性的 ivf(inverted-file)索引(默认未启用),以及面向向量规模过大、无法常驻内存的知识库的磁盘型 DiskANN 索引。23 这些功能会改变超大型知识库的扩展方式,但 0.1.10 版本线仍是预发布(alpha)状态。请将 ANN 索引视为实验性功能;在稳定的 0.1.10 发布之前,生产知识库仍应继续基于稳定的 v0.1.9 暴力 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 中切片的模式,可降低针对大型知识库进行探索性查询时的内存占用。
vec0 表中的 DELETE 支持
sqlite-vec v0.1.7 为 vec0 虚拟表添加了原生 DELETE 支持,v0.1.9 修复了涉及长度超过 12 个字符的元数据文本列的 DELETE 错误路径。1423 此前,移除向量需要删除并重建表。现在,索引器的文件移除路径可以直接删除向量:
# 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])
这简化了笔记被删除或移动时的增量重新索引。索引器不再需要维护影子“active IDs”表,也无需批量重建。
Vector Search 何时更有优势
当概念比具体措辞更重要时,Vector Search 表现出色:
- 查询:”how to handle authentication failures” → 找到关于“login error recovery”的笔记(处于相同语义空间,但关键词不同)
- 查询:”what patterns exist for caching” → 找到关于“memoization”、“Redis TTL strategies”和“HTTP cache headers”的笔记(概念相关,术语多样)
- 查询:”approaches to testing asynchronous code” → 找到关于“pytest-asyncio fixtures”、“mock event loops”和“async test patterns”的笔记(同一概念通过实现细节表达)
Vector Search 何时失效
Vector Search 不擅长处理精确标识符:
- 查询:
_rrf_fuse→ 返回关于“fusion algorithms”和“rank merging”的笔记,但实际函数定义的排序可能低于概念性讨论 - 查询:
PostToolUse→ 返回关于“tool lifecycle hooks”和“post-execution handlers”的笔记,而不是具体的 hook 名称
Vector Search 也不擅长处理结构化数据。JSON 配置文件、YAML 块和代码片段生成的 embedding 往往捕捉的是结构模式,而不是语义含义。包含 "review": true 的 JSON 文件,与关于代码审查的散文式讨论,会得到不同的 embedding。
优雅降级
如果 sqlite-vec 加载失败(缺少扩展、平台不兼容、库损坏),retriever 会回退到仅 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 会在尝试向量查询前检查 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投票方法(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之间,优先选择在该列表中排名更低的那个
完整检索流水线
本节追踪一次查询如何从输入到输出经过整条流水线:BM25搜索、向量搜索、RRF融合、token预算截断以及上下文组装。
端到端流程
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预算截断
max_tokens参数用于防止检索器返回超过AI工具可用范围的上下文。估算方式采用每个token约4个字符(对英文散文而言是合理近似)。结果会按贪心策略截断:依排名顺序加入结果,直到预算耗尽。
这是一种保守策略。更复杂的做法会考虑每条结果的质量分数,并优先选择更短、质量更高的结果,而不是更长、质量更低的结果。贪心方法更简单,实践中效果也很好,因为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
);
优雅降级路径
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
检索器会在初始化时检查能力,并调整查询策略。缺失某个组件会降低质量,但不会导致错误。唯一的硬性失败是数据库文件缺失。
生产环境统计
基于包含16,894个文件、49,746个chunk、83 MB SQLite数据库的vault测得,硬件为Apple M3 Pro:
| 指标 | 值 |
|---|---|
| 文件总数 | 16,894 |
| chunk总数 | 49,746 |
| 数据库大小 | 83 MB |
| BM25查询延迟(p50) | 12ms |
| 向量查询延迟(p50) | 8ms |
| RRF融合延迟 | 3ms |
| 端到端搜索延迟(p50) | 23ms |
| 完整重新索引时间 | 约4分钟 |
| 增量重新索引时间 | <10秒 |
| embedding模型 | potion-base-8M(256维) |
| BM25候选池 | 30 |
| 向量候选池 | 30 |
| 默认结果限制 | 10 |
| 默认token预算 | 4,000 tokens |
内容哈希与变更检测
索引器需要知道自上次索引运行以来哪些文件发生了变化。本节介绍变更检测机制和哈希策略。
文件修改时间比较
索引器会在chunks表中为每个chunk存储mtime_ns(以纳秒计的文件修改时间)。在增量运行时,索引器会:
- 扫描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,而不是内容哈希
内容哈希(文件内容的SHA-256)会比mtime比较更可靠,因为它能检测到文件被触碰但内容未变的情况(例如git checkout恢复了原始mtime)。不过,哈希要求在每次增量运行时读取每个文件。对于16,894个文件,读取文件内容需要2到3秒。从文件系统读取mtime则不到100ms。
取舍在于:mtime比较偶尔会对未变更文件触发不必要的重新索引(误报),但不会漏掉实际变更。误报的代价只是每次运行多几个embedding调用。速度差异(100ms对3秒)让mtime成为务实之选,尤其是该系统会在每次AI交互时运行。
处理删除
当文件从vault中删除时,索引器会从数据库中移除该文件的所有chunk:
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],
)
自sqlite-vec v0.1.7起,DELETE FROM chunk_vecs语句可原生工作;v0.1.9又修复了针对带有较长元数据文本列的vec0表执行DELETE操作的bug。1423更早版本需要变通方案(删除并重建虚拟表,或维护一个外部“active IDs”集合)。如果运行的是0.1.9之前的版本,请先升级,再依赖元数据较重schema中的直接删除。
FTS5内容同步表需要通过INSERT INTO chunks_fts(chunks_fts, rowid, ...) VALUES('delete', ?, ...)为每个被移除的行显式删除。索引器会将此作为文件移除流程的一部分处理。
增量重建索引与完整重建索引
索引器支持两种模式:增量模式(速度快,适合日常使用)和完整模式(速度慢,偶尔使用)。本节介绍各自的使用场景、幂等性保证以及损坏恢复。
增量重建索引
使用场景:编辑笔记后的日常索引。默认模式。
执行内容: 1. 扫描知识库中的文件变更(比较mtime) 2. 删除已删除文件对应的chunk 3. 对已变更文件重新chunking并重新生成embeddings 4. 为新文件插入新的chunk 5. 同步FTS5索引
典型耗时:对于包含16,000个文件的知识库,一天编辑量通常少于10秒。
python index_vault.py --incremental
完整重建索引
使用场景: - 更改embedding模型后(检测到模型哈希不匹配) - schema迁移后(新增列、变更索引) - 数据库损坏后(完整性检查失败) - 增量索引产生意外结果时
执行内容: 1. 删除所有现有数据(chunks、vectors、FTS5条目) 2. 扫描整个知识库 3. 对所有文件进行chunking 4. 为所有chunk生成embeddings 5. 从头构建FTS5索引
典型耗时:在Apple M3 Pro上处理16,894个文件约需4分钟。
python index_vault.py --full
幂等性
两种模式都是幂等的:同一命令运行两次会产生相同结果。索引器会先删除某个文件已有的chunk,再插入新的chunk。因此,对已经是最新状态的数据库重新运行增量索引会产生零变更。重新运行完整索引会生成完全相同的数据库。
损坏恢复
如果SQLite数据库损坏(写入期间断电、磁盘错误、事务中途进程被终止):
# Check integrity
sqlite3 vectors.db "PRAGMA integrity_check;"
# If corruption detected, full reindex rebuilds from source files
python index_vault.py --full
真实数据源始终是知识库文件,而不是数据库。数据库是派生产物,可以随时重建。这是一项关键设计属性:您永远不需要备份数据库。
--incremental标志
索引器使用--incremental运行时:
- 模型哈希检查。将存储的模型哈希与当前模型进行比较。如果不同,自动切换到完整重建索引模式,并向用户发出警告。
- 文件扫描。遍历允许的文件夹,收集文件路径和mtime。
- 变更检测。与已存储数据进行比较。
- 批量处理。以64个文件为一批,对已变更文件重新chunking并重新生成embeddings。
- 进度报告。打印已处理文件数量和耗时。
- 优雅关闭。处理SIGINT时,先完成当前文件再停止。
凭据过滤与数据边界
个人笔记中可能包含密钥:API密钥、bearer tokens、数据库连接字符串、调试期间粘贴的私钥。凭据过滤器会阻止这些内容进入检索索引。
问题
一篇关于调试OAuth集成的笔记可能包含:
The token was: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
I used this curl command:
curl -H "Authorization: Bearer sk-ant-api03-abc123..."
如果不进行过滤,JWT和API密钥都会被chunking、生成embeddings,并存入数据库。搜索“authentication”会返回包含真实密钥的chunk。更糟的是,如果检索器通过MCP将结果提供给AI工具,这些密钥会出现在AI的上下文窗口中,并可能进入工具日志。
基于模式的过滤
凭据过滤器会在每个chunk入库存储前运行,匹配25种供应商特定模式以及通用模式:
供应商特定模式:
| 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 | ... |
各类模式 |
通用模式:
| 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,且长度40+字符 |
| 密码赋值 | password\s*[:=]\s*["'][^"']+["'] |
过滤器实现
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。用于生成embedding的是清理后的文本。向量表示永远不会编码凭据模式。查询“API key”会返回讨论API密钥管理的笔记,而不是包含真实密钥的笔记。
-
替换,而不是删除。
[REDACTED:pattern-name]标记会保留周围文本的语义上下文。embedding会捕捉到“这里曾有类似凭据的内容”,但不会编码凭据本身。 -
记录模式,不记录值。过滤器会记录匹配到哪些模式(例如“Scrubbed 2 credential(s) from oauth-debug.md [jwt, bearer-token]”),但绝不会记录凭据值。
基于路径的排除
.indexignore文件提供按路径进行的粗粒度排除。凭据过滤器则在已索引文件内部提供细粒度清理。二者缺一不可:
.indexignore用于明确包含敏感内容的整个文件夹(健康笔记、财务记录、职业文档)- 凭据过滤器用于清理意外嵌入在原本可索引内容中的密钥
数据分类
对于包含多样内容的知识库,可以考虑按敏感度对笔记进行分类:
| Level | Examples | Index? | Filter? |
|---|---|---|---|
| Public | 博客草稿、技术笔记 | 是 | 是 |
| Internal | 项目计划、架构决策 | 是 | 是 |
| Sensitive | 薪资数据、健康记录 | 否(.indexignore) | N/A |
| Restricted | 凭据、私钥 | 否(.indexignore) | N/A |
MCP 服务器架构
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 路线图,了解可能影响传输方式选择的更新。
能力设计
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 在 settings 中注册(~/.claude/settings.json 中的 hooks 键下,包含事件名称和 matcher),并通过 stdin 接收 JSON 负载——不存在会被 Claude Code 自动发现的 hooks 目录,工具详情也绝不会通过 $1/$2 参数传入。
UserPromptSubmit hook——在您提交提示时查询知识库,并注入相关上下文(此事件的 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——将重要工具输出捕获回知识库,以便日后检索(通过 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 模式
桥接模块提供了一个可供 hooks 和 skills 调用的 Python API:
# obsidian_bridge.py
from retriever import HybridRetriever
_retriever = None
def get_retriever():
global _retriever
if _retriever is None:
_retriever = HybridRetriever(
db_path="/path/to/vectors.db",
vault_path="/path/to/vault",
)
return _retriever
def search_vault(query, limit=5, max_tokens=2000):
"""Search vault and return formatted context."""
retriever = get_retriever()
results = retriever.search(query, limit, max_tokens)
if not results:
return ""
lines = ["## Vault Context\n"]
for r in results:
lines.append(f"**{r['file_path']}** — {r['section']}")
lines.append(f"> {r['chunk_text'][:500]}")
lines.append("")
return "\n".join(lines)
/capture Skill
用于将洞见捕获回知识库的 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 可以将知识库操作封装为具名命令。实践者已构建 Obsidian 专用命令库,将知识库同时作为读取来源和写入目标。
信号扫描。/scan-intel 命令会查询外部来源,根据个人研究兴趣对发现进行评分,并将符合条件的信号以带有 frontmatter 的知识库笔记形式写入:
/scan-intel --topics "agent infrastructure, security" --lookback 7d
该命令从已配置的来源(arXiv、HN、RSS)获取内容,应用评分模型(相关性、可执行性、深度、权威性),并将通过筛选的信号写入特定主题的知识库文件夹。知识库由此成为自动化情报管道的下游使用者。
船长日志。/captains-log 命令会汇总所有仓库的每日 git 活动,将结构化日志条目写入知识库,并包含已做出的决策、领悟和待处理线索:
/captains-log
该命令从 GitHub 提取提交历史,按仓库分组,并格式化为叙事式日志条目。随着时间推移,这些每日日志会形成可检索的记录,说明发布了什么以及原因何在。
Obsidian 捕获。/obsidian-capture 命令会从当前 Claude Code 会话中提取一条洞见,并将其连同正确的元数据直接写入知识库:
/obsidian-capture "SAST gates in agent loops increase security degradation"
--folder AI-Tools --tags security,agents
这一模式可扩展到任何知识库操作:创建 MOC、更新项目状态笔记、关联相关信号,或根据累积的每日日志生成每周摘要。
社区示例。实践者正在发布各自的命令库。一位开发者分享了 22 个自定义的 Obsidian + Claude Code 命令,覆盖每日复盘、项目规划、研究捕获和内容工作流。1另一位开发者构建了一个“Visual Explainer” skill,可根据代码分析在知识库中生成图表笔记。2命令各有不同,但架构始终一致:Claude Code skills 作为接口,知识库笔记作为存储层,检索基础设施作为查询引擎。
上下文窗口管理
集成时应注意 Claude Code 的上下文窗口:
- 将每次查询注入的上下文限制在 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 中的项目级指令。请加入知识库搜索指南:
## 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 | 在 Settings 中注册,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 × 沙箱 read-only / workspace-write / danger-full-access(--full-auto 已在 v0.147.0 中移除) |
关键差异:两种工具现在都支持 hooks 和 skills;不同之处在于其形式。Codex 将审批策略与操作系统级沙箱模式配对使用,而不是采用 Claude Code 的权限模式;其 hook 事件也不同——应迁移模式(工作前查询知识库、工作后捕获),而不是配置。对于 Codex 中长期生效的“先搜索知识库”指令,AGENTS.md 仍是正确的位置。
Cursor 和其他工具
Cursor 及其他支持 MCP 的 AI 工具都可以连接到同一个 Obsidian MCP 服务器。本节介绍常用工具的配置方法。
Cursor
在项目根目录的 .cursor/mcp.json 中添加:
{
"mcpServers": {
"obsidian": {
"command": "python",
"args": ["/path/to/obsidian_mcp.py"],
"env": {
"VAULT_PATH": "/absolute/path/to/vault",
"DB_PATH": "/absolute/path/to/vectors.db"
}
}
}
}
Cursor 的 .cursorrules 文件可以包含使用 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 token 的上下文。在一次会话的 10 次查询中,agent 会消耗 15,000-20,000 token 的 vault 上下文。
使用缓存:3 个预构建上下文块总共占用 4,500 token。每个唯一查询的额外搜索会增加 1,500-2,000 token。在 10 次查询中,如果其中 6 次由缓存块覆盖,agent 消耗的 token 为 4,500 +(4 * 1,500)= 10,500,约为未缓存用量的一半。
捕获冗长输出的压缩摘要
工具输出可能十分冗长:堆栈跟踪、文件列表、测试结果。Hook 无法缩减模型实际看到的内容——到 PostToolUse 触发时,完整输出已经进入上下文窗口,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 token,但关键信息只有 2 行:200 个通过,1 个失败。
Hook 实现
通过带有 Bash matcher 的 PostToolUse 注册(在 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 调用都是一个全新的进程,因此无需递归保护——hook 自身的写入不会再次触发它,导出的变量也不会保留到下一次调用。
压缩启发式规则
| 输出类型 | 检测方式 | 压缩策略 |
|---|---|---|
| 测试结果 | PASSED / FAILED 关键词 |
统计通过/失败数量,仅显示失败项 |
| 文件列表 | 命令中包含 ls 或 find |
截断为前 20 个条目 + 总数 |
| 堆栈跟踪 | Traceback 关键词 |
保留首尾调用帧及错误消息 |
| Git 状态 | modified: / new file: |
按状态汇总数量 |
| 构建输出 | warning: / error: |
移除信息行,保留警告/错误 |
信号接入与分诊流水线
接入层决定哪些内容进入知识库。缺乏筛选时,知识库会不断积累噪声。本节介绍将信号路由到领域文件夹的评分流水线。
来源
信号来自多个渠道:
- RSS订阅源: 技术博客、安全公告、发布说明
- 通过 Web Clipper 添加的书签: 官方 Obsidian Web Clipper 扩展(Chrome、Firefox、Safari)是在浏览器端捕获内容时保真度最高的接入方式。2026年4月的发布周期使其在 AI 工作流中明显更实用:22
- 1.4.0(4月9日): 交互式 YouTube 字幕稿 UI——可固定视频、在字幕稿中拖动定位、自动滚动并高亮当前位置。此外,“在阅读器中打开”默认选项可一键将捕获内容直接发送至阅读器模式。
- 1.5.0–1.5.1(4月15日): 高亮查看器——可浏览和搜索整个知识库中已捕获的高亮内容。淡入过渡至阅读器模式。YouTube 播放/暂停更流畅。1.5.1 修复了 webpack 编译回归问题。
- 1.6.0–1.6.2(4月21日至23日): 重构了高亮标注 UX,并支持移动端。Defuddle 0.18 为 LinkedIn、Threads、Bluesky、Discourse 和 Medium 添加了特定来源的提取器。1.6.2 修复了 Safari 嵌入模式下的剪贴板回归问题。 请按来源域名配置模板,使 YouTube 字幕稿、GitHub README 以及长篇文章分别进入命名合理的笔记,并带有适用于下方评分流水线的正确 frontmatter。
- 新闻邮件: 从电子邮件新闻通讯中摘录的关键片段
- 手动捕获: 阅读、交流或研究过程中撰写的笔记
- 工具输出: 通过 hooks 捕获的重要 AI 工具输出
- iOS 分享扩展: Obsidian 的 iOS 应用(于2026年初更新)提供了分享扩展,可将 Safari、社交网络及其他应用中的内容直接保存到知识库,无需打开 Obsidian;1.13 系列新增了带模板变量的可配置分享表目标,其中包括
url,因此捕获页面会自动将其来源链接记录到 frontmatter 中。19 这提供了一条低摩擦的移动端接入路径——从 Safari 分享文章后,它会作为已准备好评分的知识库笔记到达。 - Obsidian CLI: Shell 脚本和 hooks 可通过
obsidian file create创建笔记,或通过obsidian file append向现有笔记追加内容,从而在桌面端实现自动化接入流水线。
评分维度
每条信号均按4个维度评分(每项为0.0至1.0):
| 维度 | 问题 | 低分(0.0-0.3) | 高分(0.7-1.0) |
|---|---|---|---|
| 相关性 | 它是否与我的活跃领域相关? | 关联较弱、超出范围 | 与当前工作直接相关 |
| 可操作性 | 我能使用这些信息吗? | 纯理论、无应用场景 | 可应用的具体技术或模式 |
| 深度 | 内容有多实质? | 标题、浅层摘要 | 包含示例的详细分析 |
| 权威性 | 来源的可信度如何? | 匿名博客、未经验证 | 一手来源、同行评审、知名专家 |
综合评分与路由
composite = (relevance * 0.35) + (actionability * 0.25) +
(depth * 0.25) + (authority * 0.15)
| 分数范围 | 操作 |
|---|---|
| 0.55+ | 自动路由到领域文件夹 |
| 0.40 - 0.55 | 加入人工审核队列 |
| < 0.40 | 丢弃(不存储) |
领域路由
得分高于0.55的信号会根据关键词匹配和主题分类,被路由到12个领域文件夹之一:
05-signals/
├── ai-tooling/ # Claude, LLMs, AI development tools
├── security/ # Vulnerabilities, auth, cryptography
├── systems/ # Architecture, distributed systems
├── programming/ # Languages, patterns, algorithms
├── web/ # Frontend, backends, APIs
├── data/ # Databases, data engineering
├── devops/ # CI/CD, containers, infrastructure
├── design/ # UI/UX, product design
├── mobile/ # iOS, Android, cross-platform
├── career/ # Industry trends, hiring, growth
├── research/ # Academic papers, whitepapers
└── other/ # Signals that don't fit a domain
生产统计
运行14个月后:
| 指标 | 数值 |
|---|---|
| 已处理信号总数 | 7,771 |
| 自动路由(>0.55) | 4,832(62%) |
| 等待审核(0.40-0.55) | 1,543(20%) |
| 已丢弃(<0.40) | 1,396(18%) |
| 活跃领域文件夹 | 12 |
| 日均信号数 | ~18 |
知识图谱模式
Obsidian 的 wiki-link 图谱编码了笔记之间的关系。本节介绍链接语义、用于上下文扩展的图遍历,以及会降低图谱质量的反模式。
Backlink 语义
每个 wiki-link 都会在图中创建一条有向边。Obsidian 会同时跟踪正向链接和 backlink:
- 正向链接: 笔记 A 包含
[[Note B]]→ A 链接至 B - Backlink: 笔记 B 显示笔记 A 引用了它
图谱会根据上下文编码不同类型的关系:
| 链接模式 | 语义 | 示例 |
|---|---|---|
| 内联链接 | “与……相关” | “详情请参阅 [[OAuth Token Rotation]]” |
| 标题链接 | “包含子主题” | “## Related\n- [[Token Rotation]]\n- [[Session Management]]” |
| 类标签链接 | “归类为” | ”[[type/reference]]” |
| MOC 链接 | “属于……的一部分” | 列出相关笔记的 Maps 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 可通过两种方式提升检索效果:
- 直接匹配。 搜索“身份验证概览”时会匹配 MOC 本身,为 agent 提供经整理的相关笔记列表。
- 上下文扩展。 找到特定笔记后,检索器可检查该笔记是否出现在任何 MOC 中,并将 MOC 的结构纳入结果,为 agent 提供更广泛主题的地图。
用于上下文扩展的图遍历
检索器的未来增强方向:找到排名靠前的结果后,沿链接扩展上下文:
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 没有可用于嵌入的文本。至少添加一段上下文,说明这些链接笔记为何相关。
为所有内容建立双向链接。 并非每次引用都需要 wiki-link。顺带提及“OAuth”并不需要 [[OAuth 2.0 Overview]]。应将 wiki-link 保留给有意建立、可供导航的关系:点击链接时应能提供有用的上下文。
开发者工作流配方
将知识库检索与日常开发任务结合起来的实用工作流。
早晨上下文加载
通过加载相关上下文开始一天的工作:
Search my vault for notes about [current project] updated in the last week
检索器会返回与当前项目相关的近期笔记,帮助您快速回顾上次进展。相比重新阅读昨天的提交消息,这种方式更高效。
编码过程中的研究捕获
实现功能时,无需离开编辑器即可捕获洞见:
/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]
以往的调试笔记往往包含根因和修复方法。对于跨项目反复出现的问题,这尤其有价值——知识库会记住您遗忘的内容。
代码审查准备
审查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条以上笔记时,可以考虑: - 将批大小从64增加到128,以加快embeddings生成 - 使用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
内存映射I/O。 mmap_size pragma会指示SQLite对数据库文件使用内存映射I/O。对于83 MB的数据库,将整个文件映射到内存中可以消除大部分磁盘读取。
FTS5优化。 完整重建索引后,运行:
INSERT INTO chunks_fts(chunks_fts) VALUES('optimize');
这会合并FTS5的内部b-tree段,降低后续搜索的查询延迟。
扩展性基准测试
在Apple M3 Pro、36 GB RAM、NVMe SSD上测得:
| 操作 | 500条笔记 | 5K条笔记 | 15K条笔记 | 50K条笔记 |
|---|---|---|---|---|
| BM25查询 | 2ms | 5ms | 12ms | 25ms |
| Vector查询 | 1ms | 3ms | 8ms | 20ms |
| RRF融合 | <1ms | <1ms | 3ms | 5ms |
| 完整搜索 | 3ms | 8ms | 23ms | 50ms |
所有基准测试均包括数据库访问、查询执行和结果格式化。MCP STDIO通信的网络延迟会额外增加1-2ms。
故障排查
索引漂移
症状: 搜索返回过期结果,或漏掉最近新增的笔记。
原因: 添加笔记后未运行增量索引器,或者文件的mtime未更新(例如,从另一台机器同步时保留了时间戳)。
修复: 运行完整重建索引:python index_vault.py --full
Embedding模型切换
症状: 更换embedding模型后,vector搜索返回毫无意义的结果。
原因: 旧向量(来自之前的模型)正在与新的查询向量比较。维度或向量空间语义不兼容。
修复: 索引器应检测模型哈希不匹配,并自动触发完整重建索引。如果没有触发,请手动清空数据库并重建索引:
rm vectors.db
python index_vault.py --full
FTS5维护
症状: 多次增量更新后,FTS5查询返回错误或不完整结果。
原因: 经过大量小规模更新后,FTS5内部段可能变得碎片化。
修复: 重建并优化:
INSERT INTO chunks_fts(chunks_fts) VALUES('rebuild');
INSERT INTO chunks_fts(chunks_fts) VALUES('optimize');
MCP超时
症状: AI工具报告MCP服务器超时。
原因: 第一次查询会触发模型加载(惰性初始化),耗时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无法加载
症状: Vector搜索被禁用;检索器以仅BM25模式运行。
原因: sqlite-vec扩展未安装、在库路径中找不到,或与SQLite版本不兼容。
修复:
# Install via pip
pip install sqlite-vec
# Or compile from source
git clone https://github.com/asg017/sqlite-vec
cd sqlite-vec && make
验证扩展是否加载:
import sqlite3
db = sqlite3.connect(":memory:")
db.enable_load_extension(True)
db.load_extension("vec0")
print("sqlite-vec loaded successfully")
大型知识库内存问题
症状: 对大型知识库(50,000条以上笔记)执行完整重建索引时出现内存不足错误。
原因: Embedding批大小过大,或所有文件内容被同时加载到内存中。
修复: 减小批大小,并以增量方式处理文件:
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将属性表作为HTML包含在内——转换为YAML frontmatter
- Notion将图片嵌入为相对路径——将图片复制到附件文件夹
- 添加标准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知识库打开(Obsidian → Open Vault → Open folder)
- 如果该目录受版本控制,请将
.obsidian/添加到.gitignore - 创建frontmatter模板并应用到现有文件
- 在阅读和整理时,开始使用
[[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插件和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从未提供过的接口——现已改写为通过设置注册的hook,使用jq从stdin读取JSON(上下文注入移至UserPromptSubmit,其stdout确实会加入上下文);而“PostToolUse上下文压缩”一节的前提(hook缩减模型所见内容)并不可能实现——已改为将压缩摘要捕获至vault,以便跨会话复用,并移除了不必要的递归保护(每次hook调用都是新进程)。MAJOR问题:1.13.4→1.13.7(已验证manifest,stable与beta版本已收敛);MCP在2026-07-28的规范说明仍写着“最终规范于7月28日发布”,而它在17天前已作为Current修订版发布(已改为过去时;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块仍调用名称冲突的二进制文件(现已在所有3个工具中统一使用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三元组——主题和代码片段必须更新),以及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服务器章节和[^24]现已涵盖这3项内容。修正: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.jsonmanifest仍显示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模型的Interpreter修复、原生Gemini API密钥、DeepSeek和Azure OpenAI处理;商店推送可能晚于GitHub日期。没有官方MCP服务器消息;无状态规范仍计划于7月28日发布。 |
26 |
| 2026-07-21 | 准确性修正:公开桌面渠道为1.12.7,而不是1.13.1。2026-06-10条目(及之后的正文引用)将1.13.1视为公开渠道版本;1.13.1更新日志页面标注为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的版本巡检未发现新版本:核心仍为1.13.2 Catalyst,Clipper为1.7.0,没有官方MCP服务器消息,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服务器或AI集成;MCP规范的无状态版本仍计划于7月28日发布。已根据obsidian.md/changelog、github.com/obsidianmd/obsidian-clipper releases和blog.modelcontextprotocol.io进行验证。 |
|
| 2026-07-07 | 准确性修正。MCPVault已明确为独立项目(npm @bitbonsai/mcpvault,仓库bitbonsai/mcpvault),现为v0.12.1,带有两项中等严重性路径过滤咨询(GHSA-9c83-rr99-vfwj、GHSA-j99q-93c9-h869)——此前[^24]链接指向了错误的仓库(MarkusPfundstein/mcp-obsidian)。已修正MarkusPfundstein/mcp-obsidian的状态:它处于积极维护状态(提交持续至2026年5月15日,新增search_by_tag/get_frontmatter),而非“自2025年6月起休眠”;它仍未发布带标签的版本。已根据GitHub提交历史、GitHub Security Advisories和npm进行验证。 |
|
| 2026-07-06 | 为提升可发现性进行编辑重构:将“Quick Start: First AI-Connected Vault”重命名为Obsidian MCP Setup(锚点#obsidian-mcp-setup),并新增“连接后Claude可以做什么”能力概览(搜索、读取、列出、格式化上下文;只读边界,写入由hook处理),内容从MCP Server Architecture章节整合而来。没有新增事实;内部链接已更新。 |
|
| 2026-06-10 | 版本时效性更新。Obsidian 1.13.1桌面端已进入公开渠道(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握手和Mcp-Session-Id)、MCP Apps(在沙盒iframe中渲染服务器端HTML)、Tasks从实验性核心升级为官方扩展、OAuth 2.0/OIDC强化,以及12个月弃用生命周期政策(最终规范于2026年7月28日发布);将MCP Spec Evolution说明中推测性的“暂定于2026年年中”路线图表述替换为明确的RC。sqlite-vec v0.1.10-alpha(2026年3月31日–5月18日)新增近似最近邻索引类型(rescore、实验性的ivf、基于磁盘的DiskANN),突破暴力KNN的限制——鉴于0.1.10系列仍为预发布版本,已标记为前瞻性/实验性功能。Obsidian 1.13.0桌面端(抢先体验,2026年5月28日)已作为当前版本更新至各处正文引用;这是一次UX/安全/开发工具版本,没有新增AI/自动化能力。 |
24 23 25 |
| 2026-06-08 | 维护检查。Model2Vec v0.8.2(2026年5月29日)发布:这是一个维护版本,为训练新增冻结权重选项,并修复多词token、训练重构和非量化权重处理问题;脚注已更新。没有其他内容比现有基线更新:Obsidian最新版本仍为1.13.0(5月28日,已在下文记录),sqlite-vec稳定版仍为v0.1.9(v0.1.10仍为alpha),MCP规范仍是2025-11-25修订版。除Model2Vec版本说明外,正文没有变更。 | 10 |
| 2026-05-28 | Obsidian 1.13.0桌面端+1.13.0移动端(Catalyst抢先体验)发布。桌面端:经过重新设计的Settings面板,可在独立窗口中打开,内置搜索和键盘导航;Obsidian URI现在会在执行操作前显示确认对话框;从网络驱动器加载HTML资源前新增警告;Search加入Bookmarks视图;增强编辑器图像处理;改进File Explorer / Properties / Sync;大量面向开发者的API和错误修复。移动端:新的iOS Share Sheet,支持配置目标位置;可从标签切换器重新排序标签;平板电脑上可通过长按手势调整分割视图和固定侧边栏大小;Bases在表格视图中新增调整列宽的菜单项;iOS和搜索错误修复。对AI工作流的影响:Obsidian URI上的确认对话框为URI驱动的MCP/agent集成增加了有意设置的门槛;Bases列宽调整菜单使Bases更适合作为agent查询的vault前端索引;iOS Share Sheet可配置目标位置,使iPhone采集路径(已记录为主要入口)能更快接入Claude/Codex流程。 | |
| 2026-05-06 | 更新并验证来源的时效性:Smart Connections v4.5.0将页脚连接移入Core;sqlite-vec v0.1.8/v0.1.9稳定版本更新了打包和DELETE行为;Model2Vec v0.8.x更新tokenizer/持久化内部实现及基准测试表;将Obsidian CLI时间线从“1.12.7引入CLI”修正为“1.12.0引入CLI,1.12.7改进安装/运行时打包”。 | |
| 2026-04-27 | Web Clipper 4月周期:1.4.0(交互式YouTube转录UI+默认Open in Reader)、1.5.0(Highlights查看器)、1.6.0(Highlighter UX全面升级+面向LinkedIn/Threads/Bluesky/Discourse/Medium的Defuddle 0.18源提取器)、1.6.1+1.6.2(Reader和Safari修复)。将Web Clipper重新定位为AI工作流主要的浏览器端采集路径,而非一笔带过的书签提及。该窗口期内没有Obsidian桌面端、Sync或Bases版本发布。 | |
| 2026-04-16 | Smart Connections v4.3.0(图谱视图、可配置停靠区、块embeddings恢复、Substrate跨插件环境)。记录2026年4月AI原生插件浪潮(Cortex、VaultSearch、LLM Wiki、Drift、EngramQuest、Hybrid Search MCP)。将MarkusPfundstein/mcp-obsidian标记为维护模式(最后一次提交于2025年6月)。Dataview处于休眠状态;Bases是新项目的继任者。Obsidian CLI 1.12.7仍是AI助手的首选桥接方案。 |
|
| 2026-04-01 | 新增Obsidian CLI章节(用于AI工作流的v1.12命令)。新增agent插件章节(Claudian、Agent Client)。记录用于vault组织的Bases核心插件。将插件数量更新至2,500+。新增iOS Share Extension作为采集来源。使用嵌入式agent插件更新兼容性矩阵。 | |
| 2026-03-30 | MCPVault v0.11.0:新增list_all_tags工具,支持.base/.canvas,重命名为@bitbonsai/mcpvault。Obsidian Desktop v1.12.7捆绑CLI二进制文件,以加快终端交互。 |
|
| 2026-03-23 | 记录sqlite-vec v0.1.7稳定版:支持vec0表的DELETE,支持用于分页的KNN距离约束。宣布将在即将发布的版本中提供DiskANN近似最近邻索引。 | |
| 2026-03-07 | 将potion-multilingual-128M(101种语言,2025年5月)加入embedding模型对比。sqlite-vec为v0.1.7-alpha.10(CI/CD修复,无功能变更)。确认MCP规范和检索技术仍为最新。 | |
| 2026-03-03 | 更新MCP规范演进(2025年11月已发布:Streamable HTTP、.well-known、工具注释)。新增Model2Vec微调和BPE/Unigram tokenizer支持。新增社区MCP服务器对比表。将Smart Connections更新至v4。 | |
| 2026-03-02 | 将potion-base-32M和potion-retrieval-32M加入模型对比。新增量化/降维章节。新增MCP规范演进说明。 | |
| 2026-03-01 | 初始发布 |
参考资料
-
Internet Vin,“我与 Obsidian 和 Claude Code 一起使用的 22 个命令”,2026年3月,x.com/internetvin/status/2026461256677245131。 ↩
-
Nicopreme,带有斜杠命令的“Visual Explainer”agent skill,x.com/nicopreme/status/2023495040258261460。 ↩
-
Cormack, G.V.、Clarke, C.L.A. 和 Buettcher, S. Reciprocal Rank Fusion 优于 Condorcet 和单个排序学习方法。SIGIR,2009。介绍了 RRF:使用 k=60 作为无需调参的参数,用于合并排序列表。 ↩↩↩
-
OpenAI Embeddings 定价。text-embedding-3-small:每百万 tokens 0.02 美元。完整重建索引的 vault 预估成本:约 0.30 美元。 ↩
-
van Dongen, T. 等。Model2Vec:将任意 Sentence Transformer 转换为小型快速模型。arXiv,2025。介绍了从句子转换器生成静态 embeddings 的蒸馏方法。 ↩
-
potion-base-8M 模型卡和Model2Vec 结果。当前发布的表格显示,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 规范。用于将 AI 工具连接到数据源的 MCP 标准。 ↩
-
Model2Vec Potion Models、potion-base-32M和potion-retrieval-32M。当前模型卡显示,potion-base-32M 的 Avg(All)为 52.83,potion-retrieval-32M 在检索表中的得分为 35.06。 ↩↩↩
-
关于下一次 MCP 协议发布的更新。历史记录:2025年11月发布的版本提供了 Streamable HTTP 传输、.well-known URL 发现、结构化工具注解和 SDK 层级标准化。该版本预告的发布周期以 2026年7月28日修订版告终——即现行规范(参见 24)。 ↩↩↩
-
Model2Vec Releases。v0.4.0(2025年2月):训练/微调支持。v0.5.0(2025年4月):后端重写、量化、降维。v0.7.0(2025年10月):词汇量化、BPE/Unigram tokenizer 支持。v0.8.0/v0.8.1(2026年3月):tokenizer 和持久化重构、Python 3.9 弃用、MTEB V2 结果更新,以及 Windows 路径兼容性。v0.8.2(2026年5月29日):维护版本,为训练添加了冻结权重选项,并修复多词 token、重构训练流程和修复非量化权重处理。 ↩↩↩
-
Smart Connections for Obsidian。Smart Connections v4:本地优先的 AI embeddings;初始索引完成后,语义搜索可离线使用。 ↩
-
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 虽出现在两者之间的仓库变更日志中,但从未发布到 npm);这是与MarkusPfundstein/mcp-obsidian不同的项目,并非其更名版本。v0.11.0(2026年3月)新增list_all_tags工具,用于扫描 frontmatter 和 hashtags 并统计数量;同时改进了点号文件夹处理,并支持.base/.canvas文件。0.12.2–0.12.4 的内容来自仓库的CHANGELOG.md,这是唯一的发布记录——该仓库的 GitHub releases endpoint 返回空列表,因此 npm 发布时间和变更日志是主要来源。0.12.2:patch_note会按字面插入newString,而非展开$'、$&、$`、$$(issue #149 / PR #153);以 vault 为前缀的绝对路径或~/风格路径会规范化为相对 vault 的路径(issue #122 / PR #151);仅通过更新 lockfile 即清除了 npm audit 的高严重性发现(PR #154)。0.12.3:新增wiki_link工具(PR #101),并通过默认路径过滤器从所有工具中排除.trash/。0.12.4:wiki_link会根据完整的相对 vault 路径而不是 basename 解析诸如[[folder/Note]]的带路径链接。两项中等严重性的 GitHub Security Advisories 会影响其路径过滤器:GHSA-9c83-rr99-vfwj(受限目录仅在 vault 根目录被拒绝,嵌套目录未受限)和GHSA-j99q-93c9-h869(可通过大小写以及末尾点号/空格等价性绕过拒绝列表)。根据 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 虚拟表提供 DELETE 支持,为分页提供 KNN 距离约束,并改进模糊测试。宣布将在未来版本中提供 DiskANN 近似最近邻索引。 ↩↩↩
-
Bases 简介。Obsidian 核心插件,于 v1.9.10 引入。使用 frontmatter 属性作为字段,在 vault 文件之上提供类似数据库的视图(表格、画廊、日历、看板)。文件以
.base格式保存。 ↩ -
Obsidian Desktop v1.12.0 更新日志和Obsidian Desktop v1.12.7 更新日志。v1.12.0 引入了用于基于终端的 vault 自动化的 CLI;v1.12.7 通过独立二进制文件、TUI 和 socket 文件行为改进了安装/运行时打包。另请参阅CLI 文档。 ↩↩
-
Claudian。将 Claude Code 作为 vault 中 AI 协作者嵌入的 Obsidian 插件。提供侧边栏聊天、上下文感知提示词、视觉支持、斜杠命令和权限模式。 ↩
-
Agent Client。通过 Agent Client Protocol(ACP)为 Claude Code、Codex CLI 和 Gemini CLI 提供统一界面的 Obsidian 插件。支持笔记提及、shell 执行和操作审批。 ↩
-
Obsidian iOS 更新日志。2026年初的更新包括 Share Extension,可将其他应用中的内容直接保存到 vault;还包括 Daily Note 和 Bookmark 小组件修复,以及 View Note 小组件刷新改进。 ↩
-
MarkusPfundstein/mcp-obsidian。仍在积极维护——提交记录延续至 2026年5月15日,近期工作增加了包括
search_by_tag和get_frontmatter在内的工具,并扩大了测试覆盖范围(已根据仓库提交历史和tools.py验证)。仍未提供标记发布版本,因此请从固定的 commit 安装。基于 Local-REST-API;论坛讨论(2026年4月)显示,社区在新配置中正逐步迁移到一流的 Obsidian CLI bridge(1.12.x),但 mcp-obsidian 对现有 REST-API 部署而言仍是可用且持续更新的选项。 ↩↩ -
Smart Connections v4.5.0 Release。2026年5月5日。页脚连接成为 Core 功能;近期 v4 版本还包括连接列表的图谱视图、可配置的连接面板位置、改进的区块 embedding 恢复、Substrate 跨插件状态、transformer 回退修复,以及减少重复的连接计算。 ↩
-
obsidianmd/obsidian-clipper releases——Web Clipper 版本与功能对应关系的主要来源。2026年4月周期:1.4.0(4月9日,YouTube transcript UI + 默认 Open in Reader)、1.5.0(4月15日,Highlights viewer + Reader 淡入)、1.5.1(4月15日,webpack 编译修复)、1.6.0(4月21日,Highlighter UX + Defuddle 0.18,支持 LinkedIn/Threads/Bluesky/Discourse/Medium 提取器)、1.6.1(4月22日,Reader outline 修复 + highlights 搜索)、1.6.2(4月23日,Safari embedded-mode clipboard 修复)。同时列于Mozilla Add-ons 商店和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 打包;v0.1.9 修复了元数据文本列超过 12 个字符时的 DELETE bug;v0.1.10-alpha.3 添加了对
INSERT OR REPLACE INTO的正确支持;v0.1.10-alpha.4(2026年5月18日)修复了使用新 ivf/diskann 功能的vec0表上ALTER TABLE RENAME失败的问题,以及 DiskANN 中缓存语句清理的 bug。0.1.10 系列仍为预发布版本。 ↩↩↩↩↩ -
MCP 2026-07-28 规范候选发布版。于 2026年5月21日宣布;最终规范于 2026年7月28日发布。这是 MCP 自推出以来规模最大的一次修订:无状态协议核心(移除
initialize握手和Mcp-Session-Idheader)、MCP Apps(在沙盒化客户端 iframe 中呈现的服务器渲染 HTML)、Tasks 从实验性核心升级为正式扩展(tasks/get、tasks/update、tasks/cancel)、OAuth 2.0 / OIDC 授权加固,以及 12 个月的功能弃用生命周期政策。 ↩↩↩↩↩ -
Obsidian Desktop v1.13.0 更新日志。抢先体验版,2026年5月28日。UX/安全性/开发者工具发布:改版后的 Settings 面板将在独立窗口中打开,并支持搜索和键盘导航;Obsidian URI 触发前提供确认对话框;为插件开发者提供新的 Settings API;并修复了 flatpak 安装的 CLI 问题。除 1.12.x 的 CLI 功能面外,没有重大的新增 AI/自动化能力。 ↩↩↩
-
Obsidian 更新日志。Obsidian 1.13.1 desktop 于 2026年6月9日作为 Catalyst 抢先体验版本发布——相较于 1.13.0,主要是 Settings UX 优化和 CodeMirror 升级,没有新增 AI/自动化能力。1.13.1 更新日志页面本身标有“Early access”,而官方自动更新 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-releasesGitHub release list 一致。于 2026-08-07 再次验证:manifest 现报告latestVersion为 1.13.4(于 2026年7月30日公开发布),beta.latestVersion为 1.13.6——1.13 系列已正式可用,上述历史行准确描述了其在相应日期的 Catalyst 专属时期。于 2026-08-14 再次验证:manifest 报告latestVersion为 1.13.7,beta.latestVersion也为 1.13.7——稳定版与 beta 版已趋于一致。 ↩↩↩↩↩↩↩↩↩