Agent Skills: Publish Zsxq Article

Publish Markdown articles to Zsxq (知识星球) as drafts. Use when user wants to publish a Markdown file to Zsxq, or mentions "发布到知识星球", "星球文章", "zsxq article". Handles Markdown content input and saves as draft (never auto-publish).

UncategorizedID: sugarforever/01coder-agent-skills/publish-zsxq-article

Install this agent skill to your local

pnpm dlx add-skill https://github.com/sugarforever/01coder-agent-skills/tree/HEAD/skills/publish-zsxq-article

Skill Files

Browse the full folder contents for publish-zsxq-article.

Download Skill

Loading file tree…

skills/publish-zsxq-article/SKILL.md

Skill Metadata

Name
publish-zsxq-article
Description
Publish Markdown articles to Zsxq (知识星球) as drafts. Use when user wants to publish a Markdown file to Zsxq, or mentions "发布到知识星球", "星球文章", "zsxq article". Handles Markdown content input and saves as draft (never auto-publish).

Publish Zsxq Article

Publish Markdown content to Zsxq (知识星球) article editor in Markdown mode, saving as draft for user review before publishing.

Prerequisites

  • Browser automation MCP (either one):
    • Chrome DevTools MCP (mcp__chrome-devtools__*)
    • Playwright MCP (mcp__playwright__*)
  • User logged into Zsxq (知识星球)

Browser MCP Tool Mapping

This skill works with both Chrome DevTools MCP and Playwright MCP:

| Action | Chrome DevTools MCP | Playwright MCP | |--------|---------------------|----------------| | Navigate | navigate_page | browser_navigate | | Take snapshot | take_snapshot | browser_snapshot | | Take screenshot | take_screenshot | browser_take_screenshot | | Click element | click | browser_click | | Fill text | fill | browser_type | | Upload file | upload_file | browser_file_upload | | Press key | press_key | browser_press_key | | Evaluate JS | evaluate_script | browser_evaluate |

Priority: Default to Playwright MCP. Use Chrome DevTools MCP only when Playwright MCP is unavailable.

Detection: At runtime, prefer mcp__playwright__browser_navigate. Fall back to mcp__chrome-devtools__navigate_page only if Playwright tools are not available.

Key URLs

  • Login page: https://wx.zsxq.com/login
  • Article editor: https://wx.zsxq.com/article?groupId={groupId}

Group ID Resolution

The Zsxq group ID is required to navigate to the article editor (the groupId= URL parameter). Do not hardcode a default.

Before any navigation, resolve the group ID in this order:

  1. Skill argument — if the user invoked the skill with a group ID, use it.
  2. Environment variable — check ZSXQ_GROUP_ID (optional, for users who publish repeatedly to the same group).
  3. Prompt the user if neither is available:

    请提供知识星球的 group ID(在星球 URL 里 groupId= 之后那串数字)。

Do not proceed to Step 2 (Navigate) without a resolved group ID.

Editor Interface

The Zsxq article editor has two modes:

Rich Text Mode (Default)

  • Standard WYSIWYG editor with formatting toolbar
  • Click "切换到 Markdown 模式 (内测)" to switch

Markdown Mode (Preferred)

  • Uses Milkdown (ProseMirror-based WYSIWYG Markdown editor)
  • Renders Markdown as formatted content (headings, bold, links, lists)
  • Click "切换到富文本模式" to switch back

IMPORTANT: Content Insertion Method The Milkdown editor requires content to be inserted via paste event, NOT direct fill:

  • fill tool → Content treated as plain text, Markdown NOT rendered
  • Paste event → Milkdown parses Markdown and renders it properly

Key Elements in Markdown Mode

  • Title input: textbox "请在这里输入标题"
  • Content area: ProseMirror editor (.ProseMirror class)
  • Save button: "保存" (saves as draft)
  • Preview button: "预览"
  • Publish button: "发布" (DO NOT USE - always save as draft)
  • Tags: "添加标签"

Main Workflow

Step 1: Prepare Content

Read the Markdown file and extract:

  • Title: from YAML frontmatter title field, or H1 header # Title, or filename
  • Content: Markdown body with the following stripped:
    • YAML frontmatter (--- delimited block at the top)
    • H1 title line (already used as the article title)
    • HTML comments (<!-- ... -->)
    • Horizontal rules (---) — Milkdown's paste handler misparses ---, causing subsequent headings and formatting to break (e.g., ## rendered as bold ** text instead of H2). Remove all --- lines before pasting.
# Read the markdown file
cat /path/to/article.md

Step 2: Navigate to Article Editor

# Navigate to the article editor with the resolved group ID (see Group ID Resolution above)
navigate_page: https://wx.zsxq.com/article?groupId={groupId}

If not logged in, the page will redirect to login. Prompt user to log in manually:

请先登录知识星球,登录完成后告诉我。
Login URL: https://wx.zsxq.com/login

Step 3: Switch to Markdown Mode

After page loads, check if already in Markdown mode by looking for "切换到富文本模式" text.

If in Rich Text mode (shows "切换到 Markdown 模式"):

  1. Click "切换到 Markdown 模式 (内测)"
  2. Confirm the dialog by clicking "确定"
// Check current mode
const switchBtn = document.querySelector('[class*="switch"]');
if (switchBtn && switchBtn.innerText.includes('切换到 Markdown')) {
  // Need to switch to Markdown mode
}

Step 4: Fill Title

  1. Find the title textbox with placeholder "请在这里输入标题"
  2. Click to focus
  3. Type the title
click: title textbox
fill: title textbox with article title

Step 5: Insert Markdown Content (via Paste Event)

CRITICAL: Do NOT use fill tool - it inserts plain text without Markdown rendering.

Instead, use evaluate_script to simulate a paste event:

// Simulate paste event to trigger Milkdown's Markdown parsing
() => {
  const markdownContent = `YOUR_MARKDOWN_CONTENT_HERE`;

  const editorEl = document.querySelector('.ProseMirror');
  if (!editorEl) return { error: 'Editor not found' };

  // Focus the editor
  editorEl.focus();

  // Create and dispatch paste event
  const clipboardData = new DataTransfer();
  clipboardData.setData('text/plain', markdownContent);

  const pasteEvent = new ClipboardEvent('paste', {
    bubbles: true,
    cancelable: true,
    clipboardData: clipboardData
  });

  editorEl.dispatchEvent(pasteEvent);

  return { success: true, charCount: markdownContent.length };
}

This method:

  1. Creates a ClipboardEvent with the Markdown content
  2. Dispatches it to the ProseMirror editor
  3. Milkdown's paste handler parses and renders the Markdown

Step 6: Add Tags (Optional)

  1. Click "添加标签"
  2. Enter tag text
  3. Confirm

Step 7: Save as Draft

IMPORTANT: Always save as draft, NEVER click "发布" (Publish)

  1. Click "保存" button to save as draft
  2. Verify save was successful
click: "保存" button

Step 8: Verify and Report

After saving:

  1. Check for success message or draft status
  2. Report to user:
草稿已保存。请在知识星球中预览并手动发布。
Draft saved. Please review in Zsxq and publish manually.

Complete Example Flow

User: "把 /path/to/my-article.md 发布到知识星球"

1. Read /path/to/my-article.md
   - Extract title from frontmatter or H1
   - Strip frontmatter, H1 title, HTML comments, and horizontal rules (`---`)
   - Get cleaned content

2. Navigate to https://wx.zsxq.com/article?groupId={resolved groupId}

3. Check if logged in
   - If not, prompt user to login

4. Switch to Markdown mode if needed
   - Click "切换到 Markdown 模式 (内测)"
   - Confirm dialog

5. Fill title
   - Click title input
   - Use `fill` tool to set title text

6. Insert content via paste event
   - Use `evaluate_script` to simulate paste event
   - This triggers Milkdown to parse and render Markdown

7. Save as draft
   - Click "保存"

8. Report success
   - "草稿已保存,请手动预览并发布"

Critical Rules

  1. NEVER click "发布" - Only save as draft using "保存"
  2. Always use Markdown mode - Switch if in Rich Text mode
  3. Check login status - Prompt user to login if needed
  4. Preserve original file - Never modify the source Markdown file
  5. Report completion - Tell user the draft is saved and needs manual review
  6. Resolve group ID first - Never hardcode a group ID. Resolve via skill argument, ZSXQ_GROUP_ID env var, or user prompt before any navigation (see Group ID Resolution)
  7. Prefer Playwright MCP - Default to Playwright MCP; only use Chrome DevTools MCP when Playwright is unavailable

Troubleshooting

Markdown Not Rendering (Shows Raw Syntax)

If you see raw Markdown syntax like **bold** or [link](url) instead of rendered formatting:

  • Cause: Content was inserted using fill tool instead of paste event
  • Solution: Use the evaluate_script method to simulate a paste event (see Step 5)

The Milkdown editor only parses Markdown when content is pasted, not when directly set.

Horizontal Rules (---) Break Formatting

If headings appear as bold text with ** markers, or formatting is garbled after a --- line:

  • Cause: Milkdown's paste handler misparses --- (horizontal rule), corrupting subsequent Markdown elements
  • Solution: Strip all --- lines from the content before pasting. The article can use headings for section separation instead.

Login Required

If page redirects or shows login prompt:

请先登录知识星球: https://wx.zsxq.com/login
登录完成后告诉我。

Content Too Long

Zsxq has a 100,000 character limit. If content exceeds:

文章内容超过100000字符限制,请考虑拆分文章。

Switch Mode Dialog

When switching to Markdown mode, a confirmation dialog appears:

  • Message: "确定要切换编辑器?当前内容将不会同步至新编辑器"
  • Click "确定" to confirm

Editor Not Loading

If editor elements are not visible:

  1. Wait for page to fully load
  2. Take a new snapshot
  3. If still not loading, refresh the page

Element Reference

| Element | Selector/Identifier | Description | |---------|---------------------|-------------| | Title input | textbox "请在这里输入标题" | Article title (max 60 chars) | | Content area | .ProseMirror (Milkdown editor) | Markdown content (max 100000 chars) | | Save button | "保存" | Save as draft | | Preview button | "预览" | Preview article | | Publish button | "发布" | DO NOT USE | | Mode switch | "切换到 Markdown 模式" / "切换到富文本模式" | Toggle editor mode | | Tags | "添加标签" | Add article tags | | Word count | "正文字数:X /100000" | Character counter |

Image Upload

Image upload works in both Rich Text mode and Markdown mode using the upload_file tool.

Prerequisites

  • Check image file size first: if > 500KB, compress to WebP or reduce quality
  • Use ls -la /path/to/image.png to check file size

Image Upload Workflow

Image upload works with the image button in both editor modes:

  1. Take snapshot to find the image button ref/uid

    • Rich Text mode: button "image"
    • Markdown mode: generic description="Add image"
  2. Upload image

    Chrome DevTools MCP:

    upload_file:
      uid: <image button uid>
      filePath: /path/to/image.png
    

    Playwright MCP:

    browser_file_upload:
      ref: <image button ref>
      paths: ["/path/to/image.png"]
    
  3. Verify upload - take screenshot to confirm image appears in editor

Key Elements for Image Upload

| Mode | Image Button | Selector in Snapshot | |------|-------------|---------------------| | Rich Text | button "image" | button "image" | | Markdown | Add image | generic description="Add image" |

Example Image Upload (Markdown Mode)

# 1. Take verbose snapshot to find image button
take_snapshot(verbose=true)

# 2. Find "Add image" button (e.g., uid=26_59)
# Look for: generic description="Add image"

# 3. Upload image directly to the button
upload_file:
  uid: 26_59  # (example uid for "Add image" button)
  filePath: /Users/user/Downloads/image.png

# 4. Verify with screenshot
take_screenshot

Example Image Upload (Rich Text Mode)

# 1. Take snapshot to find image button
take_snapshot

# 2. Find image button (e.g., uid=12_7)
# Look for: button "image"

# 3. Upload image to the button
upload_file:
  uid: 12_7  # (example uid for image button)
  filePath: /Users/user/Downloads/image.png

# 4. Verify with screenshot
take_screenshot

Image Size Limits

  • Maximum recommended: 500KB per image
  • For larger images, compress first using tools like ImageMagick or sips:
    # Check size
    ls -la /path/to/image.png
    
    # Compress if needed (macOS)
    sips -s format jpeg -s formatOptions 80 /path/to/image.png --out /path/to/image_compressed.jpg
    

Troubleshooting Image Upload

Image not appearing after upload:

  • Take a fresh verbose snapshot to get correct uid for image button
  • Verify the image file exists and is accessible
  • Check the word count indicator - it should increase after successful upload

Finding the correct button uid:

  • Use take_snapshot(verbose=true) to see element descriptions
  • In Markdown mode, look for generic description="Add image"
  • In Rich Text mode, look for button "image"

Technical Details

The Zsxq article editor uses two different editors:

Rich Text Mode (Quill)

  • Quill: A modern WYSIWYG editor
  • Image upload: Works via upload_file tool to button "image"
  • Toolbar: Standard formatting buttons including image

Markdown Mode (Milkdown)

  • Milkdown: A plugin-driven WYSIWYG markdown editor
  • ProseMirror: The underlying rich-text editing framework
  • Paste handling: Milkdown intercepts paste events and parses Markdown content
  • Image upload: Works via upload_file tool to generic description="Add image"

This is why the user's workflow via md.bytenote.net works - pasting from any source triggers Milkdown's Markdown parser, resulting in properly rendered content.