---
name: baoyu-post-to-wechat
description: 通过 API 或 Chrome CDP 向微信公众号(Official Account)发布内容。支持文章(HTML/Markdown/纯文本)与多图图文(贴图,原“图文”)推送。Markdown 文章工作流默认将普通外链转换为文末引用,以优化微信端展示。触发词包括“发布公众号”、“post to wechat”、“微信公众号”、“贴图/图文/文章”。
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-post-to-wechat
requires:
anyBins:
- bun
- npx
---
# 微信公众号内容发布指引
## 语言
**与用户语言保持一致**:用户用中文回复中文,用户用英文则回复英文。
## 脚本目录
**Agent 执行目录**:该 SKILL.md 所在目录即 `{baseDir}`,脚本调用 `{baseDir}/scripts/<name>.ts`。`${BUN_X}` 运行时逻辑:如有 `bun`,则用 `bun`;若有 `npx`,则用 `npx -y bun`;二者都无则建议安装 bun。
| 脚本 | 用途 |
|------|------|
| `scripts/wechat-browser.ts` | 图文(贴图)发布 |
| `scripts/wechat-article.ts` | 浏览器自动化文章发布 |
| `scripts/wechat-api.ts` | API 方式文章发布 |
| `scripts/md-to-wechat.ts` | Markdown 转微信格式 HTML 与图片占位 |
| `scripts/check-permissions.ts` | 检查运行环境与权限 |
## 偏好(EXTEND.md)
优先级顺序查找 EXTEND.md:
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-post-to-wechat/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-post-to-wechat/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-post-to-wechat/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-post-to-wechat/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md") { "user" }
```
┌────────────────────────────────────────────────────────┬────────────────────┐
│ 路径 │ 位置 │
├────────────────────────────────────────────────────────┼────────────────────┤
│ .baoyu-skills/baoyu-post-to-wechat/EXTEND.md │ 项目目录 │
├────────────────────────────────────────────────────────┼────────────────────┤
│ $HOME/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md │ 用户主目录 │
└────────────────────────────────────────────────────────┴────────────────────┘
┌───────────┬────────────────────────────────────────────────────────────────────────┐
│ 检查结果 │ 操作 │
├───────────┼────────────────────────────────────────────────────────────────────────┤
│ 已找到 │ 读取、解析并应用设置 │
├───────────┼────────────────────────────────────────────────────────────────────────┤
│ 未找到 │ 执行首次配置(见 [references/config/first-time-setup.md](references/config/first-time-setup.md))→保存→继续 │
└───────────┴────────────────────────────────────────────────────────────────────────┘
**EXTEND.md 配置支持**:默认主题/颜色、默认发布方式(api/browser)、默认作者、开放评论、仅粉丝可评论、Chrome 配置目录
首次设置文档:[references/config/first-time-setup.md](references/config/first-time-setup.md)
**最小支持键名**(不区分大小写,支持 `1/0` 或 `true/false`):
| 键名 | 默认值 | 对应字段 |
|---------------------|----------|---------------------------------------------------|
| `default_author` | 空 | CLI/Frontmatter 未设置作者时的兜底 |
| `need_open_comment` | `1` | `articles[].need_open_comment`(草稿接口) |
| `only_fans_can_comment` | `0` | `articles[].only_fans_can_comment`(草稿接口) |
**推荐 EXTEND.md 示例**:
```md
default_theme: default
default_color: blue
default_publish_method: api
default_author: 宝玉
need_open_comment: 1
only_fans_can_comment: 0
chrome_profile_path: /path/to/chrome/profile
```
**主题选项**:default, grace, simple, modern
**颜色预设**:blue, green, vermilion, yellow, purple, sky, rose, olive, black, gray, pink, red, orange(或 hex)
**值优先级**:
1. 命令行参数
2. Frontmatter
3. EXTEND.md(账号级 → 全局级)
4. 固定默认值
## 多账号支持
EXTEND.md 支持管理多个公众号账号。包含 `accounts:` 区块时,每账号独立凭据、Chrome 配置及默认值。
**兼容规则**:
| 条件 | 模式 | 行为描述 |
|-----------------------------|----------------|-----------------------------|
| 没有 `accounts` 区块 | 单账号 | 保持现有行为 |
| `accounts` 仅 1 个 | 单账号 | 自动选择,无需提示 |
| `accounts`>1 | 多账号 | 需发布前让用户选择账号 |
| 有 `default: true` | 多账号 | 代表默认账号,可切换 |
**多账号 EXTEND.md 示例**:
```md
default_theme: default
default_color: blue
accounts:
- name: 宝玉的技术分享
alias: baoyu
default: true
default_publish_method: api
default_author: 宝玉
need_open_comment: 1
only_fans_can_comment: 0
app_id: your_wechat_app_id
app_secret: your_wechat_app_secret
- name: AI工具集
alias: ai-tools
default_publish_method: browser
default_author: AI工具集
need_open_comment: 1
only_fans_can_comment: 0
```
**账号级支持键**(可账号设置或全局兜底):
`default_publish_method`, `default_author`, `need_open_comment`, `only_fans_can_comment`, `app_id`, `app_secret`, `chrome_profile_path`
**仅全局键**:
`default_theme`, `default_color`
### 账号选择逻辑(Step 0.5)
插入主工作流 Step 0 与 Step 1 之间:
```
if 未定义 accounts 区块:
→ 单账号模式(与当前一致)
elif accounts 数量为1:
→ 自动选取
elif 命令行 --account <alias>:
→ 匹配选择指定账号
elif 有 default: true 账号:
→ 默认选该账号,显示 "使用账号: <name> (--account 可切换)"
else:
→ 询问用户:
"检测到多个公众号账号:
1) <name1> (<alias1>)
2) <name2> (<alias2>)
请选择账号 [1-N]:"
```
### 凭据查找(API 方式)
选定 alias `{alias}` 的账号后,依次查找凭据:
1. EXTEND.md 账号区块 `app_id`、`app_secret`
2. 环境变量 `WECHAT_{ALIAS}_APP_ID` / `WECHAT_{ALIAS}_APP_SECRET`
3. `.baoyu-skills/.env` 中带前缀项
4. `~/.baoyu-skills/.env` 中带前缀项
5. 兜底为无前缀的 `WECHAT_APP_ID` / `WECHAT_APP_SECRET`
**.env 多账号示例**:
```bash
# baoyu 账号
WECHAT_BAOYU_APP_ID=your_wechat_app_id
WECHAT_BAOYU_APP_SECRET=your_wechat_app_secret
# ai-tools 账号
WECHAT_AI_TOOLS_APP_ID=your_ai_tools_wechat_app_id
WECHAT_AI_TOOLS_APP_SECRET=your_ai_tools_wechat_app_secret
```
### Chrome 配置(浏览器方式)
每个账号单独 Chrome profile,登录状态独立:
| 来源 | 路径 |
|------------------------|----------------------------------------|
| EXTEND.md 账号里配置 | 按指定路径 |
| 自动基于 alias 生成 | `{shared_profile_parent}/wechat-{alias}/` |
| 单账号兜底 | 用默认共享 profile(现有行为) |
### CLI --account 参数
所有发布脚本支持 `--account <alias>`:
```bash
${BUN_X} {baseDir}/scripts/wechat-api.ts <file> --theme default --account ai-tools
${BUN_X} {baseDir}/scripts/wechat-article.ts --markdown <file> --theme default --account baoyu
${BUN_X} {baseDir}/scripts/wechat-browser.ts --markdown <file> --images ./photos/ --account baoyu
```
## 环境预检查(可选)
首次前建议先运行环境检查,可略过。
```bash
${BUN_X} {baseDir}/scripts/check-permissions.ts
```
检查项:Chrome、profile 隔离、Bun、辅助功能、剪贴板、粘贴按键、API 凭据、Chrome 冲突等。
**如有不通过,单项给出修复建议**:
| 检查项 | 修复办法 |
|----------------|--------------------------------------------------------|
| Chrome | 安装 Chrome 或设置 `WECHAT_BROWSER_CHROME_PATH` 环境变量 |
| Profile 目录 | 用共享 profile:`baoyu-skills/chrome-profile`(参见 CLAUDE.md) |
| Bun 运行时 | `brew install oven-sh/bun/bun`(mac)或 `npm install -g bun` |
| macOS 辅助功能 | 系统设置-隐私与安全-辅助功能-启用终端 |
| 剪贴板拷贝 | 保证 Swift/AppKit 可用(mac 建议装 Xcode CLI 工具) |
| 粘贴快捷键(Mac)| 同辅助功能修复 |
| 粘贴快捷键(Linux)| 装 `xdotool`(X11)或 `ydotool`(Wayland) |
| API 凭据 | 按向导或手动配置 `.baoyu-skills/.env` |
## 图文(贴图)发布
适合最多 9 张图片的短内容:
```bash
${BUN_X} {baseDir}/scripts/wechat-browser.ts --markdown article.md --images ./images/
${BUN_X} {baseDir}/scripts/wechat-browser.ts --title "标题" --content "内容" --image img.png --submit
```
详见:[references/image-text-posting.md](references/image-text-posting.md)
## 文章发布工作流
将以下检查清单复制,每个环节打勾:
```
发布进度:
- [ ] Step 0: 加载偏好 (EXTEND.md)
- [ ] Step 0.5: 账号选择(多账号时)
- [ ] Step 1: 检测输入类型
- [ ] Step 2: 选择发布模式并配置凭据
- [ ] Step 3: 主题/颜色/元数据校验
- [ ] Step 4: 向公众号发布
- [ ] Step 5: 汇报完成
```
### Step 0: 加载偏好
读取 EXTEND.md(如上文)。
**重要**:未检测到时,必须先执行首次配置,再进行其他操作。
解析后存储下列默认值:
- `default_theme`(默认为 `default`)
- `default_color`(如没设置则省略,按主题默认色)
- `default_author`
- `need_open_comment`(默认为 `1`)
- `only_fans_can_comment`(默认为 `0`)
### Step 1: 检测输入类型
| 输入类型 | 检测逻辑 | 后续操作 |
|-------------|--------------------------------|------------------------|
| HTML 文件 | 路径以 `.html` 结尾,文件存在 | 跳到 Step 3 |
| Markdown 文件 | 路径以 `.md` 结尾,文件存在 | 进入 Step 2 |
| 纯文本 | 不是路径或找不到文件 | 另存为 markdown,进 Step 2 |
**纯文本逻辑**:
1. 根据内容前2~4个有效词自动生成 slug(kebab-case)
2. 创建目录并保存内容:
```bash
mkdir -p "$(pwd)/post-to-wechat/$(date +%Y-%m-%d)"
# 内容保存:post-to-wechat/yyyy-MM-dd/[slug].md
```
3. 剩下流程按 Markdown 处理
**Slug 示例**:
- "Understanding AI Models" → `understanding-ai-models`
- "人工智能的未来" → `ai-future`(slug 英文翻译)
### Step 2: 选择发布方式及凭据
**主动询问发布方式**(如 EXTEND.md/CLI 已指定则直接用):
| 方式 | 速度 | 要求 |
|-----------|------|----------------|
| `api`(推荐) | 快 | 需 API 凭据 |
| `browser` | 慢 | 需 Chrome 已登陆 |
**API 方式检查凭据**:
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/.env && grep -q "WECHAT_APP_ID" .baoyu-skills/.env && echo "project"
test -f "$HOME/.baoyu-skills/.env" && grep -q "WECHAT_APP_ID" "$HOME/.baoyu-skills/.env" && echo "user"
```
```powershell
# PowerShell (Windows)
if ((Test-Path .baoyu-skills/.env) -and (Select-String -Quiet -Pattern "WECHAT_APP_ID" .baoyu-skills/.env)) { "project" }
if ((Test-Path "$HOME/.baoyu-skills/.env") -and (Select-String -Quiet -Pattern "WECHAT_APP_ID" "$HOME/.baoyu-skills/.env")) { "user" }
```
**凭据未配置时引导**:
```
未检测到 WeChat API 凭据。
获取方法:
1. 访问 https://mp.weixin.qq.com
2.进入:开发→基本配置
3. 复制 AppID 与 AppSecret
保存位置?
A) 项目级:.baoyu-skills/.env(仅本项目)
B) 用户级:~/.baoyu-skills/.env(全局)
```
选择后提示并写入 `.env`:
```
WECHAT_APP_ID=<用户输入>
WECHAT_APP_SECRET=<用户输入>
```
### Step 3: 主题/颜色/元数据校验
1. **主题解析优先级**(找到即用,不再询问):
- CLI 参数 `--theme`
- EXTEND.md 里 `default_theme`
- 兜底:`default`
2. **颜色解析优先级**(找到即用,没设置则不带 color 参数):
- CLI 参数 `--color`
- EXTEND.md 里 `default_color`
- 没有则按主题默认
3. **元数据校验**(markdown frontmatter 或 HTML meta):
| 字段 | 缺失时处理 |
|--------|-------------------------|
| Title | 提示:"输入标题,回车自动从内容生成" |
| Summary| 提示:"输入摘要,回车自动生成(推荐,有利SEO)" |
| Author | 兜底顺序:CLI `--author` → frontmatter → EXTEND.md 设置 |
**自动生成逻辑**:
- **标题**:首个 H1/H2 标题,或首句文本
- **摘要**:首段文本,截断为 120 字
4. **封面校验**(API 方式必需):
1. CLI `--cover` 优先
2. frontmatter(coverImage/featureImage/cover/image)
3. 文章目录 `imgs/cover.png`
4. 内容首图
5. 仍无则中止并要求用户提供封面
### Step 4: 发布到公众号
**重要**:脚本会自动处理 markdown 转 html。不要预先自行转好 html,直接传原始 markdown 即可。API 方式渲染图片 <img> 便于上传,浏览器方式带占位符交互。
**Markdown 默认外链引用**:
- Markdown 加工为文末引用,除非用户指定 `--no-cite`
- 传 html 输入不改动链接引用
**API 方式用法**(支持 .md/.html):
```bash
${BUN_X} {baseDir}/scripts/wechat-api.ts <file> --theme <theme> [--color <color>] [--title <title>] [--summary <summary>] [--author <author>] [--cover <cover_path>] [--no-cite]
```
**重要**:始终带 `--theme` 参数,哪怕用 default。不需 color 时可省略(默认色)。
**`draft/add` 请求体规则**:
- POST https://api.weixin.qq.com/cgi-bin/draft/add?access_token=ACCESS_TOKEN
- `article_type`: news(默认)或 newspic
- news 类型需封面 thumb_media_id
- 始终提交:
- `need_open_comment`
- `only_fans_can_comment`
- `author` 路径:CLI `--author` → frontmatter → EXTEND.md
如脚本参数缺评论开关,也要确保 API body 最终带入。
**浏览器方式用法**(支持 --markdown/--html):
```bash
${BUN_X} {baseDir}/scripts/wechat-article.ts --markdown <markdown_file> --theme <theme> [--color <color>] [--no-cite]
${BUN_X} {baseDir}/scripts/wechat-article.ts --html <html_file>
```
### Step 5: 完成报告
**API 方式**包含草稿管理链接:
```
发布成功!
输入类型:[type] - [path]
方式:API
主题:[theme name] [如有 color]
文章信息:
• 标题:[title]
• 摘要:[summary]
• 图片数:[N]
• 评论:[开/关],[仅粉丝/所有人]
结果:
✓ 草稿已存入公众号后台
• media_id: [media_id]
后续可操作:
→ 草稿管理:https://mp.weixin.qq.com (登录后点“内容管理→草稿箱”)
如有新建文件:
[• post-to-wechat/yyyy-MM-dd/slug.md(纯文本情况)]
[• slug.html(转换后)]
```
**浏览器方式报告**:
```
发布成功!
输入类型:[type] - [path]
方式:浏览器
主题:[theme name] [如有 color]
文章信息:
• 标题:[title]
• 摘要:[summary]
• 图片数:[N]
结果:
✓ 草稿已保存到公众号后台
如有新建文件:
[• post-to-wechat/yyyy-MM-dd/slug.md(纯文本情况)]
[• slug.html(转换后)]
```
## 详细参考
| 主题 | 参考文档 |
|---------------------|---------------------------------------------------|
| 图文参数/图片压缩 | [references/image-text-posting.md](references/image-text-posting.md) |
| 文章主题/图片处理 | [references/article-posting.md](references/article-posting.md) |
## 功能对比
| 功能 | 图文 | 文章(API) | 文章(浏览器) |
|-----------------------------|--------|-----------|--------------|
| 纯文本输入 | ✗ | ✓ | ✓ |
| HTML 输入 | ✗ | ✓ | ✓ |
| Markdown 输入 | 仅标题/正文 | ✓ | ✓ |
| 多图 | ✓(最多9张) | ✓(内嵌) | ✓(内嵌) |
| 主题 | ✗ | ✓ | ✓ |
| 自动补全元数据 | ✗ | ✓ | ✓ |
| 封面自动兜底(imgs/cover.png)| ✗ | ✓ | ✗ |
| 评论控制(need_open_comment, only_fans_can_comment)| ✗ | ✓ | ✗ |
| 需 Chrome | ✓ | ✗ | ✓ |
| 需 API 凭据 | ✗ | ✓ | ✗ |
| 速度 | 中等 | 快 | 慢 |
## 先决条件
**API 方式**:
- 公众号 API 凭据
- Step 2 向导或手动配置 `.baoyu-skills/.env`
**浏览器方式**:
- Chrome 浏览器
- 首次需扫码登录公众号后台(session 会保留)
**配置文件查找策略(优先级高到低)**:
1. 环境变量
2. `<cwd>/.baoyu-skills/.env`
3. `~/.baoyu-skills/.env`
## 故障排查
| 问题 | 处理办法 |
|------------------|-------------------------------------------|
| 缺少 API 凭据 | 按 Step 2 指南或手动设置 .env |
| access_token 报错| 检查 API 信息有效且未过期 |
| 浏览器模式未登录 | 首次会自动打开发码窗口扫码 |
| 未检测 Chrome | 配置 WECHAT_BROWSER_CHROME_PATH 环境变量 |
| 标题/摘要缺失 | 用自动生成或手动补充 |
| 缺少封面 | frontmatter 指定或 imgs/cover.png 放文章目录 |
| 评论默认值不对 | 检查 EXTEND.md 的 need_open_comment/only_fans_can_comment|
| 粘贴失败 | 检查剪贴板权限 |
## 拓展自定义
可通过 EXTEND.md 自定义配置。见上文偏好(Preferences)部分。