x-article-publisher

from wshuyi/x-article-publisher-skill

Claude Code skill for publishing Markdown articles to X (Twitter) Articles

495 stars50 forksUpdated Jan 25, 2026
npx skills add https://github.com/wshuyi/x-article-publisher-skill --skill x-article-publisher

SKILL.md

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: ![Table](/tmp/table.png)

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: ![Diagram](/tmp/diagram.png)

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, up

...

Read full content

Repository Stats

Stars495
Forks50
LicenseMIT License