name: wxmp-draft description: End-to-end pipeline to turn a Markdown research report into a WeChat Official Account (公众号) rich-graphics article, upload images, and save as a Draft (草稿) via WeChat APIs. Never publishes. compatibility: opencode metadata: language: zh-CN output: wxmp-draft safety: no-publish license: MIT
What This Skill Does
Turn a .md research report into a WeChat Official Account rich article and save it as a Draft:
- Rewrite into a WeChat-friendly narrative (70% hardcore tech, 30% sharp metaphors; precise, entrepreneurial).
- Produce image plan + image captions.
- (Optional) Generate a cover image and “data card” images locally.
- Call WeChat APIs to:
- get
access_token - upload cover as permanent material and obtain
thumb_media_id - upload in-article images and obtain URLs
- create draft via
draft/add
- get
Hard rule: DO NOT publish / mass-send. Only draft.
Key Behavior (Per H2 Images + Typography)
- One web-sourced image per H2: with
--auto-web-images, the script searches Wikimedia Commons, downloads a suitable image, uploads to WeChat viauploadimg, then inserts it right after each H2 section heading. - No captions under images: inserted images are
<img>only (no visible attribution/caption text). - Attribution kept in metadata: source/license is stored in cache JSON (not rendered in the article).
- WeChat-stable formatting: headings are rendered as
<p style=...>blocks (not relying on<h1>/<h2>/<h3>), so Markdown hierarchy is obvious in the WeChat editor. - Tech heading styles: Chapter (章) headings use a dark "terminal" panel style; section (节, like 2.1) headings use a light "blueprint" card style; tertiary headings remain minimal.
- Title behavior (from-markdown): WeChat draft title is auto-shortened to ~10 tokens (LLM) while the body keeps the full original Markdown H1 (including bold emphasis).
- No auto subtitle injection (from-markdown): digest is used for WeChat
digestfield only; it is not inserted under the H1 to avoid duplicating the first paragraph. - Tables (default): Markdown tables are kept as real HTML
<table>and restyled with WeChat-safe inline CSS for mobile readability. - Tables (legacy image mode): use
--table-mode imageto convert Markdown tables into{{IMG:table-*}}placeholders (optionally render/upload as images with--gen-images).
Inputs
- Markdown file path (required)
- Example:
/Users/wangweiyang/Downloads/游戏运维监控工具推荐.md
- Example:
- WeChat config file path (required for live run)
- Default:
~/Downloads/wxmpdev.config - Format supported:
- env style:
APPID=...APPSECRET=...AUTHOR=...(optional)ACCESS_TOKEN=...(optional; temporary token override)PROXY=http://user:pass@host:port(optional; route traffic via whitelisted egress)HTTPS_PROXY=.../HTTP_PROXY=...(optional)
- JSON style:
{ "appid": "...", "appsecret": "...", "author": "...", "access_token": "..." }
- env style:
- Default:
Safety Rules (Non-negotiable)
- Never log or print secrets:
AppSecret,access_token, request bodies containing tokens.
- Do not call publish endpoints:
- No
/cgi-bin/freepublish/* - No
/cgi-bin/message/mass/*
- No
- WeChat constraints:
- In-article images must be uploaded via
media/uploadimgand use returned URL. - Cover must use permanent material
media_idasthumb_media_id(commonly uploaded viamaterial/add_material).
- In-article images must be uploaded via
Operational Notes (WeChat IP Whitelist)
If your Official Account has IP whitelist enabled, WeChat will reject cgi-bin/token with errcode=40164.
Two ways to proceed:
- Add this machine's public egress IP to the WeChat IP whitelist.
- Use
ACCESS_TOKEN=...in config (obtain the token from a whitelisted environment).
You can print best-effort public IP via:
wxmp-draft --draft-only --print-egress-ip
Expected Output
- A local result JSON (includes the created
draft_media_idon success) - A local manifest/cache for idempotency (avoid duplicate uploads/drafts)
- A readable
out/last_render.htmlfor human inspection
Recommended Execution
1) Draft the article content (LLM rewrite)
Read the input Markdown and produce a structured article spec (JSON) with:
title(<= 32 chars)digest(<= 128 chars)author(<= 16 chars, optional)content_html(WeChat-safe HTML)images: list of assets to upload- cover asset:
{ "id": "cover", "kind": "cover", "path": "...", "alt": "...", "caption": "..." } - inline assets:
{ "id": "table-1", "kind": "inline", "path": "...", "alt": "...", "caption": "..." }
- cover asset:
In content_html, reference inline assets using placeholders:
{{IMG:table-1}}
The uploader will replace placeholders with WeChat-hosted image URLs.
2) Run the uploader (draft-only)
Use the helper script:
wxmp-draft \
--input "/Users/wangweiyang/Downloads/游戏运维监控工具推荐.md" \
--config "~/Downloads/wxmpdev.config" \
--mode from-markdown \
--table-mode html \
--gen-images \
--auto-web-images \
--web-image-source auto \
--image-query-mode llm \
--draft-get-verify \
--draft-only
Notes:
- To preserve deep-research content, prefer
--mode from-markdownand use--image-query-mode llmto let the model generate better image queries only. --mode llmrewrites the article body; avoid it if you want the Markdown content kept verbatim.--gen-imagesgenerates a cover image and renders any remaining non-table placeholders (e.g. diagrams/checklists) into image cards.- For table images specifically, you must use
--table-mode image. --inline-cover(optional) inserts the cover image into the body; default is off to keep the strict "one image per H2" rule.
Test Command (No Publish)
After config exists, verify the end-to-end draft save:
wxmp-draft \
--input "/Users/wangweiyang/Downloads/游戏运维监控工具推荐.md" \
--config "~/Downloads/wxmpdev.config" \
--mode from-markdown \
--gen-images \
--auto-web-images \
--draft-get-verify \
--draft-only
This must print a final line containing: Draft created: media_id=....