From b060a4881864d8702921c7454807785b6a53fcc5 Mon Sep 17 00:00:00 2001
From: Pnant <73925474+Panniantong@users.noreply.github.com>
Date: Mon, 29 Jun 2026 11:04:52 +0800
Subject: [PATCH] feat(channels): add facebook and instagram opencli support
---
README.md | 20 ++++++--
agent_reach/channels/__init__.py | 26 ++++++-----
agent_reach/channels/_opencli_site.py | 48 +++++++++++++++++++
agent_reach/channels/facebook.py | 13 ++++++
agent_reach/channels/instagram.py | 13 ++++++
agent_reach/cli.py | 26 ++++++++---
agent_reach/skill/SKILL.md | 24 ++++++----
agent_reach/skill/SKILL_en.md | 20 +++++---
agent_reach/skill/references/social.md | 45 +++++++++++++++++-
docs/README_en.md | 13 ++++++
docs/install.md | 41 ++++++++++++++---
llms.txt | 14 +++---
tests/test_channel_contracts.py | 2 +
tests/test_channels.py | 64 ++++++++++++++++++++++++++
tests/test_cli.py | 56 ++++++++++++++++++++++
15 files changed, 373 insertions(+), 52 deletions(-)
create mode 100644 agent_reach/channels/_opencli_site.py
create mode 100644 agent_reach/channels/facebook.py
create mode 100644 agent_reach/channels/instagram.py
diff --git a/README.md b/README.md
index 039a06c..980858d 100644
--- a/README.md
+++ b/README.md
@@ -79,6 +79,8 @@ AI Agent 已经能帮你写代码、改文档、管项目——但你让它去
| 🐦 **Twitter/X** | 读单条推文 | 搜索推文、浏览时间线、读长文 | 告诉 Agent「帮我配 Twitter」 |
| 📺 **B站** | 搜索 + 视频详情(bili-cli,无需登录) | 字幕(OpenCLI) | 告诉 Agent「帮我配 B站」 |
| 📖 **Reddit** | —(没有零配置路径:匿名接口已被封) | 搜索 + 读帖子和评论 | 桌面装 OpenCLI 用浏览器登录态;或 rdt-cli + Cookie |
+| 📘 **Facebook** | — | 搜索、主页、Feed、群组列表 | 桌面装 OpenCLI(复用 Chrome 登录态) |
+| 📷 **Instagram** | — | 用户搜索、Profile、用户最近帖子、Explore | 桌面装 OpenCLI(复用 Chrome 登录态) |
| 📕 **小红书** | — | 搜索、阅读、评论 | 桌面装 OpenCLI(刷过小红书即可用);服务器用 xiaohongshu-mcp 扫码 |
| 💼 **LinkedIn** | Jina Reader 读公开页面 | Profile 详情、公司页面、职位搜索 | 告诉 Agent「帮我配 LinkedIn」 |
| 💻 **V2EX** | 热门帖子、节点帖子、帖子详情+回复、用户信息 | — | 无需配置 |
@@ -87,7 +89,7 @@ AI Agent 已经能帮你写代码、改文档、管项目——但你让它去
> **不知道怎么配?不用查文档。** 直接告诉 Agent「帮我配 XXX」,它知道需要什么、会一步一步引导你。
>
-> 🍪 需要 Cookie 的平台(Twitter、小红书等),**优先使用** Chrome 插件 [Cookie-Editor](https://chromewebstore.google.com/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm) 导出 Cookie,发给 Agent 即可配置。流程统一:浏览器登录 → Cookie-Editor 导出 → 发给 Agent。比扫码更简单可靠。
+> 🍪 需要 Cookie/登录态的平台(Twitter、小红书、Reddit、Facebook、Instagram 等),优先让用户在自己的浏览器里登录。OpenCLI 复用 Chrome 登录态;传统 CLI 才需要 Cookie-Editor 导出 Cookie。
>
> 🔒 Cookie 只存在你本地,不上传不外传。代码完全开源,随时可审查。
> 💻 本地电脑不需要代理。代理只有部署在服务器上才需要(~$1/月)。
@@ -133,7 +135,7 @@ AI Agent 已经能帮你写代码、改文档、管项目——但你让它去
3. **配置搜索引擎** — 通过 MCP 接入 Exa(免费,无需 API Key)
4. **检测环境** — 判断是本地电脑还是服务器,给出对应的配置建议
5. **注册 SKILL.md** — 在 Agent 的 skills 目录安装使用指南,以后 Agent 遇到"全网调研"、"搜推特"、"看视频"这类需求,会自动知道该调哪个上游工具
-6. **问你要不要更多** — 默认只激活 6 个零配置渠道;小红书、Twitter、Reddit 这些需要登录的,Agent 会列菜单问你要哪些,点名才装
+6. **问你要不要更多** — 默认只激活 6 个零配置渠道;小红书、Twitter、Reddit、Facebook、Instagram 这些需要登录态的,Agent 会列菜单问你要哪些,点名才装
安装完之后,`agent-reach doctor` 一条命令告诉你每个渠道的状态、当前走哪条路。
@@ -151,7 +153,7 @@ AI Agent 已经能帮你写代码、改文档、管项目——但你让它去
- "全网搜一下 LLM 框架对比" → Exa 语义搜索
- "订阅这个 RSS" → `feedparser` 解析
-**不需要记命令。** Agent 读了 SKILL.md 之后自己知道该调什么。需要登录的平台(小红书、Twitter、Reddit),告诉 Agent「帮我配 XXX」即可解锁。
+**不需要记命令。** Agent 读了 SKILL.md 之后自己知道该调什么。需要登录的平台(小红书、Twitter、Reddit、Facebook、Instagram),告诉 Agent「帮我配 XXX」即可解锁。
---
@@ -181,6 +183,8 @@ channels/
├── github.py → gh CLI
├── bilibili.py → bili-cli ▸ OpenCLI ▸ 搜索 API(yt-dlp 已被 B站风控封死,退役)
├── reddit.py → OpenCLI ▸ rdt-cli(无零配置路径,必须登录态)
+├── facebook.py → OpenCLI(桌面浏览器登录态)
+├── instagram.py → OpenCLI(桌面浏览器登录态)
├── xiaohongshu.py → OpenCLI ▸ xiaohongshu-mcp ▸ xhs-cli
├── linkedin.py → linkedin-mcp ▸ Jina Reader
├── rss.py → feedparser
@@ -197,6 +201,8 @@ channels/
| 读网页 | [Jina Reader](https://github.com/jina-ai/reader) | — | 免费,不需要 API Key |
| 读推特 | [twitter-cli](https://github.com/public-clis/twitter-cli) | [OpenCLI](https://github.com/jackwener/opencli) | 实测搜索稳定;OpenCLI 走浏览器登录态兜底 |
| Reddit | [OpenCLI](https://github.com/jackwener/opencli)(桌面) | [rdt-cli](https://github.com/public-clis/rdt-cli) | 匿名接口已被封、官方 API 审批制——只剩登录态路线 |
+| Facebook | [OpenCLI](https://github.com/jackwener/opencli)(桌面) | — | Graph API/Groups API 权限收紧;浏览器登录态是当前最实用路径 |
+| Instagram | [OpenCLI](https://github.com/jackwener/opencli)(桌面) | 官方 Graph API(Business/Creator + 审批) | instaloader 类路径不稳定;OpenCLI 复用真实浏览器会话 |
| YouTube 字幕 + 搜索 | [yt-dlp](https://github.com/yt-dlp/yt-dlp) | — | 154K Star,YouTube 仍是最佳(注意:不再用于 B站) |
| B站 | [bili-cli](https://github.com/public-clis/bilibili-cli) | OpenCLI ▸ 搜索 API | yt-dlp 被 B站风控 412 封死(2026-06 实测),bili-cli 无登录可搜可读 |
| 搜全网 | [Exa](https://exa.ai) via [mcporter](https://github.com/nicobailon/mcporter) | — | AI 语义搜索,MCP 接入免 Key |
@@ -225,7 +231,7 @@ Agent Reach 在设计上重视安全:
> ⚠️ **封号风险提醒:** 使用 Cookie 登录的平台(Twitter、小红书等),通过脚本/API 调用**存在被平台检测并封号的风险**。请务必使用**专用小号**,不要用你的主账号。
-需要 Cookie 的平台(Twitter、小红书)建议使用**专用小号**,不要用主账号。原因有二:
+需要 Cookie 或登录态的平台(Twitter、小红书、Reddit、Facebook、Instagram 等)建议使用**专用小号**,不要用主账号。原因有二:
1. **封号风险** — 平台可能检测到非正常浏览器的 API 调用行为,导致账号被限制或封禁
2. **安全风险** — Cookie 等同于完整登录权限,用小号可以在凭据泄露时限制影响范围
@@ -315,6 +321,12 @@ Reddit 所有访问都需要登录态(匿名接口已被全面封锁,官方
桌面电脑首选 **OpenCLI**(`agent-reach install --channels opencli`)——它复用你浏览器里的登录态,平时刷过小红书就直接能用,零配置;装完在 Chrome 商店点一次「添加扩展」即可。之后 Agent 用 `opencli xiaohongshu search "关键词"` 搜索、`opencli xiaohongshu note URL` 读笔记。服务器上用 [xiaohongshu-mcp](https://github.com/xpzouying/xiaohongshu-mcp)(自带无头浏览器,扫码登录)。已装过 xhs-cli 的老用户不受影响,它仍是备选后端(上游 2026-03 起停更,不推荐新装)。
+
+怎么让 AI Agent 读 Facebook / Instagram?
+
+桌面电脑走 **OpenCLI**:`agent-reach install --channels facebook,instagram`。装好 OpenCLI 和 Chrome 扩展后,在 Chrome 里登录 facebook.com / instagram.com,Agent 直接调用 `opencli facebook search "关键词" -f yaml`、`opencli facebook groups -f yaml`、`opencli instagram search "用户名或关键词" -f yaml`(搜用户)、`opencli instagram user USERNAME -f yaml`(读指定用户最近帖子)。服务器/无桌面环境不推荐支持这两个平台。
+
+
Compatible with Claude Code / Cursor / OpenClaw / Windsurf?
diff --git a/agent_reach/channels/__init__.py b/agent_reach/channels/__init__.py
index 1b0cea6..c698ef6 100644
--- a/agent_reach/channels/__init__.py
+++ b/agent_reach/channels/__init__.py
@@ -4,29 +4,32 @@ Channel registry — lists all supported platforms for doctor checks.
"""
from typing import List, Optional
-from .base import Channel
# Import all channels
-from .web import WebChannel
-from .github import GitHubChannel
-from .twitter import TwitterChannel
-from .youtube import YouTubeChannel
-from .reddit import RedditChannel
-from .rss import RSSChannel
+from .base import Channel
from .bilibili import BilibiliChannel
from .exa_search import ExaSearchChannel
-from .xiaohongshu import XiaoHongShuChannel
+from .facebook import FacebookChannel
+from .github import GitHubChannel
+from .instagram import InstagramChannel
from .linkedin import LinkedInChannel
-from .xiaoyuzhou import XiaoyuzhouChannel
+from .reddit import RedditChannel
+from .rss import RSSChannel
+from .twitter import TwitterChannel
from .v2ex import V2EXChannel
+from .web import WebChannel
+from .xiaohongshu import XiaoHongShuChannel
+from .xiaoyuzhou import XiaoyuzhouChannel
from .xueqiu import XueqiuChannel
-
+from .youtube import YouTubeChannel
ALL_CHANNELS: List[Channel] = [
GitHubChannel(),
TwitterChannel(),
YouTubeChannel(),
RedditChannel(),
+ FacebookChannel(),
+ InstagramChannel(),
BilibiliChannel(),
XiaoHongShuChannel(),
LinkedInChannel(),
@@ -55,5 +58,6 @@ def get_all_channels() -> List[Channel]:
__all__ = [
"Channel",
"ALL_CHANNELS",
- "get_channel", "get_all_channels",
+ "get_channel",
+ "get_all_channels",
]
diff --git a/agent_reach/channels/_opencli_site.py b/agent_reach/channels/_opencli_site.py
new file mode 100644
index 0000000..8e93766
--- /dev/null
+++ b/agent_reach/channels/_opencli_site.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+"""Shared channel helper for OpenCLI browser-session-only platforms."""
+
+from urllib.parse import urlparse
+
+from .base import Channel
+
+
+class OpenCLISiteChannel(Channel):
+ """A platform served directly by OpenCLI.
+
+ These channels are intentionally thin: Agent Reach only installs,
+ health-checks, and routes. Agents call `opencli ...` directly.
+ """
+
+ site: str = ""
+ domains: tuple[str, ...] = ()
+ usage: str = ""
+ login_hint: str = ""
+
+ backends = ["OpenCLI"]
+ tier = 1
+
+ def can_handle(self, url: str) -> bool:
+ domain = urlparse(url).netloc.lower()
+ return any(domain == d or domain.endswith(f".{d}") for d in self.domains)
+
+ def check(self, config=None):
+ from agent_reach.backends import opencli_status
+
+ self.active_backend = None
+ st = opencli_status()
+ if not st.installed:
+ return "off", (
+ f"未安装 {self.description} 后端。安装:\n"
+ " agent-reach install --channels opencli\n"
+ f"然后在 Chrome 里登录 {self.login_hint}"
+ )
+ if st.broken:
+ return "error", st.hint
+
+ self.active_backend = "OpenCLI"
+ if st.ready:
+ return "ok", (
+ f"OpenCLI 可用(复用浏览器登录态)。用法:{self.usage}。"
+ f"若提示登录,请先在 Chrome 里登录 {self.login_hint}"
+ )
+ return "warn", st.hint
diff --git a/agent_reach/channels/facebook.py b/agent_reach/channels/facebook.py
new file mode 100644
index 0000000..3ae8bd8
--- /dev/null
+++ b/agent_reach/channels/facebook.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+"""Facebook — OpenCLI backend using the user's logged-in Chrome session."""
+
+from ._opencli_site import OpenCLISiteChannel
+
+
+class FacebookChannel(OpenCLISiteChannel):
+ name = "facebook"
+ description = "Facebook 帖子、主页和群组"
+ site = "facebook"
+ domains = ("facebook.com", "fb.com", "fb.watch")
+ usage = "opencli facebook search/profile/feed/groups -f yaml"
+ login_hint = "facebook.com"
diff --git a/agent_reach/channels/instagram.py b/agent_reach/channels/instagram.py
new file mode 100644
index 0000000..6d607d4
--- /dev/null
+++ b/agent_reach/channels/instagram.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+"""Instagram — OpenCLI backend using the user's logged-in Chrome session."""
+
+from ._opencli_site import OpenCLISiteChannel
+
+
+class InstagramChannel(OpenCLISiteChannel):
+ name = "instagram"
+ description = "Instagram 用户、主页和指定用户帖子"
+ site = "instagram"
+ domains = ("instagram.com", "instagr.am")
+ usage = "opencli instagram search/profile/user/explore -f yaml"
+ login_hint = "instagram.com"
diff --git a/agent_reach/cli.py b/agent_reach/cli.py
index 00ecf0f..1d35676 100644
--- a/agent_reach/cli.py
+++ b/agent_reach/cli.py
@@ -75,7 +75,7 @@ def main():
p_install.add_argument("--channels", default="",
help="Comma-separated optional channels to install "
"(twitter,xiaoyuzhou,xueqiu,xiaohongshu,"
- "reddit,bilibili,linkedin,all)")
+ "reddit,facebook,instagram,bilibili,linkedin,all)")
# ── configure ──
p_conf = sub.add_parser("configure", help="Set a config value or auto-extract from browser")
@@ -199,11 +199,14 @@ def _cmd_install(args):
"xiaoyuzhou": _install_xiaoyuzhou_deps,
"xiaohongshu": _install_xhs_deps,
"reddit": _install_reddit_deps,
+ "facebook": _install_opencli_deps,
+ "instagram": _install_opencli_deps,
"bilibili": _install_bili_deps,
"opencli": _install_opencli_deps, # cross-channel backend, desktop only
# xueqiu: cookie-only, no install step
# linkedin: manual setup, no auto-install
}
+ OPENCLI_ONLY_CHANNELS = {"opencli", "facebook", "instagram"}
COOKIE_CHANNELS = {"twitter", "xueqiu", "bilibili"}
requested_channels = set()
@@ -224,6 +227,12 @@ def _cmd_install(args):
else:
print(f"Environment: Local computer (auto-detected)")
+ server_skipped_opencli_channels = set()
+ if env == "server" and requested_channels:
+ # OpenCLI rides a real desktop Chrome session — useless headless
+ server_skipped_opencli_channels = requested_channels & OPENCLI_ONLY_CHANNELS
+ requested_channels -= server_skipped_opencli_channels
+
# Apply explicit flags
if args.proxy:
if dry_run:
@@ -251,18 +260,21 @@ def _cmd_install(args):
else:
_install_mcporter()
+ if server_skipped_opencli_channels:
+ print()
+ print(" -- OpenCLI 需要桌面环境 + Chrome,服务器环境跳过:"
+ f"{', '.join(sorted(server_skipped_opencli_channels))}")
+
# ── Install optional channels (only if --channels specified) ──
if requested_channels and not dry_run and not safe_mode:
print()
print("Installing optional channels...")
- if env == "server" and "opencli" in requested_channels:
- # OpenCLI rides a real desktop Chrome session — useless headless
- requested_channels.discard("opencli")
- print(" -- OpenCLI 需要桌面环境 + Chrome,服务器环境跳过")
+ ran_installers = set()
for ch_name in sorted(requested_channels):
installer = CHANNEL_INSTALLERS.get(ch_name)
- if installer:
+ if installer and installer not in ran_installers:
installer()
+ ran_installers.add(installer)
if requested_channels and dry_run:
print()
@@ -327,7 +339,7 @@ def _cmd_install(args):
# First install — hint about optional channels
print()
print("More channels available! Use --channels to install:")
- print(" agent-reach install --channels=twitter,xiaohongshu,reddit,...")
+ print(" agent-reach install --channels=twitter,xiaohongshu,reddit,facebook,instagram,...")
print(" agent-reach install --channels=all (install everything)")
# Star reminder
diff --git a/agent_reach/skill/SKILL.md b/agent_reach/skill/SKILL.md
index f8176be..918ba2d 100644
--- a/agent_reach/skill/SKILL.md
+++ b/agent_reach/skill/SKILL.md
@@ -6,11 +6,11 @@ description: >
看看大家怎么评价 X / X 上有什么讨论 / research this topic。
Also MUST USE when user mentions any platform or shares any URL/链接:
- 小红书/xiaohongshu/xhs, Twitter/推特/X, B站/bilibili, Reddit, V2EX,
- LinkedIn/领英/招聘/求职/jobs, YouTube, GitHub code search, 小宇宙播客,
+ 小红书/xiaohongshu/xhs, Twitter/推特/X, B站/bilibili, Reddit, Facebook,
+ Instagram, V2EX, LinkedIn/领英/招聘/求职/jobs, YouTube, GitHub code search, 小宇宙播客,
雪球/股票行情, RSS feeds, or any web URL.
- 13 platforms, multi-backend routing (OpenCLI / per-platform CLIs / APIs).
+ 15 platforms, multi-backend routing (OpenCLI / per-platform CLIs / APIs).
Zero config for 6 channels. Run `agent-reach doctor --json` to see which
backend serves each platform right now.
@@ -18,7 +18,7 @@ description: >
发帖/评论/点赞等写操作;已有专门 skill 的平台(先用专门 skill)。
【路由方式】SKILL.md 包含路由表和常用命令,复杂场景需按需阅读对应分类的 references/*.md。
- 分类:search / social (小红书/推特/B站/V2EX/Reddit) / career(LinkedIn) / dev(github) / web(网页/文章/RSS) / video(YouTube/B站/播客)。
+ 分类:search / social (小红书/推特/B站/V2EX/Reddit/Facebook/Instagram) / career(LinkedIn) / dev(github) / web(网页/文章/RSS) / video(YouTube/B站/播客)。
triggers:
- research: 调研/全网调研/帮我调研/研究一下/research/深入了解
- search: 搜/查/找/search/搜索/查一下/帮我搜/看看大家怎么说
@@ -28,6 +28,8 @@ triggers:
- B站: bilibili/b站/哔哩哔哩
- V2EX: v2ex
- Reddit: reddit
+ - Facebook: facebook/fb/facebook groups
+ - Instagram: instagram/ig
- career: 招聘/职位/求职/linkedin/领英/找工作
- dev: github/代码/仓库/gh/issue/pr/分支/commit
- web: 网页/链接/文章/rss/读一下/打开这个
@@ -40,11 +42,11 @@ metadata:
# Agent Reach — 互联网能力路由器
-13 平台、多后端。**本 skill 存在时必须用它访问这些平台,不要自己发明方案。**
+15 平台、多后端。**本 skill 存在时必须用它访问这些平台,不要自己发明方案。**
## 常驻规则(全程适用)
-1. **动手前先体检**:多后端平台(小红书/Reddit/B站/Twitter)先跑
+1. **动手前先体检**:多后端/登录态平台(小红书/Reddit/B站/Twitter/Facebook/Instagram)先跑
`agent-reach doctor --json`,按各平台 `active_backend` 字段选命令组。
2. **声明你在用什么**:开始干活前说一句「使用 agent-reach 的 X 平台 / Y 后端」。
3. **失败按 references 里的重试链处理**,不要瞎猜命令。
@@ -60,7 +62,7 @@ metadata:
| 用户意图 | 分类 | 详细文档 |
|---------|------|---------|
| 网页搜索/代码搜索 | search | [references/search.md](references/search.md) |
-| 小红书/推特/B站/V2EX/Reddit | social | [references/social.md](references/social.md) |
+| 小红书/推特/B站/V2EX/Reddit/Facebook/Instagram | social | [references/social.md](references/social.md) |
| 招聘/职位/LinkedIn | career | [references/career.md](references/career.md) |
| GitHub/代码 | dev | [references/dev.md](references/dev.md) |
| 网页/文章/RSS | web | [references/web.md](references/web.md) |
@@ -100,6 +102,12 @@ rdt search "query" --limit 10 # 存量/服务器
# 小红书(桌面首选 OpenCLI)
opencli xiaohongshu search "query" -f yaml
+
+# Facebook / Instagram(桌面 OpenCLI,复用浏览器登录态)
+opencli facebook search "query" -f yaml
+opencli facebook groups -f yaml
+opencli instagram search "query" -f yaml # 搜用户
+opencli instagram user USERNAME -f yaml # 读指定用户最近帖子
```
## 环境检查
@@ -118,7 +126,7 @@ agent-reach doctor --json
根据用户需求,阅读对应的详细文档:
- [搜索工具](references/search.md) — Exa AI 搜索
-- [社交媒体](references/social.md) — 小红书, Twitter, B站, V2EX, Reddit(多后端命令组)
+- [社交媒体](references/social.md) — 小红书, Twitter, B站, V2EX, Reddit, Facebook, Instagram(多后端/登录态命令组)
- [职场招聘](references/career.md) — LinkedIn
- [开发工具](references/dev.md) — GitHub CLI
- [网页阅读](references/web.md) — Jina Reader, RSS
diff --git a/agent_reach/skill/SKILL_en.md b/agent_reach/skill/SKILL_en.md
index d0aa972..c30ed74 100644
--- a/agent_reach/skill/SKILL_en.md
+++ b/agent_reach/skill/SKILL_en.md
@@ -6,10 +6,10 @@ description: >
web for X", "see what people say about X", "look this up".
Also MUST USE when user mentions any platform or shares any URL/link:
- Twitter/X, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu,
+ Twitter/X, Reddit, Facebook, Instagram, YouTube, GitHub, Bilibili, XiaoHongShu,
Xiaoyuzhou Podcast, LinkedIn/jobs/recruiting, V2EX, Xueqiu (stocks), RSS.
- 13 platforms, multi-backend routing (OpenCLI / per-platform CLIs / APIs).
+ 15 platforms, multi-backend routing (OpenCLI / per-platform CLIs / APIs).
Zero config for 6 channels. Run `agent-reach doctor --json` to see which
backend serves each platform right now.
@@ -23,13 +23,13 @@ metadata:
# Agent Reach — internet capability router
-13 platforms, multiple backends each. **When this skill exists, use it for
+15 platforms, multiple backends each. **When this skill exists, use it for
these platforms — do not invent your own approach.**
## Standing rules (apply for the whole session)
-1. **Health-check before acting**: for multi-backend platforms (XiaoHongShu /
- Reddit / Bilibili / Twitter), run `agent-reach doctor --json` first and
+1. **Health-check before acting**: for multi-backend/login-backed platforms (XiaoHongShu /
+ Reddit / Bilibili / Twitter / Facebook / Instagram), run `agent-reach doctor --json` first and
pick the command group matching each platform's `active_backend`.
2. **Announce what you use**: say "using agent-reach, platform X via backend Y"
before starting.
@@ -50,7 +50,7 @@ these platforms — do not invent your own approach.**
| User intent | Category | Details |
|---------|------|---------|
| Web / code search | search | [references/search.md](references/search.md) |
-| XiaoHongShu / Twitter / Bilibili / V2EX / Reddit | social | [references/social.md](references/social.md) |
+| XiaoHongShu / Twitter / Bilibili / V2EX / Reddit / Facebook / Instagram | social | [references/social.md](references/social.md) |
| Jobs / LinkedIn | career | [references/career.md](references/career.md) |
| GitHub / code | dev | [references/dev.md](references/dev.md) |
| Web pages / articles / RSS | web | [references/web.md](references/web.md) |
@@ -90,6 +90,12 @@ rdt search "query" --limit 10 # legacy/server
# XiaoHongShu (desktop prefers OpenCLI)
opencli xiaohongshu search "query" -f yaml
+
+# Facebook / Instagram (desktop OpenCLI, browser session)
+opencli facebook search "query" -f yaml
+opencli facebook groups -f yaml
+opencli instagram search "query" -f yaml # user search
+opencli instagram user USERNAME -f yaml # recent posts from one user
```
## Environment check
@@ -111,7 +117,7 @@ common cases; references hold per-backend command groups, caveats, retry
chains — note: reference docs are written in Chinese, commands are universal):
- [Search](references/search.md) — Exa AI search
-- [Social](references/social.md) — XiaoHongShu, Twitter, Bilibili, V2EX, Reddit (multi-backend groups)
+- [Social](references/social.md) — XiaoHongShu, Twitter, Bilibili, V2EX, Reddit, Facebook, Instagram (multi-backend/login-backed groups)
- [Career](references/career.md) — LinkedIn
- [Dev](references/dev.md) — GitHub CLI
- [Web](references/web.md) — Jina Reader, RSS
diff --git a/agent_reach/skill/references/social.md b/agent_reach/skill/references/social.md
index 20ce5c4..1bd5303 100644
--- a/agent_reach/skill/references/social.md
+++ b/agent_reach/skill/references/social.md
@@ -1,6 +1,6 @@
# 社交媒体 & 社区
-小红书、Twitter/X、B站、V2EX、Reddit。
+小红书、Twitter/X、B站、V2EX、Reddit、Facebook、Instagram。
## 小红书 / XiaoHongShu(多后端)
@@ -230,3 +230,46 @@ rdt all --limit 10 # 浏览 /r/all
### 高级选项:官方 API + PRAW(仅限已有凭证的用户)
2025-11 前注册过 Reddit script app(持有 client_id/client_secret)的用户可以用 PRAW 走官方 API(100 QPM 免费)。新申请需人工审批且个人项目基本不批,**不要推荐新用户走这条路**。
+
+## Facebook(OpenCLI,必须登录态)
+
+Facebook 走 OpenCLI,复用用户 Chrome 里的 facebook.com 登录态。先跑 `agent-reach doctor --json` 看 facebook 的 `active_backend`,正常应为 `OpenCLI`。不要推荐 Jina/Exa/Graph API 作为默认路径。
+
+```bash
+# 搜索用户 / 主页 / 帖子
+opencli facebook search "query" -f yaml
+
+# 用户或主页信息
+opencli facebook profile zuck -f yaml
+
+# 当前账号 News Feed
+opencli facebook feed --limit 10 -f yaml
+
+# 当前账号可见的群组列表/最近动态
+opencli facebook groups --limit 20 -f yaml
+```
+
+> 要求 Chrome 打开且装了 OpenCLI 扩展,并已登录 facebook.com。Facebook Groups 当前只承诺读取当前账号可见的群组列表/最近动态,不承诺任意群帖子和评论 API。
+
+## Instagram(OpenCLI,必须登录态)
+
+Instagram 走 OpenCLI,复用用户 Chrome 里的 instagram.com 登录态。先跑 `agent-reach doctor --json` 看 instagram 的 `active_backend`,正常应为 `OpenCLI`。不要默认恢复 instaloader;历史上 cookies/401/429 不稳定。
+
+```bash
+# 搜索用户(不是全站帖子关键词搜索)
+opencli instagram search "query" -f yaml
+
+# 用户 Profile
+opencli instagram profile nasa -f yaml
+
+# 用户最近帖子
+opencli instagram user nasa --limit 12 -f yaml
+
+# Explore / Discover
+opencli instagram explore --limit 20 -f yaml
+
+# 当前账号收藏
+opencli instagram saved --limit 20 -f yaml
+```
+
+> 要求 Chrome 打开且装了 OpenCLI 扩展,并已登录 instagram.com。`instagram search` 是用户搜索;读帖子需要先确定 username,再用 `instagram user USERNAME`。若出现 429 / login required,先让用户在 Chrome 里重新登录并降低频率。
diff --git a/docs/README_en.md b/docs/README_en.md
index b550ff7..b2d26cc 100644
--- a/docs/README_en.md
+++ b/docs/README_en.md
@@ -71,6 +71,8 @@ Update Agent Reach: https://raw.githubusercontent.com/Panniantong/agent-reach/ma
| 🌐 **Web** | Read | Zero config | Any URL → clean Markdown ([Jina Reader](https://github.com/jina-ai/reader) ⭐9.8K) |
| 🐦 **Twitter/X** | Read · Search | Cookie | Cookie unlocks search, timeline, tweet reading, articles ([twitter-cli](https://github.com/public-clis/twitter-cli)) |
| 📕 **XiaoHongShu** | Read · Search · Comments | OpenCLI / MCP | Desktop: [OpenCLI](https://github.com/jackwener/opencli) (reuses browser session); Server: [xiaohongshu-mcp](https://github.com/xpzouying/xiaohongshu-mcp) (QR login); legacy xhs-cli still works |
+| 📘 **Facebook** | Search · Profiles · Feed · Groups list | OpenCLI | Desktop only: [OpenCLI](https://github.com/jackwener/opencli) reuses your logged-in Chrome session |
+| 📷 **Instagram** | User search · Profiles · Recent posts · Explore | OpenCLI | Desktop only: [OpenCLI](https://github.com/jackwener/opencli) reuses your logged-in Chrome session |
| 💼 **LinkedIn** | Jina Reader (public pages) | Full profiles, companies, job search | Tell your Agent "help me set up LinkedIn" |
| 💻 **V2EX** | Hot topics · Node topics · Topic detail + replies · User profile | Zero config | Public JSON API, no auth required. Great for tech community content |
| 📈 **Xueqiu (雪球)** | Stock quotes · Search · Hot posts · Hot stocks | Browser cookie | Tell your Agent "help me set up Xueqiu" |
@@ -203,6 +205,7 @@ $ agent-reach doctor
🔧 Configurable:
⬜ Reddit posts and comments — needs login: rdt-cli after `rdt login`, or OpenCLI browser session
⬜ XiaoHongShu notes — desktop: OpenCLI (browser session); server: xiaohongshu-mcp (QR)
+ ⬜ Facebook / Instagram — desktop: OpenCLI browser session
Status: 6/9 channels available
```
@@ -229,6 +232,8 @@ channels/
├── github.py → gh CLI
├── bilibili.py → bili-cli ▸ OpenCLI ▸ search API (yt-dlp retired, 412-blocked)
├── reddit.py → OpenCLI ▸ rdt-cli (no zero-config path, login required)
+├── facebook.py → OpenCLI (desktop browser session)
+├── instagram.py → OpenCLI (desktop browser session)
├── xiaohongshu.py → OpenCLI ▸ xiaohongshu-mcp ▸ xhs-cli
├── linkedin.py → linkedin-mcp ▸ Jina Reader
├── rss.py → feedparser
@@ -245,6 +250,8 @@ Each channel file **actually probes** its candidate backends in order (not just
| Read web pages | [Jina Reader](https://github.com/jina-ai/reader) | — | Free, no API key needed |
| Read tweets | [twitter-cli](https://github.com/public-clis/twitter-cli) | [OpenCLI](https://github.com/jackwener/opencli) | Reliable search in real-world tests; OpenCLI falls back on your browser session |
| Reddit | [OpenCLI](https://github.com/jackwener/opencli) (desktop) | [rdt-cli](https://github.com/public-clis/rdt-cli) | Anonymous endpoints blocked, official API gated — logged-in sessions are the only route left |
+| Facebook | [OpenCLI](https://github.com/jackwener/opencli) (desktop) | — | Graph/Groups API access is heavily restricted; browser sessions are the practical route |
+| Instagram | [OpenCLI](https://github.com/jackwener/opencli) (desktop) | Official Graph API (Business/Creator + review) | Instaloader-style paths are unstable; OpenCLI reuses the real browser session |
| YouTube subtitles + search | [yt-dlp](https://github.com/yt-dlp/yt-dlp) | — | 154K stars, still the best for YouTube (no longer used for Bilibili) |
| Bilibili | [bili-cli](https://github.com/public-clis/bilibili-cli) | OpenCLI ▸ search API | yt-dlp is 412-blocked by Bilibili (verified June 2026); bili-cli searches and reads without login |
| Search the web | [Exa](https://exa.ai) via [mcporter](https://github.com/nicobailon/mcporter) | — | AI semantic search, MCP integration, no API key |
@@ -314,6 +321,12 @@ Agent Reach uses twitter-cli which accesses Twitter via cookie auth — same as
On desktop, prefer **OpenCLI** (`agent-reach install --channels opencli`) — it reuses your browser's logged-in session, so if you've browsed XiaoHongShu you're set; one Chrome Web Store click installs the extension. Then `opencli xiaohongshu search "query"` / `opencli xiaohongshu note URL`. On servers use [xiaohongshu-mcp](https://github.com/xpzouying/xiaohongshu-mcp) (bundled headless browser, QR login). Existing xhs-cli installs keep working as a fallback backend (upstream unmaintained since 2026-03, not recommended for new setups).
+
+How to read Facebook / Instagram with an AI agent?
+
+On desktop, use **OpenCLI**: `agent-reach install --channels facebook,instagram`. Install the OpenCLI Chrome extension, log into facebook.com / instagram.com in Chrome, then the Agent can call `opencli facebook search "query" -f yaml`, `opencli facebook groups -f yaml`, `opencli instagram search "username or keyword" -f yaml` for user search, or `opencli instagram user USERNAME -f yaml` for a specific user's recent posts. Server/headless environments are not recommended for these two channels.
+
+
---
## Credits
diff --git a/docs/install.md b/docs/install.md
index 75416cb..4eff144 100644
--- a/docs/install.md
+++ b/docs/install.md
@@ -96,25 +96,28 @@ After installing the basics, **ask the user** which additional channels they nee
>
> 还有这些可选渠道,你需要哪些?
>
-> - 🌟 **OpenCLI**(桌面推荐)— 一次安装,小红书/Reddit/B站字幕/Twitter 备选全解锁(复用浏览器登录态,零配置;只需在 Chrome 商店点一次"添加扩展")
+> - 🌟 **OpenCLI**(桌面推荐)— 一次安装,小红书/Reddit/Facebook/Instagram/B站字幕/Twitter 备选全解锁(复用浏览器登录态,零配置;只需在 Chrome 商店点一次"添加扩展")
> - 🐦 **Twitter/X** — 搜推文、看时间线(需要登录 Cookie)
> - 📈 **雪球** — 股票行情、热门帖子(需要登录 Cookie)
> - 🎙️ **小宇宙播客** — 音频转文字(需要免费 Groq Key)
> - 📕 **小红书** — 搜索、阅读、评论(桌面走 OpenCLI;服务器用 xiaohongshu-mcp 扫码)
> - 📖 **Reddit** — 搜索和阅读帖子(必须登录态:桌面 OpenCLI 或 rdt-cli + Cookie)
+> - 📘 **Facebook** — 搜索、主页、Feed、群组列表(桌面走 OpenCLI,复用 Chrome 登录态)
+> - 📷 **Instagram** — 用户搜索、Profile、用户最近帖子、Explore(桌面走 OpenCLI,复用 Chrome 登录态)
> - 📺 **B站完整版** — 热门、排行、搜索、视频详情(bili-cli,无需登录)
> - 💼 **LinkedIn** — Profile、职位搜索
>
-> 告诉我你要哪些,比如"帮我装小红书和 Twitter"。或者说"全部装"。
+> 告诉我你要哪些,比如"帮我装小红书和 Twitter"、"帮我装 Facebook 和 Instagram"。或者说"全部装"。
Based on the user's choice, run:
```bash
agent-reach install --env=auto --channels=opencli,xiaohongshu # Example: desktop user chose XHS (OpenCLI-backed)
+agent-reach install --env=auto --channels=facebook,instagram # Example: desktop user chose Meta social channels
agent-reach install --env=auto --channels=all # User wants everything
```
-Supported channel names: `opencli`, `twitter`, `xiaoyuzhou`, `xueqiu`, `xiaohongshu`, `reddit`, `bilibili`, `linkedin`, `all`
+Supported channel names: `opencli`, `twitter`, `xiaoyuzhou`, `xueqiu`, `xiaohongshu`, `reddit`, `facebook`, `instagram`, `bilibili`, `linkedin`, `all`
### Step 3: Fix what's broken
@@ -128,19 +131,19 @@ Only ask the user when you genuinely need their input (credentials, permissions,
Some channels need credentials only the user can provide. Based on the doctor output, ask for what's missing:
-> 🔒 **Security tip:** For platforms that need cookies (Twitter, XiaoHongShu), we recommend using a **dedicated/secondary account** rather than your main account. Cookie-based auth carries two risks:
+> 🔒 **Security tip:** For platforms that need cookies or browser sessions (Twitter, XiaoHongShu, Reddit, Facebook, Instagram), we recommend using a **dedicated/secondary account** rather than your main account. Cookie/browser-session auth carries two risks:
> 1. **Account ban** — platforms may detect non-browser API calls and restrict or ban the account
> 2. **Credential exposure** — cookies grant full account access; using a secondary account limits the blast radius if credentials are ever compromised
-> 🍪 **Cookie 导入(所有需要登录的平台通用):**
+> 🍪 **Cookie / 登录态:**
>
-> 所有需要 Cookie 的平台(Twitter、小红书、雪球等),**优先使用 Cookie-Editor 导入**,这是最简单最可靠的方式:
+> 传统 CLI 需要 Cookie 的平台(Twitter、雪球等),**优先使用 Cookie-Editor 导入**,这是最简单最可靠的方式:
> 1. 用户在自己的浏览器上登录对应平台
> 2. 安装 [Cookie-Editor](https://chromewebstore.google.com/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm) Chrome 插件
> 3. 点击插件 → Export → Header String
> 4. 把导出的字符串发给 Agent
>
-> **本地电脑用户**也可以用 `agent-reach configure --from-browser chrome` 一键自动提取(支持 Twitter + 小红书 + 雪球)。
+> **本地电脑用户**也可以用 `agent-reach configure --from-browser chrome` 一键自动提取(支持 Twitter + 小红书 + 雪球)。OpenCLI 平台(Reddit、小红书桌面后端、Facebook、Instagram)优先复用 Chrome 登录态,不需要把 Cookie 发给 Agent。
**Twitter search & posting:**
> "To unlock Twitter search, I need your Twitter cookies. Install the Cookie-Editor Chrome extension, go to x.com/twitter.com, click the extension → Export → Header String, and paste it to me."
@@ -200,6 +203,28 @@ agent-reach install --channels opencli
> agent-reach configure xhs-cookies "key1=val1; key2=val2; ..."
> ```
+**Facebook / Instagram(桌面 OpenCLI):**
+> 这两个平台走 OpenCLI:复用用户自己的 Chrome 登录态,不保存账号密码,不走 Meta Graph API 审批流。服务器/无桌面环境不推荐支持。
+
+```bash
+agent-reach install --channels facebook,instagram
+```
+
+> 装完后:
+> 1. 确认 Chrome 已安装 OpenCLI 扩展并通过 `opencli doctor`
+> 2. 在 Chrome 里登录 facebook.com / instagram.com
+> 3. Agent 直接调用:
+> ```bash
+> opencli facebook search "query" -f yaml
+> opencli facebook profile zuck -f yaml
+> opencli facebook groups -f yaml
+> opencli instagram search "query" -f yaml # 用户搜索
+> opencli instagram profile nasa -f yaml
+> opencli instagram user nasa -f yaml # 指定用户最近帖子
+> ```
+>
+> Facebook Groups 当前只承诺读取用户登录后可见的群组列表/最近动态,不承诺任意群帖子和评论 API。Instagram 的 search 是用户搜索,不是全站帖子关键词搜索;若提示 429/登录错误,先让用户在 Chrome 里重新登录并降低频率。
+
**雪球 / Xueqiu (股票行情 + 热门帖子):**
> "雪球需要登录后的 Cookie。请先在 Chrome 里登录 xueqiu.com,然后运行:"
@@ -324,6 +349,8 @@ After installation, use upstream tools directly. See SKILL.md for the full comma
| YouTube | `yt-dlp` | `yt-dlp --dump-json URL` |
| Bilibili | `bili`(字幕走 `opencli`) | `bili search "query" --type video` / `opencli bilibili subtitle BVxxx` |
| Reddit | `opencli`(备选 `rdt`) | `opencli reddit search "query" -f yaml` / `rdt read POST_ID` |
+| Facebook | `opencli` | `opencli facebook search "query" -f yaml` |
+| Instagram | `opencli` | `opencli instagram user nasa -f yaml` |
| GitHub | `gh` | `gh search repos "query"` |
| Web | `curl` + Jina | `curl -s "https://r.jina.ai/URL"` |
| Exa Search | `mcporter` | `mcporter call 'exa.web_search_exa(...)'` |
diff --git a/llms.txt b/llms.txt
index f70e3d6..e0a154a 100644
--- a/llms.txt
+++ b/llms.txt
@@ -1,6 +1,6 @@
# Agent Reach
-> Give your AI agent eyes to see the entire internet. A unified CLI tool that lets AI agents read and search across 12+ platforms — Twitter/X, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu, Instagram, LinkedIn, Boss直聘, RSS, and any web page. One install, zero API fees.
+> Give your AI agent eyes to see the internet. Agent Reach installs, routes, and health-checks upstream tools for 15 platforms — Twitter/X, Reddit, Facebook, Instagram, YouTube, GitHub, Bilibili, XiaoHongShu, LinkedIn, V2EX, Xueqiu, Xiaoyuzhou Podcast, RSS, web search, and any web page. One install, zero API fees.
## Quick Start
@@ -10,17 +10,17 @@
## Core Commands
-- [CLI Usage](https://github.com/Panniantong/Agent-Reach/blob/main/docs/install.md): `agent-reach read ` reads any URL, `agent-reach search-twitter "query"` searches Twitter, etc.
+- [CLI Usage](https://github.com/Panniantong/Agent-Reach/blob/main/docs/install.md): `agent-reach doctor --json` shows the active backend; agents then call upstream tools directly (`opencli`, `twitter`, `bili`, `yt-dlp`, `gh`, `mcporter`, etc.).
## Key Features
-- Read any URL: tweets, Reddit posts, YouTube videos (transcripts), GitHub repos, articles, XiaoHongShu notes, Bilibili videos, RSS feeds
-- Search across platforms: Twitter/X, Reddit, GitHub, YouTube, Bilibili, XiaoHongShu, Instagram, LinkedIn, Boss直聘, Web (via Exa)
+- Read any URL: tweets, Reddit posts, Facebook pages/feed/groups, Instagram profiles/posts, YouTube videos (transcripts), GitHub repos, articles, XiaoHongShu notes, Bilibili videos, RSS feeds
+- Search/discover across platforms: Twitter/X, Reddit, Facebook, Instagram user search, GitHub, YouTube, Bilibili, XiaoHongShu, LinkedIn, V2EX, Xueqiu, Web (via Exa)
- Self-diagnosis: `agent-reach doctor` checks what works and what needs setup
- Auto-installs dependencies: `agent-reach install --env=auto`
-- Cookie-based auth for platforms that require login (Twitter, XiaoHongShu, Instagram)
-- Proxy support for platforms that block server IPs (Reddit, Bilibili)
-- Zero API fees: all backends are free and open-source (bird CLI, yt-dlp, Jina Reader, instaloader, etc.)
+- Browser-session / cookie auth for platforms that require login (Twitter, Reddit, Facebook, Instagram, XiaoHongShu, Xueqiu)
+- Proxy support for platforms that block server IPs (Reddit, Twitter)
+- Zero API fees: all backends are free and open-source (OpenCLI, twitter-cli, rdt-cli, bili-cli, yt-dlp, Jina Reader, mcporter/Exa, etc.)
## Troubleshooting
diff --git a/tests/test_channel_contracts.py b/tests/test_channel_contracts.py
index 1733b3c..7b51b02 100644
--- a/tests/test_channel_contracts.py
+++ b/tests/test_channel_contracts.py
@@ -169,6 +169,8 @@ def test_channel_can_handle_contract():
"twitter": "https://x.com/user/status/1",
"youtube": "https://youtube.com/watch?v=abc",
"reddit": "https://reddit.com/r/python",
+ "facebook": "https://www.facebook.com/zuck",
+ "instagram": "https://www.instagram.com/openai/",
"bilibili": "https://www.bilibili.com/video/BV1xx411",
"xiaohongshu": "https://www.xiaohongshu.com/explore/123",
"linkedin": "https://www.linkedin.com/in/test",
diff --git a/tests/test_channels.py b/tests/test_channels.py
index 20dda94..f6f8aa6 100644
--- a/tests/test_channels.py
+++ b/tests/test_channels.py
@@ -6,7 +6,10 @@ import shutil
import subprocess
from urllib.error import URLError
+from agent_reach.backends import OpenCLIStatus
from agent_reach.channels import get_all_channels, get_channel
+from agent_reach.channels.facebook import FacebookChannel
+from agent_reach.channels.instagram import InstagramChannel
from agent_reach.channels.v2ex import V2EXChannel
from agent_reach.channels.xiaohongshu import XiaoHongShuChannel
from agent_reach.channels.xueqiu import XueqiuChannel
@@ -27,9 +30,70 @@ class TestChannelRegistry:
assert "web" in names
assert "github" in names
assert "twitter" in names
+ assert "facebook" in names
+ assert "instagram" in names
assert "v2ex" in names
+class TestOpenCLISiteChannels:
+ def test_facebook_can_handle_common_urls(self):
+ ch = FacebookChannel()
+ assert ch.can_handle("https://www.facebook.com/zuck")
+ assert ch.can_handle("https://m.facebook.com/groups/123")
+ assert ch.can_handle("https://fb.com/some-page")
+ assert ch.can_handle("https://fb.watch/abc123")
+ assert not ch.can_handle("https://instagram.com/openai")
+
+ def test_instagram_can_handle_common_urls(self):
+ ch = InstagramChannel()
+ assert ch.can_handle("https://www.instagram.com/openai/")
+ assert ch.can_handle("https://instagram.com/p/abc123/")
+ assert ch.can_handle("https://instagr.am/p/abc123/")
+ assert not ch.can_handle("https://facebook.com/openai")
+
+ def test_opencli_ready_reports_ok(self, monkeypatch):
+ monkeypatch.setattr(
+ "agent_reach.backends.opencli_status",
+ lambda: OpenCLIStatus(
+ installed=True,
+ extension_connected=True,
+ version="1.8.3",
+ ),
+ )
+ ch = FacebookChannel()
+ status, msg = ch.check()
+ assert status == "ok"
+ assert ch.active_backend == "OpenCLI"
+ assert "opencli facebook search/profile/feed/groups -f yaml" in msg
+ assert "facebook.com" in msg
+
+ def test_opencli_missing_reports_off(self, monkeypatch):
+ monkeypatch.setattr(
+ "agent_reach.backends.opencli_status",
+ lambda: OpenCLIStatus(installed=False),
+ )
+ ch = InstagramChannel()
+ status, msg = ch.check()
+ assert status == "off"
+ assert ch.active_backend is None
+ assert "agent-reach install --channels opencli" in msg
+ assert "instagram.com" in msg
+
+ def test_opencli_installed_without_extension_reports_warn(self, monkeypatch):
+ monkeypatch.setattr(
+ "agent_reach.backends.opencli_status",
+ lambda: OpenCLIStatus(
+ installed=True,
+ hint="OpenCLI 已安装,但 Chrome 扩展未安装。",
+ ),
+ )
+ ch = InstagramChannel()
+ status, msg = ch.check()
+ assert status == "warn"
+ assert ch.active_backend == "OpenCLI"
+ assert "Chrome 扩展" in msg
+
+
class TestV2EXChannel:
def test_can_handle_v2ex_urls(self):
ch = V2EXChannel()
diff --git a/tests/test_cli.py b/tests/test_cli.py
index cc420fb..2f91be1 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -3,10 +3,12 @@
import shutil
import subprocess
+from argparse import Namespace
from unittest.mock import patch
import pytest
import requests
+
import agent_reach.cli as cli
from agent_reach.cli import main
@@ -101,6 +103,60 @@ class TestCLI:
cli._install_reddit_deps()
assert calls == ["rdt"]
+ def test_install_facebook_instagram_routes_to_opencli_once(self, monkeypatch, capsys):
+ calls = []
+
+ monkeypatch.setattr(cli, "_detect_environment", lambda: "local")
+ monkeypatch.setattr(cli, "_install_system_deps", lambda: None)
+ monkeypatch.setattr(cli, "_install_mcporter", lambda: None)
+ monkeypatch.setattr(cli, "_install_opencli_deps", lambda: calls.append("opencli"))
+ monkeypatch.setattr(cli, "_install_skill", lambda: None)
+ monkeypatch.setattr(
+ "agent_reach.doctor.check_all",
+ lambda config: {
+ "facebook": {
+ "status": "ok",
+ "name": "Facebook",
+ "message": "ok",
+ "tier": 1,
+ "backends": ["OpenCLI"],
+ "active_backend": "OpenCLI",
+ }
+ },
+ )
+ monkeypatch.setattr("agent_reach.doctor.format_report", lambda results: "report")
+
+ cli._cmd_install(
+ Namespace(
+ env="auto",
+ proxy="",
+ safe=False,
+ dry_run=False,
+ channels="facebook,instagram,opencli",
+ )
+ )
+
+ assert calls == ["opencli"]
+ assert "Installation complete" in capsys.readouterr().out
+
+ def test_install_server_dry_run_skips_opencli_only_channels(self, monkeypatch, capsys):
+ monkeypatch.setattr(cli, "_install_system_deps_dryrun", lambda: None)
+
+ cli._cmd_install(
+ Namespace(
+ env="server",
+ proxy="",
+ safe=False,
+ dry_run=True,
+ channels="facebook,instagram,opencli,bilibili",
+ )
+ )
+
+ out = capsys.readouterr().out
+ assert "服务器环境跳过:facebook, instagram, opencli" in out
+ assert "[dry-run] Would install optional channels: bilibili" in out
+ assert "facebook, instagram, opencli, bilibili" not in out
+
class TestCheckUpdateRetry:
def test_retry_timeout_classification(self):