feat: migrate Twitter backend from bird CLI to xreach CLI
bird CLI (@steipete/bird) is deprecated and no longer maintained. xreach CLI (xreach-cli on npm) is our maintained fork with: - Fixed SearchTimeline (POST + updated query ID) - Built-in proxy rotation support - Additional features (DMs, notifications, lists) Changes across 11 files: - channels/twitter.py: detect xreach instead of bird/birdx - cli.py: install/doctor/uninstall all reference xreach-cli - SKILL.md: updated command examples (bird read → xreach tweet) - guides/setup-twitter.md: rewritten for xreach - docs/troubleshooting.md: updated proxy guidance - README.md + README_en.md: all references updated - config.py: twitter_bird → twitter_xreach - core.py, mcp_server.py: comment updates npm package: https://www.npmjs.com/package/xreach-cli Source: https://github.com/Panniantong/xfetch
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Twitter/X — check if bird CLI is available."""
|
||||
"""Twitter/X — check if xreach CLI is available."""
|
||||
|
||||
import shutil
|
||||
import subprocess
|
||||
@@ -9,7 +9,7 @@ from .base import Channel
|
||||
class TwitterChannel(Channel):
|
||||
name = "twitter"
|
||||
description = "Twitter/X 推文"
|
||||
backends = ["bird CLI"]
|
||||
backends = ["xreach CLI"]
|
||||
tier = 1
|
||||
|
||||
def can_handle(self, url: str) -> bool:
|
||||
@@ -18,21 +18,21 @@ class TwitterChannel(Channel):
|
||||
return "x.com" in d or "twitter.com" in d
|
||||
|
||||
def check(self, config=None):
|
||||
bird = shutil.which("bird") or shutil.which("birdx")
|
||||
if not bird:
|
||||
xreach = shutil.which("xreach")
|
||||
if not xreach:
|
||||
return "warn", (
|
||||
"bird CLI 未安装。搜索可通过 Exa 替代。安装:\n"
|
||||
" npm install -g @steipete/bird"
|
||||
"xreach CLI 未安装。搜索可通过 Exa 替代。安装:\n"
|
||||
" npm install -g xreach-cli"
|
||||
)
|
||||
try:
|
||||
r = subprocess.run(
|
||||
[bird, "whoami"], capture_output=True, text=True, timeout=10
|
||||
[xreach, "auth", "check"], capture_output=True, text=True, timeout=10
|
||||
)
|
||||
if r.returncode == 0:
|
||||
return "ok", "完整可用(读取、搜索推文)"
|
||||
return "warn", (
|
||||
"bird CLI 已安装但未配置 Cookie。运行:\n"
|
||||
"xreach CLI 已安装但未配置 Cookie。运行:\n"
|
||||
" agent-reach configure twitter-cookies \"auth_token=xxx; ct0=yyy\""
|
||||
)
|
||||
except Exception:
|
||||
return "warn", "bird CLI 已安装但连接失败"
|
||||
return "warn", "xreach CLI 已安装但连接失败"
|
||||
|
||||
+17
-17
@@ -387,24 +387,24 @@ def _install_system_deps():
|
||||
except Exception:
|
||||
print(" ⚠️ Node.js install failed. Try: apt install nodejs npm, or nvm install 22, or download from https://nodejs.org")
|
||||
|
||||
# ── bird CLI (for Twitter search) ──
|
||||
if shutil.which("bird") or shutil.which("birdx"):
|
||||
print(" ✅ bird CLI already installed")
|
||||
# ── xreach CLI (for Twitter search) ──
|
||||
if shutil.which("xreach"):
|
||||
print(" ✅ xreach CLI already installed")
|
||||
else:
|
||||
if shutil.which("npm"):
|
||||
try:
|
||||
subprocess.run(
|
||||
["npm", "install", "-g", "@steipete/bird"],
|
||||
["npm", "install", "-g", "xreach-cli"],
|
||||
capture_output=True, text=True, timeout=120,
|
||||
)
|
||||
if shutil.which("bird"):
|
||||
print(" ✅ bird CLI installed (Twitter search + timeline)")
|
||||
if shutil.which("xreach"):
|
||||
print(" ✅ xreach CLI installed (Twitter search + timeline)")
|
||||
else:
|
||||
print(" ⬜ bird CLI install failed (optional — Twitter reading still works via Jina)")
|
||||
print(" ⬜ xreach CLI install failed (optional — Twitter reading still works via Jina)")
|
||||
except Exception:
|
||||
print(" ⬜ bird CLI install failed (optional — Twitter reading still works via Jina)")
|
||||
print(" ⬜ xreach CLI install failed (optional — Twitter reading still works via Jina)")
|
||||
else:
|
||||
print(" ⬜ bird CLI requires Node.js (optional — Twitter reading still works via Jina)")
|
||||
print(" ⬜ xreach CLI requires Node.js (optional — Twitter reading still works via Jina)")
|
||||
|
||||
# ── undici (proxy support for Node.js fetch) ──
|
||||
if shutil.which("npm"):
|
||||
@@ -417,7 +417,7 @@ def _install_system_deps():
|
||||
subprocess.run(["npm", "install", "-g", "undici"], capture_output=True, text=True, timeout=60)
|
||||
print(" ✅ undici installed (Node.js proxy support)")
|
||||
except Exception:
|
||||
print(" ⬜ undici install failed (optional — bird may not work behind proxies)")
|
||||
print(" ⬜ undici install failed (optional — xreach may not work behind proxies)")
|
||||
|
||||
|
||||
def _install_system_deps_safe():
|
||||
@@ -429,7 +429,7 @@ def _install_system_deps_safe():
|
||||
deps = [
|
||||
("gh", ["gh"], "GitHub CLI", "https://cli.github.com — or: apt install gh / brew install gh"),
|
||||
("node", ["node", "npm"], "Node.js", "https://nodejs.org — or: apt install nodejs npm"),
|
||||
("bird", ["bird", "birdx"], "bird CLI (Twitter)", "npm install -g @steipete/bird"),
|
||||
("xreach", ["xreach"], "xreach CLI (Twitter)", "npm install -g xreach-cli"),
|
||||
]
|
||||
|
||||
missing = []
|
||||
@@ -459,7 +459,7 @@ def _install_system_deps_dryrun():
|
||||
checks = [
|
||||
("gh CLI", ["gh"], "apt install gh / brew install gh"),
|
||||
("Node.js", ["node"], "curl NodeSource setup | bash + apt install nodejs"),
|
||||
("bird CLI", ["bird", "birdx"], "npm install -g @steipete/bird"),
|
||||
("xreach CLI", ["xreach"], "npm install -g xreach-cli"),
|
||||
]
|
||||
|
||||
for label, binaries, method in checks:
|
||||
@@ -690,16 +690,16 @@ def _cmd_configure(args):
|
||||
print("Testing Twitter access...", end=" ")
|
||||
try:
|
||||
import subprocess
|
||||
bird = shutil.which("bird") or shutil.which("birdx")
|
||||
if not bird:
|
||||
print("⚠️ bird CLI not installed. Run: npm install -g @steipete/bird")
|
||||
xreach = shutil.which("xreach")
|
||||
if not xreach:
|
||||
print("⚠️ xreach CLI not installed. Run: npm install -g xreach-cli")
|
||||
else:
|
||||
import os
|
||||
env = os.environ.copy()
|
||||
env["AUTH_TOKEN"] = auth_token
|
||||
env["CT0"] = ct0
|
||||
result = subprocess.run(
|
||||
[bird, "search", "test", "-n", "1"],
|
||||
[xreach, "search", "test", "-n", "1"],
|
||||
capture_output=True, text=True, timeout=15,
|
||||
env=env,
|
||||
)
|
||||
@@ -823,7 +823,7 @@ def _cmd_uninstall(args):
|
||||
print()
|
||||
print("Optional: remove tools installed by Agent Reach:")
|
||||
print(" npm uninstall -g mcporter")
|
||||
print(" npm uninstall -g @steipete/bird")
|
||||
print(" npm uninstall -g xreach-cli")
|
||||
print(" npm uninstall -g undici")
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class Config:
|
||||
FEATURE_REQUIREMENTS = {
|
||||
"exa_search": ["exa_api_key"],
|
||||
"reddit_proxy": ["reddit_proxy"],
|
||||
"twitter_bird": ["twitter_auth_token", "twitter_ct0"],
|
||||
"twitter_xreach": ["twitter_auth_token", "twitter_ct0"],
|
||||
"groq_whisper": ["groq_api_key"],
|
||||
"github_token": ["github_token"],
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
AgentReach — installer, doctor, and configuration tool.
|
||||
|
||||
Agent Reach helps AI agents install and configure upstream platform tools
|
||||
(bird CLI, yt-dlp, mcporter, gh CLI, etc.). After installation, agents
|
||||
(xreach CLI, yt-dlp, mcporter, gh CLI, etc.). After installation, agents
|
||||
call the upstream tools directly — no wrapper layer needed.
|
||||
|
||||
Usage:
|
||||
|
||||
@@ -1,67 +1,77 @@
|
||||
# Twitter 高级功能配置指南(bird CLI)
|
||||
# Twitter 高级功能配置指南(xreach CLI)
|
||||
|
||||
## 功能说明
|
||||
基础 Twitter 功能(搜索+读单条推文)无需配置,开箱即用。
|
||||
Twitter 基础阅读通过 Jina Reader 免费可用,无需配置。
|
||||
|
||||
高级功能需要 bird CLI:
|
||||
- 查看用户时间线
|
||||
- 深度搜索(更精确、更多结果)
|
||||
- 读取完整线程(thread)
|
||||
- 查看关注列表推文
|
||||
高级功能需要 xreach CLI:
|
||||
|
||||
bird 是免费开源工具(npm 包 @steipete/bird),但需要你的 Twitter 账号 cookie。
|
||||
- 搜索推文(`xreach search`)
|
||||
- 读取完整推文和对话链(`xreach tweet`、`xreach thread`)
|
||||
- 用户时间线(`xreach tweets`)
|
||||
|
||||
## Agent 可自动完成的步骤
|
||||
xreach 是免费开源工具(npm 包 xreach-cli),但需要你的 Twitter 账号 cookie。
|
||||
|
||||
## 快速配置
|
||||
|
||||
1. 检查 xreach 是否安装:
|
||||
|
||||
1. 检查 bird 是否安装:
|
||||
```bash
|
||||
which bird && echo "installed" || echo "not installed"
|
||||
which xreach && echo "installed" || echo "not installed"
|
||||
```
|
||||
|
||||
2. 安装 bird:
|
||||
2. 安装 xreach:
|
||||
|
||||
```bash
|
||||
npm install -g @steipete/bird
|
||||
npm install -g xreach-cli
|
||||
```
|
||||
|
||||
3. 测试(需要先配置 cookie):
|
||||
3. 测试是否配置好:
|
||||
|
||||
```bash
|
||||
AUTH_TOKEN="xxx" CT0="yyy" bird search "test" -n 1
|
||||
AUTH_TOKEN="xxx" CT0="yyy" xreach search "test" -n 1
|
||||
```
|
||||
|
||||
4. 用 agent-reach 配置 cookie(推荐):
|
||||
## 获取 Cookie(Cookie-Editor 方式,推荐)
|
||||
|
||||
1. 安装 [Cookie-Editor](https://cookie-editor.com/) 浏览器扩展
|
||||
2. 登录 x.com
|
||||
3. 点击 Cookie-Editor 图标 → Export → 复制全部
|
||||
4. 运行配置命令:
|
||||
|
||||
```bash
|
||||
agent-reach configure twitter-cookies "auth_token=xxx; ct0=yyy"
|
||||
agent-reach configure twitter-cookies "粘贴的 cookie JSON"
|
||||
```
|
||||
|
||||
## 需要用户手动做的步骤
|
||||
这会自动提取 `auth_token` 和 `ct0`,并写入环境变量。
|
||||
|
||||
请告诉用户:
|
||||
## 手动设置 Cookie
|
||||
|
||||
> Twitter 高级功能需要你的 Twitter 账号 cookie(完全免费)。
|
||||
>
|
||||
> **最简单的方式:**
|
||||
> 1. 安装 Chrome 插件 [Cookie-Editor](https://chromewebstore.google.com/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm)
|
||||
> 2. 打开 https://x.com 并确保已登录
|
||||
> 3. 点击 Cookie-Editor 插件图标 → Export → Header String
|
||||
> 4. 把导出的内容发给我
|
||||
>
|
||||
> **手动方式:**
|
||||
> 1. 用 Chrome 打开 https://x.com 并确保你已登录
|
||||
> 2. 按 **F12** 打开开发者工具(Mac 按 Cmd+Option+I)
|
||||
> 3. 点击顶部的 **Application**(应用)标签
|
||||
> 4. 左侧找到 **Cookies** → **https://x.com**
|
||||
> 5. 在列表中找到以下两个值,双击复制:
|
||||
> - **auth_token** — 一串字母数字
|
||||
> - **ct0** — 一串字母数字
|
||||
> 6. 把这两个值发给我
|
||||
>
|
||||
> ⚠️ 这些 cookie 让我能以你的身份读取推文(只读)。我不会发推、点赞或做任何操作。
|
||||
> ⚠️ cookie 大约 1-3 个月会过期,届时需要重新导出。
|
||||
如果你已经知道 `auth_token` 和 `ct0`:
|
||||
|
||||
## Agent 收到 cookie 后的操作
|
||||
1. 安装 xreach(如果没装):`npm install -g xreach-cli`
|
||||
|
||||
1. 安装 bird(如果没装):`npm install -g @steipete/bird`
|
||||
2. 配置 cookie:`agent-reach configure twitter-cookies "粘贴的内容"`
|
||||
3. 测试:运行 `agent-reach doctor` 确认 Twitter 状态
|
||||
4. 反馈:"✅ Twitter 高级功能已开启!现在可以搜索推文、查看时间线了。"
|
||||
5. 如果失败:"❌ Cookie 无效或已过期,请重新导出。"
|
||||
2. 设置环境变量:
|
||||
|
||||
```bash
|
||||
export AUTH_TOKEN="你的auth_token"
|
||||
export CT0="你的ct0"
|
||||
```
|
||||
|
||||
3. 测试:
|
||||
|
||||
```bash
|
||||
xreach search "test" --auth-token "$AUTH_TOKEN" --ct0 "$CT0" -n 1
|
||||
```
|
||||
|
||||
## 代理配置
|
||||
|
||||
> xreach CLI 内置代理支持,通过 `--proxy` 参数传入:
|
||||
|
||||
```bash
|
||||
xreach search "test" --auth-token "$AUTH_TOKEN" --ct0 "$CT0" --proxy "http://user:pass@host:port"
|
||||
```
|
||||
|
||||
也支持代理轮换文件:
|
||||
|
||||
```bash
|
||||
xreach search "test" --auth-token "$AUTH_TOKEN" --ct0 "$CT0" --proxy-file proxies.txt
|
||||
```
|
||||
|
||||
@@ -5,7 +5,7 @@ Agent Reach MCP Server — expose doctor/status as MCP tool.
|
||||
Run: python -m agent_reach.integrations.mcp_server
|
||||
|
||||
Agent Reach is an installer + doctor tool. For actual reading/searching,
|
||||
agents should call upstream tools directly (bird, yt-dlp, mcporter, etc.).
|
||||
agents should call upstream tools directly (xreach, yt-dlp, mcporter, etc.).
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
||||
@@ -23,7 +23,7 @@ agent-reach install --env=auto
|
||||
agent-reach doctor
|
||||
```
|
||||
|
||||
`install` auto-detects your environment and installs core dependencies (Node.js, mcporter, bird CLI, gh CLI, yt-dlp, feedparser). Run `doctor` to see what's active.
|
||||
`install` auto-detects your environment and installs core dependencies (Node.js, mcporter, xreach CLI, gh CLI, yt-dlp, feedparser). Run `doctor` to see what's active.
|
||||
|
||||
## Management
|
||||
|
||||
@@ -78,17 +78,17 @@ When a user asks to configure/enable any channel:
|
||||
|
||||
After `agent-reach install`, call the upstream tools directly. No need for `agent-reach read` or `agent-reach search`.
|
||||
|
||||
### Twitter/X (bird CLI)
|
||||
### Twitter/X (xreach CLI)
|
||||
|
||||
```bash
|
||||
# Search tweets
|
||||
bird search "query" --json -n 10
|
||||
xreach search "query" --json -n 10
|
||||
|
||||
# Read a specific tweet
|
||||
bird read https://x.com/user/status/123 --json
|
||||
xreach tweet https://x.com/user/status/123 --json
|
||||
|
||||
# Read a user's timeline
|
||||
bird timeline @username --json -n 20
|
||||
xreach tweets @username --json -n 20
|
||||
```
|
||||
|
||||
### YouTube (yt-dlp)
|
||||
@@ -248,7 +248,7 @@ for e in d.entries[:5]:
|
||||
|
||||
### Twitter "fetch failed"
|
||||
|
||||
bird CLI uses Node.js native `fetch()`, which doesn't respect `HTTP_PROXY`. Solutions:
|
||||
xreach CLI uses Node.js `undici`, which doesn't respect `HTTP_PROXY`. Solutions:
|
||||
1. Ensure `undici` is installed: `npm install -g undici`
|
||||
2. Configure proxy: `agent-reach configure proxy http://user:pass@ip:port`
|
||||
3. If still failing, use transparent proxy (Clash TUN, Proxifier)
|
||||
|
||||
Reference in New Issue
Block a user