- twitter: align backend selection with the two-phase findings pattern —
an unauthenticated twitter-cli (warn) no longer blocks a fully-working
OpenCLI (ok) further down the candidate list
- watch: use _is_newer_version like check-update (the != comparison kept
the downgrade prompt this branch fixed elsewhere)
- uninstall: third copy of the skill-dir removal also gets the symlink
guard (full `agent-reach uninstall` path)
- doctor: a stale active_backend from a previous check on the singleton
channel no longer leaks into an errored result
+4 regression tests (162 total).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
- 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>
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>
- 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
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>
- 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>
- Twitter _read_jina now detects unusable X.com responses (JS-required pages)
and shows a friendly error instead of garbage HTML
- CLI read command now shows user-friendly messages for invalid URLs
and connection errors instead of raw HTTP exception traces