App 不再是入口:用 AI Agent 从 Obsidian 和 Telegram 发布 WordPress 博客
我任务栏上的 WordPress 后台标签页还开着。已经好几周没点过了。
以前发一篇博客长什么样:打开 CMS,粘贴文字,修复粘贴时乱掉的格式,设置分类,想起来还要填摘要,点发布,等页面刷新,不确定有没有成功。顺利的话二十分钟,不顺利的话一个小时就没了。
这套流程有一个隐藏前提:写作和发布发生在同一个地方。但它们从来不在同一个地方。写作发生在 Obsidian 里,发生在备忘录里,发生在凌晨两点给自己发的语音里,发生在一段你正在进行的对话里。发布是事后的事,是你完成真正的工作之后要交的一笔税。
WP-CLI 消灭了浏览器这一步。AI Agent 消灭了”人工操作”这一步。
剩下的,是发布发生在思考本来就在的地方。
共同的底层
在讲两种工作流之前,先说它们共享的那一层:
WordPress 跑在 Docker 里,WP-CLI 安装在容器内。所有发布操作归结为一条 shell 命令:
docker exec wp_app wp post create /tmp/post.html \
--post_title="标题" \
--post_status=publish \
--post_category=3 \
--allow-root --path=/var/www/html \
--porcelain
这条命令是通用的发布原语。它不在乎内容从哪里来——文件、剪贴板、语言模型的输出、一条经过三层自动化转发的 Telegram 消息。给它合法的 HTML,给它标题,它就发布。完事。
下面两种工作流,本质上都是生成这条命令的不同方式。
第一种:Obsidian 作为内容的源头
前提
如果你用 Obsidian,你的知识已经是有结构的:文件夹、标签、日记、相互链接的概念。你的博客草稿很可能和研究笔记、读书记录、半成形的想法放在同一个 vault 里。Obsidian 是你思考的地方。
“思考”和”发布”之间的那道缝,正是手动发布流程——从 Obsidian 复制,粘贴进 WordPress,修格式,点按钮。AI Agent 填上这道缝,方式是直接坐在你的 vault 和服务器之间。
工作方式
Agent(Claude Code、本地 LLM,或任何有文件系统访问权限的 Agent)直接操作你的 Obsidian vault。不需要导出,不需要剪贴板,不需要浏览器。
Obsidian vault(本地文件)
└── posts/
└── 2026-04-20 自托管的理由.md ← Agent 读这个
|
▼
AI Agent(Claude Code)
| 读 vault 文件
| 剥离 YAML frontmatter
| Markdown → HTML
| 提取标题、日期、分类
▼
服务器上的 WP-CLI
| docker cp HTML 进容器
| wp post create
▼
WordPress — 文章已发布
Agent 读文件,解析 frontmatter 拿元数据,把 Markdown 正文转成 HTML,交给 WP-CLI。人类唯一参与的环节,是一开始写这篇文章。
对话长什么样
以 Claude Code 作为 Agent:
你: 把我博客文件夹里的”自托管的理由”发到 WordPress,日期用文档里写的那个。
Claude Code: 读取
D:\Obsidian\ThomAndScarlet\blog\posts\2026-04-20 自托管的理由.md…
标题:为什么 2026 年我还在自托管
日期:2026-04-20,分类:My Works转换 HTML,上传服务器…
发布成功。Post ID 201。地址:https://yourdomain.com/?p=201
Agent 处理了路径解析、SSH 连接、格式转换、WP-CLI 调用。你说了十个字。
技术路径
# Agent 读 Obsidian vault 文件
# 解析 YAML frontmatter:title、date、category、excerpt
# Markdown 正文转 HTML(Python markdown 库,或任意转换工具)
python3 << 'EOF'
import markdown, yaml
filepath = "/path/to/obsidian/vault/posts/post.md"
with open(filepath, encoding="utf-8") as f:
raw = f.read()
fm, body = {}, raw
if raw.startswith("---"):
parts = raw.split("---", 2)
if len(parts) >= 3:
fm = yaml.safe_load(parts[1]) or {}
body = parts[2].strip()
html = markdown.markdown(body, extensions=["tables", "fenced_code", "nl2br"])
with open("/tmp/obsidian_post.html", "w", encoding="utf-8") as f:
f.write(html)
print(f"标题: {fm.get('title')}")
print(f"日期: {fm.get('date')}")
print(f"分类: {fm.get('category')}")
EOF
# 上传服务器并发布
scp /tmp/obsidian_post.html root@your-server:/tmp/obsidian_post.html
ssh root@your-server 'docker cp /tmp/obsidian_post.html wp_app:/tmp/obsidian_post.html'
ssh root@your-server 'docker exec wp_app wp post create /tmp/obsidian_post.html \
--post_title="为什么 2026 年我还在自托管" \
--post_status=publish \
--post_date="2026-04-20 08:00:00" \
--post_date_gmt="2026-04-20 00:00:00" \
--post_category=3 \
--allow-root --path=/var/www/html \
--porcelain'
为什么对 Obsidian 用户特别友好
Obsidian 的文件结构本来就是围绕意义组织的——文件夹、标签、属性。草稿里的 YAML frontmatter 是自然的:你本来就在写 title:、date:、tags:,是为了自己的整理需求,不是为了发布。Agent 只是读了你已经写好的东西。
没有数据格式转换。没有复制粘贴摩擦。vault 文件是从第一个字到发布链接的唯一真相来源。
对那些在 Obsidian 里看着一篇草稿想”这篇应该发出去”的人来说,Agent 移除了”应该”和”现在”之间的摩擦。
第二种:IM 优先——不需要任何软件
前提
Obsidian 工作流还是假设你坐在一台有文件系统的电脑前。但想法不从那里开始。它们开始于一段对话——凌晨两点给自己的语音备忘,一段正在进行的 AI 讨论,一个在聊天途中突然清晰起来的念头。
第二种工作流的前提更简单,在实践上更激进:在想法发生的地方发布。 不需要笔记本电脑,不需要 Obsidian,不需要 Markdown 编辑器,不需要 WordPress 后台。只需要一段对话。
工作方式
AI Agent(Telegram 上的 OpenClaw、Discord 机器人,任何接入 IM 的 Agent)收到一条消息,起草、润色、发布。对话就是全部的界面。
你(在 Telegram、Discord,任何地方)
| "写一篇关于 X 的文章,发出去。"
| ——或——
| "这是我的草稿:[粘贴文字]。整理一下发出去。"
▼
AI Agent(OpenClaw / 任意接入 IM 的 Agent)
| 理解意图
| 生成或润色内容
| 转换为 HTML
▼
服务器上的 WP-CLI
| docker cp + wp post create
▼
WordPress — 文章发布,URL 返回到对话
对话场景
场景 A — 发一个想法,得到一篇文章:
你(Telegram,晚上十一点): 写一篇短文,讲为什么说”在我电脑上能跑”的人都应该用 Docker。语气随意一点,带点讽刺。发到 My Works 分类。
Agent: 好,稍等。
(45 秒)
完成——Post ID 207,地址 https://yourdomain.com/?p=207。要我把内容读给你看吗?
场景 B — 讨论,打磨,发布:
你: 我最近一直在想一件事,生产力和忙碌之间的区别。忙碌是在表演生产力。
Agent: 这个角度有意思。你想让读者读完的感觉是什么——觉得自己做错了,还是找到了出路?
你: 更像是认出来了。那种突然意识到自己演了一整天的轻微恶心感。
Agent: 明白了。我来起草,两分钟。
(草稿发来)
“忙碌是对’完成了事情’的有说服力的模拟。会议让人觉得有生产力,因为所有人都说话了。收件箱让人觉得处理完了,因为数字变小了。到了一天结束,你说不清什么东西推进了——但你确实很忙。”要从这里继续,还是方向有变化?
你: 就是这个感觉。展开到 600 字,发布。
Agent: 发布完成——Post ID 208。
场景 C — 粗稿输入,Agent 做编辑:
你: [粘贴 800 字草稿,有错别字和语病]
整理成一篇正式文章。改语法,但保留我的语气。发出去。Agent: 发布完成——Post ID 209。第三段的短句我保留了,感觉是有意为之。
为什么这改变了计算
传统发布摩擦有一个特定的形状:从”我有什么值得说的”到”它发出去了”,中间塞满了软件。打开这个 App,登录那个网站,格式化这段文字,点那个按钮。摩擦不是技术难度——是上下文切换。你在想法和发布之间打开的每一个工具,都是一个丢掉线索的机会。
IM 优先发布消灭了上下文切换。你已经在对话里了——和朋友,和 AI,和自己。文章在你思考的同一个空间里完成。Agent 处理其他一切。
这也让 Agent 成为更好的协作者。来回的对话产出比单条 prompt 更好的内容。你可以反驳,重定向,要求换一个角度。Agent 可以在动笔前问清楚方向。最后发出去的文章,比任何一次单独 prompt 的结果都更接近你真正想说的。
更大的图景:对 AI Agent 友好,是未来的标配
这两种工作流表面上看起来很不同——一个基于本地文件,一个基于对话。但它们是同一个转变的不同表达。
过去三十年里,每一个软件工具、平台和服务都围绕人工操作界面构建:浏览器、App、UI。这是正确的设计假设——对于那个时代。它正在快速成为错误的假设。
AI Agent 不用 UI。它们不点击。它们不在菜单里导航。它们读文件,调用 API,运行 shell 命令,返回结果。一个对 AI Agent 友好的服务,是一个暴露了可编程接口的服务——不是埋在需要三页文档才能配置的 API 层里,而是 Agent 可以用最少摩擦直接操作的那种。
WP-CLI 让 WordPress 对 AI Agent 友好。Agent 不需要模拟浏览器会话,不需要爬后台 UI。它运行一条命令,WordPress 响应。
这是”对 Agent 友好的基础设施”在实践中的样子:
- 结构化输入:内容是文件,元数据是参数。没有歧义。
- 可预测的输出:成功返回 post ID,失败返回非零退出码。Agent 知道发生了什么。
- 没有认证剧场:在运营者自己拥有的容器内用
--allow-root。信任在基础设施层处理,不在应用层处理。 - 可组合:每一条 WP-CLI 命令都是独立的积木。Agent 可以列文章、创建文章、更新文章、清缓存——单独执行,也可以链式执行。
Obsidian 工作流对 Agent 友好,因为 vault 是有一致命名规则和 frontmatter 结构的文件系统。Agent 不需要被告知东西在哪里就能导航。
IM 工作流对 Agent 友好,因为对话就是界面——Agent 不需要在”你说了什么”和”它需要做什么”之间翻译。它理解意图,直接行动。
这个模式将在所有领域重复:能被 Agent 读写的代码仓库,有可编程收发的邮件系统,支持自然语言调度的日历系统。能活过未来十年的应用,是 Agent 不需要 UI 就能用的那些。
对人类友好和对 Agent 友好不是对立的。它们是同一个设计原则应用在两种不同用户身上的结果。
最后一件事
这两种工作流都不需要什么稀奇的东西。Obsidian 方法用 Python 标准库和 WP-CLI。IM 方法用任何接入 IM 平台的 AI Agent。
基础设施本身不是重点。重点是,当摩擦消失之后,什么东西被发出去了。
那些以前死在备忘录里的想法——因为发布流程太重所以从来没发——它们被发出去了。那些在手机上出现在晚上十一点的念头——它们被发出去了。那些写得够好但不够精致、撑不起”打开一个 CMS”这个仪式的粗稿——它们被发出去了。
消除摩擦。看看另一边等着什么。
技术栈:Docker + WordPress + WP-CLI + OpenClaw + Hermes Agent。Obsidian 集成通过本地文件系统访问实现。IM 发布通过 Telegram/Discord 机器人连接实现。所有命令运行在自托管 VPS 上。
了解 ~/jintaoblog/朝夕见闻志⚡️ 的更多信息
订阅后即可通过电子邮件收到最新文章。
