bilibili:
- live-verified 2026-06: bilibili 412-blocks yt-dlp in every
configuration (latest version, direct, proxied, warmed cookies) while
bili-cli works fine without login — so yt-dlp no longer serves this
channel (it remains the YouTube backend)
- backends = [bili-cli, OpenCLI, B站搜索 API]: bili-cli covers
search/hot/rank/video-detail/audio, OpenCLI adds subtitles through the
browser session, the search API is the zero-dependency fallback
- when a broken candidate is bypassed by a working fallback, its
reinstall prescription is appended to the winning message instead of
being swallowed
- skill docs (social.md + video.md): "do NOT use yt-dlp for bilibili"
warning, bili-cli/OpenCLI command groups, curl fallback recipe,
B站 audio transcription path via `bili audio` + agent-reach transcribe
twitter:
- OpenCLI joins as the middle candidate [twitter-cli, OpenCLI, bird]
- social.md: explicit 4-step search retry chain (retry → upgrade →
OpenCLI → stable-command detour)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- live-verified 2026-06: anonymous .json endpoints are 403-blocked (all
variants) and the official API closed self-service registration in
2025-11 — so the channel now says plainly: every Reddit backend needs
a logged-in session, mainland China needs a proxy
- backends = [OpenCLI, rdt-cli]: OpenCLI rides the browser session
(desktop preferred); rdt-cli stays for servers and existing installs
(upstream unmaintained since 2026-03, noted in the ok message)
- install: desktop routes to OpenCLI, server installs rdt-cli from the
pinned git source (split out as _install_rdt_cli)
- skill/references/social.md: Reddit section rewritten as two backend
command groups + a PRAW note scoped to users who already hold
pre-2025-11 credentials (explicitly not recommended for new users)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- backends becomes the ordered candidate list [OpenCLI, xiaohongshu-mcp,
xhs-cli]; probing order makes the desktop/server split automatic:
OpenCLI never probes alive headless, so servers fall through to
xiaohongshu-mcp; first fully-usable candidate wins, fixable (warn)
candidates only win when nothing is fully usable
- xiaohongshu-mcp probing: HTTP reachability of localhost:18060
(proxy-bypassed) + mcporter config presence; guides through
`mcporter config add` when half-wired
- opencli backend: treat a sleeping extension service worker as ready —
verified live that `daemon status` reports disconnected while any real
command wakes it; disambiguate "sleeping" vs "never installed" via the
Chrome Extensions directory on disk (fixes active_backend flapping
between OpenCLI and xhs-cli across doctor runs)
- install: desktop installs OpenCLI; server prints the xiaohongshu-mcp
guide (binary to ~/.agent-reach/tools/, QR login, mcporter add);
xhs-cli is no longer installed by default (upstream unmaintained since
2026-03) but existing installs keep working as the last candidate
- skill/references/social.md: xiaohongshu section rewritten as three
backend command groups keyed off `doctor --json` active_backend,
including the 120s-timeout and login-first caveats for the mcp path
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- backends is now an ordered candidate list (first = preferred); channels
report the backend actually serving via active_backend, surfaced in the
doctor text report and --json
- new agent_reach/probe.py really executes upstream commands and tells
apart missing / broken (stale venv shebang after a system Python
upgrade) / timeout, with a reinstall prescription for broken installs
- all 13 channels migrated off which()-only checks: fixes bilibili
false-positive "bili-cli 可用" on broken shims, misleading xiaohongshu
"连接失败", rdt OSError crashing doctor, mcporter breakage masquerading
as "未配置"
- twitter: 15s probe + 1 retry (flaky 10s timeout), broken twitter-cli
now falls back to bird instead of aborting the check
- doctor survives per-channel exceptions; config supports per-channel
backend override (<channel>_backend / <CHANNEL>_BACKEND env)
- fix skill install/uninstall crash on symlinked skill dirs (the
"[Errno None] None" warning from shutil.rmtree on a symlink)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All three had rotted past honest usability:
- Douyin's upstream (yzfly/douyin-mcp-server) is archived and required a
4-step manual local-server setup nobody could complete
- Weibo depended on an unmaintained personal fork (mcp-server-weibo)
- WeChat full-article reading was increasingly blocked by anti-bot
(#339) while doctor still advertised it as zero-config
Removes the channel files, installers, skill routing/trigger entries,
reference sections and README rows (zh+en). Honest counts: 13 platforms,
6 zero-config. They can return when maintained upstreams exist.
Follows the v1.4.0 precedent of removing Discord/Toutiao (#234).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extracted from #318 (the UTF-8/doctor core, minus the env-wrapper feature):
- new agent_reach/utils/process.py: utf8_subprocess_env() +
mcporter_utf8_env_args() — Windows GBK consoles otherwise corrupt
Chinese output from mcporter/MCP child processes
- weibo/douyin/linkedin checks and weibo install/registration now pass
the UTF-8 env (and register the MCP server with --env PYTHONUTF8=1)
- youtube: extract _has_js_runtime_config() with an OSError guard so an
unreadable yt-dlp config can't crash doctor
- test_skill_command: open SKILL.md with explicit utf-8 (Windows GBK
default broke these tests)
Co-authored-by: chidao <2980933590@qq.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds agent_reach/transcribe.py (download → compress → chunk → transcribe with provider fallback, fully mocked tests). Maintainer follow-up on the branch: wired an agent-reach transcribe CLI subcommand + skill docs so agents can actually invoke it, added the missing configure openai-key branch the error hint referenced, removed two dead static methods. 103 tests pass; wheel-gate clean.
PyPI still only has rdt-cli 0.4.1 while the doctor hint required >=0.4.2, so the suggested install command always failed. Installs from the upstream GitHub repo pinned to the 0.4.2 commit instead, and syncs all four docs that still taught the PyPI path. Verified locally: clean-venv install from the pinned source yields rdt 0.4.2 and rdt status works. 86 tests pass. Fixes#294.
Four small correctness fixes found while live-testing community PRs:
- SKILL.md taught agents 'twitter search --limit 10' but twitter-cli
v0.8.5 has no --limit (real flag is -n/--max) — every agent following
the skill got a usage error
- transcribe_xiaoyuzhou.sh audio regex only matched lowercase .m4a/.mp3;
current episodes serve uppercase .MP3 (verified on a live episode) —
add /i flag
- reddit.py declared tier=0 (zero-config) while its own docstring says
Reddit requires login since 2024 — set tier=1 to match reality (tier
is doctor display metadata only)
- docs/README_en.md referenced the retired 'bird' CLI name once
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CRITICAL FIX: update.md was telling agents to uninstall bird CLI,
which broke users who had working bird installations. Now:
- twitter.py: prefers twitter-cli, falls back to bird/birdx if installed
- update.md: removed "clean up deprecated tools" step entirely
- Added explicit rule: "Never uninstall any existing tools the user already has"
- Tests cover twitter-cli primary + bird fallback + preference order
78 tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- WebChannel.read(): reads any URL via Jina Reader (r.jina.ai), returns Markdown
- _install_skill(): add fallback from importlib.resources to Path(__file__) for editable installs
- Explicit UTF-8 encoding on all file read/write operations
Inspired by PR #215, implemented correctly (Jina instead of raw requests).
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reddit: Exa crawling had chronic CRAWL_LIVECRAWL_TIMEOUT issues.
rdt-cli (304 stars, public-clis) works without login — search, read
full posts, and comments all verified. Massive improvement.
Bilibili: add bili-cli (590 stars) as optional enhanced backend for
hot/rank/search/feed. yt-dlp remains for video metadata + subtitles.
Also fix UA string (was "agent-reach/1.0", now proper browser UA).
75 tests passing.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Discord only returns server metadata (no messages without Bot Token),
not useful enough. Toutiao search was fragile (HTML scraping). Both
can be revisited when better upstream tools appear.
75 tests passing.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
miku_ai (Sogou WeChat search) has been unmaintained for 20 months.
Exa can search AND read WeChat articles via mp.weixin.qq.com domain
filtering — verified: search returns articles, crawling returns full text.
Jina Reader fails on WeChat (CAPTCHA block).
- wechat.py: check() now detects Exa (primary) + Camoufox (optional)
- tier downgraded from 2 to 0 (Exa is zero-config)
- skill/references/web.md: updated WeChat commands to use Exa
- 104 tests passing
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
browser_cookie3 has been unmaintained for 15+ months and breaks with
newer browser versions. rookiepy (Rust-based, 345 stars, updated 2026-01)
is now the preferred cookie extraction backend.
- xueqiu.py: try rookiepy first, fallback to browser_cookie3
- cookie_extract.py: same priority order, compatible API wrapper
- Remove bird CLI credential sync (bird repo deleted)
- 104 tests passing
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Zero-config channel (tier=0). Uses Discord Invite API to read public
server info (no auth), and Exa via mcporter for content search.
Tested: discord.gg/python returns 419K members, description, channel.
104 tests passing.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Zero-config channel (tier=0). Searches so.toutiao.com by scraping
embedded JSON from script tags. Fixes URL extraction order from PR #207
(article_url is the primary field, not display.info.url). Adds read()
via Jina Reader. 89 tests passing.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Reddit blocks nearly all non-browser access at IP level (including ISP proxies).
Switch Reddit channel to use Exa exclusively:
- Search: web_search_exa with includeDomains: ["reddit.com"]
- Read: crawling_exa for full post + comments
- check() now verifies Exa availability instead of probing Reddit API
- tier changed from 1 (needs config) to 0 (zero config)
- Removed reddit_proxy from config, CLI, and setup guide
- Updated all docs (README, README_en, install.md, SKILL.md, references)
- Fixed xreach→bird references in references/social.md
Fixes#218, Fixes#222, Fixes#221
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Xueqiu stock API requires a login session token (xq_a_token) that
is generated by Xueqiu's frontend JavaScript and cannot be obtained by
simply visiting the homepage. This caused persistent HTTP 400 (error
code 400016) for all users.
Changes:
- _ensure_cookies(): add three-level priority — config file (saved by
--from-browser) → live Chrome cookies via browser_cookie3 → homepage
fallback. The homepage-only approach only ever got acw_tc (anti-DDoS
token), never xq_a_token.
- _get_json(): switch User-Agent from "agent-reach/1.0" to a real Chrome
UA, and add Referer: https://xueqiu.com/ to all API requests.
- get_hot_posts(): replace the defunct /statuses/hot/listV3.json endpoint
(returns empty body) with the v4 public timeline endpoint; correctly
parse item.data as a JSON string to extract author, text, and likes.
- cookie_extract.py: add Xueqiu to PLATFORM_SPECS and configure_from_browser
so that `agent-reach configure --from-browser chrome` now also saves
Xueqiu cookies (only when xq_a_token is present).
- check(): improve error message to direct users to --from-browser instead
of suggesting a proxy.
- Fix urllib.parse.quote usage (was using urllib.request.quote).
- Update tier and backends description to reflect cookie requirement.
- Add 2 new tests: cookie loading from config, Referer/UA header verification.
- Update docs: README, install guide, troubleshooting, SKILL.md, CHANGELOG.
- Add 'agent-reach skill --install/--uninstall' command for explicit skill management
- Make 'agent-reach doctor' auto-install skill if not present (fixes#154)
- Add format_xhs_result() to strip bloated XHS JSON to essential fields (fixes#134)
- Add 'agent-reach format xhs' CLI command (pipe mcporter output to clean it)
- Update SKILL.md with XHS formatter usage tip
- Add tests for both features (11 new tests, 73/73 total pass)
Co-authored-by: Panniantong <panniantong@users.noreply.github.com>
* feat: add Xueqiu (雪球) channel for stock quotes and community posts
Add a Tier 0 (zero-config) channel for Xueqiu, China's popular stock
market and investment community platform. Uses auto-generated session
cookies via http.cookiejar — no login required.
Supported methods:
- get_stock_quote(symbol) — real-time quotes (A/HK/US markets)
- search_stock(query) — search by name or code
- get_hot_posts(limit) — trending community posts
- get_hot_stocks(limit, stock_type) — popular stocks leaderboard
Inspired by https://github.com/jackwener/opencli xueqiu implementation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add Xueqiu to README platform tables, remove stale Instagram ref
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: fernando_jacob <f.jacob1996@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Replace xreach CLI with bird (@steipete/bird) as Twitter/X backend
- bird uses AUTH_TOKEN/CT0 env vars (simpler than xreach's session.json)
- Accept both 'bird' and 'birdx' binary names
- Remove version detection logic (bird v0.8.0 is the baseline)
- Write credentials.env to ~/.config/bird/ for easy sourcing
- Keep xfetch session.json sync for backward compatibility
- Update SKILL.md commands: bird search/read/user-tweets/thread
- Update install/uninstall to use npm @steipete/bird
- All 52 tests pass
Reddit API requires a non-empty User-Agent header per its API rules.
Without it, the JSON endpoint returns 403 even when Reddit is reachable,
causing doctor to falsely report the channel as unavailable.
Changes:
- Add _reddit_reachable() helper that probes Reddit JSON API with UA
- doctor check() now distinguishes 'actually unreachable' from 'no proxy'
- Users on home IPs get 'ok' when Reddit is reachable; warn only on real failure
Fixes#168
- Replace brittle '"status": "ok"' string match with proper JSON parsing
in _mcporter_status_ok(). Handles Windows BOM, CRLF line endings, and
whitespace variations that caused false negatives on Windows + mcporter 0.7.3.
- Fallback to normalised string matching for backward compatibility.
- Extend config-get timeout to 15 s and list timeout to 30 s on Windows
(unchanged on Linux/macOS: 5 s / 10 s).
Fixes#159
* feat(channels): add V2EX support via public API
V2EX provides a public JSON API that requires no authentication.
This PR adds:
- agent_reach/channels/v2ex.py: V2EXChannel (tier=0, zero-config)
- can_handle() matches v2ex.com URLs
- check() verifies API reachability via urllib (no extra deps)
- Register V2EXChannel in channels/__init__.py
- SKILL.md: add V2EX section with curl examples for hot topics,
node browsing, topic detail, replies, and user info
- tests/test_channels.py: URL matching + mocked ok/warn check tests
V2EX API endpoints used:
GET /api/v2/topics/hot — hot topics
GET /api/topics/show.json — node topics / topic detail
GET /api/replies/show.json — topic replies
GET /api/members/show.json — user info
* feat(channels): expand V2EX channel with data-fetching methods
Add get_hot_topics, get_node_topics, get_topic, get_user, and search
methods to V2EXChannel using stdlib urllib only (no new dependencies).
Update unit tests and SKILL.md with Python call examples.
* feat(v2ex): add data fetching methods to V2EXChannel
Config class writes YAML (config.yaml), but xiaoyuzhou.py, cli.py, and
transcribe.sh were hardcoded to read config.json (JSON format). Users who
configured groq-key via 'agent-reach configure' would not have their key
detected because the wrong file was being read.
Fixes#128 (related to config loading)
Co-authored-by: Panniantong <panniantong@users.noreply.github.com>
xreach-cli v0.3.2 added:
- extractTweetText() preferring note_tweet.text for long tweets
- X Article URL support (/article/ path)
Previously, doctor reported 'ok' even when the user had v0.3.0/v0.3.1
installed, silently failing to read longform tweets. Now check() reads
`xreach --version` and returns a warn with upgrade instructions if the
version is below 0.3.2.
Closes#126
Co-authored-by: neo_minion1 <minion@openclaw.ai>
Fixes#128
Two bugs:
1. doctor warn message said 'agent-reach configure groq-api-key' but the
actual CLI arg is 'groq-key' (see cli.py:75 choices list and :993 handler).
Same typo existed in cli.py _install_xiaoyuzhou_deps() output.
2. check() had a logic flaw: the inner 'if not has_key' was nested inside
'if not os.environ.get(...)', so when GROQ_API_KEY env var was absent but
config.json read succeeded, the outer condition never triggered the warning.
Refactored to a flat has_key variable — cleaner and correct.
Verified: 36/36 tests pass, manual unit tests confirm warn uses 'groq-key'
and ok is returned when groq_api_key is present in config.json.
Co-authored-by: 小白(Agent) <neo@agent-reach.dev>
- Weibo now auto-installs during 'agent-reach install' (no login needed)
- Uses Panniantong/mcp-server-weibo fork with visitor passport auth fix
- Works from overseas servers without proxy or cookies
- Updated README (CN/EN), install.md, and channel check to point to fork
- 10 tools: trending, search content/users/topics, profile, feeds, comments
Co-authored-by: Panniantong <panniantong@users.noreply.github.com>
- YouTube: warn when only Node.js is installed but yt-dlp config file
is missing (previously returned "ok" incorrectly)
- Douyin: use `mcporter list` instead of calling with a hardcoded
invalid share URL that always fails
- cli: replace bare `except:` with `except Exception:` in
`_detect_environment` to avoid catching KeyboardInterrupt/SystemExit
- cli: fix unclosed file handle for cloud VM detection
- config: use `os.open()` with 0o600 mode to eliminate permission
race window when saving credentials
- wechat channel now supports both search and read
- Search: miku_ai (sogou weixin search) → article list with URLs
- Read: camoufox (stealth Firefox) → full Markdown content
- Doctor shows granular status (search only / read only / both)
- SKILL.md updated with search + read workflow examples
Co-authored-by: Panniantong <panniantong@users.noreply.github.com>
- Replace text=True with encoding='utf-8', errors='replace' in all
subprocess.run calls (channels + cli.py) to fix GBK decode errors
on Chinese Windows systems
- Use shutil.which() resolved paths in channel subprocess calls to
handle Windows .cmd wrappers (npm global installs)
Co-authored-by: Panniantong <panniantong@users.noreply.github.com>
yt-dlp now requires an external JS runtime (deno or Node.js) for YouTube.
Since agent-reach already installs Node.js, we configure yt-dlp to use it:
1. cli.py: install writes '--js-runtimes node' to ~/.config/yt-dlp/config
2. youtube.py: doctor checks JS runtime availability and config
3. SKILL.md: updated YouTube section with accurate troubleshooting
Bilibili note: 412 errors are IP-based (needs proxy), not cookie-related.
Fixes#47
- Detect ARM64 architecture and auto-add --platform linux/amd64 to
docker run hints in doctor/check output
- Add ARM64 FAQ section to setup guide with two options:
Rosetta emulation (--platform linux/amd64) or build from source
- Closes#44