The App Is No Longer the Interface: Publishing WordPress from Obsidian and Telegram with AI Agents
The browser tab for WordPress admin is still open on my taskbar. I haven’t clicked it in weeks.
Publishing a blog post used to look like this: open the CMS, paste text, fix the formatting that broke on paste, set the category, remember to add an excerpt, click Publish, wait for the page to load, wonder if it worked. Twenty minutes minimum if you’re focused. An hour if you’re not.
That workflow assumes the writing and the publishing happen in the same place. They never do. The writing happens in Obsidian, or a notes app, or a Telegram voice memo, or a conversation you’re already having. The publishing is an afterthought — a tax you pay after the actual work is done.
WP-CLI eliminated the browser step. AI agents eliminated the human-as-operator step.
What’s left is publishing that happens where the thinking already is.
The Common Foundation
Before the two workflows, the shared layer they both depend on:
WordPress runs in Docker. WP-CLI is installed inside the container. Every publish operation is a single shell command:
docker exec wp_app wp post create /tmp/post.html \
--post_title="Title" \
--post_status=publish \
--post_category=3 \
--allow-root --path=/var/www/html \
--porcelain
That command is the universal publish primitive. It doesn’t care where the content came from — a file, a clipboard, a language model’s output, a Telegram message forwarded through three layers of automation. Feed it valid HTML, give it a title, it publishes. Done.
Both workflows below are just different ways of generating that command.
Method One: Obsidian as the Source of Truth
The Premise
If you use Obsidian, your knowledge is already structured: folders, tags, daily notes, linked concepts. Your blog post drafts probably live in the same vault as your research notes, your reading logs, your half-formed ideas. Obsidian is where you think.
The gap between “thinking” and “published” is exactly the manual publishing workflow — copy from Obsidian, paste into WordPress, fix everything, click buttons. AI agents close that gap by sitting between your vault and the server.
How It Works
The agent (Claude Code, a local LLM, or any agent with filesystem access) operates directly on your Obsidian vault. No export, no clipboard, no browser.
Obsidian vault (local files)
└── posts/
└── 2026-04-20 Self-hosting in 2026.md ← agent reads this
|
▼
AI Agent (Claude Code)
| reads vault file
| strips YAML frontmatter
| converts Markdown → HTML
| extracts title, date, category
▼
WP-CLI on server
| docker cp HTML into container
| wp post create
▼
WordPress — post published
The agent reads the file, parses the frontmatter for metadata, converts the Markdown body to HTML, and hands everything to WP-CLI. The human’s only involvement was writing the post in the first place.
The Conversation
With Claude Code as the agent:
You: Publish the post “Self-hosting in 2026” from my blog posts folder. Use the date from the frontmatter.
Claude Code: Reading
D:\Obsidian\ThomAndScarlet\blog\posts\2026-04-20 Self-hosting in 2026.md…
Title: “Why Self-Hosting Wins in 2026”
Date: 2026-04-20, Category: My WorksConverting to HTML and uploading to server…
Published. Post ID 201. Live at https://yourdomain.com/?p=201
The agent handles the path resolution, the SSH connection, the format conversion, the WP-CLI invocation. The user said ten words.
The Technical Path
For anyone building this:
# Agent reads the Obsidian vault file
# Parses YAML frontmatter: title, date, category, excerpt
# Converts Markdown body to HTML (Python markdown library, or any converter)
python3 << 'EOF'
import markdown, yaml, sys
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"Title: {fm.get('title')}")
print(f"Date: {fm.get('date')}")
print(f"Category: {fm.get('category')}")
EOF
# Upload to server and publish
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="Why Self-Hosting Wins in 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'
Why This Works for Obsidian Users
Obsidian’s file structure is already organized around meaning — folders, tags, properties. YAML frontmatter in a post draft is a natural fit: you were already writing title:, date:, tags: for your own organizational reasons. The agent just reads what’s already there.
No data format conversion. No copy-paste friction. The vault file is the source of truth from first word to published URL.
For anyone who has ever looked at a draft in Obsidian and thought “I should post this someday” — the agent removes the friction between “someday” and “now.”
Method Two: IM-First Publishing — No Apps Required
The Premise
The Obsidian workflow still assumes a local machine with a file system. But the ideas don’t start there. They start in a conversation — a voice message to yourself at 2am, a back-and-forth with an AI about a topic you’re working through, a realization that arrives mid-conversation and needs to be captured before it dissolves.
The second workflow is simpler in premise, more radical in practice: publish from wherever the conversation is happening. No laptop required. No Obsidian. No Markdown editor. No WordPress admin. Just a chat.
How It Works
An AI agent (OpenClaw on Telegram, a Discord bot, any connected agent) receives a message. It drafts, polishes, and publishes. The conversation is the entire interface.
You (on Telegram, Discord, anywhere)
| "Write a post about X. Publish it."
| — or —
| "Here's my draft: [paste text]. Clean it up and post it."
▼
AI Agent (OpenClaw / any IM-connected agent)
| understands intent
| generates or refines content
| converts to HTML
▼
WP-CLI on server
| docker cp + wp post create
▼
WordPress — post published, URL returned to chat
The Conversations
Scenario A — Send an idea, get a post:
You (Telegram, 11pm): Write a short post about why people who say “it works on my machine” should be using Docker. Casual tone, a bit cynical. Post it under My Works.
Agent: On it. Give me a moment.
(45 seconds)
Done — post ID 207, live at https://yourdomain.com/?p=207. Want me to read it back?
Scenario B — Discuss, refine, publish:
You: I’ve been thinking about the difference between productivity and busyness. Something about how busyness is the performance of productivity.
Agent: That’s a good angle. What’s the feeling you want to leave the reader with — that they’re doing it wrong, or that there’s a way out?
You: More like — recognition. That slight sick feeling when they realize they’ve been performing all day.
Agent: Got it. I’ll draft something around that. Give me two minutes.
(draft arrives)
“Busyness is the convincing impression of having done something. The meeting felt productive because everyone talked. The inbox felt handled because the numbers went down. At the end of the day you couldn’t name what moved forward — but you were certainly busy.”Want me to continue from there, or does this change the direction?
You: That’s exactly it. Build it out to 600 words and publish.
Agent: Published — post ID 208.
Scenario C — Raw content, agent as copy editor:
You: [pastes 800 words of rough notes, typos and all]
Turn this into a proper post. Fix the grammar but keep my voice. Post it.Agent: Published — post ID 209. I kept the sentence fragments in the third paragraph since they felt intentional.
Why This Changes the Calculus
Traditional publishing friction has a specific shape: the gap between “I have something worth saying” and “it’s published” is filled with software. Open this app, log into that site, format this text, click that button. The friction is not technical difficulty — it’s context switching. Every tool you open between the idea and the publish is an opportunity to lose the thread.
IM-first publishing eliminates the context switch. You’re already in the conversation — with a friend, with an AI, with yourself. The post is written inside the same space where you’re thinking. The agent handles everything else.
It also happens to make the agent a better collaborator. A back-and-forth conversation produces better content than a prompt. You can push back, redirect, ask for a different angle. The agent can ask clarifying questions before it commits to a direction. The blog post that comes out is genuinely closer to what you meant than anything produced by a single prompt.
The Bigger Picture: AI Agent-Friendly Is the New Default
These two workflows look different on the surface — one is local-file-based, one is conversation-based. But they’re expressions of the same shift.
Every software tool, platform, and service is built around a human-operated interface: a browser, an app, a UI. That was the right design assumption for thirty years. It is increasingly the wrong one.
AI agents operate without UIs. They don’t click. They don’t navigate menus. They read files, call APIs, run shell commands, and return results. A service that is AI agent-friendly is a service that exposes a programmatic interface — not buried in an API tier that requires OAuth configuration and three pages of documentation, but genuinely operable by an agent with minimal friction.
WP-CLI makes WordPress AI agent-friendly. The agent doesn’t need to simulate a browser session or scrape the admin UI. It runs one command. WordPress responds.
This is what agent-friendly infrastructure looks like in practice:
- Structured input: content as a file, metadata as arguments. No ambiguity.
- Predictable output: post ID returned on success, non-zero exit code on failure. The agent knows what happened.
- No authentication theater:
--allow-rootinside a container owned by the operator. Trust is handled at the infrastructure level, not the application level. - Composable: every WP-CLI command is a building block. The agent can list posts, create posts, update posts, flush cache — all independently, all chainable.
The Obsidian workflow is agent-friendly because the vault is a structured filesystem with consistent naming and frontmatter. The agent can navigate it without being told where everything is.
The IM workflow is agent-friendly because the conversation is the interface — the agent doesn’t need to translate between what you said and what it needs to do. It understands intent and acts on it directly.
The pattern will repeat across every domain: code repositories that agents can read and write, email systems with programmatic send/receive, calendar systems with natural language scheduling. The applications that survive the next ten years will be the ones that agents can use without a UI.
Being human-friendly and agent-friendly are not opposites. They’re the same design principle applied to two different kinds of users.
One More Thing
Neither of these workflows requires anything exotic. The Obsidian method uses Python’s standard library and WP-CLI. The IM method uses any AI agent connected to any messaging platform.
The infrastructure is not the interesting part. The interesting part is what gets published when the friction disappears.
Ideas that used to die in a notes app because the publishing workflow felt too heavy — they get published. Thoughts that arrived at 11pm on a phone — they get published. Rough notes that were good enough but not polished enough for the ritual of opening a CMS — they get published.
Remove the friction. See what was waiting on the other side.
Stack: Docker + WordPress + WP-CLI + OpenClaw + Hermes Agent. Obsidian integration via local filesystem access. IM publishing via Telegram/Discord bot connections. All commands run on a self-hosted VPS.
了解 ~/jintaoblog/朝夕见闻志⚡️ 的更多信息
订阅后即可通过电子邮件收到最新文章。
