/x-article-publisher
Publish Markdown articles to X (Twitter) Articles editor with proper formatting. Use when user wants to publish a Markdown file/URL to X Articles, or mentions "publish to X", "post article to Twitter", "X article", or wants help with X Premium article publishing. Handles cover
$ npx -y skills add wshuyi/x-article-publisher-skill --skill x-article-publisher --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/x-article-publisher
Context preview
The summary Claude sees to decide when to auto-load this skill.
Publish Markdown articles to X (Twitter) Articles editor with proper formatting. Use when user wants to publish a Markdown file/URL to X Articles, or mentions "publish to X", "post article to Twitter", "X article", or wants help with X Premium article publishing. Handles cover
SKILL.md
x-article-publisher.SKILL.mdname: x-article-publisher
description: |
Publish Markdown articles to X (Twitter) Articles editor with proper formatting. Use when user wants to publish a Markdown file/URL to X Articles, or mentions "publish to X", "post article to Twitter", "X article", or wants help with X Premium article publishing. Handles cover image upload and converts Markdown to rich text automatically.
X Article Publisher
Publish Markdown content to X (Twitter) Articles editor, preserving formatting with rich text conversion.
Prerequisites
- Playwright MCP for browser automation
- User logged into X with Premium Plus subscription
- Python 3.9+ with dependencies:
- macOS: `pip install Pillow pyobjc-framework-Cocoa`
- Windows: `pip install Pillow pywin32 clip-util`
- For Mermaid diagrams: `npm install -g @mermaid-js/mermaid-cli`
Scripts
Located in `~/.claude/skills/x-article-publisher/scripts/`:
parse_markdown.py
Parse Markdown and extract structured data:
python parse_markdown.py <markdown_file> [--output json|html] [--html-only]
Returns JSON with: title, cover_image, content_images, **dividers** (with block_index for positioning), html, total_blocks
copy_to_clipboard.py
Copy image or HTML to system clipboard (cross-platform):
# Copy image (with optional compression)
python copy_to_clipboard.py image /path/to/image.jpg [--quality 80]
# Copy HTML for rich text paste
python copy_to_clipboard.py html --file /path/to/content.html
table_to_image.py
Convert Markdown table to PNG image:
python table_to_image.py <input.md> <output.png> [--scale 2]
Use when X Articles doesn't support native table rendering or for consistent styling.
Pre-Processing (Optional)
Before publishing, scan the Markdown for elements that need conversion:
Tables → PNG
# Extract table to temp file, then convert
python ~/.claude/skills/x-article-publisher/scripts/table_to_image.py /tmp/table.md /tmp/table.png
# Replace table in markdown with: 
Mermaid Diagrams → PNG
# Extract mermaid block to .mmd file, then convert
mmdc -i /tmp/diagram.mmd -o /tmp/diagram.png -b white -s 2
# Replace mermaid block with: 
Dividers (---)
Dividers are automatically detected by `parse_markdown.py` and output in the `dividers` array. They must be inserted via X Articles' **Insert > Divider** menu (HTML `<hr>` tags are ignored by X).
Workflow
**Strategy: "先文后图后分割线" (Text First, Images Second, Dividers Last)**
For articles with images and dividers, paste ALL text content first, then insert images and dividers at correct positions using block index.
1. **(Optional)** Pre-process: Convert tables/mermaid to images 2. Parse Markdown with Python script → get title, images, **dividers** with block_index, HTML 3. Navigate to X Articles editor 4. Upload cover image (first image) 5. Fill title 6. Copy HTML to clipboard (Python) → Paste with Cmd+V 7. Insert content images at positions specified by block_index 8. **Insert dividers at positions specified by block_index** (via Insert > Divider menu) 9. Save as draft (NEVER auto-publish)
高效执行原则 (Efficiency Guidelines)
**目标**: 最小化操作之间的等待时间,实现流畅的自动化体验。
1. 避免不必要的 browser_snapshot
大多数浏览器操作(click, type, press_key 等)都会在返回结果中包含页面状态。**不要**在每次操作后单独调用 `browser_snapshot`,直接使用操作返回的页面状态即可。
❌ 错误做法:
browser_click → browser_snapshot → 分析 → browser_click → browser_snapshot → ...
✅ 正确做法:
browser_click → 从返回结果中获取页面状态 → browser_click → ...
2. 避免不必要的 browser_wait_for
只在以下情况使用 `browser_wait_for`:
- 等待图片上传完成(`textGone="正在上传媒体"`)
- 等待页面初始加载(极少数情况)
**不要**使用 `browser_wait_for` 来等待按钮或输入框出现 - 它们在页面加载完成后立即可用。
3. 并行执行独立操作
当两个操作没有依赖关系时,可以在同一个消息中并行调用多个工具:
✅ 可以并行:
- 填写标题 (browser_type) + 复制HTML到剪贴板 (Bash)
- 解析Markdown生成JSON + 生成HTML文件
❌ 不能并行(有依赖):
- 必须先点击create才能上传封面图
- 必须先粘贴内容才能插入图片
4. 连续执行浏览器操作
每个浏览器操作返回的页面状态包含所有需要的元素引用。直接使用这些引用进行下一步操作:
# 理想流程(每步直接执行,不额外等待):
browser_navigate → 从返回状态找create按钮 → browser_click(create)
→ 从返回状态找上传按钮 → browser_click(上传) → browser_file_upload
→ 从返回状态找应用按钮 → browser_click(应用)
→ 从返回状态找标题框 → browser_type(标题)
→ 点击编辑器 → browser_press_key(Meta+v)
→ ...
5. 准备工作前置
在开始浏览器操作之前,先完成所有准备工作: 1. 解析 Markdown 获取 JSON 数据 2. 生成 HTML 文件到 /tmp/ 3. 记录 title、cover_image、content_images 等信息
这样浏览器操作阶段可以连续执行,不需要中途停下来处理数据。
Step 1: Parse Markdown (Python)
Use `parse_markdown.py` to extract all structured data:
python ~/.claude/skills/x-article-publisher/scripts/parse_markdown.py /path/to/article.md
Output JSON:
{
"title": "Article Title",
"cover_image": "/path/to/first-image.jpg",
"cover_exists": true,
"content_images": [
{"path": "/path/to/img2.jpg", "original_path": "/md/dir/assets/img2.jpg", "exists": true, "block_index": 5, "after_text": "context..."},
{"path": "/path/to/img3.jpg", "original_path": "/md/dir/assets/img3.jpg", "exists": true, "block_index": 12, "after_text": "another..."}
],
"html": "<p>Content...</p><h2>Section</h2>...",
"total_blocks": 45,
"missing_images": 0
}**Key fields:**
- `block_index`: The image should be inserted AFTER block element at this index (0-indexed)
- `total_blocks`: Total number of block elements in the HTML
- `after_text`: Kept for reference/debugging only, NOT for positioning
- `exists`: Whether the image file was found (if false, upload will fail)
- `original_path`: The path resolved from Markdown (before auto-search)
- `path`: The actual path to use (may differ from original_path if auto-searched)
- `missing_images`: Count of images not found anywhere
Save HTML to temp file for clipboard:
python parse_markdown.py article.md --html-only > /tmp/article_html.html
Step 2: Open X Articles Editor
浏览器错误处理
如果遇到 `Error: Browser is already in use` 错误:
# 方案1:先关闭浏览器再重新打开
browser_close
browser_navigate: https://x.com/compose/articles
# 方案2:如果 browser_close 无效(锁定),提示用户手动关闭 Chrome
# 方案3:使用已有标签页,直接导航
browser_tabs
Read more
name: x-article-publisher description: | Publish Markdown articles to X (Twitter) Articles editor with proper formatting. Use when user wants to publish a Markdown file/URL to X Articles, or mentions "publish to X", "post article to Twitter", "X article", or wants help with X Premium article publishing. Handles cover image upload and converts Markdown to rich text automatically.
X Article Publisher
Publish Markdown content to X (Twitter) Articles editor, preserving formatting with rich text conversion.
Prerequisites
- Playwright MCP for browser automation
- User logged into X with Premium Plus subscription
- Python 3.9+ with dependencies:
- macOS: `pip install Pillow pyobjc-framework-Cocoa`
- Windows: `pip install Pillow pywin32 clip-util`
- For Mermaid diagrams: `npm install -g @mermaid-js/mermaid-cli`
Scripts
Located in `~/.claude/skills/x-article-publisher/scripts/`:
parse_markdown.py
Parse Markdown and extract structured data:
python parse_markdown.py <markdown_file> [--output json|html] [--html-only]
Returns JSON with: title, cover_image, content_images, **dividers** (with block_index for positioning), html, total_blocks
copy_to_clipboard.py
Copy image or HTML to system clipboard (cross-platform):
# Copy image (with optional compression) python copy_to_clipboard.py image /path/to/image.jpg [--quality 80] # Copy HTML for rich text paste python copy_to_clipboard.py html --file /path/to/content.html
table_to_image.py
Convert Markdown table to PNG image:
python table_to_image.py <input.md> <output.png> [--scale 2]
Use when X Articles doesn't support native table rendering or for consistent styling.
Pre-Processing (Optional)
Before publishing, scan the Markdown for elements that need conversion:
Tables → PNG
# Extract table to temp file, then convert python ~/.claude/skills/x-article-publisher/scripts/table_to_image.py /tmp/table.md /tmp/table.png # Replace table in markdown with: 
Mermaid Diagrams → PNG
# Extract mermaid block to .mmd file, then convert mmdc -i /tmp/diagram.mmd -o /tmp/diagram.png -b white -s 2 # Replace mermaid block with: 
Dividers (---)
Dividers are automatically detected by `parse_markdown.py` and output in the `dividers` array. They must be inserted via X Articles' **Insert > Divider** menu (HTML `<hr>` tags are ignored by X).
Workflow
**Strategy: "先文后图后分割线" (Text First, Images Second, Dividers Last)**
For articles with images and dividers, paste ALL text content first, then insert images and dividers at correct positions using block index.
1. **(Optional)** Pre-process: Convert tables/mermaid to images 2. Parse Markdown with Python script → get title, images, **dividers** with block_index, HTML 3. Navigate to X Articles editor 4. Upload cover image (first image) 5. Fill title 6. Copy HTML to clipboard (Python) → Paste with Cmd+V 7. Insert content images at positions specified by block_index 8. **Insert dividers at positions specified by block_index** (via Insert > Divider menu) 9. Save as draft (NEVER auto-publish)
高效执行原则 (Efficiency Guidelines)
**目标**: 最小化操作之间的等待时间,实现流畅的自动化体验。
1. 避免不必要的 browser_snapshot
大多数浏览器操作(click, type, press_key 等)都会在返回结果中包含页面状态。**不要**在每次操作后单独调用 `browser_snapshot`,直接使用操作返回的页面状态即可。
❌ 错误做法: browser_click → browser_snapshot → 分析 → browser_click → browser_snapshot → ... ✅ 正确做法: browser_click → 从返回结果中获取页面状态 → browser_click → ...
2. 避免不必要的 browser_wait_for
只在以下情况使用 `browser_wait_for`:
- 等待图片上传完成(`textGone="正在上传媒体"`)
- 等待页面初始加载(极少数情况)
**不要**使用 `browser_wait_for` 来等待按钮或输入框出现 - 它们在页面加载完成后立即可用。
3. 并行执行独立操作
当两个操作没有依赖关系时,可以在同一个消息中并行调用多个工具:
✅ 可以并行: - 填写标题 (browser_type) + 复制HTML到剪贴板 (Bash) - 解析Markdown生成JSON + 生成HTML文件 ❌ 不能并行(有依赖): - 必须先点击create才能上传封面图 - 必须先粘贴内容才能插入图片
4. 连续执行浏览器操作
每个浏览器操作返回的页面状态包含所有需要的元素引用。直接使用这些引用进行下一步操作:
# 理想流程(每步直接执行,不额外等待): browser_navigate → 从返回状态找create按钮 → browser_click(create) → 从返回状态找上传按钮 → browser_click(上传) → browser_file_upload → 从返回状态找应用按钮 → browser_click(应用) → 从返回状态找标题框 → browser_type(标题) → 点击编辑器 → browser_press_key(Meta+v) → ...
5. 准备工作前置
在开始浏览器操作之前,先完成所有准备工作: 1. 解析 Markdown 获取 JSON 数据 2. 生成 HTML 文件到 /tmp/ 3. 记录 title、cover_image、content_images 等信息
这样浏览器操作阶段可以连续执行,不需要中途停下来处理数据。
Step 1: Parse Markdown (Python)
Use `parse_markdown.py` to extract all structured data:
python ~/.claude/skills/x-article-publisher/scripts/parse_markdown.py /path/to/article.md
Output JSON:
{
"title": "Article Title",
"cover_image": "/path/to/first-image.jpg",
"cover_exists": true,
"content_images": [
{"path": "/path/to/img2.jpg", "original_path": "/md/dir/assets/img2.jpg", "exists": true, "block_index": 5, "after_text": "context..."},
{"path": "/path/to/img3.jpg", "original_path": "/md/dir/assets/img3.jpg", "exists": true, "block_index": 12, "after_text": "another..."}
],
"html": "<p>Content...</p><h2>Section</h2>...",
"total_blocks": 45,
"missing_images": 0
}**Key fields:**
- `block_index`: The image should be inserted AFTER block element at this index (0-indexed)
- `total_blocks`: Total number of block elements in the HTML
- `after_text`: Kept for reference/debugging only, NOT for positioning
- `exists`: Whether the image file was found (if false, upload will fail)
- `original_path`: The path resolved from Markdown (before auto-search)
- `path`: The actual path to use (may differ from original_path if auto-searched)
- `missing_images`: Count of images not found anywhere
Save HTML to temp file for clipboard:
python parse_markdown.py article.md --html-only > /tmp/article_html.html
Step 2: Open X Articles Editor
浏览器错误处理
如果遇到 `Error: Browser is already in use` 错误:
# 方案1:先关闭浏览器再重新打开 browser_close browser_navigate: https://x.com/compose/articles # 方案2:如果 browser_close 无效(锁定),提示用户手动关闭 Chrome # 方案3:使用已有标签页,直接导航 browser_tabs
Publish Markdown articles to X (Twitter) Articles with one command. Say goodbye to tedious rich text editing.
Repo: wshuyi/x-article-publisher-skill

