关于 qmd
qmd 是面向知识库工作流的语义搜索技能,指导 Agent 优先检索相关片段,再读取完整文件。它支持 MCP 和命令行界面,并通过命名索引隔离不同知识库的数据。
主要功能
- 01混合、关键词和语义搜索
- 02按路径或文档 ID 获取内容
- 03按 glob 批量获取文档
- 04命名索引隔离知识库
适用场景
- 01查找过去的决策或项目背景
- 02创建笔记前检查已有内容
- 03按模式批量加载复盘材料
MCP 相关
通过 qmd MCP 服务提供搜索、获取文档和状态查询;索引更新与嵌入管理仅支持命令行。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ breferrari/ obsidian-mind --skill qmd安装后在 Claude Code 中输入/qmd确认已加载。
详细介绍
QMD — 保险库语义搜索
直接读取保险库文件之前,请先使用 QMD 搜索。它会返回相关片段,避免因读取完整文件而消耗上下文。
工具接口 — 优先顺序
选择当前可用的最高优先级接口,然后停止。三种接口读取同一个 SQLite 存储(参见命名索引(此保险库)),因此返回的结果相同;选择哪种接口取决于使用体验和上下文开销。
- MCP 工具(已注册时优先) —
mcp__qmd__query、mcp__qmd__get、mcp__qmd__multi_get、mcp__qmd__status。如果它们出现在工具菜单中,说明 MCP 服务已启动,并且已预先限定到此保险库。直接调用即可——无需--index参数,无需使用 shell,参数也有类型定义。这是会话期间的推荐方式。 - CLI 备用方案 —
qmd --index <name> query|search|vsearch|get|multi-get。当 MCP 服务未注册时(旧版保险库克隆、Windows 安装不一致,或在.mcp.json中禁用),或者需要在会话之外临时使用 shell 检查时使用。务必传入--index <name>。 - Grep / Glob / Read — 最后的备用方案,仅在完全未安装 QMD 时使用。它们会因读取完整文件而消耗上下文,也不会按相关性排序。
没有理由时,不要切换到更低优先级的接口——如果 MCP 已注册,在 Bash 工具中调用 CLI 只会以更慢的方式获取相同结果。
命名索引(此保险库)
此保险库使用命名 QMD 索引,使查询、更新和上下文字符串始终限定在此保险库范围内,不会与共用此计算机的其他保险库混在一起。本文档中的每条 QMD 命令都会传入 --index <name>。
在三种接口(CLI、MCP、SessionStart hook)中,索引名称的解析方式相同,因此它们始终指向同一个 SQLite 存储:
- 如果
vault-manifest.json中设置了qmd_index,则使用该值——这是显式指定的名称。 - 否则使用保险库文件夹名称,并将其转换为 slug。模板中的
qmd_index为空,因此每次安装都会使用独立的存储,无需询问。
如果希望名称在保险库文件夹重命名后仍保持不变,或者希望继续使用已创建的存储,请固定此字段。
运行命令前,请读取解析后的名称,不要自行假设会采用其中任一分支:
INDEX=$(node -e '
const ok = (s) => typeof s === "string" && /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(s);
const m = JSON.parse(require("fs").readFileSync("vault-manifest.json", "utf8"));
if (m.qmd_index && !ok(m.qmd_index)) {
process.stderr.write("qmd_index is set to an invalid name: " + JSON.stringify(m.qmd_index) + "\n");
process.exit(1);
}
const slug = require("path").basename(process.cwd()).normalize("NFKD").toLowerCase()
.replace(/[^a-z0-9._-]+/g, "-").replace(/-{2,}/g, "-").replace(/^[^a-z0-9]+|[-._]+$/g, "");
const name = [m.qmd_index, slug, m.template].find(ok);
if (!name) { process.stderr.write("no usable qmd index name — set qmd_index in vault-manifest.json\n"); process.exit(1); }
process.stdout.write(name);
') || exit 1
qmd --index "$INDEX" query "..."
该值既用作 CLI 参数,也用作文件系统路径(~/.cache/qmd/<name>.sqlite),因此无效的固定值必须在此处报错,而不能继续传递——这就是显式检查而不使用 m.qmd_index || slug 的原因。
在会话中,请直接将解析后的值代入命令——除非文件夹重命名,否则该值在保险库的整个生命周期内保持不变。
命令
每项操作都先列出 MCP 调用,再列出对应的 CLI 命令。条件允许时,优先使用 MCP。
搜索(每次查询选择一种)
- 混合搜索(质量最佳) — 使用
mcp__qmd__query,设置searches=[{type:"lex", query:"..."}, {type:"vec", query:"..."}],并传入intent参数。CLI:qmd --index <name> query "..." --json -n 10。适用于复杂或概念性查询。 - 关键词搜索(快速 BM25) — 使用
mcp__qmd__query,设置searches=[{type:"lex", query:"..."}]。CLI:qmd --index <name> search "..." --json -n 10。适用于精确词语、名称、工单编号和日期。 - 纯语义搜索 — 使用
mcp__qmd__query,设置searches=[{type:"vec", query:"..."}]。CLI:qmd --index <name> vsearch "..." --json -n 5。适用于不知道确切用词的探索性查询。
获取内容
- 按路径获取 — 使用
mcp__qmd__get,传入path参数。CLI:qmd --index <name> get "path/to/file.md"。 - 按 docid 获取 — 使用
#abc123语法调用mcp__qmd__get。CLI:qmd --index <name> get "#docid"。 - 按 glob 批量获取 — 使用
mcp__qmd__multi_get,传入pattern参数。CLI:qmd --index <name> multi-get "org/people/*.md" --json -l 40。
索引管理(仅 CLI — MCP 仅提供读取接口)
qmd --index <name> update— 文件变更后重新建立索引(速度快,增量更新约需 1–2 秒)。SessionStart hook 和 PostToolUse 防抖刷新都会自动运行此命令;通常很少需要手动运行。qmd --index <name> embed— 重新生成向量嵌入(速度较慢,在批量变更后运行)。
初始化(全新克隆)
QMD SQLite 存储位于仓库外部(~/.cache/qmd/<index>.sqlite),因此全新克隆没有索引。运行一次初始化:
node --experimental-strip-types .scripts/qmd-bootstrap.ts
此命令会解析索引名称(优先使用固定的 qmd_index,否则使用 vault 文件夹的 slug),并从 vault-manifest.json 读取 qmd_context,注册集合,附加 vault 上下文,遍历 vault 并生成嵌入。此操作具有幂等性,可安全地重复运行。
何时搜索
每种情况都列出了首选的 MCP 调用;如果尚未注册 MCP,则使用对应的 CLI 命令。
- 用户提及过去的决策、事件、人物或项目 →
mcp__qmd__query(混合搜索)。 - 用户询问“我们对 X 做了什么决定” →
mcp__qmd__query(混合搜索,并通过intent描述决策背景)。 - 用户提及某人的姓名 → 使用
searches=[{type:"lex", query:"<name>"}]调用mcp__qmd__query。 - 创建新笔记前 → 使用
searches=[{type:"vec", query:"<topic>"}]调用mcp__qmd__query,检查是否已有相关内容。 - 创建笔记后 → 使用
searches=[{type:"vec", query:"<note title>"}]调用mcp__qmd__query,查找应链接到该笔记的笔记。 - 为评审准备加载上下文 → 使用
pattern="perf/evidence/*.md"调用mcp__qmd__multi_get。 - 加载 1 对 1 会谈上下文 → 使用
searches=[{type:"lex", query:"<person name> 1-1"}]调用mcp__qmd__query。
批量更改后
在 shell 中运行 qmd --index <name> update && qmd --index <name> embed。SessionStart hook 和 PostToolUse 防抖刷新会自动运行 update,但对于创建了大量笔记的会话,应显式运行 embed。