Project Structure
The codebase is organized as a single Python package with clear separation of concerns:Module Overview
cli.py — Command-Line Interface
Purpose: Entry point for all CLI commands, argument parsing, and command orchestration. Key responsibilities:- Define all CLI commands using Click decorators
- Handle command-line arguments and options
- Coordinate between client, config, filter, and formatter modules
- Error handling and user-facing messages
cli()— Main CLI group (entry point)feed()— Fetch home timeline or following feedfavorites()— Fetch bookmarkssearch()— Search tweets by keyworduser(),user_posts(),likes()— User-related commandstweet()— Fetch tweet detail with replieslist_timeline()— Fetch list timelinefollowers(),following()— Fetch user connectionspost(),delete_tweet()— Write operationslike(),unlike(),retweet(),unretweet()— Engagement operationsfavorite(),unfavorite()— Bookmark operations
cli.py:1-527
client.py — Twitter API Client
Purpose: Core GraphQL API client with anti-detection features, rate limiting, and pagination. Key responsibilities:- Make authenticated GraphQL GET/POST requests to Twitter’s API
- TLS fingerprint impersonation using
curl_cffi(Chrome 133) - Automatic query ID resolution (fallback → live extraction → GitHub)
- Parse GraphQL responses into domain models
- Pagination and cursor management
- Rate limit handling with exponential backoff
- Generate
x-client-transaction-idheaders - Extract live feature flags from Twitter’s frontend
TwitterClient
Read operations:
fetch_home_timeline()— For You feedfetch_following_feed()— Following feed (chronological)fetch_bookmarks()— Bookmarked tweetsfetch_user()— User profile by screen namefetch_user_tweets()— User’s tweetsfetch_user_likes()— Tweets liked by userfetch_search()— Search tweets (Top/Latest/Photos/Videos)fetch_tweet_detail()— Tweet + repliesfetch_list_timeline()— Twitter List timelinefetch_followers()— User’s followersfetch_following()— Users followed by user
create_tweet()— Post a new tweet or replydelete_tweet()— Delete a tweetlike_tweet()/unlike_tweet()— Like/unlikeretweet()/unretweet()— Retweet/undo retweetbookmark_tweet()/unbookmark_tweet()— Bookmark/unbookmark
- TLS impersonation: Uses
curl_cffiwith Chrome 133 fingerprint - Full cookie forwarding: Sends ALL browser cookies, not just auth tokens
- Transaction ID generation: Dynamic
x-client-transaction-idheaders - Live feature extraction: Parses feature flags from x.com homepage
- Request jitter: Randomized delays between requests (0.7-1.5× base delay)
- Write delays: 1.5-4s random delay after write operations
- Check in-memory cache
- Use hardcoded fallback query IDs (fast path)
- On 404, fetch from GitHub (twitter-openapi project)
- Scan x.com JavaScript bundles for live query IDs
- Automatic retry with refreshed ID
client.py:1-1109
auth.py — Authentication & Cookie Extraction
Purpose: Manage Twitter cookie authentication with browser extraction and caching. Key responsibilities:- Extract cookies from local browsers (Chrome, Edge, Firefox, Brave)
- Load cookies from environment variables
- Cache cookies with 24h TTL
- Verify cookie validity before use
- Handle macOS Keychain access (required for Chrome cookie decryption)
TWITTER_AUTH_TOKEN+TWITTER_CT0environment variables- File cache (
~/.cache/twitter-cli/cookies.json, 24h TTL) - Browser extraction (auto-detect)
- In-process first: Required on macOS for Keychain access
- Subprocess fallback: Handles SQLite lock when browser is running
- Full cookie extraction: Extracts ALL Twitter cookies for full browser fingerprint
get_cookies()— Main entry point, returns{"auth_token": ..., "ct0": ..., "cookie_string": ...}load_from_env()— Load from environment variablesextract_from_browser()— Auto-detect and extract from browsersverify_cookies()— Verify tokens are valid via API call
- Location:
~/.cache/twitter-cli/cookies.json - TTL: 24 hours
- Automatically invalidated on 401/403 errors
- Permissions: 0o600 (owner read/write only)
auth.py:1-352
config.py — Configuration Management
Purpose: Load and validate configuration from YAML files with sensible defaults. Key responsibilities:- Load
config.yamlfrom current directory or project root - Deep-merge user config with defaults
- Validate and normalize configuration values
- Provide type-safe config access
load_config()— Main entry point, returns merged config dict_resolve_config_path()— Find config file in standard locations_deep_merge()— Recursively merge user config into defaults_normalize_config()— Validate types and bounds
./config.yaml(current working directory)<project-root>/config.yaml(parent of twitter_cli package)
config.py:1-167
filter.py — Tweet Scoring & Filtering
Purpose: Rank tweets by engagement metrics and apply user-defined filters. Key responsibilities:- Calculate engagement scores using weighted formula
- Filter tweets by language, retweet status
- Apply filtering modes: topN, score threshold, or all
- Sort tweets by score in descending order
- topN: Keep top N tweets by score (default: 20)
- score: Keep tweets where score ≥ minScore (default: 50)
- all: Return all tweets, sorted by score
score_tweet()— Calculate score for a single tweetfilter_tweets()— Apply all filters and return sorted list
filter.py:1-97
formatter.py — Terminal Output
Purpose: Format tweets and user profiles for terminal display using Rich library. Key responsibilities:- Render tweets as rich tables with emoji indicators
- Display tweet details in panels
- Format user profiles
- Display filter statistics
- Number formatting (K/M suffixes)
print_tweet_table()— Display tweets in a table formatprint_tweet_detail()— Display single tweet with full details in a panelprint_user_profile()— Display user profile in a panelprint_user_table()— Display user list in a tableprint_filter_stats()— Show before/after filter countsformat_number()— Convert numbers to readable format (1.2K, 3.5M)
- Verified badge (✓) for verified users
- Retweet indicator (🔄)
- Media type icons (📷 📹 🎞️)
- Quoted tweet preview
- Engagement metrics with emoji
- Tweet links
formatter.py:1-239
models.py — Data Models
Purpose: Define core data structures as simple Python dataclasses. Key models:Tweet — Represents a single tweet
Author — Tweet author information
Metrics — Engagement metrics
TweetMedia — Media attachments
UserProfile — User account information
models.py:1-70
serialization.py — JSON Serialization
Purpose: Convert domain models to/from JSON for import/export functionality. Key responsibilities:- Serialize tweets to JSON (for
--jsonand--outputflags) - Deserialize tweets from JSON (for
--inputflag) - Serialize user profiles to JSON
- Handle nested objects (Author, Metrics, quoted tweets)
tweet_to_dict()— Convert Tweet → dicttweet_from_dict()— Convert dict → Tweettweets_to_json()— Convert List[Tweet] → JSON stringtweets_from_json()— Convert JSON string → List[Tweet]user_profile_to_dict()— Convert UserProfile → dictusers_to_json()— Convert List[UserProfile] → JSON string
serialization.py:1-176
Key Design Patterns
1. Separation of Concerns
Each module has a single, well-defined responsibility:- cli.py: User interface
- client.py: API communication
- auth.py: Authentication
- filter.py: Business logic
- formatter.py: Presentation
2. Configuration-Driven Behavior
All runtime behavior is configurable via:config.yamlfor persistent settings- Environment variables for credentials and proxy
- Command-line flags for per-run overrides
3. Anti-Detection Layering
Multiple techniques work together:- TLS fingerprinting (curl_cffi)
- Full cookie forwarding
- Dynamic header generation
- Request timing randomization
- Live feature flag extraction
4. Graceful Degradation
- Query ID fallback chain (hardcoded → GitHub → live)
- Multiple cookie extraction strategies (in-process → subprocess)
- Automatic retry on rate limits
- Silent feature flag extraction failures
5. Data Flow
Testing & Development
While the codebase prioritizes rapid iteration over test coverage, key areas to understand for development: Debugging tips:Extension Points
To add new functionality:- New CLI command: Add to
cli.pywith@cli.command()decorator - New API endpoint: Add method to
TwitterClientclass inclient.py - New filter mode: Extend
filter_tweets()infilter.py - New output format: Add formatter function in
formatter.py
Dependencies
Key external libraries:- click: CLI framework
- rich: Terminal formatting
- curl_cffi: TLS fingerprint impersonation
- browser-cookie3: Cookie extraction from browsers
- x-client-transaction: Transaction ID generation
- pyyaml: Configuration parsing
- beautifulsoup4: HTML parsing for header extraction
Performance Considerations
- Startup time: 3-5s due to x.com initialization (required for anti-detection)
- Pagination: Automatic with jittered delays to avoid rate limits
- Cookie caching: 24h TTL reduces browser access overhead
- Query ID caching: In-memory cache reduces bundle scanning
Security Notes
- Cookies never leave the local machine — no external uploads
- Cookie cache permissions: 0o600 (owner-only)
- Cookie cache location:
~/.cache/twitter-cli/cookies.json - Proxy support: All requests route through
TWITTER_PROXYif set - No API keys required — uses your browser’s existing session
References
For detailed implementation:- CLI commands:
cli.py:116-526 - API client core:
client.py:291-826 - Authentication flow:
auth.py:254-300 - Filter algorithm:
filter.py:23-87 - Output formatting:
formatter.py:21-238
