agentleFS
terrysoterryso/ego-skills/skills/x-post/SKILL.md

x-post

Skill34 starsChanged 9 days agoMITView on GitHub

Post on X (x.com / twitter.com) through the logged-in Ego Lite session. Login-check first and soft-fail with exit 2 when ego-browser is missing or x.com is logged out. Sends only with --yes after the draft is shown. Uses page.fetch CreateTweet, not the composer click path. Optional --image uploads up to 4 png/jpeg/webp files only after --yes. Reply is best-effort. Use when the user asks to tweet, post, reply, or attach images on X or Twitter from Ego.

17 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use x-dm, x-human and 6 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • JakeschincariolSkill

    x-dm

    Write X DMs that get answered - the first message, the two follow-ups - and triage the user's DM inbox and message requests. Use when the user says "DM this person", "cold DM", "outreach on X", "how do I follow up", "what do I say to this DM", "go through my message requests", or is reaching out to someone specific on X.

    Also in 3 projects that use this

  • JakeschincariolSkill

    x-human

    Strip the machine fingerprint out of any draft - em dashes, AI slop words, invisible watermark characters, thread boilerplate - and score it against a five-check detection panel before it goes out. Use whenever text needs to sound human, when the user says humanize, "does this sound like AI", "remove the em dashes", "de-slop this", "this sounds like ChatGPT", or before any post, thread, reply or DM from this pack is shown to the user.

    Also in 3 projects that use this

  • lleqsnoomSkill

    x-plan

    Plan before coding — research the project and the web first, ask short plain questions until the user is sure, propose three approaches with trade-offs, then write a layered spec (contract, invariant, test) as a graph-driven scenario with guards and a memory file; gate on user approval

    Also in 3 projects that use this

  • lxyang20131208-starSkill

    x-audit

    Audit a draft X (Twitter) post or thread against the open-source X algorithm BEFORE publishing. Use when the user shares a tweet draft and wants feedback, asks "will this do well on X / Twitter", "review my post", "is this good to post", or wants to improve reach before posting. Returns a PASS / FLAG / BLOCK verdict per dimension plus a concrete rewrite.

    Also in 3 projects that use this

  • lxyang20131208-starSkill

    x-reply

    Build a reply-based growth strategy for a new or small X (Twitter) account, and draft high-quality replies. Use when the user has few followers, asks "how do I grow on X from zero", "my account is new", "who should I reply to", "help me write a reply to this tweet", or wants a cold-start plan. Returns an anchor-account strategy and concrete reply drafts.

    Also in 3 projects that use this

  • +1 more from Jakeschincariol
  • +2 more from lxyang20131208-star

The file

Files
SKILL.md

x-post

用 Ego Lite 里已经登录的 Chromium 会话往 X 发帖。主路径是 page.fetch 的 CreateTweet,不点「发帖」。

Post to X through the logged-in Ego Lite session. The primary path is page.fetch CreateTweet. Do not click the composer.

成功标准是 stdout 打出 https://x.com/<screen_name>/status/<id>。没有这条链接就不算成功。不要顺手点其它确认框。

Success is the status URL on stdout: https://x.com/<screen_name>/status/<id>. Do not click unrelated confirmations.

先装 Ego

先装 Ego Lite,保证 ego-browser 在 PATH。缺失则 soft-fail(退出码 2),不要改用 Playwright、Puppeteer 或云端浏览器。

Install Ego Lite and put ego-browser on PATH. If it is missing, soft-fail with exit 2. Do not switch to Playwright, Puppeteer, or a cloud browser.

每次发帖前:登录闸门(必做)

node scripts/check-login.mjs
node scripts/check-login.mjs --keep
退出码含义Agent 做什么
0已登录把 login_tip 告诉用户,继续
2未登录 / 无 ego-browser展示 how_to_login / how_to_login_zh,停
1其它错误报告 JSON error,不要假装已经发出

auth_token 是 HttpOnly,只存在于浏览器 Cookie 罐。不要打印 Cookie,不要粘贴 Cookie,不要代填密码。

默认 finish({ keep: [] })。--keep 才把页面留着并 handOff()。

确认规则

没有 --yes 只打印草稿并退出码 3,不发送。Agent 必须把草稿给人看,等人确认后再加 --yes。

Without --yes the command prints the draft and exits 3. It does not send. Show that draft to the user. Add --yes only after they confirm.

命令

仓库根目录:

node skills/x-post/scripts/check-login.mjs
node skills/x-post/scripts/post.mjs --text "..."
node skills/x-post/scripts/post.mjs --text "..." --yes
node skills/x-post/scripts/post.mjs --text "..." --reply-to <statusId> --yes
node skills/x-post/scripts/post.mjs --text "..." --yes --json
node skills/x-post/scripts/post.mjs --text "..." --image /absolute/path/to/image.png
node skills/x-post/scripts/post.mjs --text "..." --image /absolute/path/to/image.png --image /absolute/path/to/other.webp --yes --json
node skills/x-post/scripts/cleanup.mjs

已安装的技能目录里用 node scripts/...。

退出码含义
0已登录,或已发出并打印状态链接,或 cleanup 关掉了本机空间
3草稿已打印,拒绝发送
2未登录,或没有 ego-browser
1参数、上传、HTTP、GraphQL 或浏览器错误。先看 JSON 的 outcome,不要只看退出码

--json 打出摘要 JSON。不加 --json 且发送成功时,stdout 只有状态链接。

outcome 决定能不能再发。脚本自己不会发第二次 CreateTweet。

outcomesent含义Agent 做什么
senttrue响应里有 rest_id把状态链接给人。不要再发
not_submittedfalse请求没发出(缺 --yes 时是退出码 3;缺 transaction、图片不合格、上传失败也算)确定没发出。修原因之后才可以重新 --yes
rejectedfalse服务端明确拒绝(401、429、226、186、带 errors 的响应,以及其它 4xx JSON)definitely_unsent: true。不要自动重试
unknownnull超时、连接中断、空响应、非 JSON、没有 errors 的 5xx,或 HTTP 成功但没有 rest_id不是 sent: false。先按 verify_before_retry 到时间线核对是否已有这条帖。不要自动重发

definitely_unsent: false 且 outcome 为 unknown 时,退出码 1 只表示没确认成功,不表示没发出。

cleanup 只对任务空间 x-post 执行 finish({ keep: [] })。它不删帖。

回复

--reply-to 会在同一条 mutation 上加 variables.reply。2026-11-04 的实页 page.fetch 回复返回 GraphQL 226,没有验证成功。当尽力而为:失败就把错误给人,不要改去点回复框,不要重试。

短帖和长文

加权长度用 twitter-text v3 的 maxWeightedTweetLength(280)。不超过就发 CreateTweet。超过,或显式 --long,就发 CreateNoteTweet(2026-11-04 捕获)。普通 /compose/post 的长文就会走这条,不必打开 Articles。

CreateTweet 和 CreateNoteTweet 都带现算的 x-client-transaction-id。verification key 和 loading-x-anim 从 x.com 文档读。ondemand.s 和 main.*.js 的地址从文档或 performance 发现。字节谁先返回用谁:页面里已经加载的脚本;并行的 Node HTTPS(ECONNRESET 等中断会退避重试)和 Ego 浏览器网络。浏览器这条走 CDP Network.loadNetworkResource;该方法没有正文时,把 <script src> 插进当前 x.com 页面,再用 script 文本、performance resource、Page.getResourceContent 和 Network.getResponseBody 读取。check-login 刚结束时主页常常还没有 ondemand.s,所以短帖也会主动让浏览器去拉,而不是只读空缓存。page.fetch 不用于 abs.twimg.com(CORS 会得到 0 字节),也不为了热身去点作曲框。query id 来自这份 main.*.js。不要复用别的 GraphQL 请求上的 transaction id。长文仍在材料齐了之后打开 https://x.com/compose/post,等两秒,再发。两边都拿不到字节就退出码 1、sent: false,错误里写明缺什么。也可以传 --transaction-id。不要编一个假的。

成功仍然是 https://x.com/<screen_name>/status/<id>。长文的完整正文在 note_tweet.note_tweet_results.result.text;legacy.full_text 会被截断,不当成全文。

接口

queryId 会随 main.*.js 轮换。先从当前包里读对应的 operationName,读不到再用 2026-11-04 的捕获值:CreateTweet l4hk8uVGvR-a8kzQ4nOhPA,CreateNoteTweet seOZkIS8AysCGfPo6yYPVA。不要发明其它 query id。字段见 references/create-tweet.md。坑见 references/pitfalls.md。

没有 --image 时 media.media_entities 仍是 []。私信、点赞、关注不做。GraphQL 186 表示这条文本对短帖太长。

图片

--image <路径> 可重复,最多 4 张。只接受 png、jpeg、webp,每张不超过 5 MiB(5242880 字节)。GIF 不支持。文件是否存在、类型、大小和张数都在任何网络请求之前检查;不合格是退出码 1。没有 --yes 时草稿列出路径、字节数和 md5,不上传。加上 --yes 之后,在已登录的 x.com 页面里用 page.evaluate 走 upload.x.com 的 INIT → APPEND → FINALIZE,再把 media_id_string 放进 CreateTweet 或 CreateNoteTweet。不点「发帖」。细节见 references/media-upload.md。

Images

--image <path> is repeatable, up to 4 files. png, jpeg, and webp only, each at most 5 MiB (5242880 bytes). GIF is rejected. Existence, type, size, and count are checked before any network call; a bad file exits 1. Without --yes the draft lists path, bytes, and md5, and nothing is uploaded. With --yes, page.evaluate runs INIT → APPEND → FINALIZE on upload.x.com, then CreateTweet or CreateNoteTweet receives media_id_string. The script does not click Post. See references/media-upload.md.

Pro 冒烟(公告原文)

先 check-login(退出码 0)。把下面这段原文给人看,确认后再加 --yes。成功时 stdout 是 https://x.com/<screen_name>/status/<id>。不要删这条公告。

ego-skills x-post: post on X from a logged-in Ego Lite session (page.fetch CreateTweet). Login-check first. Nothing sends without --yes. https://github.com/terryso/ego-skills
node skills/x-post/scripts/post.mjs --text "ego-skills x-post: post on X from a logged-in Ego Lite session (page.fetch CreateTweet). Login-check first. Nothing sends without --yes. https://github.com/terryso/ego-skills"
node skills/x-post/scripts/post.mjs --text "ego-skills x-post: post on X from a logged-in Ego Lite session (page.fetch CreateTweet). Login-check first. Nothing sends without --yes. https://github.com/terryso/ego-skills" --yes

测试

npm test

npm test 用 c8 统计 scripts/lib/**/*.mjs(不含 ego-deps.mjs),行覆盖率不低于 80%。单测不访问 x.com。

Changelog

  • 0.2.1 — CreateTweet 发出之后如果超时、响应丢失或成功体不完整,outcome 是 unknown,sent 是 null。先核对时间线,不要自动重发。上传失败和请求没发出仍是 not_submitted / sent: false。图片上传自己的重试不变。
  • 0.2.0 — --image 可附最多 4 张 png/jpeg/webp(每张 ≤ 5 MiB)。上传按 2026-11-04 捕获的 upload.x.com INIT → APPEND → FINALIZE,在 page.evaluate 里执行。没有 --yes 不上传。GIF 不支持。

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.