Back to skills
SKILL.md
Wechat Publisher
ASecurity公众号文章发布工具。当用户说"存到公众号"、"发布到公众号"、"发到草稿箱"、"推到公众号"、"写到公众号"时触发。配合 kakarot-writer skill 使用:先用 kakarot-writer 风格生成 markdown 文章 → 用 wechat-publisher CLI 格式化并存入微信草稿箱。也支持纯 markdown 文件直接发布。 触发词:存到公众号、发布到公众号、发到草稿箱、推到公众号、写到公众号、发公众号、wechat publish 不触发情况:纯写作不涉及发布、不需要存草稿箱的情况。
- 2 stars
- 0 votes
- 0 copies
- 3 views
- Added September 22, 2026
Works with
Security analysis
96/100- Installs packages at runtime which could introduce malicious dependencies
Pro scans all 20 files and shows the line behind each finding
npx -y skills add Zhangs-11/zs-skills --skill wechat-publisher --agent claude-codeAre you the author of Wechat Publisher?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/zhangs-11-wechat-publisher)---
name: wechat-publisher
description: |
公众号文章发布工具。当用户说"存到公众号"、"发布到公众号"、"发到草稿箱"、"推到公众号"、"写到公众号"时触发。配合 kakarot-writer skill 使用:先用 kakarot-writer 风格生成 markdown 文章 → 用 wechat-publisher CLI 格式化并存入微信草稿箱。也支持纯 markdown 文件直接发布。
触发词:存到公众号、发布到公众号、发到草稿箱、推到公众号、写到公众号、发公众号、wechat publish
不触发情况:纯写作不涉及发布、不需要存草稿箱的情况。
---
# 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 包
```bash
cd tools/wechat-publisher
python3 -m venv venv
venv/bin/pip install -e .
```
### 2. 创建配置文件
在 `~/.wechat-publisher/.env` 中写入:
```bash
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` 命令找不到,用全路径:
```bash
# 或建立软链接
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` 已交付正文图片、截图和封面,直接复用,不重新生成或覆盖。仍缺少素材时才保留下列占位标记:
```markdown
[插图:图片内容描述]
[绘图提示:可复制的英文 prompt,适合 Midjourney / DALL-E / 即梦 等生图工具]
```
例:
```markdown
[插图:传统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` 的交付清单补齐;封面优先调用 `guizang-social-card-skill` 的真实素材 B 方案。只有专用 Skill 不可用、且文章仍缺少必要图片时,才使用本 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` 负向词,进一步压制文字渲染。
**密钥只放在运行环境中,不写入仓库或文章文件。**
```bash
export SILICONFLOW_API_KEY="用户提供的 SiliconFlow API Key"
export WECHAT_PUBLISHER_SKILL_DIR="${WECHAT_PUBLISHER_SKILL_DIR:-$HOME/.codex/skills/wechat-publisher}"
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 图片;没有占位符时,自动在正文段落后插入配图,例如 ``。
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 格式化全部使用同一份公开正文。
外链默认逐一做只读可达性检查,`404` 等失效链接会阻止上传。只有网络环境暂时不可用、且已经用其他方式逐个核验链接时,才能临时传 `--skip-link-check`;它不是常规发布选项。
```bash
# 检查当前公网 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 — 创建草稿
```bash
# 从文件
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 — 更新现有草稿
```bash
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)。只改正文/标题时也不能省。
### upload-image — 上传正文图片(返回 CDN URL)
```bash
wechat-publisher upload-image photo.jpg
# → SUCCESS: Image uploaded → http://mmbiz.qpic.cn/...
```
### upload-cover — 上传封面图(返回 media_id)
```bash
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` 样式后仍能从外层继承清晰文字颜色。
## 常见错误
| 错误 | 原因 | 处理 |
|------|------|------|
| 40164 | IP 不在白名单 | 获取当前 IP,让用户添加白名单 |
| 40007 invalid media_id | 封面 media_id 无效或为空 | 上传封面图获取正确的 media_id |
| 40001 | token 过期或无效 | 会自动刷新,持久失败检查 appsecret 是否正确 |
| 45009 | 接口频率超限 | 会自动重试 |
## 发布前失败保护
- 如果缺少封面,命令会失败并提示配置 `WECHAT_DEFAULT_COVER_MEDIA_ID`、传 `--cover-media-id`,或传 `--cover-file`。
- 如果正文仍包含 `[插图:...]` / `[绘图提示:...]`,命令会失败,防止半成品进入草稿箱。
- 如果遇到 40164,命令会提示去微信后台添加当前公网 IP 白名单。
Files in this skill
- .gitignore
- LICENSE
- README.md
- SKILL.md
- scripts/generate_wechat_images.py
- tests/test_generate_images_script.py
- tools/wechat-publisher/.env.example
- tools/wechat-publisher/.gitignore
- tools/wechat-publisher/pyproject.toml
- tools/wechat-publisher/tests/test_assets.py
- tools/wechat-publisher/tests/test_cli_helpers.py
- tools/wechat-publisher/tests/test_client.py
- tools/wechat-publisher/tests/test_formatter.py
- tools/wechat-publisher/tests/test_linkcheck.py
- tools/wechat-publisher/tests/test_publication.py
- tools/wechat-publisher/tests/test_secure_download.py
- tools/wechat-publisher/tests/test_token.py
- tools/wechat-publisher/wechat_publisher/__init__.py
- tools/wechat-publisher/wechat_publisher/cli.py
- tools/wechat-publisher/wechat_publisher/client.py
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.