A tool to collect tweets from your Twitter/X feed and filter them using Claude Haiku to remove slop
- macOS (uses AppleScript to control Chrome)
- Google Chrome browser
- Python 3.8+
- Anthropic API key (for the filter feature)
-
Clone the repository and navigate to the directory:
cd good-twitter -
Create a virtual environment and install dependencies:
python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt -
Create a
.envfile with your Anthropic API key:echo "ANTHROPIC_API_KEY=sk-ant-your-key-here" > .env
-
Make the collector script executable:
chmod +x collect.sh
-
(Optional) Set up mobile sync:
To view tweets on your phone, create a secret GitHub Gist for syncing:
a. Go to https://gist.github.com and create a new secret gist (don't check "Create public gist") b. Add any placeholder content and save c. Copy the gist ID from the URL (the part after
gist.github.com/yourusername/) d. Create config files:# Shell config (for collect.sh) cp config.example.sh config.sh # Edit config.sh and add your GIST_ID and GITHUB_USERNAME # JS config (for reader.html) cp data/config.example.js data/config.js # Edit data/config.js with the same values
Now when you run
./collect.sh -f, tweets will sync to your gist. Open the reader on your phone and tap "Sync" to pull them.
./collect.shThis will:
- Open Chrome (or use an existing Twitter tab)
- Navigate to
x.com/home - Auto-scroll and collect ~200 tweets
- Open the reader interface in your browser
./collect.sh --filteror
./collect.sh -fThis runs the Claude Haiku classifier after collection to filter out low-quality content (engagement bait, spam, etc.).
./collect.sh 500 # Collect 500 tweets
./collect.sh 300 --filter # Collect 300 tweets, then filterThe collector scrolls whichever Twitter tab/feed you're currently on.
Before running, navigate to your desired feed in Chrome:
| Feed | URL | What You Get |
|---|---|---|
| For You (FYP) | x.com/home (default tab) |
Algorithmic recommendations |
| Following (Popular) | x.com/home → click "Following" |
Tweets from accounts you follow, sorted by engagement |
| Following (Recent) | x.com/following or toggle in Following |
Chronological tweets from accounts you follow |
The script defaults to x.com/home, but if you have a Twitter tab already open, it will use that tab's current feed position. So if you last visited "Following", it will continue scrolling there.
The classification prompt determines what gets kept vs. skipped. You can customize it in two places:
- Open the reader (
data/reader.html) - Click the "Prompt" button in the header
- Edit the classification prompt in the text area
- Enter your API key
- Click "Re-run Filter" to reprocess all tweets
Changes are saved to localStorage and persist between sessions.
Edit filter.py and modify the CLASSIFICATION_PROMPT variable (around line 20):
CLASSIFICATION_PROMPT = """Classify this tweet for a technical reader. Return JSON only.
SKIP (skip: true) if: engagement bait, SaaS spam, generic AI hype...
KEEP (skip: false) if: articles, papers, GitHub links...
Author: @{handle} ({name})
Content: {text}
Links: {links}
Return ONLY valid JSON: {"skip": bool, "quality": "high"/"medium"/"low", "topic": "short_slug", "summary": "one sentence"}"""The placeholders {handle}, {name}, {text}, and {links} are automatically replaced with tweet data.
| File | Description |
|---|---|
data/collected.json |
Raw collected tweets |
data/filtered.json |
Tweets with classification metadata (when using --filter) |
data/reader.html |
The reader interface |
- Quality badges: High/Medium/Low quality indicators
- Topic tags: Auto-generated topic slugs
- Summaries: One-line summaries for each tweet
- Skipped panel: View filtered-out tweets (click "Skipped" button)
- Re-filter: Modify the prompt and re-run classification from the UI
- Paste support: Manually paste tweet JSON with Cmd+V
"Failed to inject script": Make sure Chrome is open with at least one window.
Rate limiting: The filter uses 5 parallel requests. If you hit rate limits, it will automatically retry with exponential backoff.
No tweets collected: Ensure you're logged into Twitter in Chrome and the feed is loading.