第三方工具集成的两条路:CLI 直调 vs MCP server
在 CLI Agent 里接入第三方工具的决策框架 —— 何时直接 Bash 调外部 CLI,何时走 MCP server,含主流工具速查表
Obsidian v1.12.4 起官方 CLI 全量上线,让 Agent 通过 Bash 直接调 obsidian 命令毫秒级读写 vault,附 Agent 提示词模板与对比 MCP 路径的取舍
内容摘要
2026 年 2 月 27 日,Obsidian 在 1.12.4 这个版本里把**官方命令行工具**正式塞进了主程序,对所有用户免费、不分 Catalyst License、不分平台。这个 CLI 不是社区那个老牌的 [Yakitrak/obsidian-cli](https://github.com/Yakitrak/notesmd-cli)(现在已经改名叫 NotesMD CLI 避免和官方撞名),而是一个**直接由 Obsidian 主进程托管**的二进制:你装好 Obsidian、勾上一个开关,`obsidian` 命令就出现在 PATH 里,背后是 Obsidian 自己的 metadata cache、graph index、plugin runtime。
2026 年 2 月 27 日,Obsidian 在 1.12.4 这个版本里把官方命令行工具正式塞进了主程序,对所有用户免费、不分 Catalyst License、不分平台。这个 CLI 不是社区那个老牌的 Yakitrak/obsidian-cli(现在已经改名叫 NotesMD CLI 避免和官方撞名),而是一个直接由 Obsidian 主进程托管的二进制:你装好 Obsidian、勾上一个开关,obsidian 命令就出现在 PATH 里,背后是 Obsidian 自己的 metadata cache、graph index、plugin runtime。
这件事对 CLI Agent 用户的意义被严重低估。在 Obsidian CLI 出现之前,AI 想动你的 vault 通常只有三条路:
Obsidian CLI 把这三条路一刀切掉。它的设计哲学是「远程遥控运行中的 Obsidian」——你执行 obsidian search query="kubernetes",并不是 CLI 自己去扫 markdown 文件,而是把指令通过 IPC 发给 Obsidian 主进程,让它用已经在内存里跑着的搜索引擎、metadata 缓存、插件 runtime 来完成,然后把结果序列化回标准输出。
为什么个人知识库特别适合直接调 CLI 而不是套 MCP?三句话:
什么时候应该回头去走 MCP?只有当你需要跨客户端复用(同一套能力既给 Claude Code 又给 Cursor 又给 Claude Desktop 用)、或者 Agent 跑在没有本地 Obsidian 的远端机器上时。这两类场景的取舍框架放在 /cli/cards/cli-vs-mcp-integration-paths 详谈。
| 要素 | 说明 |
|---|---|
| 官方出品 | Obsidian 1.12.4 起内置,由 Obsidian 团队维护,不是社区项目 |
| 远程遥控模型 | CLI 是 Obsidian 主进程的客户端,不是独立 headless 工具——Obsidian 必须在跑 |
| 完整应用上下文 | 自动用上插件、模板、graph、metadata cache,移动文件会自动更新 wikilinks |
| 多 vault 支持 | vault="MyVault" 参数切换,无需重启 |
| 多种输出格式 | format=json/csv/tsv/md/yaml/paths/text/tree,方便管道处理 |
| TUI 模式 | 不带参数直接 obsidian 进入文件浏览 TUI,按 / 过滤、回车打开 |
| 跨平台 | macOS/Linux 通过 symlink 注册,Windows 用 redirector,统一命令名 obsidian |
注意 Obsidian 主进程必须在跑——CLI 启动时如果检测不到主进程会直接报错退出,这一条是和 NotesMD CLI 最大的区别。
前置条件:Obsidian 1.12.4 及以上。打开 Obsidian → Settings → General → 滚到底部的 Command line interface → 点 Register CLI → 把开关打开。
/usr/local/bin(或你 PATH 里第一个可写目录)放一个 symlink 指向 Obsidian.app/Contents/MacOS/obsidian。obsidian.exe redirector 到 %LOCALAPPDATA%\Programs\obsidian-cli\ 并加进用户 PATH。注册完打开终端验证:
# 1. 确认二进制在 PATH 里
which obsidian
# /usr/local/bin/obsidian
# 2. 确认版本
obsidian version
# Obsidian 1.12.4
# 3. 列出当前注册的 vault
obsidian vaults
如果 which obsidian 提示找不到,或者出来的是 ~/go/bin/obsidian、~/.cargo/bin/obsidian 这种路径,几乎可以确定你装到的是社区 Yakitrak 版(已改名 NotesMD CLI),把它从 PATH 移走或重命名再重新 Register CLI。
下面这一组是日常和 AI Agent 配合时高频复用的:
# 1. 全文搜索(带上下文)
obsidian search:context query="kubernetes deployment" limit=5 vault="MainVault"
# 2. 读笔记内容
obsidian read file="项目/Agent Wiki/路线图.md"
# 3. 创建新笔记(可挂模板)
obsidian create name="meetings/2026-04-22-标准化会议" template="MeetingNote"
# 4. 追加内容到笔记末尾
obsidian append file="meetings/2026-04-22-标准化会议.md" content="\n## 行动项\n- [ ] 同步飞书"
# 5. 移动笔记(会自动改全 vault 的 wikilinks)
obsidian move file="inbox/random.md" to="permanent/想法/"
# 6. 反向链接 / 出链 / 孤儿
obsidian backlinks file="项目/Agent Wiki.md"
obsidian links file="项目/Agent Wiki.md"
obsidian orphans
# 7. 操作日记
obsidian daily # 打开/创建今天的日记
obsidian daily:append content="- 写完 Obsidian 卡"
obsidian daily:read
# 8. 高阶:在 Obsidian runtime 里跑一段 JS
obsidian eval code="app.vault.getMarkdownFiles().length"
参数风格统一是 key="value",不是常见的 --key value——这一点和绝大多数 Unix CLI 不一样,Agent 第一次写命令时容易踩。format=json 加上 | jq 是 Agent 的最爱:
obsidian search query="TODO" format=json | jq -r '.[].file' | head -20
把下面这段塞进项目根目录的 CLAUDE.md(或者 ~/.claude/CLAUDE.md),Claude Code 启动时会自动读到:
## Obsidian 知识库操作约定
我的 Obsidian vault 路径是 `~/Documents/MainVault`,对应 vault 名 `MainVault`。
涉及笔记的读写时,**优先调用 obsidian CLI**,不要直接用 grep/find/read:
- 搜索 → `obsidian search:context query="..." limit=10 vault="MainVault"`
- 读笔记 → `obsidian read file="..." vault="MainVault"`
- 新笔记 → `obsidian create name="..." template="..." vault="MainVault"`
- 追加 → `obsidian append file="..." content="..." vault="MainVault"`
- 移动/重命名 → `obsidian move file="..." to="..." vault="MainVault"`(会自动更新 wikilinks)
- 反向链接 → `obsidian backlinks file="..." vault="MainVault"`
只有在 obsidian CLI 明显跑不通(Obsidian 没开、vault 名错)时,才退回 grep/find。
所有命令都用 `format=json` 输出,方便我后续 jq 解析。
实际跑起来的样子:
你:把昨天日记里所有未完成的 TODO 收集成一篇周报草稿,放到 weekly/ 下。
Claude Code: [Bash] obsidian daily:read format=json | jq -r '.content' | grep -E '^- \[ \]'
Claude Code: [Bash] obsidian search:context query="TODO" limit=20 vault="MainVault" format=json
Claude Code: [Bash] obsidian create name="weekly/2026-W17-草稿.md" template="WeeklyTemplate" vault="MainVault"
Claude Code: [Bash] obsidian append file="weekly/2026-W17-草稿.md" content="$(cat <<'EOF'
## 本周未完成
- [ ] 写 Obsidian 集成卡(来自 2026-04-21 日记)
- [ ] 同步 cli-vs-mcp 决策卡(来自 2026-04-19 日记)
EOF
)" vault="MainVault"
已经把草稿放到 MainVault/weekly/2026-W17-草稿.md,包含 7 条未完成项。
整个过程没碰任何 MCP server,没启动 Local REST API,没装任何插件——这就是「官方 CLI + Bash 工具」的全部魔力。
如果你想让 Agent 帮你做一次性的 vault 大扫除,写成可复用脚本比让它一条条 Bash 更省 token:
#!/usr/bin/env bash
# tag-by-folder.sh - 给某个文件夹下所有笔记加上 #project/<name> tag
set -euo pipefail
VAULT="${1:?usage: $0 <vault> <folder> <tag>}"
FOLDER="$2"
TAG="$3"
obsidian search query="path:${FOLDER}" format=paths vault="$VAULT" | while read -r file; do
echo "Tagging: $file"
obsidian property:set file="$file" name="tags" value="$TAG" vault="$VAULT"
done
让 Agent 直接 bash tag-by-folder.sh MainVault "项目/Agent Wiki" "project/wiki",比让它生成几十条 obsidian 命令再逐条跑要快得多。
回答「我要从 CLI Agent 里碰 Obsidian vault,走哪条路」这个问题,2026 年的现实有四个候选方案:
| 维度 | 官方 CLI(推荐) | cyanheads/obsidian-mcp-server | NotesMD CLI(前 Yakitrak) | 直接 grep/cat vault 文件 |
|---|---|---|---|---|
| 是否官方 | ✅ Obsidian 团队 | ❌ 社区 | ❌ 社区 | — |
| 要不要插件 | 不要 | 必装 Local REST API 插件 + 配 API key | 不要 | 不要 |
| 要不要 Obsidian 在跑 | ✅ 必须 | ✅ 必须(要插件 listen) | ❌ 不需要,可裸跑 | ❌ |
| 能否拿到 graph/反链/插件结果 | ✅ 全部,走 Obsidian runtime | ✅ 大部分(受 REST API 暴露面限制) | ❌ 只能扫文件 | ❌ |
| 移动笔记是否自动更新 wikilinks | ✅ | ✅ | ❌(自己 sed 改) | ❌ |
| 跨客户端复用 | ❌ 只能被有 shell 的客户端调(Claude Code/Codex/Gemini CLI) | ✅ 任何 MCP host 都能用(Claude Desktop/Cursor 等) | ❌ 同左 | ❌ |
| 延迟 | 毫秒级(IPC) | 几十毫秒(HTTP loopback) | 毫秒级 | 毫秒级 |
| Token 开销 | 极低 | 中(每个工具的 schema 要进上下文) | 极低 | 取决于读了多少文件 |
| 典型场景 | 个人 Claude Code 用户、本地 Agent | 跨客户端 + Claude Desktop 用户 | 服务器/容器里写自动化脚本 | 一次性快查、CI 里没 GUI |
核心区别一句话:官方 CLI 是「最快、最原生、token 最便宜,但只在能开 shell 的本地 Agent 里能用」;MCP server 是「换来跨客户端能力的成本」;NotesMD CLI 是「没有 GUI 时的备胎」;裸文件操作是「应急路径,不要长期用」。
| 误区 | 准确理解 |
|---|---|
| 以为社区的 Yakitrak/obsidian-cli 就是官方 CLI | 完全不同的两个项目。社区版已改名为 NotesMD CLI,不依赖 Obsidian 在跑;官方 CLI 由 Obsidian 1.12.4 起官方维护,必须 Obsidian 在跑 |
| 以为 CLI 必须 Obsidian 在前台开着 | 只要 Obsidian 进程在跑就行,可以最小化、可以挂在 dock,但不能完全退出——这是和 NotesMD CLI 最大的设计差异 |
| 以为不能跨 vault 操作 | 用 vault="VaultName" 参数即可切换,CLI 会找你已注册过的所有 vault;多 vault 用户尤其推荐写到 CLAUDE.md 里说明默认 vault |
以为参数风格是 --query "xxx" | 官方 CLI 用 key="value" 风格,不是 GNU long-option 风格——Agent 第一次写命令时容易抄错;只有少数 flag(比如 --copy)用 -- 前缀 |
以为 obsidian eval 只是 dev 工具 | 这是整个 CLI 最强的逃生口:可以执行任意 Obsidian 内部 API(app.vault、app.metadataCache、app.workspace),AI Agent 可以借它干 CLI 没暴露的事 |
| 以为读笔记和读文件没区别,何必用 CLI | obsidian read 和 cat file.md 输出几乎一样,但 obsidian search / backlinks / orphans 全是 Obsidian 内存里的索引算出来的,不需要 AI 把全 vault 灌进上下文;这是个数量级的差距 |
| 以为 Claude Desktop 也能直接调 obsidian CLI | Claude Desktop 没有 Bash 工具,只能走 MCP;这种场景才该上 cyanheads/obsidian-mcp-server,不要硬掰官方 CLI |
| 优势 | 劣势 |
|---|---|
| 毫秒级响应:search 0.32s vs grep 1.95s,orphan 0.26s vs grep 15.6s(4663 篇 vault 实测) | 依赖本地 Obsidian 在跑:服务器、容器、远程开发机里没法用,要走 NotesMD 或 MCP |
| token 极省:全 vault 找孤儿从 ~7M token 降到 ~100 token(70000 倍),因为 AI 不需要读文件本身 | 跨设备同步麻烦:vault 是本地路径,开发机和笔记本上 vault 路径不一样,CLAUDE.md 里要写条件判断 |
| 零额外安装:Obsidian 本身就有,不像 MCP 路径要装 Local REST API 插件 + Node MCP server | 参数风格不 Unix:key="value" 而不是 --key value,Agent 容易写错;建议在 CLAUDE.md 里给一组速查 |
| 完整应用语义:移动文件自动改 wikilinks、改 frontmatter 立即进 metadata cache,不会破坏 graph | 必须 Obsidian 在前台进程:完全退出 Obsidian 后所有命令报错,CI/cron 场景需要先检查 |
obsidian eval 留逃生口:CLI 没暴露的能力可以直接调 Obsidian 内部 API,灵活性接近写插件 | 跨客户端能力为零:Claude Desktop、网页版、移动端都吃不到——团队要统一接入还是得 MCP |
| 官方维护:每次 Obsidian 升级 CLI 同步升级,不像社区项目可能跟不上 | Windows 上注册稍折腾:redirector 模式比 macOS/Linux 的 symlink 复杂一点,PATH 改完要重开终端 |
整体判断:个人 + 本地 Agent 场景,官方 CLI 是默认选择;只有当你跨客户端、或者跑在没有 Obsidian 的远端机器上,才往 MCP / NotesMD CLI 退。
参考答案:
obsidian search ... 只是一行字符串,几乎零开销。在 4663 篇 vault 上做一次 orphan 检测,CLI 路径只需要 ~100 token,全文件读取要 ~7M token。参考答案:
这种场景不能用官方 CLI——它依赖运行中的 Obsidian 主进程,远端无 GUI 服务器没法跑 Obsidian.app。可选方案有两条:
rg(ripgrep)+ sed 就够了。CLI Wiki 不收 ripgrep 的卡,因为它不算 AI Agent 范畴,但用在 Agent 工具链里完全没问题。如果真的需要反链、graph、插件这些 Obsidian runtime 的能力,又非要在远端用,那就只剩一条路:在远端起一个带 GUI 的 Obsidian(比如用 Xvfb 虚拟显示,或者跑在自己的 Mac/Windows 工作机上),让远端 Agent 通过 SSH 调本机 obsidian。这种方案运维成本高,多数情况下不值得,老老实实接受"远端用 NotesMD、本地用官方 CLI"的分工就好。
参考答案:
这是典型的「单一工具源 + 双客户端消费」场景,正确做法是两条路并行,不要二选一:
CLAUDE.md 里写明 obsidian 命令速查表(参考本文「Agent 提示词模板」一节),让 Code 用户直接 Bash 调,享受毫秒级响应和近零 token 成本。claude_desktop_config.json 模板里挂 cyanheads/obsidian-mcp-server,Desktop 没有 Bash 工具,只能通过 MCP 拿到工具调用能力。为什么不让所有人都走 MCP 来「统一」?因为这样会让 Code 用户白白付出 token 成本和延迟,而 MCP 暴露的能力又是官方 CLI 的子集(受限于 Local REST API 插件的接口面)。CLI Wiki 反复强调的核心立场就是这条:有官方 CLI 时,对能调 Bash 的客户端走 CLI 是最优解,对不能调 Bash 的客户端兜底走 MCP,不要为了一致性强行降级。
如果团队里要写「Obsidian 操作规范」文档,建议这样组织:
CLAUDE.md 给 Code 用户。claude_desktop_config.json 模板 + mcp_prompt.md 给 Desktop 用户。两边的"能用什么操作"保持一致,"用什么调用方式"按客户端分。元层面的决策框架可以参考 /cli/cards/cli-vs-mcp-integration-paths。
优先展示同分类且标签更接近的内容,方便继续串联学习。
在 CLI Agent 里接入第三方工具的决策框架 —— 何时直接 Bash 调外部 CLI,何时走 MCP server,含主流工具速查表
用 git worktree 跑多个并行 CLI Agent,避免分支切换打断上下文,含 worktree 管理、Agent 隔离与合并策略
飞书 2026-03 开源官方 lark-cli(200+ 命令、20+ AI Skills)让 Agent 操作消息/文档/多维表,对比官方 lark-openapi-mcp 的取舍