Compare commits

...

4 Commits

Author SHA1 Message Date
jackwener 26be7fc28f fix: revert incorrect daemon restart from postinstall
The daemon (browser bridge) only handles CDP communication — it has no
knowledge of adapters. Adapter discovery, loading, and execution all
happen in the CLI process, which is fresh each invocation. The
_loadedModules cache in execution.ts is process-local and not a real
staleness concern. Remove the unnecessary restartDaemon() call.
2026-04-11 00:45:04 +08:00
jackwener fd6756d1af fix: update CI matrix to Node 22 only (drop Node 20)
package.json requires Node >= 21 (styleText dependency). The CI matrix
was still testing Node 20 which doesn't meet this requirement.
2026-04-11 00:41:37 +08:00
jackwener 11cd9d14ad fix: align docs and skills with JS-first adapter contract
Adapters are now .js files (not .ts). Update all references across:
- README.md, README.zh-CN.md, CONTRIBUTING.md
- docs/guide/getting-started.md, docs/index.md
- skills/opencli-browser/SKILL.md, skills/opencli-explorer/SKILL.md

The runtime (discovery.ts) only loads .js from user clis/ directories,
and `opencli browser init` generates .js scaffolds. Documentation was
still teaching users to create .ts files.
2026-04-11 00:40:12 +08:00
jackwener f94458bba3 fix: project hygiene — docs, lint, daemon restart, code fence
- Update Node version requirement from >= 20 to >= 21 in 7 doc files
  (README, README.zh-CN, installation guides, troubleshooting)
- Update adapter count from 79+ to 87+ in READMEs
- Remove duplicate `lint` script (identical to `typecheck`)
- Fix TESTING.md CI matrix: Node ['22'] instead of ['20', '22']
- Fix autofix SKILL.md code fence escaping (\``` → ~~~)
- Add daemon restart to postinstall so updated adapters are picked up
- Fix preuninstall to respect OPENCLI_DAEMON_PORT env var
2026-04-11 00:36:40 +08:00
15 changed files with 37 additions and 37 deletions
+1 -1
View File
@@ -47,7 +47,7 @@ jobs:
fail-fast: false
matrix:
os: ${{ (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && fromJSON('["ubuntu-latest","macos-latest","windows-latest"]') || fromJSON('["ubuntu-latest"]') }}
node-version: ${{ (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && fromJSON('["20","22"]') || fromJSON('["22"]') }}
node-version: ${{ (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && fromJSON('["22"]') || fromJSON('["22"]') }}
shard: [1, 2]
steps:
- uses: actions/checkout@v6
+3 -3
View File
@@ -30,7 +30,7 @@ All adapters use TypeScript. Use the pipeline API for data-fetching commands, an
### Pipeline Adapter (Recommended for data-fetching commands)
Create a file like `clis/<site>/<command>.ts`:
Create a file like `clis/<site>/<command>.js`:
```typescript
import { cli, Strategy } from '@jackwener/opencli/registry';
@@ -60,11 +60,11 @@ cli({
});
```
See [`hackernews/top.ts`](clis/hackernews/top.ts) for a real example.
See [`hackernews/top.js`](clis/hackernews/top.js) for a real example.
### func() Adapter (For complex browser interactions)
Create a file like `clis/<site>/<command>.ts`:
Create a file like `clis/<site>/<command>.js`:
```typescript
import { cli, Strategy } from '@jackwener/opencli/registry';
+5 -5
View File
@@ -30,10 +30,10 @@ It also works as a **CLI hub** for local tools such as `gh`, `docker`, and other
- **AI Agent ready** — `explore` discovers APIs, `synthesize` generates adapters, `cascade` finds auth strategies, `browser` controls the browser directly.
- **External CLI Hub** — Discover, auto-install, and passthrough commands to any external CLI (gh, obsidian, docker, etc). Zero setup.
- **Self-healing setup** — `opencli doctor` diagnoses and auto-starts the daemon, extension, and live browser connectivity.
- **Dynamic Loader** — Simply drop `.ts` adapters into the `clis/` folder for auto-registration.
- **Dynamic Loader** — Simply drop `.js` adapters into the `clis/` folder for auto-registration.
- **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.
- **Broad coverage** — 79+ sites across global and Chinese platforms (Bilibili, Zhihu, Xiaohongshu, Reddit, HackerNews, and more), plus desktop Electron apps via CDP.
- **Broad coverage** — 87+ sites across global and Chinese platforms (Bilibili, Zhihu, Xiaohongshu, Reddit, HackerNews, and more), plus desktop Electron apps via CDP.
---
@@ -136,7 +136,7 @@ OpenCLI is not only for websites. It can also:
## Prerequisites
- **Node.js**: >= 20.0.0 (or **Bun** >= 1.0)
- **Node.js**: >= 21.0.0 (or **Bun** >= 1.0)
- **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.
@@ -212,7 +212,7 @@ To load the source Browser Bridge extension:
| **xiaoe** | `courses` `detail` `catalog` `play-url` `content` |
| **quark** | `ls` `mkdir` `mv` `rename` `rm` `save` `share-tree` |
79+ adapters in total — **[→ see all supported sites & commands](./docs/adapters/index.md)**
87+ adapters in total — **[→ see all supported sites & commands](./docs/adapters/index.md)**
## CLI Hub
@@ -349,7 +349,7 @@ See **[TESTING.md](./TESTING.md)** for how to run and write tests.
- **"Extension not connected"** — Ensure the Browser Bridge extension is installed and **enabled** in `chrome://extensions` in Chrome or Chromium.
- **"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** — Ensure Node.js >= 20. Some dependencies require modern Node APIs.
- **Node API errors** — Ensure Node.js >= 21. Some features require `node:util` styleText (stable in Node 21+).
- **Daemon issues** — Check status: `curl localhost:19825/status` · View logs: `curl localhost:19825/logs`
## Star History
+5 -5
View File
@@ -10,7 +10,7 @@
OpenCLI 可以用同一套 CLI 做三类事情:
- **直接使用现成适配器**:B站、知乎、小红书、Twitter/X、Reddit、HackerNews 等 [79+ 站点](#内置命令) 开箱即用。
- **直接使用现成适配器**:B站、知乎、小红书、Twitter/X、Reddit、HackerNews 等 [87+ 站点](#内置命令) 开箱即用。
- **直接驱动浏览器**:用 `opencli browser` 让 AI Agent 实时点击、输入、提取、截图、检查页面状态。
- **把新网站生成成 CLI**:通过 `explore``synthesize``generate``cascade` 从真实页面行为推导出新的适配器。
@@ -23,7 +23,7 @@ OpenCLI 可以用同一套 CLI 做三类事情:
- **输出稳定**:适配器命令返回固定结构,适合 shell、脚本、CI 和 AI Agent 工具调用。
- **面向 AI Agent**`browser` 负责实时操作,`explore` 负责探索接口,`synthesize` 负责生成适配器,`cascade` 负责探测认证路径。
- **运行成本低**:已有命令运行时不消耗模型 token。
- **天然可扩展**:既能用内置能力,也能注册本地 CLI,或直接往 `clis/``.ts` 适配器。
- **天然可扩展**:既能用内置能力,也能注册本地 CLI,或直接往 `clis/``.js` 适配器。
## 快速开始
@@ -124,7 +124,7 @@ OpenCLI 不只是网站 CLI,还可以:
## 前置要求
- **Node.js**: >= 20.0.0
- **Node.js**: >= 21.0.0
- 浏览器型命令需要 Chrome 或 Chromium 处于运行中,并已登录目标网站
> **重要**:浏览器型命令直接复用你的 Chrome/Chromium 登录态。如果拿到空数据或出现权限类失败,先确认目标站点已经在浏览器里打开并完成登录。
@@ -262,7 +262,7 @@ npm link
| **douyin** | `videos` `publish` `drafts` `draft` `delete` `stats` `profile` `update` `hashtag` `location` `activities` `collections` | 浏览器 |
| **yuanbao** | `new` `ask` | 浏览器 |
79+ 适配器 — **[→ 查看完整命令列表](./docs/adapters/index.md)**
87+ 适配器 — **[→ 查看完整命令列表](./docs/adapters/index.md)**
### 外部 CLI 枢纽
@@ -460,7 +460,7 @@ opencli cascade https://api.example.com/data
- **返回空数据,或者报错 "Unauthorized"**
- Chrome/Chromium 里的登录态可能已经过期。请打开当前页面,在新标签页重新手工登录或刷新该页面。
- **Node API 错误 (如 parseArgs, fs 等)**
- 确保 Node.js 版本 `>= 20`
- 确保 Node.js 版本 `>= 21``node:util``styleText` 需要 Node 21+
- **Daemon 问题**
- 检查 daemon 状态:`curl localhost:19825/status`
- 查看扩展日志:`curl localhost:19825/logs`
+2 -2
View File
@@ -205,12 +205,12 @@ E2E 与 smoke 都使用 `./.github/actions/setup-chrome` 准备真实 Chrome
### Sharding
单元测试使用 vitest 内置 shard,并在 Node `20` / `22` 两个版本上运行
单元测试使用 vitest 内置 shard,并在 Node `22` 上运行(项目要求 Node >= 21
```yaml
strategy:
matrix:
node-version: ['20', '22']
node-version: ['22']
shard: [1, 2]
steps:
- run: npx vitest run src/ --reporter=verbose --shard=${{ matrix.shard }}/2
+1 -1
View File
@@ -15,7 +15,7 @@ OpenCLI turns **any website** or **Electron app** into a command-line interface
- **Account-safe** — Reuses Chrome's logged-in state; your credentials never leave the browser.
- **AI Agent ready** — `explore` discovers APIs, `synthesize` generates adapters, `cascade` finds auth strategies.
- **Self-healing setup** — `opencli doctor` auto-starts the daemon and diagnoses extension + live browser connectivity.
- **Dynamic Loader** — Simply drop `.ts` adapters into the `clis/` folder for auto-registration.
- **Dynamic Loader** — Simply drop `.js` adapters into the `clis/` folder for auto-registration.
- **Dual-Engine Architecture** — Supports both declarative pipeline adapters and robust browser runtime TypeScript injections.
## Quick Start
+1 -1
View File
@@ -2,7 +2,7 @@
## Requirements
- **Node.js**: >= 20.0.0
- **Node.js**: >= 21.0.0
- **Chrome** running and logged into the target site (for browser commands)
## Install via npm (Recommended)
+1 -1
View File
@@ -25,7 +25,7 @@ OPENCLI_CDP_TARGET=detail.1688.com opencli 1688 item 841141931191 -f json
### Node API errors
- Make sure you are using **Node.js >= 20**. Some dependencies require modern Node APIs.
- Make sure you are using **Node.js >= 21**. Some features require `node:util` styleText (stable in Node 21+).
- Run `node --version` to verify.
### Daemon issues
+1 -1
View File
@@ -31,5 +31,5 @@ features:
details: "opencli doctor auto-starts the daemon and diagnoses extension + live browser connectivity."
- icon: 📦
title: Dynamic Loader
details: Simply drop .ts adapters into the clis/ folder for auto-registration. Zero boilerplate.
details: Simply drop .js adapters into the clis/ folder for auto-registration. Zero boilerplate.
---
+1 -1
View File
@@ -2,7 +2,7 @@
## 系统要求
- **Node.js**: >= 20.0.0
- **Node.js**: >= 21.0.0
- **Chrome** 已运行并登录目标网站(浏览器命令需要)
## 通过 npm 安装(推荐)
+1 -2
View File
@@ -47,10 +47,9 @@
"copy-yaml": "node scripts/copy-yaml.cjs",
"start": "node dist/src/main.js",
"start:bun": "bun dist/src/main.js",
"preuninstall": "node -e \"fetch('http://127.0.0.1:19825/shutdown',{method:'POST',headers:{'X-OpenCLI':'1'},signal:AbortSignal.timeout(3000)}).catch(()=>{})\" || true",
"preuninstall": "node -e \"fetch('http://127.0.0.1:'+(process.env.OPENCLI_DAEMON_PORT||'19825')+'/shutdown',{method:'POST',headers:{'X-OpenCLI':'1'},signal:AbortSignal.timeout(3000)}).catch(()=>{})\" || true",
"postinstall": "node scripts/postinstall.js || true; node scripts/fetch-adapters.js || true",
"typecheck": "tsc --noEmit",
"lint": "tsc --noEmit",
"prepare": "[ -d src ] && npm run build || true",
"prepublishOnly": "npm run build",
"test": "vitest run --project unit --project extension",
+1
View File
@@ -168,6 +168,7 @@ function main() {
console.log('');
console.log(' Then run \x1b[36mopencli doctor\x1b[0m to verify.');
console.log('');
}
main();
+4 -4
View File
@@ -215,15 +215,15 @@ OpenCLI autofix repaired this adapter locally, and the retry passed.
## Original failure
- Error code: `<error_code>`
\```text
~~~
<error_message>
\```
~~~
## Local fix summary
\```text
~~~
<1-2 sentence description of what you changed and why>
\```
~~~
_Issue filed by OpenCLI autofix after a verified local repair._
```
+5 -5
View File
@@ -72,7 +72,7 @@ opencli browser click 7 # all three together
4. **Wait** (if needed): `opencli browser wait selector ".loaded"` or `wait text "Success"`
5. **Verify**: `opencli browser state` or `opencli browser get value <N>`
6. **Repeat**: browser stays open between commands
7. **Save**: write a TS adapter to `~/.opencli/clis/<site>/<command>.ts`
7. **Save**: write a JS adapter to `~/.opencli/clis/<site>/<command>.js`
## Commands
@@ -159,7 +159,7 @@ opencli browser network --all # Include static resources
### Sedimentation (Save as CLI)
```bash
opencli browser init hn/top # Generate adapter scaffold at ~/.opencli/clis/hn/top.ts
opencli browser init hn/top # Generate adapter scaffold at ~/.opencli/clis/hn/top.js
opencli browser verify hn/top # Test the adapter (adds --limit 3 only if `limit` arg is defined)
```
@@ -207,7 +207,7 @@ opencli browser network # See captured API requests
opencli browser network --detail 0 # Inspect response body
# 3. Generate scaffold
opencli browser init hn/top # Creates ~/.opencli/clis/hn/top.ts
opencli browser init hn/top # Creates ~/.opencli/clis/hn/top.js
# 4. Edit the adapter (fill in func logic)
# - If API found: use fetch() directly (Strategy.PUBLIC or COOKIE)
@@ -224,7 +224,7 @@ opencli browser close
### Example adapter:
```typescript
// ~/.opencli/clis/hn/top.ts
// ~/.opencli/clis/hn/top.js
import { cli, Strategy } from '@jackwener/opencli/registry';
cli({
@@ -250,7 +250,7 @@ cli({
});
```
Save to `~/.opencli/clis/<site>/<command>.ts` → immediately available as `opencli <site> <command>`.
Save to `~/.opencli/clis/<site>/<command>.js` → immediately available as `opencli <site> <command>`.
### Strategy Guide
+5 -5
View File
@@ -151,12 +151,12 @@ fetch(url) 直接能拿到?
```bash
ls clis/<site>/ # 看同站点已有什么
cat clis/<site>/feed.ts # 读最相似的那个
cat clis/<site>/feed.js # 读最相似的那个
```
改 3 处即可:`name`、API URL、字段映射。
**Bilibili 平台 SDK**`clis/bilibili/utils.ts`):
**Bilibili 平台 SDK**`clis/bilibili/utils.js`):
- `fetchJson(page, url)` → 普通 Cookie-tier API
- `apiGet(page, path, {signed, params})` → URL 含 `/wbi/` 的接口(自动签名)
- `getSelfUid(page)` / `resolveUid(page, input)` → 用户 UID 处理
@@ -165,7 +165,7 @@ cat clis/<site>/feed.ts # 读最相似的那个
## Step 3: 编写适配器
所有适配器统一使用 TypeScript `cli()` API,放入 `clis/<site>/<name>.ts` 即自动注册。
所有适配器统一使用 `cli()` API,放入 `clis/<site>/<name>.js` 即自动注册。
完整模板(Tier 1~4)、分页模式、错误处理规范(`throw CliError` + YAML envelope)→ **[adapter-templates.md](references/adapter-templates.md)**
@@ -209,8 +209,8 @@ cli({
<!-- keep in sync with oneshot SKILL.md §测试 -->
**两种开发场景**
- **Repo 贡献**:文件放 `clis/<site>/<name>.ts``npm run build` 后自动注册
- **私人 adapter**(本地使用,无需提 PR):文件放 `~/.opencli/clis/<site>/<name>.ts`,无需 build
- **Repo 贡献**:文件放 `clis/<site>/<name>.js``npm run build` 后自动注册
- **私人 adapter**(本地使用,无需提 PR):文件放 `~/.opencli/clis/<site>/<name>.js`,无需 build
```bash
# Repo 贡献:build 后直接运行