mirror of
https://github.com/jackwener/OpenCLI.git
synced 2026-09-14 18:25:42 +08:00
0e168d570e
* refactor(browser): replace --session flag with <sessionname> positional The `--session <name>` flag was semantically required but syntactically optional, which is an anti-pattern. Required + flag is a contradiction: flag form implies "optional", required is a runtime patch on top. Session is OpenCLI's "operation target" identifier — the natural form for that is a positional argument, like `docker exec <container> <cmd>` or `git checkout <branch>`. New surface: opencli browser <sessionname> open https://x.com opencli browser <sessionname> click 12 opencli browser <sessionname> bind opencli browser <sessionname> unbind Commander 14 cannot natively combine a parent positional with subcommand dispatch — the parent's positional is shadowed by subcommand matching. To bridge that, main.ts now pre-processes argv: when the token after `browser` is non-flag and not a known subcommand name, it is treated as the sessionname and rewritten to the internal `--session <name>` flag form before commander parses it. Help text on the `browser` command is overridden via `.usage('<sessionname> <command> [options]')` so users see the positional form. Reserved subcommand names (33) are listed in cli-argv-preprocess.ts and tested for parity with cli.ts subcommand registrations. If a future subcommand is added, the test fails loudly. Synced surfaces: - README.md / README.zh-CN.md — all examples - docs/guide/browser-bridge.md (+ zh) - skills/opencli-browser/SKILL.md (bind/unbind, examples, table) - skills/opencli-usage/SKILL.md - tests/e2e/browser-tabs.test.ts - CHANGELOG.md (Unreleased BREAKING) The internal `--session` flag and the unit tests calling `program.parseAsync(['...', 'browser', '--session', 'foo', ...])` are preserved as a stable internal API: tests bypass main.ts pre-processing and exercise commander directly. The pre-processor has its own targeted test file (cli-argv-preprocess.test.ts, 10 tests, all green). Verification: - npx tsc --noEmit — pass - npx vitest run --project unit — 1073/1074 pass (1 unrelated skip) - npx vitest run --project extension — 61/61 pass - npm run check:typed-error-lint — baseline 189 - npm run check:silent-column-drop — baseline 103 * fix(cli-argv): only rewrite when `browser` is the root command The preprocessor was looping through every argv slot and would mis-rewrite occurrences of the literal word `browser` deeper in argv (e.g. `opencli adapter init browser/x` or arg values containing `browser`). Now the preprocessor walks past leading root flags + their values to identify the root command token, and only acts when that token is `browser`. The full set of root value-consuming flags (`ROOT_VALUE_FLAGS`) is documented inline and kept in sync with the `program.option()` calls in cli.ts. Adds regression tests: - `opencli adapter init browser x` not rewritten - URL/path values containing `browser` not rewritten - `list browser state` (different root command) not rewritten - `--profile work browser foo state` correctly identifies `foo` as sessionname (not as --profile's value) - `--profile=work` long-form-with-equals consumes one slot only - boolean flags (`-v`) don't consume the next value 12/12 preprocessor tests pass. * fix(cli-argv): hide --session flag, fail-fast on retired form, rename to <session> Three blockers in #1505 review: 1. `--session` flag was still visible in `opencli browser --help` and could be used as a public entrance, contradicting "positional only" UX. Fix: switch from `.requiredOption()` to `.addOption(new Option(...).hideHelp())`. The flag is preserved as an internal API for the daemon protocol and direct `program.parseAsync` callers (tests), but is no longer documented or surfaced in structured help. 2. `opencli browser --session foo state` still succeeded. Now the argv preprocessor throws `BrowserSessionArgvError` when root `browser` is followed by `--session`, and main.ts catches it and exits with a user-facing usage error pointing to the positional form. 3. Missing-session error message exposed the internal flag: `required option '--session <name>' not specified`. Now `getBrowserSession()` in the action body throws `<session> is a required positional argument: opencli browser <session> <command>`, and commander no longer guards the hidden option. Also (per @WAWQAQ) rename placeholder `<sessionname>` -> `<session>` everywhere user-facing — shorter, matches CLI convention. The help text "<session> is a required positional: pass the name of the browser session..." carries the "name" semantics in description, not in the placeholder itself. Sync surfaces: - src/cli.ts — usage line, addOption with hideHelp, descriptions - src/cli-argv-preprocess.ts — throw on --session form - src/cli-argv-preprocess.test.ts — refusal test for old form - src/cli.test.ts — assertions updated for hidden option + new error path - src/help.ts — read `_usage` private field to respect `.usage()` override (commander's `.usage()` getter returns auto-generated form if not set, which would otherwise pollute every namespace's usage string) - src/main.ts — catch BrowserSessionArgvError, stderr + exit - README.md / README.zh-CN.md - docs/guide/browser-bridge.md / docs/zh/guide/browser-bridge.md - skills/opencli-browser/SKILL.md / skills/opencli-usage/SKILL.md - CHANGELOG.md Manual smoke tests (against built dist): - `opencli browser --help` shows `Usage: opencli browser <session> <command> [options]` - `opencli browser --help` Options block does NOT show `--session` - `opencli browser --session foo state` → friendly error, no commander stacktrace - `opencli browser state` → `<session> is a required positional argument: opencli browser <session> <command>` - `opencli browser foo state` → parses correctly * fix: inject <session> into subcommand help paths and drop stale sessions ref Two follow-up blockers from #1505 review: 1. Subcommand help and structured help still rendered the command path without the parent's positional. `opencli browser foo state --help` showed `Usage: opencli browser state [options]`, which would lead users (and agents reading structured help) to think `opencli browser state` was a valid invocation. Now: - `commanderPath()` injects an ancestor's leading-positional placeholder (extracted from its `.usage()` override) between the ancestor's name and the next path segment when building paths upward. - `commandPathFromRoot()` strips placeholder segments (e.g. `<session>`) from the relative `name` field so agents can still address subcommands by their leaf name; placeholders remain in the `command` / `usage` display paths. - `program.configureHelp({ commandUsage: ... })` is applied recursively to every descendant of `browser`, because commander does NOT inherit `configureHelp` into subcommands. Result: opencli browser <session> click --help -> Usage: opencli browser <session> click [target] [options] Daemon, plugin, adapter, profile namespaces (no `.usage()` override) are unaffected. 2. `skills/opencli-browser/SKILL.md` still referenced `opencli browser sessions`, which was removed in #1470. Replaced the sentence with the underlying invariant ("Bound sessions have no OpenCLI idle-close timer; the binding lasts until `unbind`, tab close, window close, or daemon restart") without mentioning the deleted command. Tests: - cli.test.ts: structured help expectations updated to include `<session>` in command/usage paths (3 tests) - cli-argv-preprocess.test.ts: 12 tests still green - 1136/1137 unit+extension green (1 unrelated skip) - typed-error-lint baseline 189 - silent-column-drop baseline 103
440 lines
25 KiB
Markdown
440 lines
25 KiB
Markdown
# OpenCLI
|
|
|
|
> **Turn websites, browser sessions, Electron apps, and local tools into deterministic interfaces for humans and AI agents.**
|
|
> Reuse your logged-in browser, automate live workflows, and crystallize repeated actions into reusable CLI commands.
|
|
|
|
[](./README.zh-CN.md)
|
|
[](https://www.npmjs.com/package/@jackwener/opencli)
|
|
[](https://nodejs.org)
|
|
[](./LICENSE)
|
|
|
|
OpenCLI gives you one surface for three different kinds of automation:
|
|
|
|
- **Use built-in adapters** for sites like Bilibili, Zhihu, Xiaohongshu, Reddit, HackerNews, Twitter/X, and [many more](#built-in-commands).
|
|
- **Let AI Agents operate any website** — install the `opencli-adapter-author` skill in your AI agent (Claude Code, Cursor, etc.), and it can navigate, click, type/fill, extract, and inspect any page through your logged-in browser via `opencli browser` primitives.
|
|
- **Write new adapters** end-to-end with `opencli browser` + the `opencli-adapter-author` skill, which guides from first recon through field decoding, code, and `opencli browser verify`.
|
|
|
|
It also works as a **CLI hub** for local tools such as `gh`, `docker`, `tg-cli`, `discord-cli`, `wx-cli`, and other binaries you register yourself, plus **desktop app adapters** for Electron apps like Cursor, Codex, Antigravity, ChatGPT, and Notion.
|
|
|
|
## Highlights
|
|
|
|
- **Desktop App Control** — Drive Electron apps (Cursor, Codex, ChatGPT, Notion, etc.) directly from the terminal via CDP.
|
|
- **Browser Automation for AI Agents** — Install the `opencli-adapter-author` skill, and your AI agent can operate any website: navigate, click, type/fill, extract, screenshot — all through your logged-in Chrome session.
|
|
- **Multi-profile Browser Bridge** — Install the extension in each Chrome profile you want to use, then route commands with `--profile`, `OPENCLI_PROFILE`, or `opencli profile use`.
|
|
- **Website → CLI** — Turn any website into a deterministic CLI: 100+ site surfaces are already registered, or write your own with the `opencli-adapter-author` skill + `opencli browser verify`.
|
|
- **Account-safe** — Reuses Chrome/Chromium logged-in state; your credentials never leave the browser.
|
|
- **AI Agent ready** — One skill takes you from site recon through API discovery, field decoding, adapter writing, and verification.
|
|
- **CLI Hub** — Discover, auto-install, and passthrough commands to any external CLI (gh, docker, obsidian, tg-cli, discord-cli, wx-cli, etc).
|
|
- **Zero LLM cost** — No tokens consumed at runtime. Run 10,000 times and pay nothing.
|
|
- **Deterministic** — Same command, same output schema, every time. Pipeable, scriptable, CI-friendly.
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
### 1. Install OpenCLI
|
|
|
|
OpenCLI requires **Node.js >= 21**.
|
|
|
|
```bash
|
|
node --version
|
|
npm install -g @jackwener/opencli
|
|
```
|
|
|
|
### 2. Install the Browser Bridge Extension
|
|
|
|
OpenCLI connects to Chrome/Chromium through a lightweight Browser Bridge extension plus a small local daemon. The daemon auto-starts when needed.
|
|
|
|
**Option A — Chrome Web Store (recommended):**
|
|
Install **OpenCLI** from the [Chrome Web Store](https://chromewebstore.google.com/detail/opencli/ildkmabpimmkaediidaifkhjpohdnifk).
|
|
|
|
**Option B — Manual install:**
|
|
1. Download the latest `opencli-extension-v{version}.zip` from the GitHub [Releases page](https://github.com/jackwener/opencli/releases).
|
|
2. Unzip it, open `chrome://extensions`, and enable **Developer mode**.
|
|
3. Click **Load unpacked** and select the unzipped folder.
|
|
|
|
### 3. Verify the setup
|
|
|
|
```bash
|
|
opencli doctor
|
|
```
|
|
|
|
### 4. Optional: name your Chrome profile
|
|
|
|
Each Chrome profile runs its own OpenCLI extension instance. If you use multiple Chrome profiles, list the connected profiles and assign local aliases:
|
|
|
|
```bash
|
|
opencli profile list
|
|
opencli profile rename <contextId> work
|
|
opencli profile use work
|
|
opencli --profile work browser state
|
|
```
|
|
|
|
With only one connected profile, OpenCLI uses it automatically. With multiple connected profiles and no default, OpenCLI asks you to choose instead of guessing.
|
|
|
|
### 5. Run your first commands
|
|
|
|
```bash
|
|
opencli list
|
|
opencli hackernews top --limit 5
|
|
opencli bilibili hot --limit 5
|
|
```
|
|
|
|
## For Humans
|
|
|
|
Use OpenCLI directly when you want a reliable command instead of a live browser session:
|
|
|
|
- `opencli list` shows every registered command.
|
|
- `opencli <site> <command>` runs a built-in or generated adapter.
|
|
- `opencli external register mycli` exposes a local CLI through the same discovery surface.
|
|
- `opencli doctor` helps diagnose browser connectivity.
|
|
|
|
## Extending OpenCLI
|
|
|
|
If you want to add your own commands, start with the [Extending OpenCLI guide](./docs/guide/extending-opencli.md). README keeps this short; the guide covers the directory layout, source-control model, and install commands.
|
|
|
|
| Need | Recommended path |
|
|
|------|------------------|
|
|
| Keep personal website commands in your own Git repo | `opencli plugin create` + `opencli plugin install file://...` |
|
|
| Quickly draft a private local adapter | `opencli browser init <site>/<command>` in `~/.opencli/clis/` |
|
|
| Modify an official adapter locally | `opencli adapter eject <site>` + `opencli adapter reset <site>` |
|
|
| Publish or install third-party commands | `opencli plugin install github:user/repo` |
|
|
| Wrap an existing local binary | `opencli external register <name>` |
|
|
|
|
## For AI Agents
|
|
|
|
OpenCLI's browser commands are designed to be used by AI Agents — not run manually. Install skills into your AI agent (Claude Code, Cursor, etc.), and the agent operates websites on your behalf using your logged-in Chrome session.
|
|
|
|
### Install skills
|
|
|
|
```bash
|
|
npx skills add jackwener/opencli
|
|
```
|
|
|
|
Or install only what you need:
|
|
|
|
```bash
|
|
npx skills add jackwener/opencli --skill opencli-adapter-author
|
|
npx skills add jackwener/opencli --skill opencli-autofix
|
|
npx skills add jackwener/opencli --skill opencli-browser
|
|
npx skills add jackwener/opencli --skill opencli-usage
|
|
npx skills add jackwener/opencli --skill smart-search
|
|
```
|
|
|
|
### Which skill to use
|
|
|
|
| Skill | When to use | Example prompt to your AI agent |
|
|
|-------|------------|-------------------------------|
|
|
| **opencli-adapter-author** | Operate a site in real time, or write a reusable adapter for a new site | "Help me check my Xiaohongshu notifications" / "Write an adapter for douyin trending" / "Make a command that grabs the top posts from this page" |
|
|
| **opencli-autofix** | Repair a broken adapter when a built-in command fails | "`opencli zhihu hot` is returning empty — fix it" |
|
|
| **opencli-browser** | Browser automation reference for AI agents | "Use browser commands to scrape this page" |
|
|
| **opencli-usage** | Quick reference for all OpenCLI commands and sites | "What commands does OpenCLI have for Twitter?" |
|
|
| **smart-search** | Search across existing OpenCLI capabilities | "Find me a Bilibili trending adapter" |
|
|
|
|
### How it works
|
|
|
|
Once `opencli-adapter-author` is installed, your AI agent can:
|
|
|
|
1. **Navigate** to any URL using your logged-in browser
|
|
2. **Read** page content via structured DOM snapshots (not screenshots)
|
|
3. **Interact** — click buttons, fill forms, select options, press keys
|
|
4. **Extract** data from the page or intercept network API responses
|
|
5. **Wait** for elements, text, or page transitions
|
|
|
|
The agent handles all the `opencli browser` commands internally — you just describe what you want done in natural language.
|
|
|
|
**Skill references:**
|
|
- [`skills/opencli-adapter-author/SKILL.md`](./skills/opencli-adapter-author/SKILL.md) — browser operation + adapter authoring, end-to-end
|
|
- [`skills/opencli-autofix/SKILL.md`](./skills/opencli-autofix/SKILL.md) — repair broken adapters
|
|
- [`skills/opencli-browser/SKILL.md`](./skills/opencli-browser/SKILL.md) — browser automation reference
|
|
- [`skills/opencli-usage/SKILL.md`](./skills/opencli-usage/SKILL.md) — command and site reference
|
|
- [`skills/smart-search/SKILL.md`](./skills/smart-search/SKILL.md) — capability search
|
|
|
|
Available browser commands include `open`, `state`, `click`, `type`, `fill`, `select`, `keys`, `wait`, `get`, `find`, `extract`, `frames`, `screenshot`, `scroll`, `back`, `eval`, `network`, `tab list`, `tab new`, `tab select`, `tab close`, `init`, `verify`, and `close`.
|
|
|
|
`opencli browser` commands require a `<session>` positional immediately after `browser`. `opencli browser work open <url>` and `opencli browser work tab new [url]` both return a target ID. Use `opencli browser work tab list` to inspect target IDs, then pass `--tab <targetId>` to route a command to a specific tab. `tab new` creates a new tab without changing the default browser target; only `tab select <targetId>` promotes that tab to the default target for later untargeted commands in the same session.
|
|
|
|
## Core Concepts
|
|
|
|
### `browser`: AI Agent browser control
|
|
|
|
`opencli browser` commands are the low-level primitives that AI Agents use to operate websites. You don't run these manually — instead, install the `opencli-adapter-author` skill into your AI agent, describe what you want in natural language, and the agent handles the browser operations.
|
|
|
|
For example, tell your agent: *"Help me check my Xiaohongshu notifications"* — the agent will use `opencli browser <session> open`, `state`, `click`, etc. under the hood.
|
|
|
|
### Built-in adapters: stable commands
|
|
|
|
Use site-specific commands such as `opencli hackernews top` or `opencli reddit hot` when the capability already exists. These are deterministic and work without browser — ideal for both humans and AI agents.
|
|
|
|
### Writing a new adapter
|
|
|
|
When the site you need is not yet covered, use the `opencli-adapter-author` skill. It takes the agent end-to-end:
|
|
|
|
1. Recon the site and classify its pattern (SPA / SSR / JSONP / Token / Streaming).
|
|
2. Discover the right endpoint — network inspection, initial state, bundle search, token trace, or interceptor fallback.
|
|
3. Decide the auth strategy — `PUBLIC` / `COOKIE` / `INTERCEPT` / `UI` / `LOCAL`.
|
|
4. Decode response fields and design output columns.
|
|
5. `opencli browser recon analyze <url>` for one-shot recon, then `opencli browser recon init <site>/<name>` → write adapter → `opencli browser recon verify <site>/<name>`.
|
|
6. Persist site knowledge to `~/.opencli/sites/<site>/` so the next adapter for the same site is faster.
|
|
|
|
### CLI Hub and desktop adapters
|
|
|
|
OpenCLI is not only for websites. It can also:
|
|
|
|
- expose local binaries like `gh`, `docker`, `obsidian`, `tg-cli`, `discord-cli`, `wx-cli`, or custom tools through `opencli <tool> ...`
|
|
- control Electron desktop apps through dedicated adapters and CDP-backed integrations
|
|
|
|
## Prerequisites
|
|
|
|
- **Node.js**: >= 21.0.0 (required for the standard npm install path)
|
|
- **Bun**: >= 1.0 (optional alternative runtime)
|
|
- **Chrome or Chromium** running and logged into the target site for browser-backed commands
|
|
|
|
> **Important**: Browser-backed commands reuse your Chrome/Chromium login session. If you get empty data or permission-like failures, first confirm the site is already open and authenticated in Chrome/Chromium.
|
|
|
|
## Configuration
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `OPENCLI_DAEMON_PORT` | `19825` | HTTP port for the daemon-extension bridge |
|
|
| `OPENCLI_PROFILE` | — | Browser Bridge profile alias/contextId to use when multiple Chrome profiles are connected |
|
|
| `OPENCLI_WINDOW` | command default | Set to `foreground` or `background` to override Browser Bridge window placement. Browser-backed commands also accept `--window <foreground\|background>`. |
|
|
| `OPENCLI_KEEP_TAB` | command default | Set to `true` or `false` to keep or release the browser tab lease after a browser-backed adapter command. Browser-backed adapter commands also accept `--keep-tab <true\|false>`. |
|
|
| `OPENCLI_BROWSER_CONNECT_TIMEOUT` | `30` | Seconds to wait for browser connection |
|
|
| `OPENCLI_BROWSER_COMMAND_TIMEOUT` | `60` | Seconds to wait for a single browser command |
|
|
| `OPENCLI_CDP_ENDPOINT` | — | Chrome DevTools Protocol endpoint for remote browser or Electron apps |
|
|
| `OPENCLI_CDP_TARGET` | — | Filter CDP targets by URL substring (e.g. `detail.1688.com`) |
|
|
| `OPENCLI_VERBOSE` | `false` | Enable verbose logging (`-v` flag also works) |
|
|
| `DEBUG_SNAPSHOT` | — | Set to `1` for DOM snapshot debug output |
|
|
|
|
`opencli browser *` requires an explicit `<session>` positional, uses a foreground browser window by default, and keeps that session's tab lease until `opencli browser <session> close` or idle cleanup. Browser-backed adapters use a background adapter window and release one-shot tab leases by default. Interactive adapters can declare `siteSession: 'persistent'` to keep a stable site tab for continuity; pass `--site-session ephemeral` for a one-shot tab.
|
|
|
|
## Update
|
|
|
|
```bash
|
|
npm install -g @jackwener/opencli@latest
|
|
|
|
# If you use the packaged OpenCLI skills, refresh them too
|
|
npx skills add jackwener/opencli
|
|
```
|
|
|
|
Or refresh only the skills you actually use:
|
|
|
|
```bash
|
|
npx skills add jackwener/opencli --skill opencli-adapter-author
|
|
npx skills add jackwener/opencli --skill opencli-autofix
|
|
npx skills add jackwener/opencli --skill opencli-browser
|
|
npx skills add jackwener/opencli --skill opencli-usage
|
|
npx skills add jackwener/opencli --skill smart-search
|
|
```
|
|
|
|
## For Developers
|
|
|
|
Install from source:
|
|
|
|
```bash
|
|
git clone git@github.com:jackwener/opencli.git
|
|
cd opencli
|
|
npm install
|
|
npm run build
|
|
npm link
|
|
```
|
|
|
|
To load the source Browser Bridge extension:
|
|
|
|
1. Open `chrome://extensions` and enable **Developer mode**.
|
|
2. Click **Load unpacked** and select this repository's `extension/` directory.
|
|
|
|
## Built-in Commands
|
|
|
|
| Site | Commands |
|
|
|------|----------|
|
|
| **xiaohongshu** | `search` `note` `comments` `feed` `user` `download` `publish` `notifications` `creator-notes` `creator-notes-summary` `creator-note-detail` `creator-profile` `creator-stats` |
|
|
| **rednote** | `search` `note` `comments` `user` `download` `feed` `notifications` |
|
|
| **bilibili** | `hot` `search` `history` `feed` `ranking` `download` `comments` `dynamic` `favorite` `following` `me` `subtitle` `video` `user-videos` |
|
|
| **tieba** | `hot` `posts` `search` `read` |
|
|
| **hupu** | `hot` `search` `detail` `mentions` `reply` `like` `unlike` |
|
|
| **twitter** | `trending` `search` `timeline` `tweets` `lists` `list-tweets` `list-add` `list-remove` `bookmarks` `post` `download` `profile` `article` `like` `likes` `notifications` `reply` `reply-dm` `thread` `follow` `unfollow` `followers` `following` `block` `unblock` `bookmark` `unbookmark` `delete` `hide-reply` `accept` |
|
|
| **reddit** | `hot` `frontpage` `popular` `search` `subreddit` `read` `user` `user-posts` `user-comments` `upvote` `upvoted` `save` `saved` `comment` `subscribe` |
|
|
| **zhihu** | `hot` `search` `question` `download` `follow` `like` `favorite` `comment` `answer` |
|
|
| **amazon** | `bestsellers` `search` `product` `offer` `discussion` `movers-shakers` `new-releases` `rankings` |
|
|
| **1688** | `search` `item` `assets` `download` `store` |
|
|
| **gitee** | `trending` `search` `user` |
|
|
| **gemini** | `new` `ask` `image` `deep-research` `deep-research-result` |
|
|
| **claude** | `ask` `send` `new` `status` `read` `history` `detail` |
|
|
| **yuanbao** | `new` `ask` |
|
|
| **notebooklm** | `status` `list` `open` `current` `get` `history` `summary` `note-list` `notes-get` `source-list` `source-get` `source-fulltext` `source-guide` |
|
|
| **spotify** | `auth` `status` `play` `pause` `next` `prev` `volume` `search` `queue` `shuffle` `repeat` |
|
|
| **xianyu** | `search` `item` `chat` `publish` |
|
|
| **xiaoe** | `courses` `detail` `catalog` `play-url` `content` |
|
|
| **quark** | `ls` `mkdir` `mv` `rename` `rm` `save` `share-tree` |
|
|
| **uiverse** | `code` `preview` |
|
|
| **baidu-scholar** | `search` |
|
|
| **google-scholar** | `search` `cite` `profile` |
|
|
| **gov-law** | `search` `recent` |
|
|
| **gov-policy** | `search` `recent` |
|
|
| **nowcoder** | `hot` `trending` `topics` `recommend` `creators` `companies` `jobs` `search` `suggest` `experience` `referral` `salary` `papers` `practice` `notifications` `detail` |
|
|
| **wanfang** | `search` |
|
|
| **hackernews** | `top` `new` `best` `ask` `show` `jobs` `search` `user` |
|
|
| **xiaoyuzhou** | `auth*` `podcast*` `podcast-episodes*` `episode*` `download*` `transcript*` |
|
|
|
|
100+ site surfaces in total — **[→ see all supported sites & commands](./docs/adapters/index.md)**
|
|
|
|
`*` `opencli xiaoyuzhou podcast`, `podcast-episodes`, `episode`, `download`, and `transcript` require local Xiaoyuzhou credentials in `~/.opencli/xiaoyuzhou.json`.
|
|
|
|
## CLI Hub
|
|
|
|
OpenCLI acts as a universal hub for your existing command-line tools — unified discovery, pure passthrough execution, and auto-install (if a tool isn't installed, OpenCLI runs `brew install <tool>` automatically before re-running the command).
|
|
|
|
| External CLI | Description | Example |
|
|
|--------------|-------------|---------|
|
|
| **gh** | GitHub CLI | `opencli gh pr list --limit 5` |
|
|
| **obsidian** | Obsidian vault management | `opencli obsidian search query="AI"` |
|
|
| **docker** | Docker | `opencli docker ps` |
|
|
| **lark-cli** | Lark/Feishu — messages, docs, calendar, tasks, 200+ commands | `opencli lark-cli calendar +agenda` |
|
|
| **dws** | DingTalk — cross-platform CLI for DingTalk's full suite, designed for humans and AI agents | `opencli dws msg send --to user "hello"` |
|
|
| **wecom-cli** | WeCom/企业微信 — CLI for WeCom open platform, for humans and AI agents | `opencli wecom-cli msg send --to user "hello"` |
|
|
| **tg-cli** | Telegram — local-first sync, search, and export via MTProto for AI agents | `opencli tg search "AI news" -f json` |
|
|
| **discord-cli** | Discord — local-first sync, search, and export via SQLite for AI agents | `opencli discord recent --channel general` |
|
|
| **wx-cli** | WeChat — query local WeChat data: sessions, messages, search, contacts, export | `opencli wx search "OpenCLI"` |
|
|
| **vercel** | Vercel — deploy projects, manage domains, env vars, logs | `opencli vercel deploy --prod` |
|
|
|
|
**Register your own** — add any local CLI so AI agents can discover it via `opencli list`:
|
|
|
|
```bash
|
|
opencli external register mycli
|
|
```
|
|
|
|
### Desktop App Adapters
|
|
|
|
Control Electron desktop apps directly from the terminal. Each adapter has its own detailed documentation:
|
|
|
|
| App | Description | Doc |
|
|
|-----|-------------|-----|
|
|
| **Cursor** | Control Cursor IDE — Composer, chat, code extraction | [Doc](./docs/adapters/desktop/cursor.md) |
|
|
| **Codex** | Drive OpenAI Codex CLI agent headlessly | [Doc](./docs/adapters/desktop/codex.md) |
|
|
| **Antigravity** | Control Antigravity Ultra from terminal | [Doc](./docs/adapters/desktop/antigravity.md) |
|
|
| **ChatGPT App** | Automate ChatGPT macOS desktop app | [Doc](./docs/adapters/desktop/chatgpt-app.md) |
|
|
| **ChatWise** | Multi-LLM client (GPT-4, Claude, Gemini) | [Doc](./docs/adapters/desktop/chatwise.md) |
|
|
| **Notion** | Search, read, write Notion pages | [Doc](./docs/adapters/desktop/notion.md) |
|
|
| **Discord** | Discord Desktop — messages, channels, servers | [Doc](./docs/adapters/desktop/discord.md) |
|
|
| **Doubao** | Control Doubao AI desktop app via CDP | [Doc](./docs/adapters/desktop/doubao-app.md) |
|
|
|
|
To add a new Electron app, start with [docs/guide/electron-app-cli.md](./docs/guide/electron-app-cli.md).
|
|
|
|
## Download Support
|
|
|
|
OpenCLI supports downloading images, videos, and articles from supported platforms.
|
|
|
|
| Platform | Content Types | Notes |
|
|
|----------|---------------|-------|
|
|
| **xiaohongshu** | Images, Videos | Downloads all media from a note |
|
|
| **rednote** | Images, Videos | Downloads all media from a signed rednote note URL |
|
|
| **bilibili** | Videos | Requires `yt-dlp` installed |
|
|
| **twitter** | Images, Videos | From user media tab or single tweet |
|
|
| **douban** | Images | Poster / still image lists |
|
|
| **pixiv** | Images | Original-quality illustrations, multi-page |
|
|
| **1688** | Images, Videos | Downloads page-visible product media from item pages |
|
|
| **xiaoyuzhou** | Audio, Transcript | Downloads episode audio and transcript JSON/text with local credentials |
|
|
| **zhihu** | Articles (Markdown) | Exports with optional image download |
|
|
| **weixin** | Articles (Markdown) | WeChat Official Account articles |
|
|
|
|
For video downloads, install `yt-dlp` first: `brew install yt-dlp`
|
|
|
|
```bash
|
|
opencli xiaohongshu download "https://www.xiaohongshu.com/search_result/<id>?xsec_token=..." --output ./xhs
|
|
opencli xiaohongshu download "https://xhslink.com/..." --output ./xhs
|
|
opencli rednote download "https://www.rednote.com/search_result/<id>?xsec_token=..." --output ./rednote
|
|
opencli bilibili download BV1xxx --output ./bilibili
|
|
opencli twitter download elonmusk --limit 20 --output ./twitter
|
|
opencli 1688 download 841141931191 --output ./1688-downloads
|
|
opencli xiaoyuzhou download 69b3b675772ac2295bfc01d0 --output ./xiaoyuzhou
|
|
opencli xiaoyuzhou transcript 69dd0c98e2c8be31551f6a33 --output ./xiaoyuzhou-transcripts
|
|
```
|
|
|
|
`opencli xiaoyuzhou download` and `transcript` require local Xiaoyuzhou credentials in `~/.opencli/xiaoyuzhou.json`.
|
|
|
|
## Output Formats
|
|
|
|
All built-in commands support `--format` / `-f` with `table` (default), `json`, `yaml`, `md`, and `csv`.
|
|
|
|
```bash
|
|
opencli bilibili hot -f json # Pipe to jq or LLMs
|
|
opencli bilibili hot -f csv # Spreadsheet-friendly
|
|
opencli bilibili hot -v # Verbose: show pipeline debug steps
|
|
```
|
|
|
|
## Exit Codes
|
|
|
|
opencli follows Unix `sysexits.h` conventions so it integrates naturally with shell pipelines and CI scripts:
|
|
|
|
| Code | Meaning | When |
|
|
|------|---------|------|
|
|
| `0` | Success | Command completed normally |
|
|
| `1` | Generic error | Unexpected / unclassified failure |
|
|
| `2` | Usage error | Bad arguments or unknown command |
|
|
| `66` | Empty result | No data returned (`EX_NOINPUT`) |
|
|
| `69` | Service unavailable | Browser Bridge not connected (`EX_UNAVAILABLE`) |
|
|
| `75` | Temporary failure | Command timed out — retry (`EX_TEMPFAIL`) |
|
|
| `77` | Auth required | Not logged in to target site (`EX_NOPERM`) |
|
|
| `78` | Config error | Missing credentials or bad config (`EX_CONFIG`) |
|
|
| `130` | Interrupted | Ctrl-C / SIGINT |
|
|
|
|
```bash
|
|
opencli spotify status || echo "exit $?" # 69 if browser not running
|
|
opencli gh issue list 2>/dev/null
|
|
[ $? -eq 77 ] && opencli gh auth login # auto-auth if not logged in
|
|
```
|
|
|
|
## Plugins
|
|
|
|
Extend OpenCLI with community-contributed adapters:
|
|
|
|
```bash
|
|
opencli plugin install github:user/opencli-plugin-my-tool
|
|
opencli plugin list
|
|
opencli plugin update --all
|
|
opencli plugin uninstall my-tool
|
|
```
|
|
|
|
| Plugin | Type | Description |
|
|
|--------|------|-------------|
|
|
| [opencli-plugin-github-trending](https://github.com/ByteYue/opencli-plugin-github-trending) | JS | GitHub Trending repositories |
|
|
| [opencli-plugin-hot-digest](https://github.com/ByteYue/opencli-plugin-hot-digest) | JS | Multi-platform trending aggregator |
|
|
| [opencli-plugin-juejin](https://github.com/Astro-Han/opencli-plugin-juejin) | JS | 稀土掘金 (Juejin) hot articles |
|
|
| [opencli-plugin-vk](https://github.com/flobo3/opencli-plugin-vk) | JS | VK (VKontakte) wall, feed, and search |
|
|
|
|
See [Plugins Guide](./docs/guide/plugins.md) for creating your own plugin.
|
|
|
|
## For AI Agents (Developer Guide)
|
|
|
|
Before writing any adapter code, read the [`opencli-adapter-author` skill](./skills/opencli-adapter-author/SKILL.md). It takes you end-to-end:
|
|
|
|
- Recon the site and pick a pattern (SPA / SSR / JSONP / Token / Streaming).
|
|
- Discover the right endpoint via `opencli browser <session> network`, `eval`, or the interceptor fallback.
|
|
- Decide auth strategy (`PUBLIC` / `COOKIE` / `INTERCEPT` / `UI` / `LOCAL`).
|
|
- Run `opencli browser recon analyze <url>` for one-shot recon, decode response fields, design columns, scaffold with `opencli browser recon init`.
|
|
- Verify with `opencli browser recon verify <site>/<name>` before shipping.
|
|
|
|
For long-lived personal commands that should live in your own Git repo, use a local plugin instead; see [Extending OpenCLI](./docs/guide/extending-opencli.md). Quick private adapters can still live at `~/.opencli/clis/<site>/<name>.js`. Site knowledge (endpoints, field maps, fixtures) accumulates in `~/.opencli/sites/<site>/` so the next adapter for the same site starts from context instead of zero.
|
|
|
|
## Testing
|
|
|
|
See **[TESTING.md](./TESTING.md)** for how to run and write tests.
|
|
|
|
## Troubleshooting
|
|
|
|
- **"Extension not connected"** — Ensure the Browser Bridge extension is installed from the [Chrome Web Store](https://chromewebstore.google.com/detail/opencli/ildkmabpimmkaediidaifkhjpohdnifk) and **enabled** in `chrome://extensions`.
|
|
- **"attach failed: Cannot access a chrome-extension:// URL"** — Another extension may be interfering. Try disabling other extensions temporarily.
|
|
- **Empty data or 'Unauthorized' error** — Your Chrome/Chromium login session may have expired. Navigate to the target site and log in again.
|
|
- **Node API errors / missing `fetch` / startup crash on old Node** — OpenCLI requires **Node.js >= 21**. Run `node --version`, upgrade Node if needed, then retry.
|
|
- **Daemon issues** — Check status: `curl localhost:19825/status` · View logs: `curl localhost:19825/logs`
|
|
|
|
## Star History
|
|
|
|
[](https://star-history.com/#jackwener/opencli&Date)
|
|
|
|
## License
|
|
|
|
[Apache-2.0](./LICENSE)
|