← 博客Obsidian · MCP · Cloudflare
Obsidian 搬进了我的 AI 中枢:一个连接通往所有服务,还有智能体画的图
我的 Obsidian 仓库现在放在 Cloudflare 上,kosh 则是一个 MCP 连接,通往任务、笔记、Telegram、Go-Alpha、Instagram 和我的 Mac。智能体直接在仓库里画 Excalidraw 图。它是怎么搭起来的,边界又在哪里。
发布于 2026年10月31日7 分钟阅读
TL;DR
我的 Obsidian 仓库不再放在 Mac 上了。它现在在 Cloudflare 上,在 kosh-vault 里。Mac 和 iPhone 通过 Self-hosted LiveSync 插件与它同步。
kosh 是我的个人 AI 中枢。它是一个 MCP 连接,背后是我所有的服务:任务、笔记、Telegram、Go-Alpha、Instagram、Mac 上的看门狗,以及 Mac 上的 shell。
现在,智能体还会直接在仓库里画 Excalidraw 图。我打开 Obsidian,就能看到它的想法变成了一张图。我可以手动修改,智能体也能看到我的修改。
以前的痛点
问题有两个。每个下面都写着:以前怎样,现在怎样。
1. 每个服务都是一个单独的连接
以前 — 5 个连接:
Claude ──▶ 任务
Claude ──▶ Telegram
Claude ──▶ Go-Alpha
Claude ──▶ Instagram
Claude ──▶ 笔记(只能在 Mac 上)
现在 — 1 个连接:
Claude ──▶ kosh ──▶ 上面所有服务而且每个客户端都是这样:Claude Code、claude.ai、手机。每新增一个服务,都得在每个客户端里分别添加。笔记则只能在 Mac 上让 Claude 编辑。
2. 智能体的修改要绕一大圈才能到达笔记
以前:
智能体 ──▶ GitHub ──(最多 2 分钟)──▶ Mac ──(iCloud)──▶ iPhone
现在:
智能体 ──▶ kosh-vault ──(约 1 秒)──▶ Mac 和 iPhone以前,修改要靠 Obsidian Git 插件从 GitHub 拉取——最多两分钟,而且只有 Mac 上的 Obsidian 开着才行。要到 iPhone,还得再经过 iCloud。现在仓库在云端,Mac 可以睡眠。
仓库搬到了云端
我想要唯一的事实来源。一个不会跟着笔记本一起睡着的来源。
正好有现成的项目:livesync-workers,一个运行在 Cloudflare Workers 上的 Self-hosted LiveSync 插件后端。我 fork 了它,取名 kosh-vault。
现在,事实来源是 Durable Object 里的一个 SQLite 数据库。Mac 和 iPhone 上的 Obsidian 与它保持实时连接,每次改动大约一秒就能收到。说白了,就是跑在 WebSocket 上的 Obsidian。
Mac 可以睡眠——仓库对智能体依然可用。其他所有副本都只是跟随云端:每小时一次备份到 GitHub,以及 iCloud 里的一个只读镜像。
keepReplicationActiveInBackground: true。否则,Obsidian 窗口被其他窗口挡住时同步会暂停,智能体的修改要等我看过去时才会到。kosh:一扇门
kosh 是 Cloudflare 上的几个 Worker。名字来自哥萨克的 kosh,即扎波罗热营地(Sich)的指挥部。
在内部,每个服务仍是独立的。Telegram 和 Go-Alpha 运行在 Cloudflare Containers 里。Instagram 是普通的 Worker。笔记是 kosh-vault。但从外面看,入口只有一个:/mcp。
这在实际中意味着:
- 中枢把所有服务的工具汇总成一个列表,保留它们原来的名字。客户端看到的只是一个连接。
- 服务之间通过 Cloudflare 的 service bindings 通信,而不是通过带共享令牌的公开地址。
- 第三方服务的密钥,我都粘贴在同一个连接页面上。它们加密保存,任何地方都不会再把它们显示出来。
- 某个服务宕机时,它的工具仍留在列表里,调用会如实回答:“不可用”。
kosh 的意义就在于:我所有的服务都能通过它访问,而不用一个个单独连接。
任务就是 markdown
我唯一的任务系统,就是仓库里的笔记。一个区域,一个文件。优先级是那一行上的 Obsidian Tasks 表情符号。
智能体用 tasks_* 工具添加、移动和完成任务。每次写入都会核对内容哈希:如果文件在此期间被改过,操作就重新执行。每次修改还会作为一行记入日志。
任务看板由 kosh 自己绘制,放在一个 Excalidraw 文件里。我手动改了列表,一分钟内定时任务就会发现,并重绘看板。只有看板上的内容真正变了,它才会写入。
智能体会画图
这是最新的部分。四个工具:drawing_list、drawing_read、drawing_create、drawing_edit。
我说:“画一下这个流程是怎么运作的。”智能体就在仓库里创建一个 .excalidraw.md 文件。一秒后它就到了我的 Mac 上,Excalidraw 插件把它当作自己的文件打开。
智能体
│ 请求修改图(drawing_edit)
▼
kosh
│ 写入绘图文件
▼
kosh-vault(Cloudflare)
│ LiveSync 送达,约 1 秒
▼
Obsidian 里打开的图随之更新Excalidraw 插件有自己的 CLI,但它需要 Mac 上的 Obsidian 正在运行。所以 kosh 自己按插件的格式写文件——即使 Mac 在睡眠也能工作。下面每条规则都在真实插件上测试过:
- 每个被修改的元素都会得到新版本号,且不小于以秒计的当前时间。否则,打开着的图会悄悄忽略这次修改。
- 删除要用
isDeleted标记。一个只是从文件里消失的元素,会留在打开的视图里,并在下次保存时回来。 - 文字要在两处修改:JSON 里和 Text Elements 部分。以 Text Elements 为准。
- 文件以压缩形式写入,和插件自己写的一样。这样打开的视图就没有理由再保存一次。
布局不必由智能体自己计算:有自动布局。六个分区里的 80 个方块和 118 条箭头,2.9 秒就能排好。第一张真正的图我在自己的 Obsidian 里看了,说:“对,都很好。”
实话实说:局限
最薄弱的环节,是智能体修改时正在我屏幕上打开着的图。
第一次外部修改之后,插件会再保存一次这张图。如果这次保存还没到云端,智能体又写了一次,LiveSync 里就会出现冲突。
冲突不会丢东西:LiveSync 会保留两个版本。但笔记在磁盘上会卡住不动,屏幕上还会弹出“Conflicting changes”对话框。下面是一次实测的结果——对一张打开的图连续修改:
| 两次修改的间隔 | 被接受的写入 | 冲突对话框 |
|---|---|---|
| 15 秒 | 25 | 0 |
| 5 秒 | 30 | 1 |
| 1 秒 | 3 | 1 |
| 无间隔 | 6 | 1 |
样本很小。这是趋势,不是统计。留出间隔也不等于保证。
所以 kosh 学会了自己合并这类冲突。它找出两个版本的共同祖先,逐个元素比较。我改了方块 C,智能体改了方块 A?两处修改都会保留,对话框大约 10 秒后自己关闭。修复后的同一测试:
| 两次修改的间隔 | 被接受的写入 | 冲突对话框 |
|---|---|---|
| 5 秒 | 24 | 0 |
| 1 秒 | 29 | 1 — 12 秒后自行关闭 |
kosh 有意不合并的情况:双方改了同一个元素。两个版本都可能是我自己的工作,所以这个对话框留给我处理。我两台设备之间的冲突,kosh 也不碰——它只处理其中一个版本由它自己写入的冲突。
我踩过的坑
- Linter 弄坏了图。它的一条规则把分区标题改成了小写开头。Excalidraw 插件查找这些标题时区分大小写,于是再也找不到它们——每次保存都会多追加一个分区。解决办法:在 Linter 中排除
.excalidraw.md。 - 不要在同一台 Mac 上再开第二个 Obsidian。一个使用独立主目录的测试副本弹出了系统对话框,提议重置我的钥匙串。
- Mac 上的 shell 不是沙盒。kosh 可以以我的身份在我的笔记本上执行命令。所以凡是删除、安装、推送或涉及密钥的操作,都必须先得到我对这条具体命令的“同意”。我还可以在 Mac 本机上用一个文件关闭这个通道。
- livesync-workers 是个年轻的项目,只有一位作者。所以我 fork 了它,并每小时备份到 GitHub。
它带给我什么
我打开任何一个 Claude 客户端,无论是在 Mac 上、浏览器里还是手机上,它都已经拥有一切:任务、笔记、Telegram、调研、Mac 的健康状态。
那些难以记在脑子里的东西,智能体会摆到画布上。我看一眼,动手改一改——智能体也能看到我的修改。
发现错误了吗?
本文里有事实错误、别扭的翻译,或者哪里读起来不对?告诉我——用你自己的语言。