
tweet-rl-tracker
by different-ai
CLI-first banking for agents
SKILL.md
name: tweet-rl-tracker description: Create and manage a Notion-based tweet performance tracking system for "poor man's reinforcement learning" license: MIT compatibility: opencode metadata: service: notion, chrome-devtools-mcp category: content
What I Do
Set up a Notion database to track tweet performance and enable a feedback loop for improving tweet quality over time. This is "poor man's reinforcement learning" - manually logging outcomes to discover what works.
NEW: Screenshot Capture - Automatically capture screenshots from tweet links (including video frames at 10 seconds) using Chrome DevTools MCP.
The RL Loop
1. WRITE -> Draft tweet with a hypothesis (hook type, topic, etc.)
2. POST -> Publish to Twitter/X
3. LOG -> Record in Notion after 24-48hrs with metrics
4. SCORE -> Mark "Worked?" based on engagement rate
5. REVIEW -> Weekly: compare winners vs losers, extract patterns
6. REPEAT -> Apply learnings to step 1
Database Schema
Core Fields (Outcomes)
| Property | Type | Purpose |
|---|---|---|
| Tweet | title | The tweet text |
| Likes | number | Primary engagement signal |
| Impressions | number | Reach/views |
| Score | formula | Likes / Impressions * 100 (engagement %) |
| Worked? | checkbox | Binary gut-check - was this a win? |
Input Features (What You Controlled)
| Property | Type | Options |
|---|---|---|
| Hook | select | Question, Bold Claim, Story, List, How-To, Contrarian, Data/Stats |
| Topic | select | (customize to your niche) |
| Posted | date | When you posted |
Optional Extensions
| Property | Type | Purpose |
|---|---|---|
| Replies | number | Conversation signal |
| Retweets | number | Amplification signal |
| Link | url | Link to original tweet |
| Notes | rich_text | Why did it work/fail? |
Setup Instructions
Step 1: Create the Page and Database
Use the Notion MCP tools to create:
notion_notion-create-pages with:
- title: "Tweet Lab" (or your preferred name)
- content: Brief intro about the system
Then inside that page, create a database with:
notion_notion-create-database with the schema above
Step 2: Example Notion Tool Calls
Create the container page:
{
"pages": [
{
"properties": { "title": "Tweet Lab" },
"content": "## Tweet Performance Tracker\n\nA simple system to track what works and improve over time.\n\n### The Loop\n1. Post tweet\n2. Log metrics after 24-48hrs\n3. Mark if it \"Worked\"\n4. Weekly: review patterns\n\n<database>Tweets</database>"
}
]
}
Create the database (after getting page_id):
{
"parent": { "page_id": "<page-id-from-above>" },
"title": [{ "type": "text", "text": { "content": "Tweets" } }],
"properties": {
"Tweet": { "type": "title", "title": {} },
"Likes": { "type": "number", "number": { "format": "number" } },
"Impressions": { "type": "number", "number": { "format": "number" } },
"Score": {
"type": "formula",
"formula": {
"expression": "if(prop(\"Impressions\") > 0, prop(\"Likes\") / prop(\"Impressions\") * 100, 0)"
}
},
"Worked?": { "type": "checkbox", "checkbox": {} },
"Hook": {
"type": "select",
"select": {
"options": [
{ "name": "Question", "color": "blue" },
{ "name": "Bold Claim", "color": "red" },
{ "name": "Story", "color": "green" },
{ "name": "List", "color": "yellow" },
{ "name": "How-To", "color": "purple" },
{ "name": "Contrarian", "color": "orange" },
{ "name": "Data/Stats", "color": "pink" }
]
}
},
"Topic": {
"type": "select",
"select": { "options": [] }
},
"Posted": { "type": "date", "date": {} }
}
}
Using the System
Daily: Log Tweets
After 24-48 hours, add a row:
- Copy tweet text
- Pull Likes and Impressions from Twitter analytics
- Select the Hook type you used
- Select or create a Topic tag
Weekly: Review Session
- Sort by Score (descending) - what performed best?
- Filter by "Worked?" = true - what patterns emerge?
- Group by Hook - which hook types win?
- Group by Topic - which topics resonate?
Monthly: Form Hypotheses
Based on patterns, create hypotheses to test:
- "Questions about [topic] get 2x engagement"
- "Bold claims underperform for my audience"
- "Threads outperform single tweets"
Then deliberately test these in the next month.
Key Insights
What Makes This Work
- Track inputs, not just outputs - Without knowing what you tried (hook, topic), you can't learn what caused success
- Binary "Worked?" is powerful - Forces a clear decision, easier to analyze than continuous scores
- Review regularly - Data without reflection is useless
- Test hypotheses deliberately - Don't just observe, experiment
Common Pitfalls
- Logging inconsistently (do it same time each day/week)
- Not tracking input features (hook, topic)
- Never reviewing the data
- Optimizing for wrong metric (likes vs. replies vs. followers)
Customization
Different Goals = Different Metrics
| Goal | Primary Metric | Formula |
|---|---|---|
| Virality | Retweets / Impressions | Amplification rate |
| Engagement | (Likes + Replies) / Impressions | Interaction rate |
| Growth | Profile clicks / Impressions | Curiosity rate |
| Community | Replies / Impressions | Conversation rate |
Add Your Topics
Update the Topic select options based on your niche. Examples:
- Tech founder: Product, Fundraising, Hiring, Lessons, Industry
- Creator: Process, Tools, Mindset, Results, Behind-the-scenes
Troubleshooting
"I forget to log tweets"
- Set a daily/weekly calendar reminder
- Add a "Logged?" checkbox to your posting workflow
- Batch log once per week instead of daily
"I don't know what hook I used"
- Decide BEFORE posting, not after
- Add hook type to your tweet drafting process
- When in doubt, pick the closest match
"My Score is always low"
- Engagement rates are typically 1-5% - this is normal
- Compare relative performance, not absolute numbers
- Consider using a different base metric for "Worked?"
Screenshot Capture with Chrome MCP
Prerequisites
- Chrome DevTools MCP configured in your MCP client
- Logged into Twitter/X in the Chrome profile
Database Field
The Tweets database includes a Screenshot field (type: files) to store captured images.
Data Source ID: a6913492-bfdc-4f6a-b539-ea98b57a2738
Workflow: Capture Tweet Screenshot
Given a tweet URL like https://x.com/username/status/1234567890:
Step 1: Navigate to Tweet
// Open new page with the tweet
new_page({ url: 'https://x.com/username/status/1234567890' });
// Wait for tweet to load
wait_for({ text: 'Reply' }); // or wait for specific tweet content
Step 2: Take Screenshot of Tweet
// Take full page screenshot
take_screenshot({ fullPage: false });
// Or screenshot specific element (the tweet article)
take_snapshot(); // Get element uids first
take_screenshot({ uid: 'tweet-article-uid' });
Step 3: For Video Tweets - Capture Frame at 10 Seconds
// 1. Find and click the video to start playing
take_snapshot();
click({ uid: 'video-player-uid' });
// 2. Wait 10 seconds for video to play
// (Use evaluate_script to seek if possible)
evaluate_script({
function: `() => {
const video = document.querySelector('video');
if (video) {
video.currentTime = 10;
video.pause();
return { success: true, duration: video.duration };
}
return { success: false };
}`,
});
// 3. Take screenshot of the video frame
take_screenshot({ fullPage: false });
Step 4: Extract Tweet Metadata
evaluate_script({
function: `() => {
// Extract tweet text
const tweetText = document.querySelector('[data-testid="tweetText"]')?.textContent || '';
// Extract author
const author = document.querySelector('[data-testid="User-Name"]')?.textContent || '';
// Extract metrics (likes, retweets, etc.)
const metrics = {};
document.querySelectorAll('[data-testid="like"], [data-testid="retweet"]').forEach(el => {
const label = el.getAttribute('aria-label') || '';
if (label.includes('like')) metrics.likes = parseInt(label) || 0;
if (label.includes('repost')) metrics.retweets = parseInt(label) || 0;
});
// Check if video exists
const hasVideo = !!document.querySelector('video');
const hasImage = !!document.querySelector('[data-testid="tweetPhoto"]');
return {
text: tweetText,
author,
metrics,
mediaType: hasVideo ? 'Video' : hasImage ? 'Image' : 'None'
};
}`,
});
Complete Example: Add Tweet with Screenshot
User: Add this tweet to the tracker: https://x.com/unvalley_/status/2005899617775542298
Agent workflow:
1. new_page({ url: 'https://x.com/unvalley_/status/2005899617775542298' })
2. wait_for({ text: 'Reply' })
3. take_snapshot() - to see page structure
4. evaluate_script() - extract tweet text, author, media type
5. If video: seek to 10s and pause
6. take_screenshot() - capture the visual
7. Save screenshot to local file (screenshot is returned as base64)
8. Create Notion page with extracted data + screenshot file
Saving Screenshot to Notion
Important: Notion's files property requires external URLs. The workflow is:
- Take screenshot with Chrome MCP (returns base64)
- Save to a publicly accessible location (e.g., upload to S3, Cloudinary, or use a temp file host)
- Add the URL to the Notion page's Screenshot field
// After taking screenshot, you'll get base64 data
// Save it locally first:
const fs = require('fs');
const screenshotPath = `/tmp/tweet-${Date.now()}.png`;
fs.writeFileSync(screenshotPath, Buffer.from(base64Data, 'base64'));
// Then upload to your preferred hosting and get URL
// Finally, create Notion page with the screenshot URL
Quick Reference: Chrome MCP Tools for Tweet Capture
| Tool | Purpose |
|---|---|
new_page | Navigate to tweet URL |
wait_for | Wait for tweet to load |
take_snapshot | Get accessibility tree (find element uids) |
take_screenshot | Capture visual screenshot |
evaluate_script | Extract tweet data, control video playback |
click | Click play button on video |
Troubleshooting Screenshots
"Tweet not loading"
- Check if logged into Twitter in Chrome profile
- Twitter may require login for some content
- Try
wait_forwith longer timeout
"Video won't seek"
- Some videos are streaming and don't support seeking
- Try clicking play first, then waiting 10 seconds naturally
- Use
setTimeoutin evaluate_script if needed
"Screenshot is blank"
- Wait longer for content to render
- Check if page has overlay/modal blocking content
- Try
fullPage: trueto capture everything
"Can't upload to Notion"
- Notion files require external URLs
- Use a file hosting service (S3, Cloudinary, imgur)
- Or embed screenshot as image in page content instead
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
1ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon


