--- name: opencli description: "OpenCLI — Make any website your CLI. Zero risk, AI-powered, reuse Chrome login. 80+ commands across 19 sites." version: 0.7.3 author: jackwener tags: [cli, browser, web, mcp, playwright, bilibili, zhihu, twitter, github, v2ex, hackernews, reddit, xiaohongshu, xueqiu, youtube, boss, coupang, AI, agent] --- # OpenCLI > Make any website your CLI. Reuse Chrome login, zero risk, AI-powered discovery. > [!CAUTION] > **AI Agent 必读:创建或修改任何适配器之前,你必须先阅读 [CLI-EXPLORER.md](./CLI-EXPLORER.md)!** > 该文档包含完整的 API 发现工作流(必须使用 Playwright MCP Bridge 浏览器探索)、5 级认证策略决策树、平台 SDK 速查表、`tap` 步骤调试流程、分页 API 模板、级联请求模式、以及常见陷阱。 > **本文件(SKILL.md)仅提供命令参考和简化模板,不足以正确开发适配器。** ## Install & Run ```bash # npm global install (recommended) npm install -g @jackwener/opencli opencli # Or from source cd ~/code/opencli && npm install npx tsx src/main.ts # Update to latest npm update -g @jackwener/opencli ``` ## Prerequisites Browser commands require: 1. Chrome browser running **(logged into target sites)** 2. [Playwright MCP Bridge](https://chromewebstore.google.com/detail/playwright-mcp-bridge/mmlmfjhmonkocbjadbfplnigmagldckm) extension installed 3. Run `opencli setup` to auto-discover token and configure all tools > **Note**: You must be logged into the target website in Chrome before running commands. Tabs opened during command execution are auto-closed afterwards. Public API commands (`hackernews`, `github search`, `v2ex`) need no browser. ## Commands Reference ### Data Commands ```bash # Bilibili (browser) opencli bilibili hot --limit 10 # B站热门视频 opencli bilibili search --keyword "rust" # 搜索视频 opencli bilibili me # 我的信息 opencli bilibili favorite # 我的收藏 opencli bilibili history --limit 20 # 观看历史 opencli bilibili feed --limit 10 # 动态时间线 opencli bilibili user-videos --uid 12345 # 用户投稿 opencli bilibili subtitle --bvid BV1xxx # 获取视频字幕 (支持 --lang zh-CN) opencli bilibili dynamic --limit 10 # 动态 opencli bilibili ranking --limit 10 # 排行榜 opencli bilibili following --limit 20 # 我的关注列表 (支持 --uid 查看他人) # 知乎 (browser) opencli zhihu hot --limit 10 # 知乎热榜 opencli zhihu search --keyword "AI" # 搜索 opencli zhihu question --id 34816524 # 问题详情和回答 # 小红书 (browser) opencli xiaohongshu search --keyword "美食" # 搜索笔记 opencli xiaohongshu notifications # 通知(mentions/likes/connections) opencli xiaohongshu feed --limit 10 # 推荐 Feed opencli xiaohongshu me # 我的信息 opencli xiaohongshu user --uid xxx # 用户主页 # 雪球 Xueqiu (browser) opencli xueqiu hot-stock --limit 10 # 雪球热门股票榜 opencli xueqiu stock --symbol SH600519 # 查看股票实时行情 opencli xueqiu watchlist # 获取自选股/持仓列表 opencli xueqiu feed # 我的关注 timeline opencli xueqiu hot --limit 10 # 雪球热榜 opencli xueqiu search --keyword "特斯拉" # 搜索 # GitHub (public) opencli github search --keyword "cli" # 搜索仓库 # Twitter/X (browser) opencli twitter trending --limit 10 # 热门话题 opencli twitter bookmarks --limit 20 # 获取收藏的书签推文 opencli twitter search --keyword "AI" # 搜索推文 opencli twitter profile elonmusk # 用户资料 opencli twitter timeline --limit 20 # 时间线 opencli twitter thread 1234567890 # 推文 thread(原文 + 回复) opencli twitter article 1891511252174299446 # 推文长文内容 opencli twitter follow elonmusk # 关注用户 opencli twitter unfollow elonmusk # 取消关注 opencli twitter bookmark https://x.com/... # 收藏推文 opencli twitter unbookmark https://x.com/... # 取消收藏 # Reddit (browser) opencli reddit hot --limit 10 # 热门帖子 opencli reddit hot --subreddit programming # 指定子版块 opencli reddit frontpage --limit 10 # 首页 /r/all opencli reddit popular --limit 10 # /r/popular 热门 opencli reddit search --query "AI" --sort top --time week # 搜索(支持排序+时间过滤) opencli reddit subreddit --name rust --sort top --time month # 子版块浏览(支持时间过滤) opencli reddit read --post_id 1abc123 # 阅读帖子 + 评论 opencli reddit user --username spez # 用户资料(karma、注册时间) opencli reddit user-posts --username spez # 用户发帖历史 opencli reddit user-comments --username spez # 用户评论历史 opencli reddit upvote --post_id xxx --direction up # 投票(up/down/none) opencli reddit save --post_id xxx # 收藏帖子 opencli reddit comment --post_id xxx --text "Great!" # 发表评论 opencli reddit subscribe --subreddit python # 订阅子版块 opencli reddit saved --limit 10 # 我的收藏 opencli reddit upvoted --limit 10 # 我的赞 # V2EX (public + browser) opencli v2ex hot --limit 10 # 热门话题 opencli v2ex latest --limit 10 # 最新话题 opencli v2ex topic --id 1024 # 主题详情 opencli v2ex daily # 每日签到 (browser) opencli v2ex me # 我的信息 (browser) opencli v2ex notifications --limit 10 # 通知 (browser) # Hacker News (public) opencli hackernews top --limit 10 # Top stories # BBC (public) opencli bbc news --limit 10 # BBC News RSS headlines # 微博 (browser) opencli weibo hot --limit 10 # 微博热搜 # BOSS直聘 (browser) opencli boss search --query "AI agent" # 搜索职位 opencli boss detail --securityId xxx # 职位详情 # YouTube (browser) opencli youtube search --query "rust" # 搜索视频 opencli youtube video --url "https://www.youtube.com/watch?v=xxx" # 视频元数据(标题、播放量、描述等) opencli youtube transcript --url "https://www.youtube.com/watch?v=xxx" # 获取视频字幕/转录 opencli youtube transcript --url "xxx" --lang zh-Hans --mode raw # 指定语言 + 原始时间戳模式 # Yahoo Finance (browser) opencli yahoo-finance quote --symbol AAPL # 股票行情 # Reuters (browser) opencli reuters search --query "AI" # 路透社搜索 # 什么值得买 (browser) opencli smzdm search --keyword "耳机" # 搜索好价 # 携程 (browser) opencli ctrip search --query "三亚" # 搜索目的地 ``` ### Management Commands ```bash opencli list # List all commands opencli list --json # JSON output opencli list -f yaml # YAML output opencli validate # Validate all CLI definitions opencli validate bilibili # Validate specific site opencli setup # Interactive token setup (auto-discover + TUI checkbox) opencli doctor # Diagnose token & extension config across all tools opencli doctor --live # Also test live browser connectivity opencli doctor --fix # Fix mismatched configs (interactive confirmation) opencli doctor --fix -y # Fix all configs non-interactively ``` ### AI Agent Workflow ```bash # Deep Explore: network intercept → response analysis → capability inference opencli explore --site # Synthesize: generate evaluate-based YAML pipelines from explore artifacts opencli synthesize # Generate: one-shot explore → synthesize → register opencli generate --goal "hot" # Strategy Cascade: auto-probe PUBLIC → COOKIE → HEADER opencli cascade # Explore with interactive fuzzing (click buttons to trigger lazy APIs) opencli explore --auto --click "字幕,CC,评论" # Verify: validate adapter definitions opencli verify ``` ## Output Formats All built-in commands support `--format` / `-f` with `table`, `json`, `yaml`, `md`, and `csv`. The `list` command supports the same formats and also keeps `--json` as a compatibility alias. ```bash opencli list -f yaml # YAML command registry opencli bilibili hot -f table # Default: rich table opencli bilibili hot -f json # JSON (pipe to jq, feed to AI agent) opencli bilibili hot -f yaml # YAML (readable structured output) opencli bilibili hot -f md # Markdown opencli bilibili hot -f csv # CSV ``` ## Verbose Mode ```bash opencli bilibili hot -v # Show each pipeline step and data flow ``` ## Creating Adapters > [!TIP] > **快速模式**:如果你只想为一个具体页面生成一个命令,直接看 [CLI-ONESHOT.md](./CLI-ONESHOT.md)。 > 只需要一个 URL + 一句话描述,4 步搞定。 > [!IMPORTANT] > **完整模式 — 在写任何代码之前,先阅读 [CLI-EXPLORER.md](./CLI-EXPLORER.md)。** > 它包含:① AI Agent 浏览器探索工作流(必须用 Playwright MCP 抓包验证 API)② 认证策略决策树 ③ 平台 SDK(如 Bilibili 的 `apiGet`/`fetchJson`)④ YAML vs TS 选择指南 ⑤ `tap` 步骤调试方法 ⑥ 级联请求模板 ⑦ 常见陷阱表。 > **下方仅为简化模板参考,直接使用极易踩坑。** ### YAML Pipeline (declarative, recommended) Create `src/clis//.yaml`: ```yaml site: mysite name: hot description: Hot topics domain: www.mysite.com strategy: cookie # public | cookie | header | intercept | ui browser: true args: limit: type: int default: 20 description: Number of items pipeline: - navigate: https://www.mysite.com - evaluate: | (async () => { const res = await fetch('/api/hot', { credentials: 'include' }); const d = await res.json(); return d.data.items.map(item => ({ title: item.title, score: item.score, })); })() - map: rank: ${{ index + 1 }} title: ${{ item.title }} score: ${{ item.score }} - limit: ${{ args.limit }} columns: [rank, title, score] ``` For public APIs (no browser): ```yaml strategy: public browser: false pipeline: - fetch: url: https://api.example.com/hot.json - select: data.items - map: title: ${{ item.title }} - limit: ${{ args.limit }} ``` ### TypeScript Adapter (programmatic) Create `src/clis//.ts`. It will be automatically dynamically loaded (DO NOT manually import it in `index.ts`): ```typescript import { cli, Strategy } from '../../registry.js'; cli({ site: 'mysite', name: 'search', strategy: Strategy.INTERCEPT, // Or COOKIE args: [{ name: 'keyword', required: true }], columns: ['rank', 'title', 'url'], func: async (page, kwargs) => { await page.goto('https://www.mysite.com/search'); // Inject native XHR/Fetch interceptor hook await page.installInterceptor('/api/search'); // Auto scroll down to trigger lazy loading await page.autoScroll({ times: 3, delayMs: 2000 }); // Retrieve intercepted JSON payloads const requests = await page.getInterceptedRequests(); let results = []; for (const req of requests) { results.push(...req.data.items); } return results.map((item, i) => ({ rank: i + 1, title: item.title, url: item.url, })); }, }); ``` **When to use TS**: XHR interception (`page.installInterceptor`), infinite scrolling (`page.autoScroll`), cookie extraction, complex data transforms (like GraphQL unwrapping). ## Pipeline Steps | Step | Description | Example | |------|-------------|---------| | `navigate` | Go to URL | `navigate: https://example.com` | | `fetch` | HTTP request (browser cookies) | `fetch: { url: "...", params: { q: "..." } }` | | `evaluate` | Run JavaScript in page | `evaluate: \| (async () => { ... })()` | | `select` | Extract JSON path | `select: data.items` | | `map` | Map fields | `map: { title: "${{ item.title }}" }` | | `filter` | Filter items | `filter: item.score > 100` | | `sort` | Sort items | `sort: { by: score, order: desc }` | | `limit` | Cap result count | `limit: ${{ args.limit }}` | | `intercept` | Declarative XHR capture | `intercept: { trigger: "navigate:...", capture: "api/hot" }` | | `tap` | Store action + XHR capture | `tap: { store: "feed", action: "fetchFeeds", capture: "homefeed" }` | | `snapshot` | Page accessibility tree | `snapshot: { interactive: true }` | | `click` | Click element | `click: ${{ ref }}` | | `type` | Type text | `type: { ref: "@1", text: "hello" }` | | `wait` | Wait for time/text | `wait: 2` or `wait: { text: "loaded" }` | | `press` | Press key | `press: Enter` | ## Template Syntax ```yaml # Arguments with defaults ${{ args.keyword }} ${{ args.limit | default(20) }} # Current item (in map/filter) ${{ item.title }} ${{ item.data.nested.field }} # Index (0-based) ${{ index }} ${{ index + 1 }} ``` ## 5-Tier Authentication Strategy | Tier | Name | Method | Example | |------|------|--------|---------| | 1 | `public` | No auth, Node.js fetch | Hacker News, V2EX | | 2 | `cookie` | Browser fetch with `credentials: include` | Bilibili, Zhihu | | 3 | `header` | Custom headers (ct0, Bearer) | Twitter GraphQL | | 4 | `intercept` | XHR interception + store mutation | 小红书 Pinia | | 5 | `ui` | Full UI automation (click/type/scroll) | Last resort | ## Environment Variables | Variable | Default | Description | |----------|---------|-------------| | `OPENCLI_BROWSER_CONNECT_TIMEOUT` | 30 | Browser connection timeout (sec) | | `OPENCLI_BROWSER_COMMAND_TIMEOUT` | 45 | Command execution timeout (sec) | | `OPENCLI_BROWSER_EXPLORE_TIMEOUT` | 120 | Explore timeout (sec) | | `PLAYWRIGHT_MCP_EXTENSION_TOKEN` | — | Auto-approve extension connection | ## Troubleshooting | Issue | Solution | |-------|----------| | `npx not found` | Install Node.js: `brew install node` | | `Timed out connecting to browser` | 1) Chrome must be open 2) Install MCP Bridge extension and configure token | | `Target page context` error | Add `navigate:` step before `evaluate:` in YAML | | Empty table data | Check if evaluate returns JSON string (MCP parsing) or data path is wrong |