agentleFS
Zhangs-11Zhangs-11/zs-skills/wechat-publisher/SKILL.md

wechat-publisher

Skill2 starsChanged 3 months agoMITView on GitHub

将文章存入公众号草稿时用。不用于纯写作、个人微信消息或无需上传的本地排版。

  • Reads credentials
  • Installs packages

11 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Files
SKILL.md

wechat-publisher 公众号发布工具

作者在「卡卡罗特学AI」公众号写文章,写完后需要一键存到微信草稿箱,不用手动复制粘贴。

架构概览

kakarot-writer skill 生成 markdown 文章
       │
       ▼
复用 writer 已交付的正文图 + 21:9 封面
       │(素材缺失时才补图)
       ▼
guizang-social-card-skill 或 scripts/generate_wechat_images.py
       │
       ▼
wechat-publisher create --title "xxx" --content-file xxx.md --cover-file images/<文章名>/cover.jpg
       │
       ├─ formatter.py  →  Markdown → 微信兼容 HTML
       ├─ token.py      →  access_token 缓存管理
       ├─ client.py     →  微信 API HTTP 调用
       └─ 微信服务器     →  草稿箱 +1

安装

仅首次安装时执行。如果用户已经装过,跳过这一步。

1. 安装 Python 包

cd tools/wechat-publisher
python3 -m venv venv
venv/bin/pip install -e .

系统 Python 缺少 ensurepip、python3 -m venv 报错时,改用 uv 创建环境(uv 建的环境不带 pip,安装也用 uv):

uv venv --python 3.12 venv
uv pip install --python venv/bin/python -e .

2. 创建配置文件

在 ~/.wechat-publisher/.env 中写入:

WECHAT_APP_ID=wx你的AppID
WECHAT_APP_SECRET=你的AppSecret
WECHAT_AUTHOR=卡卡罗特学AI
WECHAT_DEFAULT_COVER_MEDIA_ID=你的封面media_id

注意: 密钥在用户本地 ~/.wechat-publisher/.env,不在仓库里。WECHAT_DEFAULT_COVER_MEDIA_ID 先用 wechat-publisher upload-cover 上传一张封面图获取 media_id 再填入。

3. 添加 PATH

如果 wechat-publisher 命令找不到,用全路径:

# 或建立软链接
ln -sf $(pwd)/tools/wechat-publisher/venv/bin/wechat-publisher ~/.local/bin/wechat-publisher

4. IP 白名单

微信 API 要求调用方的公网 IP 在公众号后台白名单中。如果遇到 40164 错误,告诉用户当前 IP 并让用户去 mp.weixin.qq.com → 开发 → 基本配置 → IP 白名单 添加。

工作流

当用户说"写一篇 XX 文章存到公众号"时,必须按以下步骤执行:

第一步:写作

调用 kakarot-writer skill 生成 markdown 文章。

标题、事实边界、文章主线和口语风格以 kakarot-writer 的完整规则为准。发布 skill 不再重复发明另一套写作规则,避免两个 skill 互相冲突。

发布前编辑检查

进入配图前,确认文章已经完成 kakarot-writer 的自检,尤其检查:

  • 标题承诺能被正文证据兑现,没有暗示不存在的实测或独家经历。
  • 没有把推测写成亲历;数据、发布日期、榜单和引用没有未说明的事实缺口。
  • 前三段已经建立事件、阅读理由或作者关系,全文围绕同一条主线推进。
  • 口语来自真实语境,没有为了模仿作者批量堆叠口癖和夸张标点。

如果存在事实缺口,先向用户确认或收窄断言,不要带着问题进入发布流程。

如果 kakarot-writer 已交付正文图片、截图和封面,直接复用,不重新生成或覆盖。仍缺少素材时才保留下列占位标记:

[插图:图片内容描述]
[绘图提示:可复制的英文 prompt,适合 Midjourney / DALL-E / 即梦 等生图工具]

例:

[插图:传统RAG工作流程图]
[绘图提示:A clean technical diagram showing the classic RAG pipeline, flat design with blue and white color scheme, modern minimalist style.]

这告诉用户两个信息:哪里需要配图、用什么 prompt 生成图片。

绘图提示的写法(重要):

  • 有创意,用视觉比喻概括语义,不要把正文文字照搬进去。prompt 描述的是「一个画面/场景」,不是「这段话写了啥」。
  • 纯英文。中文一旦进 prompt,生图模型 Z-Image-Turbo 会把中文直接画到图上,且常带错别字。
  • 画面里不要出现任何文字(prompt 末尾脚本会自动追加强力的「无文字」约束 + negative_prompt,你自己写的时候也别要求图上有字)。
  • 例(解释「海量上下文被收束成清晰的推理」):A vast turbulent cloud of glowing particles funneling through a sleek device into one calm focused beam of blue light, flat editorial illustration, blue palette, no text

第二步:保存

将文章保存到 ~/公众号草稿/ 目录。

第三步:检查并补齐图片

先检查文章中引用的本地图片是否存在,并确认已有 21:9 主封面。只要 kakarot-writer 已完成真实截图、正文图和封面,就跳过生图脚本,避免把已经确认的素材替换成概念图。

素材不完整时,优先回到 kakarot-writer 的交付清单补齐,封面工具顺序按 kakarot-writer/references/delivery.md 的「封面」一节执行。只有那里的工具都不可用、且文章仍缺少必要图片时,才使用本 Skill 自带的 SiliconFlow 回退脚本,默认模型是 Tongyi-MAI/Z-Image-Turbo。

如果文章包含 [插图:...] / [绘图提示:...],脚本会按这些 prompt 生成对应正文图(优先走这条,因为 prompt 是你手写的、有创意)。如果文章没有占位符,脚本会按正文段落自动插入 3 张配图,并生成封面图——auto 兜底通道会先用对话模型(deepseek-ai/DeepSeek-V3)把中文段落转成英文视觉概念再生图,绝不把中文塞进画面,从根上避免图上出现原文和错别字。封面也走概念化(不再把标题原文塞进 prompt,并去掉「杂志封面」这类诱导加标题字的措辞,缩写如 AI/GPT 也会被剔除)。封面对文字最敏感,要最稳就手动传 --cover-prompt "英文创意概念"。

图片目录:每篇文章的图存在以文件名命名的独立子目录 images/<文章名>/ 下(封面 cover.jpg、正文 01-image.jpg…),多篇之间不会再互相覆盖。

所有生图 prompt 末尾都会自动叠加统一创作方向(视觉比喻、蓝色调、画面零文字)+ negative_prompt 负向词,进一步压制文字渲染。

密钥只放在运行环境中,不写入仓库或文章文件。

export SILICONFLOW_API_KEY="用户提供的 SiliconFlow API Key"
# 填本 Skill 的实际安装目录,例如 ~/.claude/skills/wechat-publisher 或 ~/.codex/skills/wechat-publisher
export WECHAT_PUBLISHER_SKILL_DIR="<本 Skill 的实际安装目录>"
export WECHAT_PUBLISHER_PYTHON="$WECHAT_PUBLISHER_SKILL_DIR/tools/wechat-publisher/venv/bin/python"
export WECHAT_PUBLISHER_BIN="$WECHAT_PUBLISHER_SKILL_DIR/tools/wechat-publisher/venv/bin/wechat-publisher"

"$WECHAT_PUBLISHER_PYTHON" "$WECHAT_PUBLISHER_SKILL_DIR/scripts/generate_wechat_images.py" \
  --article ~/公众号草稿/文件名.md \
  --title "文章标题" \
  --auto-insert 3

脚本会:

  1. 调用 https://api.siliconflow.cn/v1/images/generations 生成图片。
  2. 立即下载图片到 ~/公众号草稿/images/<文章名>/,不要只保存临时 URL。
  3. 把正文占位符替换成真实 Markdown 图片;没有占位符时,自动在正文段落后插入配图,例如 ![配图1](images/<文章名>/01-image.jpg)。
  4. 生成封面图 images/<文章名>/cover.jpg。

硬性检查: 继续发布前,文章中的所有图片路径都必须存在,所有占位符都已替换,并且有可用封面文件或 cover_media_id。只有实际执行回退脚本时,才要求命令输出至少一个 IMAGE: ... 和一个 COVER: ...。否则停止并报告缺失项。

第四步:对抗式事实审查(强制,不可跳过)

发布到草稿箱之前,必须自动跑一轮对抗式审查:

  1. 派 2 个独立审查 agent(带 WebSearch/WebFetch),立场设定为「假定作者写错/编造,逐条推翻」:一个专攻数字/榜单/价格/时间,一个专攻引语/人物身份/定性表述
  2. 审查结论与原始调研冲突时,必须亲自去一手来源(官方原文)定案,不采信任何单一 agent
  3. 绝对化表述(「没法刷」「史上最X」「全球第一」)要么有一手来源,要么加「有分析说」「据官方说法」限定
  4. 全部修正后才进入发布步骤,发布后把审查结果汇报给用户(❌抓出的错误 / ⚠️措辞修正 / ✅确认无误清单)

第五步:预检并尝试发布

wechat-publisher 会自动上传正文 Markdown 图片到微信 CDN。封面图用 --cover-file 上传成微信永久素材,再用返回的 media_id 创建草稿。已经是 mmbiz.qpic.cn 的图片不会重复上传。

发布前,CLI 会先执行统一的内容契约:移除开头 YAML frontmatter,只消费 <!-- kakarot:delivery-appendix --> 之前的公开正文,并拒绝正文里的一级标题、未隔离的截图清单/封面方案/备选标题/事实确认项。标题只通过 --title 传入,因此不会在正文中重复。摘要提取、图片上传、外链检查和 HTML 格式化全部使用同一份公开正文。

要读者复制的网址写成「标签:」一行、完整网址单独一行,CLI 会把这一行渲染成独立网址块;不要给标签再套 Markdown 链接,否则底部参考资料会重复同一个地址。

外链默认逐一做只读可达性检查,404 等失效链接会阻止上传。只有网络环境暂时不可用、且已经用其他方式逐个核验链接时,才能临时传 --skip-link-check;它不是常规发布选项。

# 检查当前公网 IP
curl -s ip.sb

# 只读预检,不上传图片、不创建草稿
"$WECHAT_PUBLISHER_BIN" preflight \
  --title "文章标题" \
  --content-file ~/公众号草稿/文件名.md \
  --cover-file ~/公众号草稿/images/<文章名>/cover.jpg

# 尝试发布
"$WECHAT_PUBLISHER_BIN" create \
  --title "文章标题" \
  --content-file ~/公众号草稿/文件名.md \
  --cover-file ~/公众号草稿/images/<文章名>/cover.jpg \
  --digest "120字以内摘要"

第六步:结果处理

成功 → 告知用户 SUCCESS: Draft created (media_id=xxx)

失败(40164 IP白名单) → 告诉用户当前IP,让用户去微信后台添加白名单,然后重新运行发布命令

失败(其他错误) → 根据错误信息处理

读取超时 → 创建或更新结果未知。先检查公众号草稿箱,不要立刻重复执行,以免生成重复草稿。

命令参考

create — 创建草稿

# 从文件
wechat-publisher create --title "标题" --content-file article.md

# 自动上传封面文件
wechat-publisher create --title "标题" --content-file article.md --cover-file images/<文章名>/cover.jpg

# 从管道
cat article.md | wechat-publisher create --title "标题"

update — 更新现有草稿

wechat-publisher update --media-id "xxx" --title "新标题" --content-file article.md --cover-file images/<文章名>/cover.jpg

⚠️ 必须每次都带 --cover-file 或 --cover-media-id,否则封面会被重置为默认封面(WECHAT_DEFAULT_COVER_MEDIA_ID)。只改正文/标题时也不能省。

更新前先读回后台版本。 作者可能已经在公众号后台手改过草稿,直接 update 会用本地母稿整篇覆盖这些修改。每次 update 前先执行:

wechat-publisher get --media-id "xxx" --out draft-current.html

它把后台当前的 HTML 存到 draft-current.html,把一块一行的可读文本存到 draft-current.txt。拿这份文本和本地母稿逐段比对,把作者在后台的修改先合进母稿,再 update。比对时忽略小标题前的图标、引用开头的 💡 和参考资料编号,这些是格式化时加的。

update 会重新提交封面,作者在后台调过的封面裁剪位置会恢复默认。更新后告诉作者需要重新检查封面裁剪。

upload-image — 上传正文图片(返回 CDN URL)

wechat-publisher upload-image photo.jpg
# → SUCCESS: Image uploaded → http://mmbiz.qpic.cn/...

upload-cover — 上传封面图(返回 media_id)

wechat-publisher upload-cover cover.jpg
# → SUCCESS: Cover uploaded (media_id=xxx)

样式机制

formatter.py 自动将 markdown 转为微信内联样式 HTML:

元素效果
正文段落16px, 深灰, 行距 1.85
===高亮===蓝色渐变底强调
==注意小句==仅把字变成主题蓝(无底色、不加粗),标关键句用,代替加粗
> 引用💡 蓝色竖线卡片
## 二级标题左竖线小标题:蓝色左竖线 + 同色蓝字 + 加粗,字号与正文一致(前置图标,标题没带 emoji 会自动补 🔹)
### 三级标题同款,竖线略细
---· · · 分隔符
`代码`浅灰底圆角代码
代码块浅灰底、深色字、蓝色左边框的高对比代码块
**加粗**700 字重深色
*斜体*斜体
表格微信兼容表格样式
外链正文标注序号,底部生成参考资料

内容质检规则

高流量 AI 公众号文章发布前要做以下检查:

  1. 标题有具体对象、反常识或真实体验,不使用空泛震惊体。
  2. 前三行必须交代“发生了什么”和“为什么值得读”。
  3. 只强调真正决定读者理解的关键判断,避免按固定段数机械加粗;跨平台母稿优先使用通用的 **加粗**,不主动加入平台私有语法。
  4. 配图必须服务理解,且图里不要出现任何文字(生图模型画中文会出错别字)。优先用视觉比喻/概念图传达意思,绘图提示用纯英文手写、有创意,不要把正文照搬进 prompt。
  5. 一手来源标为 POC、Preview、beta、experimental 或 RC 的能力保留成熟度限定;事实、官方说法和作者推断分层表达。
  6. 官方仓库与文档的具体链接必须通过预检实际打开;不能只凭记忆猜默认分支是 main 或 master。
  7. 发布前检查格式化后的代码块、表格和强调块:外层容器与内部文字元素都要明确设置高对比颜色。代码块优先浅底深字,确保微信清除内部 code 样式后仍能从外层继承清晰文字颜色。

常见错误

错误原因处理
40164IP 不在白名单获取当前 IP,让用户添加白名单
40007 invalid media_id封面 media_id 无效或为空上传封面图获取正确的 media_id
40001token 过期或无效会自动刷新,持久失败检查 appsecret 是否正确
45009接口频率超限会自动重试

发布前失败保护

  • 如果缺少封面,命令会失败并提示配置 WECHAT_DEFAULT_COVER_MEDIA_ID、传 --cover-media-id,或传 --cover-file。
  • 如果正文仍包含 [插图:...] / [绘图提示:...],命令会失败,防止半成品进入草稿箱。
  • 如果遇到 40164,命令会提示去微信后台添加当前公网 IP 白名单。

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.