baoyu-danger-x-to-markdown
Converts X (Twitter) tweets and articles to markdown with YAML front matter. Uses reverse-engineered API requiring user consent. Use when user mentions "X to markdown", "tweet to markdown", "save tweet", or provides x.com/twitter.com URLs for conversion.
1How It Works & Mechanism
The core mechanism is reverse-engineering X's GraphQL API: it scrapes queryId and featureSwitches from the HTML of x.com pages, then interpolates variables into /i/api/graphql/<queryId>/<Operation> requests.
const url = new URL(`https://x.com/i/api/graphql/${queryInfo.queryId}/TweetResultByRestId`);
Requests carry X's public web bearer token and a fixed User-Agent—serving as a way to impersonate the official web client, which is why it does not require an official API key.
export const DEFAULT_BEARER_TOKEN =
Authentication relies on cookies: it checks environment variables X_AUTH_TOKEN / X_CT0 (optionally X_GUEST_TOKEN / X_TWID) first, followed by a local cookie file, and finally reads from Chrome via CDP.
const authToken = process.env.X_AUTH_TOKEN?.trim();
Fetched tweets/articles are converted into markdown: threads are linked following TweetDetail conversation structures, Articles use full text from articleEntity, quoted tweets are parsed separately, and output files are generated with YAML front matter.
**File structure**: `x-to-markdown/{username}/{tweet-id}/{content-slug}.md`
Media localization is an optional step: enabling --download-media downloads images/videos to sibling imgs/ and videos/ directories relative to the markdown file, rewriting links to relative local paths.
if (hostname.includes("video.twimg.com")) return "video";
Consent gating is strictly enforced: if consent.json (accepted + disclaimerVersion 1.0) is missing, it must display the disclaimer to the user and obtain explicit consent; it exits immediately if declined.
This tool uses a reverse-engineered X API, NOT official.
Initial setup is also mandatory: when EXTEND.md does not exist, an interactive tool prompt must ask for preferences (media processing policy, default output directory, save location); silently writing default values is explicitly forbidden.
**CRITICAL**: When EXTEND.md is not found, you **MUST use `AskUserQuestion`** to ask the user for their preferences before creating EXTEND.md.
Media handling defaults to 'generate markdown first, then ask': it runs once without media download flags, checks if the output still contains remote media URLs, and only prompts whether to download and re-runs to overwrite links if remote media is found.
5. If user confirms → run script **again** with `--download-media` (overwrites markdown with localized links)
2Core Capabilities
3External Dependencies
| Kind | Dependency / Endpoint |
|---|---|
| network | x.com(GraphQL /i/api/graphql/… 与首页 HTML 抓 queryId) |
| network | pbs.twimg.com(图片媒体下载) |
| network | video.twimg.com(视频媒体下载) |
| package | baoyu-chrome-cdp ^0.1.1(npm,CDP 取 cookie) |
| cli | bun / npx(${BUN_X} 运行时) |
4Recommended Governance & Evidence
- SKILL.md / 脚本: Invokes unreleased or reverse-engineered private APIs / spoofs client identifiers
- SKILL.md / 脚本参数: Involves bypassing automated detection, disabling host sandboxes, or skipping SSL certificate validation
- SKILL.md / 会话存储: Reads or reuses browser user login states and session cookies
- 本地凭据 / 浏览器配置: Reads user login cookies/sessions/keyrings: cookies: auth_token, ct0 (required), optionally gt, twid; sources = env (X_AUTH_TOKEN / X_CT0 / X_GUEST)
- scripts/: Executes local scripts or commands: scripts/main.ts (executed via bun; launches/attaches to Chrome debugging sessions on demand to read cookies)
- 网络端点: Declares external network access: https://x.com/i/api/graphql/<queryId>/<Operation> (TweetResultByRestId / Twe)
- 本地工作目录: File read/write and artifact output: x-to-markdown/{username}/{tweet-id}/{content-slug}.md (or path specified by -o)
5Second-Pass Verification
- [ok] 逆向 GraphQL 请求 + 客户端冒充(red 主因) — graphql.ts 从首页 HTML 抓 queryId/featureSwitches,拼 https://x.com/i/api/graphql/${queryId}/Operation;constants.ts 提供 FALLBACK_QUERY_ID 与硬编码 bearer/UA。
- [ok] 浏览 cookie 读取 — cookies.ts:buildInlineCookiesFromEnv 读 X_AUTH_TOKEN/X_CT0/X_GUEST_TOKEN/X_TWID;loadXCookiesFromFile 读本地文件;loadXCookiesFromCdp 经 CDP 取;hasRequiredXCookies 校验 auth_token 与 ct0。
- [ok] 媒体下载范围 — media-localizer.ts 仅对 pbs.twimg.com / video.twimg.com 判定类型并 fetch 下载,且只在 --download-media 路径调用(SKILL.md 的三态策略)。
- [ok] 两道用户门禁 — SKILL.md:consent.json(accepted + disclaimerVersion 1.0)与 EXTEND.md 首次设置(三问,禁止静默默认),后者被单独标为 BLOCKING。
- [ok] 无 TLS 降级 / 无 stealth 伪装 / 无任意代码执行 — 相关 token 全目录零命中;入口是单个 URL;无 eval/动态 import 远程模块。
- [ok] 与 baoyu-post-to-x 的路线差异(避免档位观感不一致) — post-to-x 走真实 UI + CDP 自动化(另行定级);本 skill 走私有 API 伪造请求 → red。差异来源是技术路线,已在 reason 写明。
- [ok] meta 元数据 — GitHub API:MIT、25926 stars、pushed_at 2026-09-10T15:13:43Z;本地 HEAD 与 pin 1567581c26ec… 一致。
6Verdict & Scenarios
bb27420994157cc5…