| name | twitter-cli-skill |
| description | Terminal-first Twitter/X CLI for reading feeds, bookmarks, search, and posting tweets without API keys |
| triggers | ["show my Twitter timeline","search tweets about","post a tweet from terminal","fetch Twitter bookmarks","get user tweets from CLI","read Twitter feed in terminal","export tweets as JSON","view tweet replies"] |
twitter-cli
Skill by ara.so — Devtools Skills collection.
Overview
twitter-cli is a Python-based terminal CLI for Twitter/X that works without API keys. It uses browser cookie authentication to read timelines (For You, Following), bookmarks, search results, user profiles, and post/delete tweets. All commands support structured output (--json, --yaml) for AI agent pipelines.
Key capabilities:
- Read: feed, bookmarks, search, tweet detail, article, list timeline, user lookup
- Write: post, reply, quote, delete, like, retweet, bookmark
- Auth: browser cookie extraction (Arc/Chrome/Edge/Firefox/Brave) or env vars
- Anti-detection: TLS fingerprinting, full cookie forwarding, request jitter
- Output: rich tables (default), JSON, YAML, Markdown (articles)
Installation
uv tool install twitter-cli
pipx install twitter-cli
uv tool upgrade twitter-cli
From source:
git clone git@github.com:jackwener/twitter-cli.git
cd twitter-cli
uv sync
Authentication
Priority order:
- Environment variables:
TWITTER_AUTH_TOKEN + TWITTER_CT0
- Browser cookies (auto-extracted from Arc/Chrome/Edge/Firefox/Brave)
Browser cookie extraction (recommended):
twitter feed
TWITTER_BROWSER=chrome twitter feed
TWITTER_CHROME_PROFILE="Profile 2" twitter feed
Manual environment variables:
export TWITTER_AUTH_TOKEN="your_auth_token"
export TWITTER_CT0="your_ct0_token"
twitter feed
Proxy support:
export TWITTER_PROXY=http://127.0.0.1:7890
export TWITTER_PROXY=socks5://127.0.0.1:1080
Core Commands
Read Timeline
twitter feed
twitter feed -t following
twitter feed --max 20
twitter feed --full-text
twitter feed --json
twitter feed --yaml
twitter feed --filter --max 50
twitter feed --cursor "DAABCgABGdE..."
Search
twitter search "AI agent"
twitter search "machine learning" -t Latest
twitter search "python" --full-text --json
twitter search "climate" --from scientist --lang en --since 2026-01-01
twitter search "news" --exclude retweets --has links
twitter search "trending" -o results.json
twitter search "tech" --filter
Bookmarks
twitter bookmarks
twitter bookmarks --max 30 --full-text
twitter bookmarks --yaml
Tweet Detail (tweet + replies)
twitter tweet 1234567890
twitter tweet https://x.com/user/status/1234567890
twitter tweet 1234567890 --full-text
twitter tweet 1234567890 --json
Show Command (open tweet by index)
twitter show 2
twitter show 2 --full-text
twitter show 2 --json
Twitter Article (fetch and export as Markdown)
twitter article 1234567890
twitter article https://x.com/user/article/1234567890
twitter article 1234567890 --markdown
twitter article 1234567890 --output article.md
twitter article 1234567890 --json
List Timeline
twitter list 1539453138322673664
twitter list 1539453138322673664 --cursor "DAABCgABGdE..."
twitter list 1539453138322673664 --full-text
User Lookup
twitter user elonmusk
twitter user-posts elonmusk --max 20
twitter user-posts elonmusk --full-text -o tweets.json
twitter likes elonmusk --max 30
twitter followers elonmusk --max 50
twitter following elonmusk --max 50
Write Operations
Post Tweet
twitter post "Hello from twitter-cli!"
twitter post "Hello!" --image photo.jpg
twitter post "Gallery" -i a.png -i b.jpg -i c.webp
twitter post "Hello from twitter-cli!" --json
Reply
twitter post "Nice!" --reply-to 1234567890
twitter reply 1234567890 "Great!" -i screenshot.png
Quote Tweet
twitter quote 1234567890 "Check this out"
twitter quote 1234567890 "Look at this chart" -i chart.png
Delete Tweet
twitter delete 1234567890
Like / Unlike
twitter like 1234567890
twitter like 1234567890 --yaml
twitter unlike 1234567890
Retweet / Unretweet
twitter retweet 1234567890
twitter unretweet 1234567890
Bookmark / Unbookmark
twitter bookmark 1234567890
twitter unbookmark 1234567890
Follow / Unfollow
twitter follow elonmusk --json
twitter unfollow elonmusk
Configuration
Create config.yaml in your working directory:
fetch:
count: 50
filter:
mode: "topN"
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
maxRetries: 3
retryBaseDelay: 5.0
maxCount: 200
Scoring formula:
score = likes_w * likes
+ retweets_w * retweets
+ replies_w * replies
+ bookmarks_w * bookmarks
+ views_log_w * log10(max(views, 1))
Filter modes:
topN: Keep highest N tweets by score
score: Keep tweets where score >= minScore
all: Return all tweets sorted by score
AI Agent Usage
All commands support --json or --yaml for structured output. Non-TTY stdout defaults to YAML.
Example: Fetch and parse timeline
import subprocess
import yaml
result = subprocess.run(
["twitter", "feed", "--max", "10", "--yaml"],
capture_output=True,
text=True,
check=True
)
data = yaml.safe_load(result.stdout)
for tweet in data["tweets"]:
print(f"{tweet['author']['username']}: {tweet['text']}")
Example: Post tweet from Python
import subprocess
import json
result = subprocess.run(
["twitter", "post", "Hello from Python!", "--json"],
capture_output=True,
text=True,
check=True
)
response = json.loads(result.stdout)
print(f"Tweet ID: {response['tweetId']}")
Example: Search and filter
twitter search "AI agent" --since 2026-05-17 --filter --max 10 --json
Structured output contract: See SCHEMA.md
Common Patterns
Export bookmarks to file
twitter bookmarks --max 100 --json > bookmarks.json
Monitor user tweets
twitter user-posts elonmusk --max 5 --yaml
Search and rank by engagement
twitter search "AI" --filter --max 10 --full-text
Post with multiple images
twitter post "My photo gallery" -i img1.jpg -i img2.png -i img3.webp
Reply to tweet with image
twitter reply 1234567890 "Here's the screenshot" -i screenshot.png
Extract article as Markdown
twitter article 1234567890 --markdown --output ~/articles/ai-safety.md
Use proxy for all requests
export TWITTER_PROXY=http://127.0.0.1:7890
twitter feed --max 20
Troubleshooting
No Twitter cookies found
Solution:
- Log 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 for diagnostics:
twitter -v feed
Cookie expired (HTTP 401/403)
Solution: Re-login to x.com and retry.
Keychain access denied (macOS)
SSH sessions:
security unlock-keychain ~/Library/Keychains/login.keychain-db
Local terminal:
- Open Keychain Access → search for "<Browser> Safe Storage"
- Access Control → add Terminal app → Save Changes
- Or click "Always Allow" when prompted
Twitter API error 404
Solution: Retry command. The client attempts a live queryId fallback when GraphQL IDs rotate.
Invalid tweet JSON file
Solution: Regenerate using:
twitter feed --json > tweets.json
Windows: no pipe output in AI agent subprocess
Issue: ConPTY intercepts pipe output from network commands.
Fix:
- Use Git Bash as terminal shell
- Set
"windowsEnableConpty": false in terminal settings
- Standard
subprocess.run(capture_output=True) works correctly
Rate limiting (HTTP 429)
Solution:
- Use
--max to limit requests
- Set
TWITTER_PROXY to avoid direct IP exposure
- Increase
rateLimit.requestDelay in config.yaml
- Use residential proxies instead of datacenter IPs
Best Practices
- Use a proxy — set
TWITTER_PROXY to avoid direct IP exposure
- Keep request volumes low — prefer
--max 20 over --max 500
- Don't run too frequently — each startup fetches x.com to initialize headers
- Use browser cookie extraction — provides full cookie fingerprint
- Avoid datacenter IPs — residential proxies are safer
- Upgrade regularly —
uv tool upgrade twitter-cli to avoid outdated API handling
Output Modes
- Rich table (default): Interactive reading in terminal
--full-text: Show full tweet text in tables
--yaml: Structured output for agents (default for non-TTY)
--json: Strict JSON for parsers
-c / --compact: Token-efficient compact output
-o FILE: Save to file
Development
uv sync --extra dev
uv run ruff check .
uv run pytest -q
Project Structure
twitter_cli/
├── cli.py # Command-line interface
├── client.py # HTTP client + anti-detection
├── graphql.py # GraphQL query IDs, URL building
├── parser.py # Tweet/User/Media parsing
├── auth.py # Cookie extraction
├── config.py # Configuration loading
├── filter.py # Ranking/scoring logic
├── formatter.py # Rich table formatting
├── output.py # JSON/YAML serialization
└── models.py # Data models (Tweet, User, Media)
Example Workflows
Daily AI news digest
twitter search "AI" --since 2026-05-17 --filter --max 20 --json > ai_digest.json
Bookmark analysis
import subprocess
import yaml
from collections import Counter
result = subprocess.run(
["twitter", "bookmarks", "--max", "200", "--yaml"],
capture_output=True, text=True, check=True
)
data = yaml.safe_load(result.stdout)
hashtags = []
for tweet in data["tweets"]:
hashtags.extend([h["text"] for h in tweet.get("hashtags", [])])
print(Counter(hashtags).most_common(10))
Post with automated image
import subprocess
subprocess.run(["python", "generate_chart.py"], check=True)
subprocess.run([
"twitter", "post",
"Daily metrics update",
"-i", "chart.png",
"--json"
], check=True)
Monitor user and alert on keyword
#!/bin/bash
tweets=$(twitter user-posts elonmusk --max 5 --yaml)
if echo "$tweets" | grep -q "Mars"; then
echo "Alert: New Mars tweet from @elonmusk"
fi
Related Projects
License: Apache-2.0
Repository: https://github.com/jackwener/twitter-cli
PyPI: https://pypi.org/project/twitter-cli/