mcpField
Q
qmd

qmd

github.com/breferrari生产力5.5k82 次安装2 周前更新
代码仓库

关于 qmd

qmd 是面向知识库工作流的语义搜索技能,指导 Agent 优先检索相关片段,再读取完整文件。它支持 MCP 和命令行界面,并通过命名索引隔离不同知识库的数据。

主要功能

  1. 01混合、关键词和语义搜索
  2. 02按路径或文档 ID 获取内容
  3. 03按 glob 批量获取文档
  4. 04命名索引隔离知识库

适用场景

  1. 01查找过去的决策或项目背景
  2. 02创建笔记前检查已有内容
  3. 03按模式批量加载复盘材料

MCP 相关

通过 qmd MCP 服务提供搜索、获取文档和状态查询;索引更新与嵌入管理仅支持命令行。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/breferrari/obsidian-mind --skill qmd

安装后在 Claude Code 中输入/qmd确认已加载。

详细介绍

QMD — 保险库语义搜索

直接读取保险库文件之前,请先使用 QMD 搜索。它会返回相关片段,避免因读取完整文件而消耗上下文。

工具接口 — 优先顺序

选择当前可用的最高优先级接口,然后停止。三种接口读取同一个 SQLite 存储(参见命名索引(此保险库)),因此返回的结果相同;选择哪种接口取决于使用体验和上下文开销。

  1. MCP 工具(已注册时优先) — mcp__qmd__query、mcp__qmd__get、mcp__qmd__multi_get、mcp__qmd__status。如果它们出现在工具菜单中,说明 MCP 服务已启动,并且已预先限定到此保险库。直接调用即可——无需 --index 参数,无需使用 shell,参数也有类型定义。这是会话期间的推荐方式。
  2. CLI 备用方案 — qmd --index <name> query|search|vsearch|get|multi-get。当 MCP 服务未注册时(旧版保险库克隆、Windows 安装不一致,或在 .mcp.json 中禁用),或者需要在会话之外临时使用 shell 检查时使用。务必传入 --index <name>。
  3. Grep / Glob / Read — 最后的备用方案,仅在完全未安装 QMD 时使用。它们会因读取完整文件而消耗上下文,也不会按相关性排序。

没有理由时,不要切换到更低优先级的接口——如果 MCP 已注册,在 Bash 工具中调用 CLI 只会以更慢的方式获取相同结果。

命名索引(此保险库)

此保险库使用命名 QMD 索引,使查询、更新和上下文字符串始终限定在此保险库范围内,不会与共用此计算机的其他保险库混在一起。本文档中的每条 QMD 命令都会传入 --index <name>。

在三种接口(CLI、MCP、SessionStart hook)中,索引名称的解析方式相同,因此它们始终指向同一个 SQLite 存储:

  1. 如果 vault-manifest.json 中设置了 qmd_index,则使用该值——这是显式指定的名称。
  2. 否则使用保险库文件夹名称,并将其转换为 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。

评论

支持 Markdown