# Soia Media Publish X Thread

> 将成文草稿改写为带编号、符合字数限制的 X thread，并可按授权存草稿。触发：「发成 X thread」「拆成推文串」「thread 这篇」

- Skill: `soia-team/soia-media-publish-x-thread` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add soia-team/soia-media-publish-x-thread`
- Raw SKILL.md: https://api.skillmd.com/api/skills/soia-team/soia-media-publish-x-thread/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: soia-team (https://skillmd.com/u/soia-team)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/soia-team/soia-media-publish-x-thread

---


# soia-media-publish-x-thread

把 `compose` 产出的成文草稿改写成适合 X 的 thread。默认在回复中交付 Markdown 文本，供客户人工复制发布；本 skill 不调用 X API、不自动发送、不修改原稿。

## 客户可读说明

### 这个技能可以做什么

读取客户提供的成文草稿，保留核心观点和必要证据，重组为有连续阅读节奏的 X thread：首条负责让人继续读，中间条目各自完成一个逻辑动作，末条给出自然的 CTA。

| 客户想要 | 技能会做 | 客户能看到 |
|---|---|---|
| 把文章发成 X thread | 提取主线、拆分论证、编号并控制每条长度 | 一组可复制的 Markdown 推文条目 |
| 草稿含代码、命令或链接 | 保持代码与 URL 原样，必要时调整周边文字 | 未被截断的代码/链接，以及无法安全拆分处的明确提示 |
| 需要发布到 X | 只生成发布文本 | “产出文本、人工发布”；不会调用 X API 或发送任何内容 |

### 客户如何使用

其他可识别说法包括「发条 X」「发个推」；若目标是 X Articles 长文草稿，转交 `soia-media-publish-x-article`。

1. 说明“发成 X thread”“拆成推文串”或“thread 这篇”，并提供成文草稿、文件内容或路径。
2. 如有要求，一并说明目标读者、口吻、是否保留标题、CTA 方向和需要保留的代码/链接。
3. Agent 先确认输入范围与主线，再输出 thread；默认不覆盖原稿，客户指定路径时才另存。
4. 客户人工复制每条并发布到 X；发布顺序按编号执行。

### 依赖与安装

安装（推荐：装整个领域插件，一次装好本仓全部技能）：

```bash
claude plugin marketplace add soia-team/soia-open-skills
```

```bash
claude plugin install soia-media-content@soia
```

只要这一个技能时，可用 npx 路线。注意技能会落进共享真源 `~/.agents/skills`；若同时装了插件，同一技能会出现两份索引且各自漂移，建议二选一：

```bash
npx skills add soia-team/soia-open-media-content-skills -g -a '*' -s soia-media-publish-x-thread -y
```

- 本技能是纯 LLM 改写流程，无 scripts、无私有配置、无 API key 和无外部服务依赖。
- `soia-media-compose-article-draft` 是常见上游产物，但不是安装级强依赖；也可以直接提供任意成文草稿。
- 当前不接 X API。任何“发布”都只表示生成文本，人工发布由客户完成。

**WorkBuddy** 的装载单位是角色化专家而不是插件，`npx skills add -a '*'` 覆盖不到它，需要单独安装，见 [docs/install/workbuddy.md](https://github.com/soia-team/soia-open-skills/blob/main/docs/install/workbuddy.md)。

### 日志与完成回执

每次执行都要回报实际处理范围、条目数量和人工发布边界，不把“已生成”说成“已发布”。最低格式：

```markdown
完成：已将 <输入范围> 改写为 <N> 条 X thread 文本，未调用 X API。

日志摘要：
- started: <输入来源、目标口吻与约束>
- processed: <条目数量；长度检查结果>
- created/updated: <回复文本或客户指定的输出位置>
- skipped/failed: <未处理内容及原因；没有则写“无”>

验证：
- <每条 ≤280 字符、编号连续、代码/链接完整性核对结果>

问题与下一步：
- 请人工按 (1/N) 顺序复制发布；<其它问题，没有则写“无”>
```

## 拆条规则

### 1. 先确定主线

- 用一句话写出这篇文章要让读者记住的核心判断；thread 的每条都必须服务于这条主线。
- 保留会改变结论的证据、例子、限定条件和来源；删除重复铺垫、无关支线和无法核验的夸张表述。
- 若原稿有多个同等重要的主题，先询问客户选择主线；低风险时可选择最能代表原稿的主线，并在回执中说明。

### 2. 组织连续阅读

- 首条写清主题与冲突/收益，用具体事实、反常识判断或问题制造继续阅读的理由；不要只复述标题。
- 中间条目一条只承担一个动作：提出问题、给出判断、解释原因、展示例子、补充限制或落到方法。
- 每条即使脱离上下文也要基本可懂；用自然的承接词维持 thread 的推进感，避免把文章段落机械切碎。
- 末条收束核心判断，并给出与文章内容匹配的 CTA（例如回复经历、收藏方法、继续讨论）；不制造虚假的紧迫感。

### 3. 长度与完整性

- 每条包含 `(1/N)`、`(2/N)` 等编号，`N` 使用最终条目总数；编号连续且不漏条。
- 每条正文不超过 280 字符，按 X 的实际字符计数方式核对；编号、空格和标点也计入长度预算。
- 不在代码块中间断条，不改写命令、变量名、JSON、正则、文件路径或 URL；代码和链接过长时，拆分周边解释或明确提示客户需手动处理。
- 不为了塞进长度上限而删掉否定词、单位、限定条件、来源或关键标点；无法同时满足长度和完整性时，先报告冲突并请求取舍。
- 保留原稿事实，不新增未经输入支持的数字、案例、引用或结论。

## 输出格式

默认输出为 Markdown 列表，每条一个段落：

```markdown
- (1/N) <首条抓钩子与主题>
- (2/N) <一个完整的论证动作>
- …
- (N/N) <核心收束 + CTA>
```

列表之外可附一行“长度检查：通过/需人工复核”和必要的取舍说明。不要把条目伪装成已发布链接，不要输出 API 调用结果。客户未指定落盘位置时，只产出回复文本；指定位置时再写入独立草稿文件，绝不覆盖源文件。

## 浏览器直填模式（可选）

客户说「填进 X」「存到 X 草稿」「直接发」时启用。**主路线是自带的 Playwright 脚本，宿主无关**——在 Claude Code、Codex、Gemini CLI、opencode 等任何能跑 Python 的宿主中行为一致；不依赖任何宿主专属浏览器工具。普通短帖不需要 Premium 订阅。

### 主路线：scripts/x_post.py（宿主无关）

依赖（一次性）：`pip install playwright && python -m playwright install chromium`。

```bash
python3 scripts/x_post.py login                  # 首次：弹窗人工登录，登录态存本地 profile
python3 scripts/x_post.py status                 # 检查登录态
python3 scripts/x_post.py draft "(1/2) …" "(2/2) …"   # 填入并保存草稿（默认档）
python3 scripts/x_post.py send "文案" --yes      # 发布档：仅在授权条件满足时传 --yes
```

- 脚本优先用**系统已装的真 Chrome**（channel=chrome，界面与日常 Chrome 一致；未装则回退自带 Chromium）。
- **为什么仍需登录一次**：Chrome 136+ 官方安全策略禁止任何自动化驱动用户默认 profile（防 cookie 窃取），运行中的 Chrome 也会锁 profile——直接复用日常 Chrome 登录态在技术上被平台封死。脚本因此使用独立 profile：**首次 `login` 登录一次，之后永久复用**，不会反复要求登录。
- 登录态只存在本地 profile 目录（默认 `~/.config/soia-skills/…/x-profile`，可用 `--profile-dir` / `SOIA_X_PROFILE_DIR` 覆盖），不导出 cookie、不进仓库和日志；也不走「解 Keychain 导 Chrome cookie」路线——临时明文 cookie 在多宿主环境是不可接受的攻击面。
- 脚本内置三道闸：未登录拦截、`send` 缺 `--yes` 拒绝、单条超 280 字符拒绝。
- 输出为单行 JSON 回执（action/parts/url 等），任何宿主可机读。

### 备选路线：宿主浏览器工具

宿主恰好提供浏览器控制（如 Claude Code 的 claude-in-chrome，经浏览器扩展复用用户真实 Chrome 登录态——这是免重复登录的唯一正规路径）时可优先走宿主工具，**客户零登录成本**，页面改版时适应性也更好；流程与授权档位与主路线完全一致。没有宿主工具时**不得**以此为由跳过脚本主路线。

### 两档授权，绝不越档（两条路线通用）

| 档位 | 触发条件 | 收尾动作 |
|---|---|---|
| 存草稿（默认） | 客户只说「填进去/存草稿」 | 存入未发送帖子；回执告知位置（更多 > 未发送帖子） |
| 直接发布 | 客户**在本次会话中逐字给出内容或确认最终文案，并明确说「发」** | 发布并尽力取推文 URL 写进回执 |

红线：默认档绝不发布；内容是 AI 改写产物（非客户逐字给出）时，即使客户此前说过「直接发」，也必须先把最终文案展示给客户确认后才可发布；发布档必须逐字使用客户确认过的文案，不得代改。

**回执**：草稿档报「已存入未发送帖子 + 条数」；发布档报推文 URL（未捕获则如实说明）；中途失败（选择器改版/登录失效）如实报告停在哪一步。

### 验证与测试

脚本层前向测试（无需登录态，改脚本后必跑）：`status` 对空 profile 返回 `logged_in:false`；`draft` 未登录时拦截并指引 login；`send` 缺 `--yes` 拒绝；单条 >280 字符拒绝——四条均以单行 JSON 退出。带登录态验证：`login` 后 `draft` 单条+多条各一次，在 X「未发送帖子」中人工确认；`send --yes` 以回执含真实推文 URL 为通过标准（2026-07-21 已在真实账号验证发布链路）。

