Skip to content
Automation
Skill

/x-twitter

Post to X via a signed-in browser session (live method — no API keys); API v2 path for search/read/engagement.

From plugin
sutando
41087 skills20 hooks

Claude Code

$ npx -y skills add sonichi/sutando --skill x-twitter --agent claude-code

SKILL.md

x-twitter.SKILL.md
name: x-twitter
description: "Post to X via a signed-in browser session (live method — no API keys); API v2 path for search/read/engagement."

X (Twitter)

Post, search, read, and monitor X from the command line.

When to use

The user wants to **post to / read from X (Twitter)** — publish a tweet or thread, reply, search recent tweets, check mentions/timeline, or pull engagement on a known tweet id. Not for other social platforms.

Failure modes

  • **403 / "not permitted"** on post → the X API tier doesn't allow writes, or the

app lacks Read+Write permission (regenerate the access token AFTER setting RW).

  • **429 rate-limited** → API v2 free tier has low write/read caps; back off and retry later, don't loop.
  • **401** → a key in `.env` is missing or stale. The skill uses five: `X_API_KEY`, `X_API_SECRET`, `X_ACCESS_TOKEN`, `X_ACCESS_TOKEN_SECRET`, and `X_BEARER_TOKEN`. **Reads authenticate with the bearer token**, so a 401 on search/mentions/timeline is most often a stale `X_BEARER_TOKEN`, not the OAuth pair.
  • **Done =** the command prints the new tweet id / the result rows; a post with no id back did not publish.

Usage

Posting — use the browser session (live method)

The OAuth1 API post path below is **NOT wired** on this fleet: posting needs 4 write keys (X_API_KEY/SECRET + X_ACCESS_TOKEN/SECRET) that are not in the vault. Posting is NOT credit-gated — it just needs those keys, which we don't have. **Do not conclude "X is blocked."** The working path is a signed-in Chrome-for-Testing browser session:

# Is the profile signed in?  (headless, exit 0 = yes, 2 = no)
node skills/x-twitter/x-post-browser.mjs check

# Owner signs in once (headed GUI window; email/phone — Google/Apple OAuth stay blocked)
node skills/x-twitter/x-post-browser.mjs login

# Compose only, screenshot, DO NOT publish  (always run this first)
node skills/x-twitter/x-post-browser.mjs post "Your tweet text" --dry-run

# Publish  (only after owner OKs the dry-run)
node skills/x-twitter/x-post-browser.mjs post "Your tweet text"
  • Profile: `<workspace>/data/x-browser-profile`, resolved through `scripts/sutando-config.sh workspace`

(override with `$X_BROWSER_PROFILE`, declared in this skill's `manifest.json`). Per-host, holds live session cookies, and never synced — `data/` is in the vault `exclude` list. A profile still sitting at the pre-#2133 location is used with a one-line notice until you move it, so upgrading does not cost you a fresh sign-in. `$X_LOGIN_DONE_SENTINEL` and `$X_LOGIN_TIMEOUT_ITERS` are declared alongside it but are test/CI controls — there is no reason to set them by hand. Sign-in survives ONLY because `check`/`post` strip Playwright's `--use-mock-keychain` so cookies decrypt with the real login keychain — see `memory/reference_x_browser_signin_oauth_blocked_use_email_phone.md`.

  • **Always `--dry-run` first and confirm with the owner before publishing.** Nothing

posts without an explicit OK.

API v2 usage (search / read / engagement — reads only, no post keys)

# Post
python3 skills/x-twitter/x-post.py post "Your tweet text"
python3 skills/x-twitter/x-post.py post "With video" --media /path/to/video.mp4
python3 skills/x-twitter/x-post.py post --reply-to 123456789 "Reply text"

# Search
python3 skills/x-twitter/x-post.py search "sutando agent"
python3 skills/x-twitter/x-post.py search "from:Chi_Wang_" --limit 5

# Read a tweet
python3 skills/x-twitter/x-post.py read 2040817066199195818

# Mentions & your own timeline (OAuth1 — resolves users/me)
python3 skills/x-twitter/x-post.py mentions
python3 skills/x-twitter/x-post.py timeline

# ANOTHER account's timeline (bearer only — no OAuth1 needed)
python3 skills/x-twitter/x-post.py user-timeline Chi_Wang_
python3 skills/x-twitter/x-post.py user-timeline Chi_Wang_ --limit 100 --exclude retweets,replies

# Engagement (likes, retweets, views)
python3 skills/x-twitter/x-post.py engagement 2040817066199195818

Which auth each command needs

`search`, `read` and `user-timeline` run on **`X_BEARER_TOKEN` alone** — app-only auth, stdlib urllib, no `requests`/`requests_oauthlib` install. `post`, `mentions` and `timeline` need the OAuth1 four (`X_API_KEY`, `X_API_SECRET`, `X_ACCESS_TOKEN`, `X_ACCESS_TOKEN_SECRET`).

**`timeline` vs `user-timeline` is an auth distinction, not a scope one.** `timeline` resolves `users/me`, which is OAuth1-only; `user-timeline` takes a handle and reads the same endpoint (`users/{id}/tweets`) over bearer. On a bearer-only host `timeline` cannot run and `user-timeline` can.

**`--limit` is 5..100 on `user-timeline`** — this endpoint's own bound. `search` rejects below 10; different endpoints, different bounds. Outside the range the command refuses locally (rc=2) rather than letting X return a 400 that reads like an account problem.

**`--exclude replies` keeps self-replies.** X drops replies to *others* and retains an author's own thread continuations, so `--exclude retweets,replies` can still return a tweet whose `in_reply_to_user_id` is the author. Measured, not assumed.

Setup

1. Install Python dependencies (one-time):

   pip3 install requests requests-oauthlib

2. Go to https://developer.x.com and sign in 3. Create a Project + App 4. Generate keys and add to `.env`:

   X_API_KEY=...
   X_API_SECRET=...
   X_ACCESS_TOKEN=...
   X_ACCESS_TOKEN_SECRET=...

Notes

  • Free tier: 500 posts/month, search recent tweets (7 days)
  • Video upload uses chunked upload (supports 4K)
  • Always confirm post content with user before publishing
Read more
@sonichi
Ships withsutando

My AI Stand — Realtime by Day, Rewriting Itself by Night. Summon my AI superpower. Voice, vision, screen, meetings, calls when I'm engaged. Learns my patterns, ships its own code when I'm not. Runs across my Macs, interacts with people & their Stands.

Stars on GitHub

Momentum

stars in total
410
Star history of sonichi/sutando on GitHub, a chart by star-history.com

Other skills on sutando.

ag2-space-mcp

ag2-space-mcp

Connect this Sutando install to AG2 Space's hosted MCP as its own agent, without the desktop app, and know which room and Commons…

@sonichi@sonichiInstall Skill
ag2space-voice

ag2space-voice

s.space voice surface — binds the room the s.space client announces to the voice session's origin, so work delegated by voice in…

@sonichi@sonichiInstall Skill
agent-activity

agent-activity

Streams what the agent is doing into the room, as rows the desktop client renders in an **events drawer** above the composer…

@sonichi@sonichiInstall Skill
agent-registry

agent-registry

Local Agent Registry — a standalone, dependency-free service that tracks running Claude Code (and other) agent instances. Agents…

@sonichi@sonichiInstall Skill
agent-room-ops

agent-room-ops

For an all-room analysis sweep, use the tested window collector and coverage contract in…

@sonichi@sonichiInstall Skill
answer-format

answer-format

Deterministic final-answer normalizer — a last-step pass for any task that ends in a *precise* answer (a number, a short string,…

@sonichi@sonichiInstall Skill

More skills from other plugins.

agent-builder

agent-builder

Load immediately after an Agent intent, before the first agent_builder_* call. Governs how you create, configure, test, and…

n8n2w209k
@n8n-io@n8n-ioInstall Skill
browser-use

browser-use

Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…

@browser-use@browser-useInstall Skill
add-anydoc

add-anydoc

Add local office-document-to-Markdown conversion to NanoClaw agent containers with the pinned Firecrawl AnyDoc CLI. Use when…

@nanocoai@nanocoaiInstall Skill

Questions about x-twitter.

Which coding agents can use x-twitter?
x-twitter installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.