baoyu-post-to-x
Posts content and articles to X (Twitter). Supports regular posts with images/videos and X Articles (long-form Markdown). In Codex, honor explicit requests for the Codex Chrome plugin/@chrome by using the Chrome Extension workflow; otherwise use Chrome Computer Use when available and fall back to real Chrome CDP scripts only when allowed. Use when user asks to "post to X", "tweet", "publish to Twitter", or "share on X".
1实现原理 · 为什么它能做到
它不用 Playwright/Puppeteer,而是驱动一个真实 Chrome(CDP 连接),让 X 看到的是普通浏览器会话;脚本负责把内容填进真实 UI,发布动作留给用户或 --submit。
Uses real Chrome with CDP to bypass anti-automation.
发图的第一手段不是 CDP 合成事件,而是真实系统级 Cmd+V 键击:先把图片写进系统剪贴板,再让 osascript/xdotool/ydotool 向 Chrome 窗口发粘贴键,CDP 合成事件只作兜底。
Sends real Cmd+V keystroke to Chrome, bypassing CDP's synthetic events that X can detect
常规贴/视频/引用/长文四条路径共用同一套 Chrome 层:解析或复用调试端口、共享 profile、注入文本用 execCommand('insertText') 或 Input.insertText,上传用 DOM.setFileInputFiles 直接塞文件路径。
const X_COMPOSE_URL = 'https://x.com/compose/post';
发布默认不自动:脚本把内容填好后停下并提示人工点发布;只有显式 --submit 才会点 tweetButton / publishButton。
Post composed. Please review and click the publish button in the browser.
凭据面是 X 会话 cookie:通过 CDP Network.getCookies 读 x.com/twitter.com 的 cookie,仅断言 auth_token 与 ct0 存在(值不打印不落盘),凭据仓库就是这个共享 Chrome profile。
const REQUIRED_X_SESSION_COOKIES = ['auth_token', 'ct0'] as const;
复用已运行的 Chrome 是设计内的:先扫 ps aux 找带同一 profile 与 --remote-debugging-port 的进程,找到就连上去,不再新开浏览器。
line.includes(options.profileDir) && line.includes("--remote-debugging-port=")
多平台剪贴板/键击适配是自带的:macOS 用内联 Swift/AppKit 写剪贴板 + osascript 发键,Linux 用 wl-copy/xclip + xdotool/ydotool,Windows 用 PowerShell STA 与 SendKeys。
await runCommand('swift', [swiftPath, 'image', imagePath]);
附带一个会动手的预检脚本:检查 Chrome、profile 隔离性、bun、辅助功能权限、剪贴板往返、粘贴键能力与正在运行的 Chrome 冲突,失败即退出码 1。
Checks: Chrome, profile isolation, Bun, Accessibility, clipboard, paste keystroke, Chrome conflicts.
2核心能力
3外部依赖
| Kind | Dependency / Endpoint |
|---|---|
| cli | npx -y bun(跑同目录兄弟脚本与自身) |
| cli | osascript(macOS:激活 Chrome、发送 Cmd+V) |
| cli | swift(macOS:编译内联 AppKit 剪贴板源码) |
| cli | xdotool / ydotool(Linux X11/Wayland 粘贴键) |
| cli | powershell.exe / cmd.exe / wslpath(Windows 与 WSL 路径与键击) |
| cli | ps aux / pgrep / which / where(进程与工具探测) |
| cli | 真实 Chrome/Chromium/Edge 二进制(以 CDP 参数启动) |
| network | X 发帖页与长文编辑器 |
| network | 本地 Chrome DevTools 端点(HTTP 探测 + WebSocket CDP) |
| network | markdown 里引用的任意 http(s) 图片会被下载到本地临时目录(经 baoyu-md) |
| package | baoyu-chrome-cdp / baoyu-md / front-matter / highlight.js / marked / remark-* / unified(scripts/package.json 声明) |
4管控建议与判定依据
- SKILL.md / 脚本: 调用未公开或逆向工程的私有 API / 伪造客户端标识
- SKILL.md / 脚本参数: 包含绕过自动化检测、关闭宿主沙箱或跳过 SSL 证书校验
- SKILL.md / 会话存储: 读取或复用浏览器用户登录态与会话 Cookie
- 本地凭据 / 浏览器配置: 读取用户登录 Cookie/会话/密钥环: 经 CDP Network.getCookies 读取 x.com / twitter.com 的会话 cookie,并断言 auth_token 与
- scripts/: 执行本地脚本或命令: ${BUN_X} {baseDir}/scripts/x-browser.ts|x-video.ts|x-quote.ts|x-article.ts
- 网络端点: 声明外部网络访问: https://x.com/compose/post 与 https://x.com/compose/articles(真实浏览器页面)
- 本地工作目录: 文件读写与工件输出: $TMPDIR/x-article-content.html(长文正文 HTML)与 $TMPDIR/x-article-images(正文图临时目录
5第二遍独立确认
- [ok] 反自动化侦测的绕过(判红主因) — README 'bypass anti-automation' + regular-posts.md 的 Cmd+V/合成事件两段 + paste-from-clipboard.ts 顶部注释互相印证;x-browser.ts 里 pasteFromClipboard('Google Chrome', 5, 500) 为首选,CDP 键事件为 fallback。
- [ok] cookie 面边界:只经 CDP 读、不落盘 — x-utils.ts 经 Network.getCookies 取 x.com/twitter.com cookie 并在内存构建 map,仅断言 auth_token/ct0 存在;全目录 grep 未发现写入 cookie 文件或读取 Cookies SQLite('Cookies' 只出现在单测字面量里)。
- [ok] 接管已运行调试会话 — packages/baoyu-chrome-cdp 通过 ps aux 匹配 profileDir + --remote-debugging-port 找端口并连接;x-utils.ts 也自行 spawnSync('ps', ['aux']) 做占用判定。
- [ok] 发布动作默认关闭 — tweetButton/publishButton 的 click 都包在 --submit 分支内;未提交时脚本打印提示让用户自己在浏览器点发布;SKILL.md 另有『必须当轮明确确认』的硬规则。
- [ok] 进程级动作(pkill) — SKILL.md 第 321 行给出 pkill -f "Chrome.*remote-debugging-port" …; sleep 2 的清理配方;该命令不在任何 TS 脚本内,需由 agent 执行——已写入 security.scripts_executed 与 risks。
- [discrepancy] 文档与实现不一致(--disable-blink-features) — references/regular-posts.md 宣称 CDP 路线会用 --disable-blink-features=AutomationControlled 启动 Chrome,但 x-utils.ts 只传 extraArgs: ['--start-maximized'];该参数仅出现在 packages/baoyu-chrome-cdp/src/mermaid.ts 的无头渲染启动里。故『绕过』的实际手段是真实键击 + 真实浏览器,而非该启动参数。
- [ok] 单测是否触碰网络/浏览器 — x-utils.test.ts 与 md-to-html.test.ts 均为纯函数/临时目录测试(锁文件判定、启动重试判定、cookie map、markdown 解析),无网络、无 Chrome 启动。
- [ok] 档位复核(批4 终裁) — 按 Main 终裁与范式红档『反反爬/绕过』字面命中判 red(撤回先前的 orange);同时保留可减轻情节的说明:无 TLS/沙箱降级、无未转义插值、cookie 不落盘、发布默认关闭。
6结论
83fb7a73416e3fe3…