使用 qmd 搜索个人知识库、笔记、文档和会议记录
qmd 是一款本地、设备端的个人知识库搜索引擎。它索引 Markdown 笔记、会议记录、文档和任何文本文件,然后提供结合关键词匹配、语义理解和 LLM 驱动重排序的混合搜索——全部在本地运行,无需云端依赖。
由 Tobi Lütke 创建。MIT 许可证。
# 检查版本
node --version # 必须 >= 22
# macOS — 通过 Homebrew 安装或升级
brew install node@22
# Linux — 使用 NodeSource 或 nvm
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
# 或使用 nvm:
nvm install 22 && nvm use 22
macOS 系统自带的 SQLite 不支持扩展加载。通过 Homebrew 安装:
brew install sqlite
npm install -g @tobilu/qmd
# 或使用 Bun:
bun install -g @tobilu/qmd
首次运行会自动下载 3 个本地 GGUF 模型(约 2GB):
| 模型 | 用途 | 大小 |
|---|---|---|
| embeddinggemma-300M-Q8_0 | 向量嵌入 | ~300MB |
| qwen3-reranker-0.6b-q8_0 | 结果重排序 | ~640MB |
| qmd-query-expansion-1.7B | 查询扩展 | ~1.1GB |
qmd --version
qmd status
| 命令 | 功能 | 速度 |
|---|---|---|
qmd search "query" | BM25 关键词搜索(无需模型) | ~0.2s |
qmd vsearch "query" | 语义向量搜索(1个模型) | ~3s |
qmd query "query" | 混合搜索 + 重排序(全部3个模型) | ~2-3s 热启动, ~19s 冷启动 |
qmd get | 获取完整文档内容 | 即时 |
qmd multi-get "glob" | 批量获取多个文件 | 即时 |
qmd collection add --name | 添加目录为集合 | 即时 |
qmd context add "描述" | 添加上下文元数据以改善检索 | 即时 |
qmd embed | 生成/更新向量嵌入 | 不定 |
qmd status | 显示索引健康状态和集合信息 | 即时 |
qmd mcp | 启动 MCP 服务器(stdio) | 持久 |
qmd mcp --http --daemon | 启动 MCP 服务器(HTTP,模型常驻内存) | 持久 |
将 qmd 指向包含文档的目录:
# 添加笔记目录
qmd collection add ~/notes --name notes
# 添加项目文档
qmd collection add ~/projects/myproject/docs --name project-docs
# 添加会议记录
qmd collection add ~/meetings --name meetings
# 列出所有集合
qmd collection list
上下文元数据帮助搜索引擎理解每个集合包含什么内容。这能显著提升检索质量:
qmd context add qmd://notes "个人笔记、想法和日志"
qmd context add qmd://project-docs "主项目的技术文档"
qmd context add qmd://meetings "会议记录和行动项"
qmd embed
此命令处理所有集合中的文档并生成向量嵌入。添加新文档或集合后需要重新运行。
qmd status # 显示索引健康状态、集合统计、模型信息
适用于:精确术语、代码标识符、名称、已知短语。
无需加载模型——近乎即时的结果。
qmd search "authentication middleware"
qmd search "handleError async"
适用于:自然语言问题、概念性查询。
加载嵌入模型(首次查询约 3 秒)。
qmd vsearch "限流器如何处理突发流量"
qmd vsearch "改善引导流程的想法"
适用于:质量要求高的重要查询。
使用全部 3 个模型——查询扩展、并行 BM25+向量、重排序。
qmd query "关于数据库迁移做了什么决定"
在单个查询中组合不同的搜索类型以获得精确结果:
# BM25 精确术语 + 向量概念搜索
qmd query $'lex: rate limiternvec: 节流在高负载下如何工作'
# 带查询扩展
qmd query $'expand: database migration plannlex: "schema change"'
| 语法 | 效果 | 示例 |
|---|---|---|
term | 前缀匹配 | perf 匹配 "performance" |
"phrase" | 精确短语 | "rate limiter" |
-term | 排除术语 | performance -sports |
对于复杂主题,写出你期望答案的样子:
qmd query $'hyde: 迁移计划分为三个阶段。首先,添加新列而不删除旧列。然后回填数据。最后切换并删除遗留列。'
qmd search "query" --collection notes
qmd query "query" --collection project-docs
qmd search "query" --json # JSON 输出(最适合解析)
qmd search "query" --limit 5 # 限制结果数量
qmd get "#abc123" # 按文档 ID 获取
qmd get "path/to/file.md" # 按文件路径获取
qmd get "file.md:50" -l 100 # 获取指定行范围
qmd multi-get "journals/*.md" --json # 按 glob 批量获取
qmd 提供 MCP 服务器,通过原生 MCP 客户端直接向 Agent 提供搜索工具。这是首选的集成方式——配置后,Agent 自动获得 qmd 工具,无需每次加载此技能。
添加到 ~/.hermes/config.yaml:
mcp_servers:
qmd:
command: "qmd"
args: ["mcp"]
timeout: 30
connect_timeout: 45
这会注册工具:mcp_qmd_search、mcp_qmd_vsearch、mcp_qmd_deep_search、mcp_qmd_get、mcp_qmd_status。
权衡:模型在首次搜索调用时加载(约 19 秒冷启动),然后在此会话中保持热加载。偶尔使用可以接受。
单独启动 qmd 守护进程——它让模型常驻内存:
# 启动守护进程(跨 Agent 重启持久存在)
qmd mcp --http --daemon
# 默认运行在 http://localhost:8181
然后配置 Agent 通过 HTTP 连接:
mcp_servers:
qmd:
url: "http://localhost:8181/mcp"
timeout: 30
权衡:运行时占用约 2GB 内存,但每次查询都很快(约 2-3 秒)。最适合频繁搜索的用户。
cat > ~/Library/LaunchAgents/com.qmd.daemon.plist << 'EOF'
Label
com.qmd.daemon
ProgramArguments
qmd
mcp
--http
--daemon
RunAtLoad
KeepAlive
StandardOutPath
/tmp/qmd-daemon.log
StandardErrorPath
/tmp/qmd-daemon.log
EOF
launchctl load ~/Library/LaunchAgents/com.qmd.daemon.plist
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/qmd-daemon.service << 'EOF'
[Unit]
Description=QMD MCP Daemon
After=network.target
[Service]
ExecStart=qmd mcp --http --daemon
Restart=on-failure
RestartSec=10
Environment=PATH=/usr/local/bin:/usr/bin:/bin
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable --now qmd-daemon
systemctl --user status qmd-daemon
连接后,以下工具可用为 mcp_qmd_*:
| MCP 工具 | 对应命令 | 描述 |
|---|---|---|
mcp_qmd_search | qmd search | BM25 关键词搜索 |
mcp_qmd_vsearch | qmd vsearch | 语义向量搜索 |
mcp_qmd_deep_search | qmd query | 混合搜索 + 重排序 |
mcp_qmd_get | qmd get | 按 ID 或路径获取文档 |
mcp_qmd_status | qmd status | 索引健康状态和统计 |
MCP 工具接受结构化 JSON 查询进行多模式搜索:
{
"searches": [
{"type": "lex", "query": "authentication middleware"},
{"type": "vec", "query": "用户登录如何验证"}
],
"collections": ["project-docs"],
"limit": 10
}
当未配置 MCP 时,直接通过终端使用 qmd:
terminal(command="qmd query '关于 API 重新设计做了什么决定' --json", timeout=30)
对于安装和管理任务,始终使用终端:
terminal(command="qmd collection add ~/Documents/notes --name notes")
terminal(command="qmd context add qmd://notes '个人研究笔记和想法'")
terminal(command="qmd embed")
terminal(command="qmd status")
了解内部原理有助于选择正确的搜索模式:
智能分块(Smart Chunking):文档在自然断点(标题、代码块、空行)处分割,目标约 900 个 token,15% 重叠。代码块永远不会在中间被分割。
qmd context add 能显著提升检索准确性。描述每个集合包含什么。qmd embed。qmd search 求速度——需要快速关键词查找(代码标识符、精确名称)时,BM25 即时且无需模型。qmd query 求质量——问题具有概念性或用户需要最佳结果时,使用混合搜索。正常现象——qmd 首次使用时自动下载约 2GB 的 GGUF 模型。这是一次性操作。
这发生在模型未加载到内存时。解决方案:
qmd mcp --http --daemon)保持热加载qmd search(仅 BM25)安装 Homebrew SQLite:brew install sqlite
然后确保它在 PATH 中优先于系统 SQLite。
运行 qmd collection add --name 添加目录,然后运行 qmd embed 索引它们。
为非英文内容设置 QMD_EMBED_MODEL 环境变量:
export QMD_EMBED_MODEL="your-multilingual-model"
~/.cache/qmd/index.sqlite
评论区