📄 SKILL.md

← 返回目录


name: baoyu-post-to-wechat description: Posts content to WeChat Official Account (微信公众号) via API or Chrome CDP. Supports article posting (文章) with HTML, markdown, or plain text input, and image-text posting (贴图, formerly 图文) with multiple images. Markdown article workflows default to converting ordinary external links into bottom citations for WeChat-friendly output. Use when user mentions "发布公众号", "post to wechat", "微信公众号", or "贴图/图文/文章". version: 1.56.1 metadata: openclaw: homepage: https://github.com/JimLiu/baoyu-skills#baoyu-post-to-wechat requires: anyBins: - bun - npx

Post to WeChat Official Account

Language

Match user's language: Respond in the same language the user uses. If user writes in Chinese, respond in Chinese. If user writes in English, respond in English.

Script Directory

Agent Execution: Determine this SKILL.md directory as {baseDir}, then use {baseDir}/scripts/.ts. Resolve ${BUN_X} runtime: if bun installed → bun; if npx available → npx -y bun; else suggest installing bun.

| Script | Purpose | |--------|---------| | scripts/wechat-browser.ts | Image-text posts (图文) | | scripts/wechat-article.ts | Article posting via browser (文章) | | scripts/wechat-api.ts | Article posting via API (文章) | | scripts/md-to-wechat.ts | Markdown → WeChat-ready HTML with image placeholders | | scripts/check-permissions.ts | Verify environment & permissions |

Preferences (EXTEND.md)

Check EXTEND.md existence (priority order):

macOS, Linux, WSL, Git Bash

test -f .baoyu-skills/baoyu-post-to-wechat/EXTEND.md && echo "project" test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-post-to-wechat/EXTEND.md" && echo "xdg" test -f "$HOME/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md" && echo "user"

PowerShell (Windows)

if (Test-Path .baoyu-skills/baoyu-post-to-wechat/EXTEND.md) { "project" } $xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" } if (Test-Path "$xdg/baoyu-skills/baoyu-post-to-wechat/EXTEND.md") { "xdg" } if (Test-Path "$HOME/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md") { "user" }

┌────────────────────────────────────────────────────────┬───────────────────┐ │ Path │ Location │ ├────────────────────────────────────────────────────────┼───────────────────┤ │ .baoyu-skills/baoyu-post-to-wechat/EXTEND.md │ Project directory │ ├────────────────────────────────────────────────────────┼───────────────────┤ │ $HOME/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md │ User home │ └────────────────────────────────────────────────────────┴───────────────────┘

┌───────────┬───────────────────────────────────────────────────────────────────────────┐ │ Result │ Action │ ├───────────┼───────────────────────────────────────────────────────────────────────────┤ │ Found │ Read, parse, apply settings │ ├───────────┼───────────────────────────────────────────────────────────────────────────┤ │ Not found │ Run first-time setup (references/config/first-time-setup.md) → Save → Continue │ └───────────┴───────────────────────────────────────────────────────────────────────────┘

EXTEND.md Supports: Default theme | Default color | Default publishing method (api/browser) | Default author | Default open-comment switch | Default fans-only-comment switch | Chrome profile path

First-time setup: references/config/first-time-setup.md

Minimum supported keys (case-insensitive, accept 1/0 or true/false):

| Key | Default | Mapping | |-----|---------|---------| | default_author | empty | Fallback for author when CLI/frontmatter not provided | | need_open_comment | 1 | articles[].need_open_comment in draft/add request | | only_fans_can_comment | 0 | articles[].only_fans_can_comment in draft/add request |

Recommended EXTEND.md example:

default_theme: default
default_color: blue
default_publish_method: api
default_author: 宝玉
need_open_comment: 1
only_fans_can_comment: 0
chrome_profile_path: /path/to/chrome/profile

Theme options: default, grace, simple, modern

Color presets: blue, green, vermilion, yellow, purple, sky, rose, olive, black, gray, pink, red, orange (or hex value)

Value priority: 1. CLI arguments 2. Frontmatter 3. EXTEND.md (account-level → global-level) 4. Skill defaults

Multi-Account Support

EXTEND.md supports managing multiple WeChat Official Accounts. When accounts: block is present, each account can have its own credentials, Chrome profile, and default settings.

Compatibility rules:

| Condition | Mode | Behavior | |-----------|------|----------| | No accounts block | Single-account | Current behavior, unchanged | | accounts with 1 entry | Single-account | Auto-select, no prompt | | accounts with 2+ entries | Multi-account | Prompt to select before publishing | | accounts with default: true | Multi-account | Pre-select default, user can switch |

Multi-account EXTEND.md example:

default_theme: default
default_color: blue

accounts: - name: 宝玉的技术分享 alias: baoyu default: true default_publish_method: api default_author: 宝玉 need_open_comment: 1 only_fans_can_comment: 0 app_id: your_wechat_app_id app_secret: your_wechat_app_secret - name: AI工具集 alias: ai-tools default_publish_method: browser default_author: AI工具集 need_open_comment: 1 only_fans_can_comment: 0

Per-account keys (can be set per-account or globally as fallback): default_publish_method, default_author, need_open_comment, only_fans_can_comment, app_id, app_secret, chrome_profile_path

Global-only keys (always shared across accounts): default_theme, default_color

Account Selection (Step 0.5)

Insert between Step 0 and Step 1 in the Article Posting Workflow:

if no accounts block:
    → single-account mode (current behavior)
elif accounts.length == 1:
    → auto-select the only account
elif --account  CLI arg:
    → select matching account
elif one account has default: true:
    → pre-select, show: "Using account:  (--account to switch)"
else:
    → prompt user:
      "Multiple WeChat accounts configured:
       1)  ()
       2)  ()
       Select account [1-N]:"

Credential Resolution (API Method)

For a selected account with alias {alias}:

1. app_id / app_secret inline in EXTEND.md account block 2. Env var WECHAT_{ALIAS}_APP_ID / WECHAT_{ALIAS}_APP_SECRET (alias uppercased, hyphens → underscores) 3. .baoyu-skills/.env with prefixed key WECHAT_{ALIAS}_APP_ID 4. ~/.baoyu-skills/.env with prefixed key 5. Fallback to unprefixed WECHAT_APP_ID / WECHAT_APP_SECRET

.env multi-account example:

Account: baoyu

WECHAT_BAOYU_APP_ID=your_wechat_app_id WECHAT_BAOYU_APP_SECRET=your_wechat_app_secret

Account: ai-tools

WECHAT_AI_TOOLS_APP_ID=your_ai_tools_wechat_app_id WECHAT_AI_TOOLS_APP_SECRET=your_ai_tools_wechat_app_secret

Chrome Profile (Browser Method)

Each account uses an isolated Chrome profile for independent login sessions:

| Source | Path | |--------|------| | Account chrome_profile_path in EXTEND.md | Use as-is | | Auto-generated from alias | {shared_profile_parent}/wechat-{alias}/ | | Single-account fallback | Shared default profile (current behavior) |

CLI --account Argument

All publishing scripts accept --account :

${BUN_X} {baseDir}/scripts/wechat-api.ts  --theme default --account ai-tools
${BUN_X} {baseDir}/scripts/wechat-article.ts --markdown  --theme default --account baoyu
${BUN_X} {baseDir}/scripts/wechat-browser.ts --markdown  --images ./photos/ --account baoyu

Pre-flight Check (Optional)

Before first use, suggest running the environment check. User can skip if they prefer.

${BUN_X} {baseDir}/scripts/check-permissions.ts

Checks: Chrome, profile isolation, Bun, Accessibility, clipboard, paste keystroke, API credentials, Chrome conflicts.

If any check fails, provide fix guidance per item:

| Check | Fix | |-------|-----| | Chrome | Install Chrome or set WECHAT_BROWSER_CHROME_PATH env var | | Profile dir | Shared profile at baoyu-skills/chrome-profile (see CLAUDE.md Chrome Profile section) | | Bun runtime | brew install oven-sh/bun/bun (macOS) or npm install -g bun | | Accessibility (macOS) | System Settings → Privacy & Security → Accessibility → enable terminal app | | Clipboard copy | Ensure Swift/AppKit available (macOS Xcode CLI tools: xcode-select --install) | | Paste keystroke (macOS) | Same as Accessibility fix above | | Paste keystroke (Linux) | Install xdotool (X11) or ydotool (Wayland) | | API credentials | Follow guided setup in Step 2, or manually set in .baoyu-skills/.env |

Image-Text Posting (图文)

For short posts with multiple images (up to 9):

${BUN_X} {baseDir}/scripts/wechat-browser.ts --markdown article.md --images ./images/
${BUN_X} {baseDir}/scripts/wechat-browser.ts --title "标题" --content "内容" --image img.png --submit

See references/image-text-posting.md for details.

Article Posting Workflow (文章)

Copy this checklist and check off items as you complete them:

Publishing Progress:
  • [ ] Step 0: Load preferences (EXTEND.md)
  • [ ] Step 0.5: Resolve account (multi-account only)
  • [ ] Step 1: Determine input type
  • [ ] Step 2: Select method and configure credentials
  • [ ] Step 3: Resolve theme/color and validate metadata
  • [ ] Step 4: Publish to WeChat
  • [ ] Step 5: Report completion

Step 0: Load Preferences

Check and load EXTEND.md settings (see Preferences section above).

CRITICAL: If not found, complete first-time setup BEFORE any other steps or questions.

Resolve and store these defaults for later steps:

|------------|-----------|--------| | HTML file | Path ends with .html, file exists | Skip to Step 3 | | Markdown file | Path ends with .md, file exists | Continue to Step 2 | | Plain text | Not a file path, or file doesn't exist | Save to markdown, continue to Step 2 |

Plain Text Handling:

1. Generate slug from content (first 2-4 meaningful words, kebab-case) 2. Create directory and save file:

mkdir -p "$(pwd)/post-to-wechat/$(date +%Y-%m-%d)"

Save content to: post-to-wechat/yyyy-MM-dd/[slug].md

3. Continue processing as markdown file

Slug Examples:

|--------|-------|--------------| | api (Recommended) | Fast | API credentials | | browser | Slow | Chrome, login session |

If API Selected - Check Credentials:

macOS, Linux, WSL, Git Bash

test -f .baoyu-skills/.env && grep -q "WECHAT_APP_ID" .baoyu-skills/.env && echo "project" test -f "$HOME/.baoyu-skills/.env" && grep -q "WECHAT_APP_ID" "$HOME/.baoyu-skills/.env" && echo "user"

PowerShell (Windows)

if ((Test-Path .baoyu-skills/.env) -and (Select-String -Quiet -Pattern "WECHAT_APP_ID" .baoyu-skills/.env)) { "project" } if ((Test-Path "$HOME/.baoyu-skills/.env") -and (Select-String -Quiet -Pattern "WECHAT_APP_ID" "$HOME/.baoyu-skills/.env")) { "user" }

If Credentials Missing - Guide Setup:

WeChat API credentials not found.

To obtain credentials: 1. Visit https://mp.weixin.qq.com 2. Go to: 开发 → 基本配置 3. Copy AppID and AppSecret

Where to save? A) Project-level: .baoyu-skills/.env (this project only) B) User-level: ~/.baoyu-skills/.env (all projects)

After location choice, prompt for values and write to .env:

WECHAT_APP_ID=
WECHAT_APP_SECRET=

Step 3: Resolve Theme/Color and Validate Metadata

1. Resolve theme (first match wins, do NOT ask user if resolved): - CLI --theme argument - EXTEND.md default_theme (loaded in Step 0) - Fallback: default

2. Resolve color (first match wins): - CLI --color argument - EXTEND.md default_color (loaded in Step 0) - Omit if not set (theme default applies)

3. Validate metadata from frontmatter (markdown) or HTML meta tags (HTML input):

| Field | If Missing | |-------|------------| | Title | Prompt: "Enter title, or press Enter to auto-generate from content" | | Summary | Prompt: "Enter summary, or press Enter to auto-generate (recommended for SEO)" | | Author | Use fallback chain: CLI --author → frontmatter author → EXTEND.md default_author |

Auto-Generation Logic:

1. Use CLI --cover if provided. 2. Else use frontmatter (coverImage, featureImage, cover, image). 3. Else check article directory default path: imgs/cover.png. 4. Else fallback to first inline content image. 5. If still missing, stop and request a cover image before publishing.

Step 4: Publish to WeChat

CRITICAL: Publishing scripts handle markdown conversion internally. Do NOT pre-convert markdown to HTML — pass the original markdown file directly. This ensures the API method renders images as tags (for API upload) while the browser method uses placeholders (for paste-and-replace workflow).

Markdown citation default: