Skip to content
Writing
Skill

/ray-wechat

把定稿长文排成手机友好的公众号富文本并生成预览;Ray 明确同意后写入或更新公众号草稿箱并回读核对。用于“公众号排版”“推到公众号草稿箱”“更新微信草稿”。含糊说法先只做预览;不发布、不群发。

BOOST
From plugin
rayskills
3088 skills
Install
$ npx -y skills add imraywang/rayskills --skill ray-wechat --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/ray-wechat

Context preview

The summary Claude sees to decide when to auto-load this skill.

把定稿长文排成手机友好的公众号富文本并生成预览;Ray 明确同意后写入或更新公众号草稿箱并回读核对。用于“公众号排版”“推到公众号草稿箱”“更新微信草稿”。含糊说法先只做预览;不发布、不群发。

SKILL.md

ray-wechat.SKILL.md
name: ray-wechat
description: 把定稿长文排成手机友好的公众号富文本并生成预览;Ray 明确同意后写入或更新公众号草稿箱并回读核对。用于“公众号排版”“推到公众号草稿箱”“更新微信草稿”。含糊说法先只做预览;不发布、不群发。

Ray WeChat

把公众号交付拆成两个门:先确认本地排版,再修改线上草稿。排版完成不等于草稿已保存;接口返回成功也不等于中文、封面和正文正确。

固定边界

1. 只接收已经通过 `ray-writer` 检查的定稿。知识库中的 `content-pack` 是写作任务说明,不是正文;事实、判断或文章结构仍在变化时先退回写作阶段。 2. 封面来自 `ray-cover`。公众号封面与 X Article 封面分别使用,不拉伸代替。 3. 没有用户在当前任务中明确说“保存到/更新微信草稿箱”时,只生成本地 HTML 和预览,不调用微信写接口。 4. 文章已有 `wechat_draft_media_id` 时只更新原草稿;没有 ID 才允许创建,并必须显式使用创建确认参数。 5. 默认不生成作者签名、二维码或“点赞在看转发”尾注。原文自带时按原文保留;用户要求去掉时整块删除。 6. 只保存草稿,不调用 `freepublish/*`、群发或任何发布接口;读取已发表文章也是另一个只读任务,不能混入草稿写入流程。 7. 不在日志、命令参数或报错中输出 AppSecret、access token 或图片服务密钥。 8. `kind: translation` 或 `kind: repost` 的译介稿多一道授权门:`source_permission` 不是 `granted` 或 `open-license` 时只做本地产物,不写后台。写入后也不勾选原创声明——公众号的转载声明需要原作者在后台加白名单,那是用户动作。 9. 所有公众号接口默认经过 `~/.wewrite/fixed-egress.json` 中声明的固定出口。固定出口不可用、出口地址不符或配置缺失时立即停止,不静默改用本机动态地址;只有用户明确要求直连时才临时设置 `RAY_WECHAT_DIRECT=1`。网络路径不改变草稿写入授权。

0. 先判定授权

开始前根据用户当前这轮原话选择唯一一级。这张表和判定规则与 `ray` 主入口、`ray-x-article` 完全一致,不在本 Skill 里另作解释:

| 级别 | 可以做什么 | 判定依据 | |---|---|---| | `local_only` | 只做本地产物:排版、手机预览、交付包,不碰任何线上后台 | 用户只说“先看看”“给我预览”“准备交付包”,或整句没有指名平台落点 | | `draft_write` | 创建或更新平台草稿,并完整回读验收 | 本轮原话同时出现**具体平台**和**落点**,例如“保存到微信草稿箱”“更新原来的公众号草稿” | | 公开发布 | 不属于内容生产管线 | 这套判定永远不产生它;必须另开明确的发布任务 |

判定规则三条:

1. **只指名平台、动词模糊**——“推送到微信”“同步到两个平台”“上架后台”——不直接升为 `draft_write`。先把本地产物做完,然后用一句话问清楚:“本地已经好了,要现在写进公众号草稿箱吗?”得到肯定答复再写。既不擅自写,也不做完就不吭声。 2. **完全没指名平台落点**——“过稿 OK”“进入下一阶段”“走完整发布流程”——一律 `local_only`,不问也不写。 3. **用户明确说“发布”“群发”“公开”**——仍然只做到草稿,并说明公开发布超出本 Skill 边界,不调用发布接口。

过去任务的许可、X 平台的许可、已有 media ID、白名单已经修好,都不构成本轮授权。不确定一律降到 `local_only`。

1. 读取当前状态

读取文章 Markdown、排版 HTML、公众号封面和 frontmatter。至少确认:

  • `title`
  • `wechat_draft_media_id`(若存在)
  • `wechat_draft_cover` 或本地公众号封面
  • `wechat_draft_theme`
  • 用户本轮是“看预览”还是已经授权“推送到草稿箱”
  • 用户当前原话能否明确判定为 `draft_write`
  • `publish_exclude_sections`(若存在):列出的章节(如 `待确认`)在生成预览和草稿时自动剔除,母稿不改。正文带「待确认」而用户本轮没说已经看过时,推送前用一句话提醒一次

先核对源文件角色。`kind: content-pack`、`kind: idea` 或 `kind: research` 必须停止,沿 frontmatter 中的 `draft` 链接找到正文;不要因为文件名写着“成稿包”就把任务说明当成最终文章。

`kind: translation` 或 `kind: repost` 是译介稿,正文属于原作者。除了本轮授权判定,还要读 `source_permission`:只有 `granted` 和 `open-license` 能进后台,`pending` 停在本地并告诉用户缺的是原作者许可,不是脚本问题。契约见 `ray-writer/references/translation.md`。

文章没有兼容知识库时仍可在当前工作区交付,但不要自行创建固定名称的 vault。需要长期回流时先转交 `ray-obsidian`。

2. 生成排版与预览

先读 [layout-contract.md](references/layout-contract.md) 和 [theme-library.md](references/theme-library.md)。默认使用三套自有主风格,根据文章的主要阅读动作选择:

  • `ray-judgment`(Ray 判断):观点、争议判断、力量感和行动号召。
  • `ray-method`(Ray 方法):教程、步骤、工具盘点和行动指南。
  • `ray-deepread`(Ray 深读):科技评论、专业分析和长篇解释。

用户仍在探索时只给最契合的一套推荐和一个备选,确认后再排。用户明确要求第三方主题时才调用已经安装的外部排版 Skill;`gzh-design` 可以作为外部排版器使用,但不得把它的 AGPL 组件代码复制进本仓库。

默认使用自有渲染器生成干净正文与手机预览:

python3 scripts/render_article.py \
  --article <文章.md> \
  --theme <ray-judgment|ray-method|ray-deepread> \
  --html <公众号正文.html> \
  --preview <手机预览.html>

排版必须做到:

  • 标题由公众号后台承担,正文 HTML 从全局 `<section>` 开始。
  • 长文有明确章节和扫读重点,默认不新增卡片、标签、装饰性英文或金句容器。
  • Markdown 每段只留一个空行;HTML 中不存在空 `<p>`。
  • 原文加粗完整保留,不主动把每段关键词做成下划线。
  • 不拆开 Instagram、YouTube 等英文词做下划线或高亮。
  • 署名策略与用户要求一致,不留下占位符。

生成带复制按钮的本地预览。实际以手机宽度打开,检查首屏、目录、章节、长英文、结尾和横向溢出。用户确认风格之前不进入下一步。

3. 本地交付门

运行:

python3 scripts/prepare_article.py \
  --article <文章.md> \
  --html <公众号正文.html> \
  --signature absent \
  --out <交付清单.json>

`--signature` 使用 `absent`、`present` 或 `inherit`。任何 ERROR 都要修复并重跑;不要绕过原文遗漏、空段落、章节数量、英文拆词或署名检查。

渲染器故意在 `<img src>` 里留下本地绝对路径,本地预览才能真的看到图。因此正文带图时,这一步必然报 `images are not uploaded yet`:

  • `local_only` 到此为止。这条 ERROR 是预期结果,也是唯一允许留下的 ERROR,不要为了让状态变绿去手工改 HTML。
  • `draft_write` 继续走 3.1,上传完成后重跑本门,必须 `status: ready` 才进入第 4 步。

译介稿还会验证授权与署名。`source_permission` 未放行、正文里找不到原作者或原文链接,都是硬 ERROR,只能回 `ray-writer` 补,不在 HTML 里手工加一行了事。出处链接写成 Markdown 超链接时会留下一条提醒:URL 只在 `href` 里,公众号正文的外链多数账号点不开,建议改成纯文本。

3.1 上传正文图片(仅 `draft_write`)

先干跑,确认待传清单与正文引用一一对应、文件都在磁盘上:

python3 scripts/wechat_images.py --html <公众号正文.html> --dry-run

确认后正式上传,脚本会就地把本地路径换成 `mmbiz.qpic.cn` 永久链接:

python3 scripts/wechat_images.py \
  --html <公众号正文.html> \
  --config ~/.wewrite/config.yaml
  • 走 `media/uploadimg`,返回正文永久链接,不占素材库配额,也不产生任何发布动作。
  • 按文件内容 sha256 缓存在 `~/.wewrite/image-cache.json`,重排或改主题后重跑不会重复上传。
  • 超过 1MB 或非 jpg/png 的图会先转成不超过 1600px 的 JPEG 副本再上传,源文件不动。
  • 有任何一张图不在磁盘上,脚本在上传开始前就整体失败,不会传一半。

4. 创建或更新草稿

先读 [wechat-api.md](references/wechat-api.md) 和 [recovery-runbook.md](references/recovery-runbook.md)。凭证优先从 `WECHAT_APPID`、`WECHAT_SECRET` 读取,也可以使用已有的 `~/.wewrite/config.yaml`。不要把密钥拼进可见命令。

公众号图片上传、封面上传、草稿读写和回读默认都经过 `~/.wewrite/fixed-egress.json` 中确认过的固定出口。脚本会在取得 token 前先核对公网地址;地址不符或隧道不可用时原地停止,不会静默切回家宽。若微信仍报 `40164`,按恢复手册的「IP 白名单」核对固定地址是否仍在后台白名单,再从同一步重试。不得绕过 `prepare_article.py`、`wechat_images.py`、`wechat_draft.py` 或完整回读,更不得改用 `freepublish/*` 做查重、验证或发布。

更新已有草稿:

python3 scripts/wechat_draft.py update \
  --article <文章.md> \
  --html <公众号正文.html> \
  --config ~/.wewrite/config.yaml \
  --theme <主题标识> \
  --signature absent \
  --record \
  --confirm

没有草稿 ID 且用户明确同意创建时:

python3 scripts/wechat_draft.py create \
  --article <文章.md> \
  --html <公众号正文.html> \
  --cover <公众号封面.png> \
  --digest "文章摘要" \
  --config ~/.wewrite/config.yaml \
  --theme <主题标识> \
  --signature absent \
  --record \
  --confirm

`update` 必须先读取原草稿,保留作者、封面和评论设置;文章 frontmatter 的正确标题优先于后台旧标题。`create` 必须有封面和摘要。两个动作都必须在写入后再次读取草稿并验收,只有验收通过才允许 `--record` 回写本地状态。

只回读核对、不写入时用 `python3 scripts/wechat_draft.py verify --article <文章.md> --html <公众号正文.html> --config ~/.wewrite/config.yaml`(读 frontmatter 里的 media ID,只读)。

5. 最终验收

以下条件同时满足才算完成:

  • 更新的是原 media ID,或明确创建后得到一个新 ID;没有重复草稿。
  • 标题、摘要、作者和封面符合预期。
  • 原文所有章节和段落按原顺序存在,首句与末句可找到。
  • 空段落为零;章节数、重点样式数与本地交付清单相符。
  • 署名策略生效,没有占位符。
  • 中文没有乱码,英文专名没有被拆开。
  • frontmatter 只在远端回读通过后更新为 `wechat_draft_status: draft`。
  • 没有调用发布接口。
  • 本地记录使用准确字段 `wechat_draft_status: draft`,不写近似字段。

遇到网络、白名单、凭证、编码或回读不一致时,不宣称成功。按恢复手册修复同一草稿并重新验收。

真机复核

回读通过只证明内容进对了草稿,不证明它在微信里长得对。本地预览用的是浏览器渲染,微信会给未显式声明的属性注入自己的默认样

Read more
Ships withrayskills

8 个从真实业务中沉淀的 AI Skill:默认替你判断下一步,也能把稳定流程连续跑完。 rayskills 是一套给 Claude Code、Codex 等 AI Agent 使用的 builder 工具箱。它不是一堆“应该怎么想”的提示词,而是把真实工作中反复出现、容易犯错的流程,收敛成可以直接执行、可以验证、可以恢复的 Skill。 不用先记住 8 个名字。把处境交给 /ray: 下一步还不稳定时,它只选择此刻最该做的一步。 终点已经明确、阶段之间有正式交接时,它连续执行整条管线。

Get the whole plugin

Other skills on rayskills.

ray-cover
Skill

ray-cover

给定稿的文章或视频做带中文标题的封面:文章封面(公众号 2.33:1、X 16:9、X Article 5:2)用 Punk 风格库(MIT 版);视频封面(默认只出 3:4、默认小Lin风A;要时出 9:16 竖屏和 16:9 横屏)用 Ray 真人照片…

ray-explainer
Skill

ray-explainer

把文章或观点做成知识解说视频(默认竖屏,要求时出横屏;1.5–3 分钟,用 Ray 的复刻音色配音 + 字幕):真实画面优先(录屏、实拍、截图),近几期主要走 HyperFrames…

ray-kb
Skill

ray-kb

把灵感、观察或长文写成 Ray 能直接开机录的中文口播稿(Ray 口吻、观点说满,存疑处列进「待确认」);也审读口播稿,或对照录制稿学习 Ray…

ray-obsidian
Skill

ray-obsidian

新建、检查或适配面向内容生产的 Obsidian 知识库结构(资料、知识、选题、写作、发布、回流)。用于“搭一个 Obsidian 知识库”“把 vault 接入内容管线”“检查知识库结构”,或 ray-writer…

ray-writer
Skill

ray-writer

把灵感、剪藏、调研或草稿写成有 Ray 态度的中文长文(公众号 / X 长文),接入知识库的成稿与发布流程;也做带授权署名的译介稿。用于“写成文章”“写一篇公众号或 X 长文”“重写这篇”“翻译转载”。改口播转 ray-kb;不发布。

ray-x-article
Skill

ray-x-article

把完成的长文和 5:2 封面写进已登录的 X Articles 后台存为草稿,核对预览并把草稿地址回写知识库。用于“放进 X 后台”“存为 X Article 草稿”“推送到 X”。只存草稿:不点 Publish,不重复建同题草稿。