Home / All Skills / Content & Media Creation / twitter-reader
Content & Media Creation · daymade/claude-code-skills

twitter-reader

Fetch Twitter/X post content including long-form Articles with full images and metadata. Use when Claude needs to retrieve tweet/article content, author info, engagement metrics, and embedded media. Supports individual posts and X Articles (long-form content). Automatically downloads all images to local attachments folder and generates complete Markdown with proper image references. Preferred over Jina for X Articles with images.

L4 High-Privilege · Graded auth & full auditV1 Commit-PinnedExecute CommandInstall DepsNetwork AccessWrite FileDual-pass Audit
Author daymadeGitHub daymade/claude-code-skills ↗Stars 1378License MITCommit 63a65c1fcc
Control levels describe skill capabilities and suggested control measures; they do not represent quality or safety certifications, nor do they dictate usability. Usage decisions rest entirely with users and administrators. Different agent hosts apply varying constraints; do not assume hosts provide automatic protection. Third-party skill copyrights belong to their original authors. Use at your own risk.

1How It Works & Mechanism

The preferred path for single-post plain text requires no login and no API key, directly curling the fxtwitter mirror API, with the full text extracted from tweet.text (the documentation notes that the full_text key does not exist) — this path requires zero credentials and zero configuration, replacing Jina as the default since 2026-08-30.

twitter-reader/SKILL.md
works direct, and returns the **full note_tweet body in `tweet.text`** (the `full_text` key does not exist; a 2,324-char long-form announcement came back complete):
The documentation provides an inline `curl -sS --max-time 20 "https://api.fxtwitter.com/<user>/status/<id>" | python3 -c ...` recipe executed directly by the agent (without script encapsulation); after the mirror API returns structured JSON, only the created_at and text fields are extracted. This is the skill's actual answer to reading single posts: no page scraping, no official API calls, relying entirely on a third-party mirror.

The primary path for X Articles (long-form articles with images) is handled by fetch_article.py: it first uses `uv run --with twitter-cli` to install and execute on the fly the `twitter article` subcommand from the PyPI package twitter-cli, retrieving structured YAML containing author/metrics/articleText.

twitter-reader/scripts/fetch_article.py
def run_twitter_cli(url: str) -> dict: """Fetch article data using twitter-cli via uv run.""" cmd = ["uv", "run", "--with", "twitter-cli", "twitter", "article", url]
Each execution resolves and installs twitter-cli ephemerally via uv (version unpinned), and the output is parsed using yaml.safe_load in parse_yaml_output to extract the data field. Metadata (createdAtLocal/author/metrics{likes,retweets,bookmarks}/articleTitle/articleText) relies entirely on the proprietary output format of this third-party CLI; this repository does not implement any direct Twitter API connections.

Body content (including images) is scraped via Jina Reader (r.jina.ai): carrying a Bearer token if JINA_API_KEY is present, or anonymously if not; the body text is then sliced out using the 'Markdown Content:' marker, falling back to articleText returned by twitter-cli if Jina fails.

twitter-reader/scripts/fetch_article.py
api_key = os.getenv("JINA_API_KEY", "") jina_url = f"https://r.jina.ai/{url}" cmd = ["curl", "-s", jina_url] if api_key: cmd.extend(["-H", f"Authorization: Bearer {api_key}"])
The documentation explicitly notes that anonymous r.jina.ai access to x.com suffers from intermittent global 403 bans due to third-party abuse (tested on 2026-08-30), positioning Jina as a 'usable but unreliable' body content source; the key here is an optional optimization rather than a strict requirement.

Image localization is the script's core value-add: regex extracts pbs.twimg.com/media links from scraped Markdown → deduplicates and standardizes them to ?format=jpg&name=large → downloads them individually via curl to attachments/date-author-title/ → regex-replaces remote image URLs in the body text with local relative paths.

twitter-reader/scripts/fetch_article.py
pattern = r'https://pbs\.twimg\.com/media/[^\s\)"\']+'
extract_image_urls strictly recognizes the pbs.twimg.com/media prefix, confining the download surface to Twitter's image CDN; download_images flushes files to disk using `curl -sL url -o filepath` (no timeout, sequential, sequential naming like 01-image.jpg...), and replace_image_urls rewrites all remote URLs into attachments/... local relative references, ensuring Markdown remains viewable offline.

Output convention: YYYY-MM-DD-title.md (including YAML frontmatter: source/author/date/likes/retweets/bookmarks) + an attachment directory of the same name; the date takes the first 10 characters of createdAtLocal, while the title and author are sanitized and truncated to 60 characters via sanitize_filename.

twitter-reader/scripts/fetch_article.py
md = f"""--- source: {source_url} author: {author.get("name", "")} date: {date_str} likes: {metrics.get("likes", 0)}
generate_markdown concatenates frontmatter + body text; if the body contains localized image references, it is first rewritten via replace_image_urls before assembly. The overall workflow functions as a 'webpage/tweet → clean PKM file' converter tailored for Obsidian-style knowledge bases.

Jina text mode serves as a fallback bypass: fetch_tweet.py (single tweet, strictly requires JINA_API_KEY, HTTPS only) and fetch_tweets.sh (bash batch loop, regex allows http/https) directly curl r.jina.ai and pass through the Bearer token.

twitter-reader/scripts/fetch_tweets.sh
for url in "$@"; do if [[ ! "$url" =~ ^https?://(x\.com|twitter\.com)/ ]]; then
This bypass is explicitly designated as a fallback in SKILL.md (the documentation acknowledges that the shared key has a 402 insufficient balance error and the batch script is currently unusable), with the core recommendation being 'do not rely on it' — making this a rare skill that explicitly documents the risks of its own backup channel.

2Core Capabilities

01Login-free full-text retrieval of single posts (preferred fxtwitter channel)
02X Article long-form content scraping (including note_tweet-level extended text)
03Structured metadata: author, date, and engagement metrics (likes/retweets/bookmarks)
04Automatic batch downloading of embedded images to local attachments directory and rewriting to local references
05Generation of Markdown files with YAML frontmatter (source/author/date/likes/retweets/bookmarks) tailored for PKM systems
06Single/batch scraping in Jina text mode (fetch_tweet.py / fetch_tweets.sh) with URL allowlist validation
07Content source degradation and fault tolerance: fallback to twitter-cli articleText when Jina fails; empirical testing and documentation of third-party channel instability

3External Dependencies

KindDependency / Endpoint
clicurl
cliuv (Python 包管理器)
clipython3(含内联 -c 解析)
packagetwitter-cli(PyPI,uv 现场安装并执行 twitter article 子命令,未 pin 版本)
packagepyyaml
apiJina Reader API
networkfxtwitter 镜像 API
networkTwitter 图片 CDN(图片下载目标)
networkx.com / twitter.com(被抓取目标,经 fxtwitter/Jina 代理访问)

4Recommended Governance & Evidence

Suggested Controls for Safe Operation
For Agent Runtime
Graded/per-use authorization, sandbox recommended
For Administrators
Approval workflow, rollback support, full audit
Evidence & Triggers (File Paths & Excerpts)
  • scripts/: Executes local script or command: scripts/fetch_article.py —— `uv run --with pyyaml python scripts/fetch_arti
  • scripts/ 或 SKILL.md: Declares dynamic installation of external language package dependencies
  • 网络端点: Declares external network access: https://api.fxtwitter.com/<user>/status/<id> (keyless mirror, SKILL.md fxtwitter section)
  • 本地工作目录: File read/write and artifact output: fetch_article.py: writes <output_dir>/YYYY-MM-DD-<safe_title>.md and <output_dir>/a
Audit Notes: Investigative advisory, not an official certification. The orange rating is assigned because it literally meets both conditions in the orange criteria table: (a) Reading environment variable credentials — JINA_API_KEY is strictly read and transmitted externally by two scripts (destination is unique and predictable: r.jina.ai itself, with no cookies/keychain/hardcoded keys, avoiding higher severity tiers); (b) Dependency on third-party remote packages — the main execution path installs and runs twitter-cli (unpinned) on the fly from PyPI via uv each run, executing code outside the audit scope of this repository and beyond the boundary covered by .security-scan-passed (static gitleaks scan of this directory's text). The scripts themselves have no shell=True, no obfuscation, no concealed exfiltration, download endpoints are regex-restricted strictly to pbs.twimg.com, and the keyless fxtwitter path uses zero credentials — keeping it below red tier. However, the combination of 'remote packages + env credentials' precludes green/blue tiers, and yellow tier's 'public APIs/official CLIs only with predictable exfiltration' does not entirely apply; hence rated Orange: use after evaluation.

5Second-Pass Verification

  • [ok] fxtwitter API(api.fxtwitter.com)调用点真实存在 — SKILL.md fxtwitter 段内联 curl 配方原文命中;文档自述 2026-08-30 实测过 2,324 字符 note_tweet 完整返回。仅验证调用点,端点当前可达性未在线复核
  • [ok] Jina r.jina.ai 调用点真实存在 — 三个脚本各自命中:fetch_tweet.py `jina_api_url = f"https://r.jina.ai/{url}"`、fetch_tweets.sh `curl -s "https://r.jina.ai/${url}"`、fetch_article.py run_jina_api;Bearer 头与 JINA_API_KEY 读取逐处对上
  • [ok] twitter-cli 依赖真实存在(uv run --with) — fetch_article.py run_twitter_cli 的 argv 原文命中;SKILL.md Quick Start 另以 `uv run --with pyyaml` 启动脚本,与 parse_yaml_output 的 yaml 导入一致
  • [ok] pbs.twimg.com 图片下载路径真实存在且仅此 CDN — extract_image_urls 正则仅匹配 pbs\.twimg\.com/media/ 前缀;download_images 用 curl -sL 落盘。未发现其他图片域名
  • [ok] JINA_API_KEY 读取点全覆盖、无硬编码密钥 — grep JINA_|sk- 于 twitter-reader/ 命中仅 3 处 env 读取(无字面量);全仓库 CHANGELOG 记录 2026-01-05 前后『Removed hardcoded API keys』。SKILL.md 所述『shared key 402 余额尽』系作者侧市场共享 key,仓库内无对应字符串
  • [ok] URL 校验形态:前缀白名单而非权威解析 — fetch_tweet.py/fetch_article.py 用 startswith(("https://x.com/","https://twitter.com/"));fetch_tweets.sh 用正则 ^https?://(x\.com|twitter\.com)/。三处均要求主机后紧跟 /,可挡 https://x.com.evil.com 型主机混淆;bash 版放行 http:// 与文档『HTTPS only』表述存在出入(py 版严格)
  • [ok] 无隐藏脚本/无混淆/无隐蔽外发 — 目录仅 SKILL.md + 3 脚本 + .security-scan-passed 标记;脚本全部为列表式 subprocess,无 shell=True/eval/curl 之外的网络动词;.security-scan-passed 为纯文本记录,无执行作用
  • [ok] 功能声明与代码能力相符性 — 『长文带图 + 元数据 + 自动下载 + Markdown』在 fetch_article.py 中逐项落实;但核心卖点依赖第三方间歇服务:Jina 匿名被全局 ban 时正文只剩 twitter-cli 的 articleText 兜底(可能不含图),文档已如实标注『Preferred over Jina…』仅针对有图场景——无夸大但有外部依赖边界

6Verdict & Scenarios

  • Zero-cost path for single posts: prioritizes login-free and keyless fxtwitter mirror, with documentation providing fully executable curl recipes
  • One-click conversion of long-form articles with images into local PKM files: automated metadata + image downloading + URL rewriting + YAML frontmatter
  • Honest documentation: records failure experiences such as intermittent global bans and shared key exhaustion for primary/fallback channels (Jina) directly in SKILL.md with degradation designs, preventing agents from treating unreliable paths as primary channels
  • Extremely narrow dependency footprint: requires only curl + uv + two small scripts with no heavy runtime, producing a clean output structure (YYYY-MM-DD-title.md + attachments/)
  • Best for: Individuals or teams needing to convert X posts/articles (with images) into clean local Markdown for notes, PKM, or secondary processing; Claude Code-style environments; scenarios where users are willing to supply their own Jina key (optional) and accept third-party mirrors and proxy channels.
    Not for: Scenarios requiring reply threads/comment lists (replies are count-only), data requiring authenticated login states, zero-tolerance supply chain policies or offline environments (twitter-cli is installed on the fly via uv each time), and large-scale compliant web crawling treating X scraping as a core service.
    Install Agent-Ready
    ① Verified Mirror 2026-09-06
    Option A · Direct DownloadDownload twitter-reader.tar.gz
    sha256: 6e441b1396143142…
    Option B · Copy Guide for Agent
    install.json
    Agents automatically download and verify mirrors from this JSON guide.
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit 63a65c1fcc.