AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
翻譯準備中
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Universal content reader MCP Server for 10+ platforms
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Give your agent a URL. Let x-reader handle the source.
x-reader is a universal content reader for AI agents. It reads X/Twitter, articles, YouTube, Bilibili, podcasts, WeChat, Xiaohongshu, Telegram, RSS, and the open web, then normalizes the result into structured source content for downstream research, summarization, and automation.
Its differentiator is evidence-aware reading: a search snippet is not the source, a tweet caption is not the attached video, and a video description is not a transcript. When a material source layer is still missing, x-reader keeps that gap explicit instead of pretending the read is complete.
简体中文: README.zh-CN.md · Website: xreader.leolabs.me · Try it in the browser
Paste this into your AI agent (Claude Code, Codex, Cursor, …):
Set up x-reader on this computer by following the official instructions at https://github.com/runesleo/x-reader/blob/main/install.md.
Your agent installs the skill and the CLI, runs the read-only x-reader doctor self-check, and reads a first link with you. The steps it follows are in install.md; to do it by hand, see below.
The plugin bundles the skills in skills/ and the x-reader MCP server (started with uvx, so uv must be installed).
/plugin install x-reader --marketplace runesleo/x-readercodex plugin marketplace add runesleo/x-reader, then codex plugin add x-reader@runesleo.cursor-plugin/plugin.json; Cursor Marketplace listing is not live yet.Optional sources (logged-in pages, Telegram, transcription) still need the setup in install.md.
The same runesleo marketplace lists Leo's other tools. After adding it, install any of them by name:
| Plugin | What it does | Claude Code | Codex |
|---|---|---|---|
| polymarket-toolkit | Read-only Polymarket wallet profiles, PnL, Brier scores | ✓ | ✓ |
| x-signal-digest | Turn an X feed into 0–3 useful signals | ✓ | ✓ |
| video-explainer-kit | Brief → reviewed vertical explainer video | ✓ | ✓ |
| talk-human | Make drafts sound like you | ✓ | ✓ |
| multi-ai-sync | Check every agent's results reach your machine | ✓ | ✓ |
The public beta is live for public X, YouTube, and generic web URLs: Product · 中文 · Open app. Paste a URL and it returns the same canonical evidence states used by x-reader: PASS, PARTIAL, FAIL, or UNKNOWN. Results can be copied as a human-readable receipt or JSON, and shared without upgrading missing evidence into success.
Run it locally with x-reader-web, or use the hosted beta above. See Evidence Receipt, the distribution plan, and the public-beta gate.
npx skills add runesleo/x-reader --skill x-reader
Then give your agent a URL and ask it to read the original source. For example:
Read the original source. If it contains attached video/audio that matters to the answer, consume that too. Tell me what you actually read and what is still missing.
The canonical skill uses an explicit evidence contract:
PASS original source + all material media needed for the answer were read
PARTIAL some material layer is still missing
FAIL the original source could not be fetched reliably
UNKNOWN retrieved material is too ambiguous to verify
Run the same evidence contract through a small local web surface:
pip install -e .
x-reader-web --host 127.0.0.1 --port 8787
The current hosted-MVP policy accepts public X/Twitter, YouTube, and generic web URLs only. It uses a fresh temporary HOME/inbox per request and does not inherit saved browser sessions, Telegram credentials, Groq keys, Obsidian/output paths, or external X cookies.
The web layer does not add a second reader or evidence state machine: it invokes the existing x-reader URL --json path in the isolated environment and projects the result into PASS / PARTIAL / FAIL / UNKNOWN.
See Evidence Receipt for API examples, the isolation boundary, and the mixed-media receipt contract.
The source-fetch hardening has a live, reproducible delta against public v0.3.0:
https://example.com: v0.3.0 hit Jina HTTP 401 and failed; v0.3.1 safely falls back to direct_html_pinned and returns READ.media_status=present, so post text can be READ while unconsumed attached media stays PARTIAL.Watch the 12-second MP4 proof · v0.3.1 release notes
A public X benchmark was run end-to-end after the Agent Skill merged to main:
Source:
https://x.com/dontbesilent/status/2103875422522077377
Post text PASS fetched from the original status via oEmbed
Attached video PASS public MP4 resolved and downloaded
Video duration ~178.3 seconds
Spoken content PASS native zh subtitle track retrieved and read
Broken URL FAIL non-zero exit + machine-readable JSON error
The public owner/repo install path was also verified from a fresh directory:
npx skills add runesleo/x-reader --skill x-reader
# Repository cloned
# Found 3 skills
# Selected 1 skill: x-reader
# Installation complete
See First-success receipt for the dated verification details.
Agents can often find something about a URL while still missing the source the user asked about.
x-reader makes these distinctions explicit:
| What the agent has | What it may claim |
|---|---|
| Search result / preview card | Discovery only — not source evidence |
| X post text | Claims in the post text only |
| X post text + unconsumed attached video | Post may pass; video stays PARTIAL |
| First post of a thread, quoted post or X Article not read | PARTIAL until that layer is shown absent (a quoted post can also be read; an X Article body never is) |
| Video page title / description | Metadata only — not spoken content |
| Subtitle track covering the whole video | Spoken-content evidence; the video stays PARTIAL because pictures are not analyzed |
| Login wall / deleted page / empty payload | FAIL or PARTIAL, never invented completion |
| Paywall teaser, cookie wall, menu-only page | PARTIAL, FAIL or UNKNOWN; a generic page passes only with substantial prose |
| Source | Base read path | Media / gated completion |
|---|---|---|
| X / Twitter | oEmbed → FxTwitter → Article/Jina → Playwright | Agent Skill can inspect attached media with local media tools |
| Web / articles | Pinned direct read (checks redirects and embedded audio/video) → Jina Reader text | A redirect into X, YouTube, podcasts, etc. is handed to that reader; the hosted beta shows the direct read |
| YouTube | yt-dlp metadata/subtitles | Groq Whisper fallback when configured |
| Bilibili | Bilibili API | Subtitle/audio transcription workflow |
| Jina → Playwright | Headless browser fallback for public articles; saved login sessions are not used yet | |
| Xiaohongshu | Jina → Playwright | One-time local login may be required |
| Telegram | Telethon | Telegram credentials required |
| RSS | feedparser | — |
| Xiaoyuzhou / Apple Podcasts | Episode page and show notes | Spoken audio only with the opt-in local ASR flags below; notes alone stay PARTIAL |
Platform behavior changes over time. x-reader's contract is to expose the gap rather than overclaim coverage.
Install directly from GitHub:
pip install "x-reader @ git+https://github.com/runesleo/x-reader.git"
Read a URL:
x-reader https://x.com/elonmusk/status/123456
Check what is ready and what is missing (read-only; add --json for agents):
x-reader doctor
Get the complete machine-readable payload:
x-reader https://x.com/elonmusk/status/123456 --json
Multiple URLs:
x-reader https://url1.com https://url2.com --json
Browser fallback:
pip install "x-reader[browser] @ git+https://github.com/runesleo/x-reader.git"
playwright install chromium
x-reader login twitter
x-reader login xhs
By default, local cookies stay local. External cookie forwarding is opt-in only.
skills/
├── x-reader/ # canonical source-first URL reader (CLI bootstrap + evidence contract)
├── link-reader/ # drop-a-link workflow: read original → explain → judge (pairs with x-reader)
├── video/ # video/podcast transcription workflow
└── analyzer/ # evidence-grounded content analysis
List them without installing:
npx skills add runesleo/x-reader --list
Recommended install
| Use case | Skills |
|---|---|
| Fetch URLs with PASS/PARTIAL/FAIL receipts | x-reader only |
| “Here’s a link — what does it say?” (default bare-link behavior) | x-reader + link-reader |
# Reader + interpretation workflow (Claude Code / Cursor / Codex)
npx skills add runesleo/x-reader --skill x-reader --skill link-reader -g -y
link-reader does not replace x-reader: it routes all fetches through the x-reader CLI or MCP tools, adds evidence-level language, thread/media coverage discipline, and an optional offline check_reading_coverage.py validator under skills/link-reader/scripts/. Follow install.md once so x-reader doctor is green before relying on media or logged-in sources.
Works with any host that supports Agent Skills (Claude Code, Cursor, Codex, and compatible agents): install into the agent’s global or project skills directory, then paste a URL and ask for the original source.
npx skills add runesleo/x-reader --skill x-reader --skill link-reader -g -y
Then paste any URL with no other instructions. Expected behavior:
x-reader, not search snippets.PASS / PARTIAL / FAIL / UNKNOWN. For example, post text read but the attached video not → PARTIAL.Optional offline check on a structured thread receipt:
python3 skills/link-reader/scripts/check_reading_coverage.py --target-id "POST_ID" < receipt.json
Clone and install the MCP extra:
git clone https://github.com/runesleo/x-reader.git
cd x-reader
pip install -e ".[mcp]"
Run directly from a clone:
python mcp_server.py
Or launch the packaged MCP entrypoint straight from GitHub with uvx:
uvx --with "mcp[cli]>=1.0,<2" \
--from git+https://github.com/runesleo/x-reader.git \
x-reader-mcp
The x-reader-mcp console entrypoint is packaged inside x_reader; the root mcp_server.py remains as a backward-compatible source-checkout shim.
Tools exposed:
read_url(url)read_batch(urls)list_inbox()detect_platform(url)For Claude Code, add the server with the CLI instead of editing a Claude Desktop config:
claude mcp add x-reader -- python /absolute/path/to/x-reader/mcp_server.py
Use --scope user if you want the server available beyond the current project.
The MCP server currently targets FastMCP 1.x; the mcp and all extras intentionally pin mcp<2.
Podcast episode show notes are not an audio transcript. x-reader classifies supported podcast episode URLs as source_type=podcast and marks metadata-only reads PARTIAL.
For a local, explicitly requested and bounded 12-second sample using free on-device Whisper (still PARTIAL, never a full episode):
# Local CLI only (not on the hosted web reader); experimental.
python -m pip install "x-reader[media] @ git+https://github.com/runesleo/x-reader.git"
# Also install ffmpeg and yt-dlp to PATH
x-reader 'https://www.xiaoyuzhoufm.com/episode/6abb9b69195d838e2aeb9c2b' --media-preview-seconds 12 --json
For an explicit complete short-audio read (public Xiaoyuzhou only, ≤2 MiB encoded / ≤120 seconds) (experimental, local CLI only):
x-reader 'https://www.xiaoyuzhoufm.com/episode/6a14e9dd3209346094186445' --media-full-short --json
Short mode returns PASS only after exact HTTP 206 source bytes, SHA-256, audio/PCM durations and full-input local ASR processing are verified. Episodes exceeding the short-mode limits remain PARTIAL in that mode.
Experimental resumable long audio: The local CLI supports a separately opted-in, single public Xiaoyuzhou episode up to 64 MiB encoded and 90 minutes. It uses verified 1-MiB HTTP 206 chunks, strong-ETag source versioning, local 60-second PCM/ASR segments, temporal coverage checks, and private on-disk checkpoints:
# Local CLI only; not available on the hosted web reader.
x-reader 'https://www.xiaoyuzhoufm.com/episode/6aab4896051af796b9e966c5' --media-full-long --json
One real 277.9-second episode passed full-source proof and resumed all 5/5 source chunks plus 5/5 ASR checkpoints on repeat. Very long or inaccessible audio remains PARTIAL, not a false PASS. The cached audio chunks and ASR text persist locally in a private directory; use an isolated X_READER_LONG_CACHE_DIR for sensitive workflows. Machine transcripts can still be wrong. No background work or paid API is enabled. See media coverage, short-source proof, and the 2026-10-10 long-audio verification.
For local media extraction:
# macOS
brew install yt-dlp ffmpeg
# Linux
pip install yt-dlp
sudo apt install ffmpeg
For Whisper transcription, set a Groq API key:
export GROQ_API_KEY=your_key_here
The current YouTube Groq transcription code uses whisper-large-v3.
import asyncio
from x_reader.reader import UniversalReader
async def main():
reader = UniversalReader()
content = await reader.read("https://example.com")
print(content.title)
print(content.content[:200])
asyncio.run(main())
Copy .env.example to .env.
| Variable | Required | Description |
|---|---|---|
TG_API_ID | Telegram only | Telegram API ID |
TG_API_HASH | Telegram only | Telegram API hash |
GROQ_API_KEY | Whisper only | Groq transcription API |
INBOX_FILE | No | Inbox JSON path |
OUTPUT_DIR | No | Optional Markdown output directory |
OBSIDIAN_VAULT | No | Optional Obsidian vault path |
User gives URL
│
├─ text source
│ └─ platform fetcher → UnifiedContent → CLI JSON / inbox
│
├─ video / audio matters
│ └─ subtitle first → transcription fallback → evidence receipt
│
└─ analysis requested
└─ analyze only after source coverage is known
Core package:
x_reader/
├── cli.py
├── reader.py
├── schema.py
├── login.py
├── fetchers/
│ ├── twitter.py
│ ├── youtube.py
│ ├── bilibili.py
│ ├── wechat.py
│ ├── xhs.py
│ ├── telegram.py
│ ├── rss.py
│ ├── jina.py
│ └── browser.py
└── utils/
Leo (@runes_leo) — AI × Crypto independent builder.
leolabs.me — writing · community · open-source tools · indie projects.
Learn in public. Build in public.
MIT