skills/browser/plugins/twitter/SKILL.md
# twitter Browser plugin for extracting tweets from Twitter/X pages. Auto-loaded on `x.com` and `twitter.com`. ## Routes - `*://x.com/i/lists/*` — list timelines (browser + node) - `*://x.com/*/status/*` — tweet threads (browser + node) - `*://x.com/*` — any X page (browser + node) ## How Scrolling Works Twitter uses a **virtual DOM** — it replaces tweet articles as you scroll, keeping only ~10–15 tweets in the DOM at a time. The `twitter.fetch()` (node) function handles this by scrolling i
npx skillsauth add hayeah/dotfiles skills/browser/plugins/twitterInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Browser plugin for extracting tweets from Twitter/X pages. Auto-loaded on x.com and twitter.com.
*://x.com/i/lists/* — list timelines (browser + node)*://x.com/*/status/* — tweet threads (browser + node)*://x.com/* — any X page (browser + node)Twitter uses a virtual DOM — it replaces tweet articles as you scroll, keeping only ~10–15 tweets in the DOM at a time. The twitter.fetch() (node) function handles this by scrolling incrementally and collecting unique tweet IDs into a Map before they scroll out of view.
The scroll container is window (not a nested div), so window.scrollBy() is used.
Available as twitter in browser eval scope on x.com pages.
Extract all currently visible tweets from the DOM.
Returns: Array<Tweet>
Tweet = {
id: string, // tweet ID (numeric string)
author: string, // @handle without the @
displayName: string, // display name
text: string, // tweet text content
time: string, // ISO 8601 datetime
url: string, // canonical tweet URL
retweet: string|null, // retweet attribution text, or null
images: string[], // pbs.twimg.com/media URLs
}
Returns IDs of all currently visible tweets.
Returns: string[]
Scroll down by amount pixels (default: window.innerHeight).
Returns: number (new scrollY)
Scroll to absolute position y.
Returns: { scrollY: number, scrollHeight: number, atBottom: boolean }
Returns: boolean
Returns: string
--node)Scroll through the page and collect tweets, handling virtual DOM turnover.
Options:
limit — max tweets to collect (default: 100)until — ISO date string; stop when oldest tweet is before this datedelay — ms to wait after each scroll (default: 1500)scrollAmount — pixels per scroll step (default: window.innerHeight)maxStalls — stop after this many scrolls with no new tweets (default: 5)verbose — log progress to stderr (default: false)Returns: { tweets: Tweet[], scrollCount: number, stoppedReason: "limit"|"until"|"bottom"|"stalled" }
Like fetch() but saves tweets as JSON to path.
Returns: { saved: string, count: number, scrollCount: number, stoppedReason: string }
Like fetch() but returns tweets formatted as a markdown string.
Returns: string
Get currently visible tweets (browser):
browser eval 'JSON.stringify(twitter.tweets())'
Scroll through a list and save 50 tweets to JSON:
browser eval --node 'return JSON.stringify(await twitter.save("/tmp/tweets.json", {limit: 50, verbose: true}))'
Get tweets as markdown (pipe to file):
browser eval --node 'return await twitter.fetchMarkdown({limit: 30})' > tweets.md
Collect tweets newer than a date:
browser eval --node 'return JSON.stringify(await twitter.fetch({until: "2026-03-30T00:00:00Z", limit: 200}))'
Check scroll state:
browser eval 'JSON.stringify(twitter.scrollState())'
tools
Web UI development — Vite+ toolchain setup and browser-based E2E testing workflow.
tools
Tooling and style guide for TypeScript projects.
development
Capture tmux pane content and export as text, HTML, SVG, PNG, or JPG. Use when you need a screenshot or text dump of a tmux pane for sharing, feeding to AI, or archiving terminal state.
testing
Copy-edit text. Fix grammar and/or tidy text into a concise listicle.