当用户想写或发布微信公众号文章时使用——他们给出零散思路、草稿或笔记,请你润色、生成题图和解释图,或准备上传到 mp.weixin.qq.com。触发词:"写一篇微信文章"、"公众号"、"润色"、"题图"、"发公众号"、"/wjs-publishing-wechat"。
npx skills add https://github.com/jianshuo/claude-skills --skill wjs-publishing-wechat
帮用户写微信公众号文章。轻润色,不重写。 自动生成题图和解释图,一行命令推草稿。
写或润色每一篇文章前,先读同目录的 STYLE.md,并严格遵循。 那是王建硕本人维护的风格定义文件——语气 DNA、长度、加粗、排版、红线清单全在那里。本 SKILL.md 只管机制与工作流(脚本、配图、HTML 转换、发布)。
风格上 STYLE.md 与本文件冲突时,以 STYLE.md 为准。要调风格 = 改 STYLE.md,不在这里改、更不在草稿里改。
下面只保留机制相关的写作约束:
python3 -c "import re; t=open('article.md').read(); t=re.sub(r'\!\[.*?\]\(.*?\)','',t); print(len(re.findall(r'[一-鿿]',t)) + len(re.findall(r'[A-Za-z]+',t)))"
upload-draft.sh 把 ... 渲染成红色粗体(用法见 STYLE.md「加粗加红」)。upload-draft.sh 自动跑 scripts/pangu.py,Claude 不用手动加空格。 <section style="background:#f6f8fa;border-radius:6px;padding:14px 16px;overflow-x:auto;font-family:Menlo,Consolas,monospace;font-size:14px;line-height:1.8;color:#24292e;">npm install -g xxx<br>xxx run</section>
bash 块,脚本转成独立 <p><code>…</code></p>`。触发条件:这篇在介绍 / 推荐某个具体的 Claude Code skill。
前置 — 确认 skill 已发布:王建硕自己的 wjs-* skill 由 ~/.claude/skills-publish-hook.sh 自动 push 到 github.com/jianshuo/claude-skills,用 gh api repos/jianshuo/claude-skills/contents/<skill-name> 确认。别人的 skill 先确认在公开 git repo 里。
末尾附下面这段(<SKILL_NAME> 替换成实际名):
## 安装方法
不用复制命令。打开你用的 AI agent——Claude Code、Codex、Kimi Code、OpenClaw 都可以,对它说一句:
> 安装 https://github.com/jianshuo/claude-skills/blob/main/<SKILL_NAME>/SKILL.md
它会自己 fetch、放到 skill 目录里、提示你重启对话。
用 Hermes 的话直接命令行:
\`\`\`bash
hermes skills install https://github.com/jianshuo/claude-skills/blob/main/<SKILL_NAME>/SKILL.md
\`\`\`
装完之后,对 agent 说一句「<一句最自然的触发语,紧扣这个 skill 的入口>」,就能用。
规则:
github.com/<owner>/<repo>/blob/main/<path>——浏览器能直接看,LLM agent 也能从 blob URL 抽 markdown## 后注 则放后注之前输入形式:完整草稿 / 散乱思路 / 长段没分段 / 语音转写(可能有错字)。太散就问一个问题:"想写一篇文章,还是几个独立想法?"——只问这一次。
触发:润色完、文字即将定稿之前,每篇都过。逐句扫个人隐私信息——具体人名、餐厅 / 店铺 / 场所名、精确地点 / 住址、电话 / 邮箱 / 微信号等——这些不能进最终发布版,泛化替换或删除。判定边界、替换示例、城市级地名照留等细则见 STYLE.md「10. 隐私红线」。
命中的项并进交付改动清单(标「隐私」);一处都没有也说一句「隐私扫描:无」。拿不准的列出来问用户,不擅自删有意为之的细节。
给 3 个候选:A) 直白型;B) 故事型;C) 原文里最有味道的一句。不做标题党、夸张、"震惊"、"必看"。
勾住读者、激发点击——用「好奇缺口」:抛出文章里最反直觉 / 最有张力的那个点(结论、代价、转折、数字),但留一手,把答案留在正文,让人非点进来不可。仍是王建硕语气(具体、诚恳、话说一半的克制),钩子来自真东西不是形容词;绝不标题党、夸张、营销腔。不是第一段的复制。规则与例子见 STYLE.md「6. 标题与摘要」。
~/.claude/skills/wjs-publishing-wechat/scripts/gen-cover-ai.sh <article-folder> ["目标字词"]
~/.claude/skills/wjs-publishing-wechat/scripts/gen-illustration.sh <article-folder>
meta.json 取 title;建议挑核心概念字词(1–4 字)gpt-image-2-skill 的 --provider codex,需要 ~/.codex/auth.json解释图必须在 markdown 里被引用——article.md 要有 ! 一行,否则草稿里看不到。
⚠️ 正文里除 cover.png / illustration.png 外的图不会自动上 CDN。 用户给的本地截图(如 img-xxx.png)每张先 md2wechat upload_image img-xxx.png --json 拿 data.wechat_url,再替换 article.md 里的本地路径。验证:grep -c mmbiz content.html = 正文图片数,grep -c 'img-' content.html = 0。
默认插入位置:正文最后落点之后(有 ## 后注 放后注前;有 ## 安装方法 放安装方法前)。
绝不给解释图写引导语——不写「整件事画起来是这样」「如图所示」之类,图自己说话。详见 [[no-illustration-caption]]。
> 安全网:illustration.png 存在但 article.md 没引用时,upload-draft.sh 自动插入并改写,幂等。
在工作目录(默认 ~/wechat-publish/articles/)创建:
articles/2026-05-09-{slug}/
├── article.md # 润色后的 markdown
├── cover.png # 题图 900×383
├── illustration.png # 解释图
├── meta.json # { title, summary, author, date, slug }
└── original.md # 用户原始输入
{slug}:拼音首字母 + 关键词,30 字符内。
触发:文件包就绪、即将跑 upload-draft.sh 之前。这一步不可跳过、不能自作主张选——必须停下来,把标题选项发给用户、等用户回一个字母再继续。
给 4 个候选,排版成一目了然的列表:
meta.json 里现有的 title,原样列出(让用户知道「不改」长什么样)发完候选后说一句:「回 A 用原标题,或 B/C/D 选新的,也可以自己给一个。」然后停。
用户选定后:
python3 把 meta.json 的 title 改成选中的那条(cover.png 已生成,不必因标题变化重画题图,除非用户要求)upload-draft.sh)~/.claude/skills/wjs-publishing-wechat/scripts/upload-draft.sh <workspace>/articles/YYYY-MM-DD-{slug}
脚本做的事:
pangu.py 加盘古之白md2wechat upload_image cover.png → 拿 thumb_media_idillustration.png 存在但没引用时自动插入并 upload 拿 CDN URL(幂等安全网)build-recent-articles.py,默认开,见下节)article.md 生成 content.html(转换规则见下)draft.json,调 create_draft 或(publish.json 有 draft_media_id 时)draft/update 原地更新scripts/open-draft-edit.sh——读已登录浏览器的 session token、按标题查出 appmsgid、直达这一篇的编辑页(没登录则回退开首页);Linux 开 mp.weixin.qq.com 首页。WECHAT_PUBLISH_NO_OPEN=1 关掉git add / commit / push 文章目录到 origin每次发布,upload-draft.sh 会在文末自动挂一个最近已发布文章的链接列表(默认 5 篇),用微信编辑器原生的文章超链接格式(mp_article_text_link + data-linktype="2",同账号 /s/ 链接才点得动)。
机制 = 本地账本 + 离线渲染,发布步骤零网络、确定性、离线可跑:
publish.json 里的 permalink(https://mp.weixin.qq.com/s/…)+ published_at。build-recent-articles.py <article-folder> 扫同级 */publish.json 里有 permalink 的文章,按 published_at 倒序取最近 N 篇(排除本篇),在 article.md 的 <!--RECENT_ARTICLES_START/END--> 标记区内幂等重写一个 raw-HTML 块(content.html 构建器原样透传,微信忽略注释)。账本为空就不挂,从不报错、从不阻断发布。build-recent-articles.py <folder> --print(只打印不写);--count N 改数量。WECHAT_PUBLISH_NO_RECENT=1;改数量:WECHAT_RECENT_COUNT=8。账本怎么来 — backfill-permalinks.py(偶尔跑一次):permalink 只有文章正式发布后、从公众号后台才拿得到(草稿→发布是手动点的,不回流)。这个脚本调网页后台 appmsgpublish(已发布列表)拉全账号,按标题精确匹配把 permalink/published_at 写回各 publish.json。只精确匹配——发布标题常和 meta.title 不一样,模糊匹配会写错链接,对不上的会列出来留你手动处理。
~/.claude/skills/wjs-publishing-wechat/scripts/backfill-permalinks.py [articles根目录] [--dry-run]
鉴权走网页 session(不是发布 API 的 access_token),cookie 几小时过期,所以是「偶尔维护」不是每次发布都跑。三个值任选其一给:① 环境变量 WECHAT_MP_COOKIE / WECHAT_MP_TOKEN / WECHAT_MP_FAKEID;② 会话文件(默认 ~/.config/wjs-wechat/mp-session.env,里面 export 同名三个变量)。抓法:登录 mp.weixin.qq.com → 内容管理 → 已发布 → DevTools Network 找 appmsgpublish 请求 → Copy as cURL,token/fakeid 在 URL 里,Cookie 在请求头。
> upload-draft.sh 发布时若检测到上述凭据/会话文件,会先尽力刷新账本再注入(非致命,过期就跳过);没配就直接用现有本地账本。配好会话文件后,发布即「自动回填 + 自动挂最近文章」一步到位。
article.md 写作约束(影响 Claude 怎么写;其他 HTML 细节脚本自理):
<p> / <h2> / <h3> / <img> / <strong> / <em> / <code> / <ul> / <ol> / <li> / pipe table< 开头的块原样输出,整段必须是一个块,内部不能有空行<br> 分行(用于排比 / 并列短句):硬规则:行尾绝不能是逗号「,」,分行边界只能落在句末标点(。?!)之后环境变量:
WECHAT_PUBLISH_FORCE_NEW=1 — 强制建新草稿(不复用 draft_media_id)WECHAT_PUBLISH_NO_OPEN=1 — 不自动打开浏览器WECHAT_PUBLISH_NO_PUSH=1 — 不自动 pushWECHAT_PUBLISH_NO_RECENT=1 — 不注入文末「最近文章」列表WECHAT_RECENT_COUNT=N — 「最近文章」列出几篇(默认 5)WECHAT_MP_COOKIE / WECHAT_MP_TOKEN / WECHAT_MP_FAKEID 或 WECHAT_MP_SESSION(会话文件路径,默认 ~/.config/wjs-wechat/mp-session.env)— 配上则发布时自动刷新 permalink 账本前置依赖:
md2wechat CLI 装好且 WECHAT_APPID + WECHAT_SECRET 配好(md2wechat config show)errcode=40164常见 errcode:40164 IP 不在白名单 | 45004 summary 为空 / 太短 | 40007 老 draft_media_id 被删(脚本自动 fallback 建新)。
成功后到草稿箱 → 手机预览 → 发布。
全部移到 STYLE.md——错字模式、分段规则、红线清单、交付前先给改动清单,都在那里。润色前读 STYLE.md,按它执行。
依赖外部 skill:gpt-image-2-skill(cover/illustration 生成)+ /md2wechat(upload + draft)。
articles/YYYY-MM-DD-{slug}/ 文件夹存在Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. When Claude needs to work with professional documents (.docx files) for: (1) Creating new documents, (2) Modifying or editing content, (3) Working with tracked changes, (4) Adding comments, or any other document tasks
Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.
Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.
Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text/tables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting/decrypting PDFs, extracting images, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill.
Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files). Triggers include: any mention of 'Word doc', 'word document', '.docx', or requests to produce professional documents with formatting like tables of contents, headings, page numbers, or letterheads. Also use when extracting or reorganizing content from .docx files, inserting or replacing images in documents, performing find-and-replace in Word files, working with tracked changes or comments, or converting content into a polished Word document. If the user asks for a 'report', 'memo', 'letter', 'template', or similar deliverable as a Word or .docx file, use this skill. Do NOT use for PDFs, spreadsheets, Google Docs, or general coding tasks unrelated to document generation.
Use this skill any time a .pptx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx file (even if the extracted content will be used elsewhere, like in an email or summary); editing, modifying, or updating existing presentations; combining or splitting slide files; working with templates, layouts, speaker notes, or comments. Trigger whenever the user mentions \"deck,\" \"slides,\" \"presentation,\" or references a .pptx filename, regardless of what they plan to do with the content afterward. If a .pptx file needs to be opened, created, or touched, use this skill.
Create and edit Obsidian Flavored Markdown with wikilinks, embeds, callouts, properties, and other Obsidian-specific syntax. Use when working with .md files in Obsidian, or when the user mentions wikilinks, callouts, frontmatter, tags, embeds, or Obsidian notes.
Take jianshuo/wjs-publishing-wechat from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference npm.
Without those the skill loads but fails at the first command.