baoyu-post-to-wechat
npx skills add https://github.com/prettyhe/baoyu-skills --skill baoyu-post-to-wechat
Agent 安装分布
Skill 文档
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 SKILL_DIR, then use ${SKILL_DIR}/scripts/<name>.ts.
| 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/generate-cover.ts |
Generate cover images (å°é¢å¾çæ) – No system dependencies |
Preferences (EXTEND.md)
Use Bash to check EXTEND.md existence (priority order):
# Check project-level first
test -f .baoyu-skills/baoyu-post-to-wechat/EXTEND.md && echo "project"
# Then user-level (cross-platform: $HOME works on macOS/Linux/WSL)
test -f "$HOME/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md" && echo "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 â Use defaults â âââââââââââââ´ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
EXTEND.md Supports: Default theme | Default publishing method (api/browser) | Default author | Chrome profile path
Image-Text Posting (徿)
For short posts with multiple images (up to 9):
npx -y bun ${SKILL_DIR}/scripts/wechat-browser.ts --markdown article.md --images ./images/
npx -y bun ${SKILL_DIR}/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 1: Determine input type
- [ ] Step 2: Check markdown-to-html skill
- [ ] Step 3: Convert to HTML
- [ ] Step 4: Validate metadata (title, summary)
- [ ] Step 5: Check and prepare cover image
- [ ] Step 6: Select method and configure credentials
- [ ] Step 7: Publish to WeChat
- [ ] Step 8: Report completion
Step 0: Load Preferences
Check and load EXTEND.md settings (see Preferences section above).
Step 1: Determine Input Type
| Input Type | Detection | Action |
|---|---|---|
| HTML file | Path ends with .html, file exists |
Skip to Step 4 |
| 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, then Step 2 |
Plain Text Handling:
- Generate slug from content (first 2-4 meaningful words, kebab-case)
- 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
- Continue processing as markdown file
Slug Examples:
- “Understanding AI Models” â
understanding-ai-models - “人工æºè½çæªæ¥” â
ai-future(translate to English for slug)
Step 2: Check Markdown-to-HTML Skill
Skip if: Input is .html file
Skill Discovery:
# Check if baoyu-markdown-to-html exists
test -f skills/baoyu-markdown-to-html/SKILL.md && echo "found"
| Result | Action |
|---|---|
| Found | Read its SKILL.md, continue to Step 3 |
| Multiple skills | AskUserQuestion to choose |
| Not found | Show installation suggestion |
When Not Found:
No markdown-to-html skill found.
Suggested installation:
https://github.com/JimLiu/baoyu-skills/blob/main/skills/baoyu-markdown-to-html/SKILL.md
Options:
A) Cancel - install the skill first
B) Continue - provide HTML file manually
Step 3: Convert Markdown to HTML
Skip if: Input is .html file
- Ask theme preference (unless specified in EXTEND.md or CLI):
| Theme | Description |
|---|---|
default |
ç»å ¸ä¸»é¢ – ä¼ ç»æçï¼æ é¢å± ä¸å¸¦åºè¾¹ï¼äºçº§æ é¢ç½åå½©åº |
grace |
ä¼é ä¸»é¢ – æåé´å½±ï¼åè§å¡çï¼ç²¾è´å¼ç¨å |
simple |
ç®æ´ä¸»é¢ – ç°ä»£æç®é£ï¼ä¸å¯¹ç§°åè§ï¼æ¸ ç½çç½ |
- Execute conversion (using the discovered skill):
npx -y bun ${MD_TO_HTML_SKILL_DIR}/scripts/main.ts <markdown_file> --theme <theme>
- Parse JSON output to get:
htmlPath,title,author,summary,contentImages
Step 4: Validate Metadata
Check extracted metadata from Step 3 (or HTML meta tags if direct 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)” |
Auto-Generation Logic:
- Title: First H1/H2 heading, or first sentence
- Summary: First paragraph, truncated to 120 characters
Step 5: Check and Prepare Cover Image
CRITICAL: WeChat Official Account requires a cover image for article (news) type posts.
Check for existing cover image sources (in priority order):
- CLI argument:
--cover <path> - Frontmatter fields:
featureImage,coverImage,cover,image - First image in HTML content (will be used if found)
If NO cover image found, use AskUserQuestion to prompt user with options:
Cover image required for WeChat article posting.
How would you like to provide a cover image?
Options to present:
| Option | Description |
|---|---|
| Generate based on article content (Recommended) | Auto-generate a cover image using ImageMagick with article title and theme colors |
| Provide image path | Specify a local file path or URL to an existing image |
| Use first image from content | Extract and use the first image found in the article (if available) |
| Cancel | Stop publishing to add cover image manually |
If user chooses “Generate based on article content”:
- Check ImageMagick installation:
which convert || which magick
- Choose generation method:
Method A: ImageMagick (Recommended if installed)
If ImageMagick IS installed, use it directly:
# Extract article title and generate cover
convert -size 900x500 \
-define gradient:angle=135 \
gradient:'#667eea'-'#764ba2' \
-gravity center \
-font "DejaVu-Sans-Bold" \
-pointsize 48 \
-fill white \
-annotate +0-30 '<Article Title Line 1>' \
-pointsize 36 \
-annotate +0+30 '<Article Title Line 2>' \
<output_directory>/<article-basename>-cover.jpg
Method B: Node.js Script (Fallback – No system dependencies required)
If ImageMagick is NOT installed, use the npx fallback script:
# Generate cover using Node.js (works anywhere, no sudo needed)
npx -y bun ${SKILL_DIR}/scripts/generate-cover.ts \
--title "<Article Title>" \
--output <output_directory>/<article-basename>-cover.jpg \
--gradient-start "#667eea" \
--gradient-end "#764ba2"
Fallback script features:
- â No system dependencies (ImageMagick) required
- â Works on any platform with Node.js/Bun
- â No sudo/admin privileges needed
- â Supports multiple image libraries (tries @napi-rs/canvas â sharp â SVG fallback)
- â Auto-wraps long titles
- â Customizable colors and dimensions
Library installation (optional, for better output):
# For PNG/JPEG output (choose one):
npm install @napi-rs/canvas # Recommended - native performance
# OR
npm install sharp # Alternative - pure Node.js
If neither library is installed, the script will generate an SVG file (which WeChat API also accepts).
- Extract article title from HTML/markdown
- Generate cover image using the chosen method:
# Example: Generate gradient background with title text
convert -size 900x500 \
-define gradient:angle=135 \
gradient:'#667eea'-'#764ba2' \
-gravity center \
-font "DejaVu-Sans-Bold" \
-pointsize 48 \
-fill white \
-annotate +0-30 '<Article Title Line 1>' \
-pointsize 36 \
-annotate +0+30 '<Article Title Line 2>' \
<output_directory>/cover-<slug>.jpg
- Save to same directory as the article with naming pattern:
<article-basename>-cover.jpg - Use this generated image as
--coverparameter
Image Requirements:
- Format: JPEG, PNG, GIF, or WebP
- Recommended size: 900x500px or 2:1 aspect ratio
- File size: < 2MB
Step 6: Select Publishing Method and Configure
Ask publishing method (unless specified in EXTEND.md or CLI):
| Method | Speed | Requirements |
|---|---|---|
api (Recommended) |
Fast | API credentials |
browser |
Slow | Chrome, login session |
If API Selected – Check Credentials:
# Check project-level
test -f .baoyu-skills/.env && grep -q "WECHAT_APP_ID" .baoyu-skills/.env && echo "project"
# Check user-level
test -f "$HOME/.baoyu-skills/.env" && grep -q "WECHAT_APP_ID" "$HOME/.baoyu-skills/.env" && echo "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=<user_input>
WECHAT_APP_SECRET=<user_input>
Step 6: Publish to WeChat
API method:
npx -y bun ${SKILL_DIR}/scripts/wechat-api.ts <html_file> [--title <title>] [--summary <summary>] [--inline-css]
CRITICAL: Style Preservation (API method):
- ALWAYS use
--inline-cssfor HTML files with styling (especially those with<style>tags) - WeChat Official Account does NOT support
<style>tags or external CSS - Without
--inline-css, all styles will be removed and the article will appear unstyled - The
--inline-cssflag converts CSS rules to inlinestyle="..."attributes - Recommended command for styled HTML:
npx -y bun ${SKILL_DIR}/scripts/wechat-api.ts <html_file> --cover <cover_image> --inline-css
Image Handling (API method):
- Automatically downloads remote images (HTTP/HTTPS URLs)
- Auto-cleans metadata for images containing AIGC/Coze markers (e.g.,
AIGC{...}) - Retries with forced cleaning if upload fails due to “unsupported file type” errors
- Supports formats: JPEG, PNG, GIF, WebP
Browser method:
npx -y bun ${SKILL_DIR}/scripts/wechat-article.ts --html <html_file>
Step 7: Completion Report
For API method, include draft management link:
WeChat Publishing Complete!
Input: [type] - [path]
Method: API
Theme: [theme name]
Article:
⢠Title: [title]
⢠Summary: [summary]
⢠Images: [N] inline images
Result:
â Draft saved to WeChat Official Account
⢠media_id: [media_id]
Next Steps:
â Manage drafts: https://mp.weixin.qq.com (ç»å½åè¿å
¥ãå
容管çãâãè稿箱ã)
Files created:
[⢠post-to-wechat/yyyy-MM-dd/slug.md (if plain text)]
[⢠slug.html (converted)]
For Browser method:
WeChat Publishing Complete!
Input: [type] - [path]
Method: Browser
Theme: [theme name]
Article:
⢠Title: [title]
⢠Summary: [summary]
⢠Images: [N] inline images
Result:
â Draft saved to WeChat Official Account
Files created:
[⢠post-to-wechat/yyyy-MM-dd/slug.md (if plain text)]
[⢠slug.html (converted)]
Detailed References
| Topic | Reference |
|---|---|
| Image-text parameters, auto-compression | references/image-text-posting.md |
| Article themes, image handling | references/article-posting.md |
Feature Comparison
| Feature | Image-Text | Article (API) | Article (Browser) |
|---|---|---|---|
| Plain text input | â | â | â |
| HTML input | â | â | â |
| Markdown input | Title/content | â (via skill) | â (via skill) |
| Multiple images | â (up to 9) | â (inline) | â (inline) |
| Auto-clean image metadata | â | â (AIGC/Coze) | N/A |
| CSS inline conversion | â | â (–inline-css) | Auto |
| Auto-generate cover | â | â (2 methods) | â |
| Cover generation methods | N/A | ImageMagick + Node.js | Manual |
| Themes | â | â | â |
| Auto-generate metadata | â | â | â |
| Requires Chrome | â | â | â |
| Requires API credentials | â | â | â |
| Requires system dependencies | â | â (npx fallback) | â |
| Speed | Medium | Fast | Slow |
Prerequisites
For API method:
- WeChat Official Account API credentials
- Guided setup in Step 5, or manually set in
.baoyu-skills/.env
For Browser method:
- Google Chrome
- First run: log in to WeChat Official Account (session preserved)
For Markdown conversion:
- A markdown-to-html skill (e.g.,
baoyu-markdown-to-html) - If not installed, the workflow will suggest installation
Config File Locations (priority order):
- Environment variables
<cwd>/.baoyu-skills/.env~/.baoyu-skills/.env
Troubleshooting
| Issue | Solution |
|---|---|
| No markdown-to-html skill | Install baoyu-markdown-to-html from suggested URL |
| Missing API credentials | Follow guided setup in Step 6 |
| Missing cover image | Use auto-generation (ImageMagick or npx fallback) or provide image path |
| Cover generation failed | Try npx fallback: npx -y bun ${SKILL_DIR}/scripts/generate-cover.ts --title "Title" --output cover.jpg |
| Styles lost in WeChat | Add --inline-css flag to preserve HTML styles |
| Access token error | Check if API credentials are valid and not expired |
| Access token error 40164 (invalid ip) | Add current server IP to WeChat Official Account whitelist: mp.weixin.qq.com â å¼å â åºæ¬é ç½® â IPç½åå |
| Not logged in (browser) | First run opens browser – scan QR to log in |
| Chrome not found | Set WECHAT_BROWSER_CHROME_PATH env var |
| Title/summary missing | Use auto-generation or provide manually |
| Paste fails | Check system clipboard permissions |
| Image upload 40113 (unsupported file type) | Auto-resolved: Script automatically cleans AIGC/Coze metadata. If persists, manually download and re-save image without metadata. |
Extension Support
Custom configurations via EXTEND.md. See Preferences section for paths and supported options.