twitter-cli
twitter-cli — a Claude Code skill from jackwener/twitter-cli
Features
- ✓Timeline: fetch `for-you` and `following` feeds
- ✓Bookmarks: list saved tweets from your account
- ✓Search: find tweets by keyword with Top/Latest/Photos/Videos tabs
- ✓Tweet detail: view a tweet and its replies; use `show <N>` to open tweet #N from the last list output
- ✓Article: fetch a Twitter Article and export it as Markdown
- ✓List timeline: fetch tweets from a Twitter List
- ✓User lookup: fetch user profile, tweets, likes, followers, and following
- ✓`--full-text`: disable tweet text truncation in rich table output
- ✓Structured output: export any data as YAML or JSON for scripting and AI agent integration
- ✓Optional scoring filter: rank tweets by engagement weights
- ✓Structured output contract: [SCHEMA.md](./SCHEMA.md)
- ✓Post: create new tweets and replies, with optional image attachments (up to 4)
- ✓Quote: quote-tweet with optional images
- ✓Delete: remove your own tweets
- ✓Like / Unlike: manage tweet likes
- ✓Retweet / Unretweet: manage retweets
- ✓Bookmark: bookmark/unbookmark (`favorite/unfavorite` kept as compatibility aliases)
- ✓Write commands also support explicit `--json` / `--yaml` output now
- ✓Cookie auth: use browser cookies or environment variables
- ✓Full cookie forwarding: extracts ALL browser cookies for richer browser context
- ✓TLS fingerprint impersonation: `curl_cffi` with dynamic Chrome version matching
- ✓`x-client-transaction-id` header generation
- ✓Request timing jitter to avoid pattern detection
- ✓Write operation delays (1.5–4s random) to mitigate rate limits
- ✓Proxy support via `TWITTER_PROXY` environment variable
- ✓`fetch.count` is the default item count for read commands when `--max` is omitted
- ✓Rich table output truncates long tweet text by default; use `--full-text` to show full body text in list views
- ✓Default behavior: no ranking filter unless `--filter` is passed
- ✓With `--filter`: tweets are scored/sorted using `config.filter`
- ✓`mode: "topN"` keeps the highest `topN` tweets by score
- ✓`mode: "score"` keeps tweets where `score >= minScore`
- ✓`mode: "all"` returns all tweets after sorting by score
- ✓**Use a proxy** — set `TWITTER_PROXY` to avoid direct IP exposure
- ✓**Keep request volumes low** — use `--max 20` instead of `--max 500`
- ✓**Don't run too frequently** — each startup fetches x.com to initialize anti-detection headers
- ✓**Use browser cookie extraction** — provides full cookie fingerprint
- ✓**Avoid datacenter IPs** — residential proxies are much safer
- ✓Use the default rich table for interactive reading
- ✓Use `--full-text` when reading long posts in terminal tables
- ✓Use `--yaml` or `--json` for scripts and agent pipelines
- ✓Use `-c` / `--compact` when token efficiency matters more than completeness
- ✓`No Twitter cookies found`
- ✓`Cookie expired or invalid (HTTP 401/403)`
- ✓`Unable to get key for cookie decryption` (macOS Keychain)
- ✓`Twitter API error 404`
- ✓`Invalid tweet JSON file`
- ✓**Windows: no output captured by pipe/subprocess** (AI agent integration)
Installation Guide
# Recommended: uv tool (fast, isolated)
uv tool install twitter-cli
# Alternative: pipx
pipx install twitter-cliUpgrade to the latest version:
uv tool upgrade twitter-cli
# Or: pipx upgrade twitter-cliTip: Upgrade regularly to avoid unexpected errors from outdated API handling.
Install from source:
git clone git@github.com:jackwener/twitter-cli.git
cd twitter-cli
uv syncQuick Start
# Fetch home timeline (For You)
twitter feed
# Fetch Following timeline
twitter feed -t following
# Enable ranking filter explicitly
twitter feed --filterUsage
# Feed
twitter feed --max 50
twitter feed --cursor "<next-cursor-from-previous-response>"
twitter feed --full-text
twitter feed --output tweets.json
twitter feed --input tweets.json
twitter feed --json # Structured stdout for scripts/agents
# Bookmarks
twitter bookmarks
twitter bookmarks --full-text
twitter bookmarks --max 30 --yaml
# Search
twitter search "Claude Code"
twitter search "AI agent" -t Latest --max 50
twitter search "AI agent" --full-text
twitter search "机器学习" --yaml
twitter search "python" --from elonmusk --lang en --since 2026-01-01
twitter search --from bbc --exclude retweets --has links
twitter search "topic" -o results.json # Save to file
twitter search "trending" --filter # Apply ranking filter
# Tweet detail (view tweet + replies)
twitter tweet 1234567890
twitter tweet 1234567890 --full-text
twitter tweet https://x.com/user/status/1234567890
# Open tweet by index from last list output
twitter show 2 # Open tweet #2 from last feed/search
twitter show 2 --full-text # Full text in reply table
twitter show 2 --json # Structured output
# Twitter Article
twitter article 1234567890
twitter article https://x.com/user/article/1234567890 --json
twitter article 1234567890 --markdown
twitter article 1234567890 --output article.md
# List timeline
twitter list 1539453138322673664
twitter list 1539453138322673664 --full-text
# User
twitter user elonmusk
twitter user-posts elonmusk --max 20
twitter user-posts elonmusk --full-text
twitter user-posts elonmusk -o tweets.json
twitter likes elonmusk --max 30 # ⚠️ own likes only (private since Jun 2024)
twitter likes elonmusk --full-text
twitter likes elonmusk -o likes.json
twitter followers elonmusk --max 50
twitter following elonmusk --max 50
# Write operations
twitter post "Hello from twitter-cli!"
twitter post "Hello!" --image photo.jpg # Post with image
twitter post "Gallery" -i a.png -i b.jpg -i c.webp # Up to 4 images
twitter post "reply text" --reply-to 1234567890
twitter reply 1234567890 "Nice!" -i screenshot.png # Reply with image
twitter quote 1234567890 "Look" -i chart.png # Quote with image
twitter post "Hello from twitter-cli!" --json
twitter delete 1234567890
twitter like 1234567890
twitter like 1234567890 --yaml
twitter unlike 1234567890
twitter retweet 1234567890
twitter unretweet 1234567890
twitter bookmark 1234567890
twitter unbookmark 1234567890
twitter follow elonmusk --jsonAuthentication
twitter-cli uses this auth priority:
TWITTER_AUTH_TOKEN + TWITTER_CT0Browser extraction is recommended — it forwards ALL Twitter cookies (not just auth_token + ct0) and aligns request headers with your local runtime, which is closer to normal browser traffic than minimal cookie auth.
Chrome multi-profile: All Chrome profiles are scanned automatically. To specify a profile:
TWITTER_CHROME_PROFILE="Profile 2" twitter feedBrowser priority: If you have multiple browsers, set TWITTER_BROWSER to try a specific browser first:
TWITTER_BROWSER=chrome twitter feed # Supported: arc, chrome, edge, firefox, braveAfter loading cookies, the CLI performs lightweight verification. Commands that require account access fail fast on clear auth errors (401/403).
Proxy Support
Set TWITTER_PROXY to route all requests through a proxy:
# HTTP proxy
export TWITTER_PROXY=http://127.0.0.1:7890
# SOCKS5 proxy
export TWITTER_PROXY=socks5://127.0.0.1:1080Using a proxy can help reduce IP-based rate limiting risks.
Configuration
Create config.yaml in your working directory:
fetch:
count: 50
filter:
mode: "topN" # "topN" | "score" | "all"
topN: 20
minScore: 50
lang: []
excludeRetweets: false
weights:
likes: 1.0
retweets: 3.0
replies: 2.0
bookmarks: 5.0
views_log: 0.5
rateLimit:
requestDelay: 2.5 # base delay between requests (randomized ×0.7–1.5)
maxRetries: 3 # retry count on rate limit (429)
retryBaseDelay: 5.0 # base delay for exponential backoff
maxCount: 200 # hard cap on fetched itemsFetch behavior:
fetch.count is the default item count for read commands when --max is omitted--full-text to show full body text in list viewsFilter behavior:
--filter is passed--filter: tweets are scored/sorted using config.filterScoring formula:
score = likes_w * likes
+ retweets_w * retweets
+ replies_w * replies
+ bookmarks_w * bookmarks
+ views_log_w * log10(max(views, 1))Mode behavior:
mode: "topN" keeps the highest topN tweets by scoremode: "score" keeps tweets where score >= minScoremode: "all" returns all tweets after sorting by scoreBest Practices (Avoiding Bans)
TWITTER_PROXY to avoid direct IP exposure--max 20 instead of --max 500Output Modes
--full-text when reading long posts in terminal tables--yaml or --json for scripts and agent pipelines-c / --compact when token efficiency matters more than completenessTroubleshooting
No Twitter cookies found- Ensure you are logged in to
x.com in a supported browser (Arc/Chrome/Edge/Firefox/Brave).- Or set
TWITTER_AUTH_TOKEN and TWITTER_CT0 manually.- Run with
-v to see browser extraction diagnostics.Cookie expired or invalid (HTTP 401/403)- Re-login to
x.com and retry.Unable to get key for cookie decryption (macOS Keychain)- SSH sessions: Keychain is locked by default over SSH. Run:
security unlock-keychain ~/Library/Keychains/login.keychain-db- Local terminal: Open Keychain Access → search for "\<Browser\> Safe Storage" → Access Control → add your Terminal app → Save Changes.
- Or click "Always Allow" when the Keychain authorization popup appears.
Twitter API error 404- This can happen when upstream GraphQL query IDs rotate.
- Retry the command; the client attempts a live queryId fallback.
Invalid tweet JSON file- Regenerate input using
twitter feed --json > tweets.json.- This is a ConPTY issue, not a twitter-cli bug. Windows Terminal's ConPTY pseudo-terminal can intercept pipe output from commands with network latency.
- Fix: Use Git Bash as your terminal shell and set
"windowsEnableConpty": false in your terminal settings.- If disabling ConPTY with PowerShell, emoji output may fail with
UnicodeEncodeError: 'gbk'. Git Bash handles UTF-8 natively.- Standard
subprocess.run(capture_output=True) and file redirection (> file 2>&1) work correctly regardless of ConPTY.Structured error codes commonly include not_authenticated, not_found, invalid_input, rate_limited, and api_error.
Development
# Install dev dependencies
uv sync --extra dev
# Lint + tests
uv run ruff check .
uv run pytest -qCurrent CI validates the project on Python 3.8, 3.10, and 3.12.
Project Structure
twitter_cli/
├── __init__.py
├── cli.py
├── client.py
├── graphql.py # GraphQL query IDs, URL building, JS bundle scanning
├── parser.py # Tweet, User, Media parsing logic
├── auth.py
├── config.py
├── constants.py
├── exceptions.py
├── filter.py
├── formatter.py
├── output.py
├── serialization.py
└── models.pyUse as AI Agent Skill
twitter-cli ships with a [SKILL.md](./SKILL.md) so AI agents can execute common X/Twitter workflows.
#### Skills CLI (Recommended)
npx skills add jackwener/twitter-cli| Flag | Description |
| --- | --- |
| -g | Install globally (user-level, shared across projects) |
| -a claude-code | Target a specific agent |
| -y | Non-interactive mode |
#### Manual Install
mkdir -p .agents/skills
git clone git@github.com:jackwener/twitter-cli.git .agents/skills/twitter-cli#### ~~OpenClaw / ClawHub~~ (Deprecated)
⚠️ ClawHub install method is deprecated and no longer supported. Use [Skills CLI](#skills-cli-recommended) or Manual Install above.