@jackwener/opencli 1.5.8 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +35 -1
- package/README.zh-CN.md +17 -1
- package/SKILL.md +31 -851
- package/autoresearch/baseline-browse.txt +1 -0
- package/autoresearch/baseline-skill.txt +1 -0
- package/autoresearch/browse-tasks.json +688 -0
- package/autoresearch/eval-browse.ts +185 -0
- package/autoresearch/eval-skill.ts +248 -0
- package/autoresearch/run-browse.sh +9 -0
- package/autoresearch/run-skill.sh +9 -0
- package/dist/browser/base-page.d.ts +48 -0
- package/dist/browser/base-page.js +160 -0
- package/dist/browser/cdp.js +4 -106
- package/dist/browser/daemon-client.d.ts +20 -7
- package/dist/browser/daemon-client.js +39 -39
- package/dist/browser/daemon-client.test.js +77 -0
- package/dist/browser/discover.d.ts +1 -4
- package/dist/browser/discover.js +9 -23
- package/dist/browser/errors.d.ts +4 -0
- package/dist/browser/errors.js +20 -0
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/page.d.ts +10 -35
- package/dist/browser/page.js +55 -187
- package/dist/browser/tabs.js +5 -5
- package/dist/browser.test.js +15 -15
- package/dist/cli-manifest.json +294 -22
- package/dist/cli.js +392 -0
- package/dist/clis/amazon/bestsellers.d.ts +21 -0
- package/dist/clis/amazon/bestsellers.js +130 -0
- package/dist/clis/amazon/bestsellers.test.js +20 -0
- package/dist/clis/amazon/discussion.d.ts +20 -0
- package/dist/clis/amazon/discussion.js +91 -0
- package/dist/clis/amazon/discussion.test.d.ts +1 -0
- package/dist/clis/amazon/discussion.test.js +36 -0
- package/dist/clis/amazon/offer.d.ts +23 -0
- package/dist/clis/amazon/offer.js +140 -0
- package/dist/clis/amazon/offer.test.d.ts +1 -0
- package/dist/clis/amazon/offer.test.js +29 -0
- package/dist/clis/amazon/product.d.ts +18 -0
- package/dist/clis/amazon/product.js +92 -0
- package/dist/clis/amazon/product.test.d.ts +1 -0
- package/dist/clis/amazon/product.test.js +24 -0
- package/dist/clis/amazon/search.d.ts +18 -0
- package/dist/clis/amazon/search.js +87 -0
- package/dist/clis/amazon/search.test.d.ts +1 -0
- package/dist/clis/amazon/search.test.js +22 -0
- package/dist/clis/amazon/shared.d.ts +64 -0
- package/dist/clis/amazon/shared.js +255 -0
- package/dist/clis/amazon/shared.test.d.ts +1 -0
- package/dist/clis/amazon/shared.test.js +33 -0
- package/dist/clis/gemini/ask.d.ts +1 -0
- package/dist/clis/gemini/ask.js +40 -0
- package/dist/clis/gemini/image.d.ts +1 -0
- package/dist/clis/gemini/image.js +105 -0
- package/dist/clis/gemini/new.d.ts +1 -0
- package/dist/clis/gemini/new.js +20 -0
- package/dist/clis/gemini/utils.d.ts +34 -0
- package/dist/clis/gemini/utils.js +463 -0
- package/dist/clis/gemini/utils.test.d.ts +1 -0
- package/dist/clis/gemini/utils.test.js +31 -0
- package/dist/clis/notebooklm/compat.test.d.ts +1 -1
- package/dist/clis/notebooklm/compat.test.js +3 -3
- package/dist/clis/notebooklm/current.js +2 -3
- package/dist/clis/notebooklm/get.js +2 -3
- package/dist/clis/notebooklm/history.js +2 -3
- package/dist/clis/notebooklm/note-list.js +2 -3
- package/dist/clis/notebooklm/notes-get.js +2 -3
- package/dist/clis/notebooklm/open.d.ts +1 -0
- package/dist/clis/notebooklm/open.js +41 -0
- package/dist/clis/notebooklm/open.test.d.ts +1 -0
- package/dist/clis/notebooklm/open.test.js +63 -0
- package/dist/clis/notebooklm/source-fulltext.js +2 -3
- package/dist/clis/notebooklm/source-get.js +2 -3
- package/dist/clis/notebooklm/source-guide.js +2 -3
- package/dist/clis/notebooklm/source-list.js +2 -3
- package/dist/clis/notebooklm/status.js +1 -2
- package/dist/clis/notebooklm/summary.js +2 -3
- package/dist/clis/notebooklm/utils.d.ts +2 -1
- package/dist/clis/notebooklm/utils.js +20 -21
- package/dist/clis/twitter/article.js +28 -1
- package/dist/clis/xiaohongshu/creator-note-detail.test.js +11 -11
- package/dist/clis/xiaohongshu/creator-notes-summary.test.js +6 -6
- package/dist/clis/xiaohongshu/creator-notes.test.js +22 -22
- package/dist/clis/xiaohongshu/note.js +11 -0
- package/dist/clis/xiaohongshu/note.test.js +49 -0
- package/dist/commanderAdapter.js +7 -4
- package/dist/commanderAdapter.test.js +76 -0
- package/dist/commands/daemon.js +8 -47
- package/dist/commands/daemon.test.js +45 -70
- package/dist/discovery.js +27 -0
- package/dist/doctor.d.ts +1 -2
- package/dist/doctor.js +7 -8
- package/dist/explore.js +1 -1
- package/dist/output.js +28 -0
- package/dist/output.test.js +15 -0
- package/dist/pipeline/executor.js +2 -7
- package/dist/pipeline/steps/browser.js +1 -1
- package/dist/pipeline/template.js +25 -3
- package/dist/record.d.ts +50 -0
- package/dist/record.js +298 -57
- package/dist/record.test.d.ts +1 -0
- package/dist/record.test.js +293 -0
- package/dist/registry.d.ts +2 -0
- package/dist/registry.js +1 -0
- package/dist/registry.test.js +10 -0
- package/dist/runtime.js +3 -3
- package/dist/snapshotFormatter.d.ts +1 -1
- package/dist/snapshotFormatter.js +4 -4
- package/dist/snapshotFormatter.test.d.ts +1 -1
- package/dist/snapshotFormatter.test.js +2 -2
- package/dist/types.d.ts +11 -1
- package/dist/types.js +1 -1
- package/docs/.vitepress/config.mts +2 -0
- package/docs/adapters/browser/amazon.md +53 -0
- package/docs/adapters/browser/gemini.md +72 -0
- package/docs/adapters/browser/notebooklm.md +5 -5
- package/docs/adapters/index.md +3 -1
- package/docs/guide/getting-started.md +21 -0
- package/docs/superpowers/specs/2026-04-02-browse-skill-testing-design.md +144 -0
- package/docs/zh/guide/getting-started.md +21 -0
- package/extension/package-lock.json +2 -2
- package/extension/src/background.test.ts +7 -163
- package/extension/src/background.ts +58 -161
- package/extension/src/cdp.ts +77 -124
- package/extension/src/protocol.ts +5 -5
- package/package.json +1 -1
- package/skills/opencli-explorer/SKILL.md +853 -0
- package/skills/opencli-oneshot/SKILL.md +222 -0
- package/skills/opencli-operate/SKILL.md +213 -0
- package/skills/opencli-usage/SKILL.md +152 -0
- package/skills/opencli-usage/browser.md +429 -0
- package/skills/opencli-usage/desktop.md +118 -0
- package/skills/opencli-usage/plugins.md +82 -0
- package/skills/opencli-usage/public-api.md +149 -0
- package/src/browser/base-page.ts +197 -0
- package/src/browser/cdp.ts +7 -131
- package/src/browser/daemon-client.test.ts +103 -0
- package/src/browser/daemon-client.ts +55 -43
- package/src/browser/discover.ts +9 -21
- package/src/browser/errors.ts +22 -0
- package/src/browser/index.ts +1 -1
- package/src/browser/page.ts +57 -209
- package/src/browser/tabs.ts +5 -5
- package/src/browser.test.ts +15 -15
- package/src/cli.ts +392 -0
- package/src/clis/amazon/bestsellers.test.ts +22 -0
- package/src/clis/amazon/bestsellers.ts +180 -0
- package/src/clis/amazon/discussion.test.ts +38 -0
- package/src/clis/amazon/discussion.ts +131 -0
- package/src/clis/amazon/offer.test.ts +35 -0
- package/src/clis/amazon/offer.ts +185 -0
- package/src/clis/amazon/product.test.ts +26 -0
- package/src/clis/amazon/product.ts +131 -0
- package/src/clis/amazon/search.test.ts +24 -0
- package/src/clis/amazon/search.ts +128 -0
- package/src/clis/amazon/shared.test.ts +37 -0
- package/src/clis/amazon/shared.ts +316 -0
- package/src/clis/gemini/ask.ts +46 -0
- package/src/clis/gemini/image.ts +115 -0
- package/src/clis/gemini/new.ts +22 -0
- package/src/clis/gemini/utils.test.ts +36 -0
- package/src/clis/gemini/utils.ts +523 -0
- package/src/clis/notebooklm/compat.test.ts +3 -3
- package/src/clis/notebooklm/current.ts +2 -3
- package/src/clis/notebooklm/get.ts +1 -3
- package/src/clis/notebooklm/history.ts +1 -3
- package/src/clis/notebooklm/note-list.ts +1 -3
- package/src/clis/notebooklm/notes-get.ts +1 -3
- package/src/clis/notebooklm/open.test.ts +78 -0
- package/src/clis/notebooklm/open.ts +61 -0
- package/src/clis/notebooklm/source-fulltext.ts +1 -3
- package/src/clis/notebooklm/source-get.ts +1 -3
- package/src/clis/notebooklm/source-guide.ts +1 -3
- package/src/clis/notebooklm/source-list.ts +1 -3
- package/src/clis/notebooklm/status.ts +1 -2
- package/src/clis/notebooklm/summary.ts +1 -3
- package/src/clis/notebooklm/utils.ts +29 -20
- package/src/clis/twitter/article.ts +31 -1
- package/src/clis/xiaohongshu/creator-note-detail.test.ts +11 -11
- package/src/clis/xiaohongshu/creator-notes-summary.test.ts +6 -6
- package/src/clis/xiaohongshu/creator-notes.test.ts +22 -22
- package/src/clis/xiaohongshu/note.test.ts +51 -0
- package/src/clis/xiaohongshu/note.ts +18 -0
- package/src/commanderAdapter.test.ts +109 -0
- package/src/commanderAdapter.ts +8 -4
- package/src/commands/daemon.test.ts +50 -84
- package/src/commands/daemon.ts +8 -56
- package/src/discovery.ts +22 -0
- package/src/doctor.ts +8 -9
- package/src/explore.ts +1 -1
- package/src/output.test.ts +17 -0
- package/src/output.ts +27 -0
- package/src/pipeline/executor.ts +2 -7
- package/src/pipeline/steps/browser.ts +1 -1
- package/src/pipeline/template.ts +27 -4
- package/src/record.test.ts +362 -0
- package/src/record.ts +341 -62
- package/src/registry.test.ts +12 -0
- package/src/registry.ts +3 -0
- package/src/runtime.ts +3 -3
- package/src/snapshotFormatter.test.ts +2 -2
- package/src/snapshotFormatter.ts +4 -4
- package/src/types.ts +11 -1
- package/.agents/skills/cross-project-adapter-migration/SKILL.md +0 -249
- package/.agents/workflows/cross-project-adapter-migration.md +0 -54
- package/dist/clis/notebooklm/bind-current.js +0 -29
- package/dist/clis/notebooklm/bind-current.test.d.ts +0 -1
- package/dist/clis/notebooklm/bind-current.test.js +0 -35
- package/dist/clis/notebooklm/binding.test.js +0 -44
- package/extension/dist/background.js +0 -819
- package/src/clis/notebooklm/bind-current.test.ts +0 -43
- package/src/clis/notebooklm/bind-current.ts +0 -36
- package/src/clis/notebooklm/binding.test.ts +0 -53
- /package/dist/browser/{mcp.d.ts → bridge.d.ts} +0 -0
- /package/dist/browser/{mcp.js → bridge.js} +0 -0
- /package/dist/{clis/notebooklm/bind-current.d.ts → browser/daemon-client.test.d.ts} +0 -0
- /package/dist/clis/{notebooklm/binding.test.d.ts → amazon/bestsellers.test.d.ts} +0 -0
- /package/src/browser/{mcp.ts → bridge.ts} +0 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opencli-oneshot
|
|
3
|
+
description: Use when quickly generating a single OpenCLI command from a specific URL and goal description. 4-step process — open page, capture API, write YAML adapter, test. For full site exploration, use opencli-explorer instead.
|
|
4
|
+
tags: [opencli, adapter, quick-start, yaml, cli, one-shot, automation]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# CLI-ONESHOT — 单点快速 CLI 生成
|
|
8
|
+
|
|
9
|
+
> 给一个 URL + 一句话描述,4 步生成一个 CLI 命令。
|
|
10
|
+
> 完整探索式开发请看 [CLI-EXPLORER.md](./CLI-EXPLORER.md)。
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 输入
|
|
15
|
+
|
|
16
|
+
| 项目 | 示例 |
|
|
17
|
+
|------|------|
|
|
18
|
+
| **URL** | `https://x.com/jakevin7/lists` |
|
|
19
|
+
| **Goal** | 获取我的 Twitter Lists |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 流程
|
|
24
|
+
|
|
25
|
+
### Step 1: 打开页面 + 抓包
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
1. browser_navigate → 打开目标 URL
|
|
29
|
+
2. 等待 3-5 秒(让页面加载完、API 请求触发)
|
|
30
|
+
3. browser_network_requests → 筛选 JSON API
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**关键**:只关注返回 `application/json` 的请求,忽略静态资源。
|
|
34
|
+
如果没有自动触发 API,手动点击目标按钮/标签再抓一次。
|
|
35
|
+
|
|
36
|
+
### Step 2: 锁定一个接口
|
|
37
|
+
|
|
38
|
+
从抓包结果中找到**那个**目标 API。看这几个字段:
|
|
39
|
+
|
|
40
|
+
| 字段 | 关注什么 |
|
|
41
|
+
|------|----------|
|
|
42
|
+
| URL | API 路径 pattern(如 `/i/api/graphql/xxx/ListsManagePinTimeline`) |
|
|
43
|
+
| Method | GET / POST |
|
|
44
|
+
| Headers | 有 Cookie? Bearer? CSRF? 自定义签名? |
|
|
45
|
+
| Response | 数据在哪个路径(如 `data.list.lists`) |
|
|
46
|
+
|
|
47
|
+
### Step 3: 验证接口能复现
|
|
48
|
+
|
|
49
|
+
在 `browser_evaluate` 中用 `fetch` 复现请求:
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
// Tier 2 (Cookie): 大多数情况
|
|
53
|
+
fetch('/api/endpoint', { credentials: 'include' }).then(r => r.json())
|
|
54
|
+
|
|
55
|
+
// Tier 3 (Header): 如 Twitter 需要额外 header
|
|
56
|
+
const ct0 = document.cookie.match(/ct0=([^;]+)/)?.[1];
|
|
57
|
+
fetch('/api/endpoint', {
|
|
58
|
+
headers: { 'Authorization': 'Bearer ...', 'X-Csrf-Token': ct0 },
|
|
59
|
+
credentials: 'include'
|
|
60
|
+
}).then(r => r.json())
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
如果 fetch 能拿到数据 → 用 YAML 或简单 TS adapter。
|
|
64
|
+
如果 fetch 拿不到(签名/风控)→ 用 intercept 策略。
|
|
65
|
+
|
|
66
|
+
### Step 4: 套模板,生成 adapter
|
|
67
|
+
|
|
68
|
+
根据 Step 3 判定的策略,选一个模板生成文件。
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 认证速查
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
fetch(url) 直接能拿到? → Tier 1: public (YAML, browser: false)
|
|
76
|
+
fetch(url, {credentials:'include'})? → Tier 2: cookie (YAML)
|
|
77
|
+
加 Bearer/CSRF header 后拿到? → Tier 3: header (TS)
|
|
78
|
+
都不行,但页面自己能请求成功? → Tier 4: intercept (TS, installInterceptor)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 模板
|
|
84
|
+
|
|
85
|
+
### YAML — Cookie/Public(最简)
|
|
86
|
+
|
|
87
|
+
```yaml
|
|
88
|
+
# src/clis/<site>/<name>.yaml
|
|
89
|
+
site: mysite
|
|
90
|
+
name: mycommand
|
|
91
|
+
description: "一句话描述"
|
|
92
|
+
domain: www.example.com
|
|
93
|
+
strategy: cookie # 或 public (加 browser: false)
|
|
94
|
+
|
|
95
|
+
args:
|
|
96
|
+
limit:
|
|
97
|
+
type: int
|
|
98
|
+
default: 20
|
|
99
|
+
|
|
100
|
+
pipeline:
|
|
101
|
+
- navigate: https://www.example.com/target-page
|
|
102
|
+
|
|
103
|
+
- evaluate: |
|
|
104
|
+
(async () => {
|
|
105
|
+
const res = await fetch('/api/target', { credentials: 'include' });
|
|
106
|
+
const d = await res.json();
|
|
107
|
+
return (d.data?.items || []).map(item => ({
|
|
108
|
+
title: item.title,
|
|
109
|
+
value: item.value,
|
|
110
|
+
}));
|
|
111
|
+
})()
|
|
112
|
+
|
|
113
|
+
- map:
|
|
114
|
+
rank: ${{ index + 1 }}
|
|
115
|
+
title: ${{ item.title }}
|
|
116
|
+
value: ${{ item.value }}
|
|
117
|
+
|
|
118
|
+
- limit: ${{ args.limit }}
|
|
119
|
+
|
|
120
|
+
columns: [rank, title, value]
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### TS — Intercept(抓包模式)
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
// src/clis/<site>/<name>.ts
|
|
127
|
+
import { cli, Strategy } from '../../registry.js';
|
|
128
|
+
|
|
129
|
+
cli({
|
|
130
|
+
site: 'mysite',
|
|
131
|
+
name: 'mycommand',
|
|
132
|
+
description: '一句话描述',
|
|
133
|
+
domain: 'www.example.com',
|
|
134
|
+
strategy: Strategy.INTERCEPT,
|
|
135
|
+
browser: true,
|
|
136
|
+
args: [
|
|
137
|
+
{ name: 'limit', type: 'int', default: 20 },
|
|
138
|
+
],
|
|
139
|
+
columns: ['rank', 'title', 'value'],
|
|
140
|
+
func: async (page, kwargs) => {
|
|
141
|
+
// 1. 导航
|
|
142
|
+
await page.goto('https://www.example.com/target-page');
|
|
143
|
+
await page.wait(3);
|
|
144
|
+
|
|
145
|
+
// 2. 注入拦截器(URL 子串匹配)
|
|
146
|
+
await page.installInterceptor('target-api-keyword');
|
|
147
|
+
|
|
148
|
+
// 3. 触发 API(滚动/点击)
|
|
149
|
+
await page.autoScroll({ times: 2, delayMs: 2000 });
|
|
150
|
+
|
|
151
|
+
// 4. 读取拦截的响应
|
|
152
|
+
const requests = await page.getInterceptedRequests();
|
|
153
|
+
if (!requests?.length) return [];
|
|
154
|
+
|
|
155
|
+
let results: any[] = [];
|
|
156
|
+
for (const req of requests) {
|
|
157
|
+
const items = req.data?.data?.items || [];
|
|
158
|
+
results.push(...items);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return results.slice(0, kwargs.limit).map((item, i) => ({
|
|
162
|
+
rank: i + 1,
|
|
163
|
+
title: item.title || '',
|
|
164
|
+
value: item.value || '',
|
|
165
|
+
}));
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### TS — Header(如 Twitter GraphQL)
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
import { cli, Strategy } from '../../registry.js';
|
|
174
|
+
|
|
175
|
+
cli({
|
|
176
|
+
site: 'twitter',
|
|
177
|
+
name: 'mycommand',
|
|
178
|
+
description: '一句话描述',
|
|
179
|
+
domain: 'x.com',
|
|
180
|
+
strategy: Strategy.HEADER,
|
|
181
|
+
browser: true,
|
|
182
|
+
args: [
|
|
183
|
+
{ name: 'limit', type: 'int', default: 20 },
|
|
184
|
+
],
|
|
185
|
+
columns: ['rank', 'name', 'value'],
|
|
186
|
+
func: async (page, kwargs) => {
|
|
187
|
+
await page.goto('https://x.com');
|
|
188
|
+
const data = await page.evaluate(`(async () => {
|
|
189
|
+
const ct0 = document.cookie.match(/ct0=([^;]+)/)?.[1];
|
|
190
|
+
if (!ct0) return { error: 'Not logged in' };
|
|
191
|
+
const bearer = 'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D...';
|
|
192
|
+
const res = await fetch('/i/api/graphql/QUERY_ID/Endpoint', {
|
|
193
|
+
headers: {
|
|
194
|
+
'Authorization': 'Bearer ' + decodeURIComponent(bearer),
|
|
195
|
+
'X-Csrf-Token': ct0,
|
|
196
|
+
'X-Twitter-Auth-Type': 'OAuth2Session',
|
|
197
|
+
},
|
|
198
|
+
credentials: 'include',
|
|
199
|
+
});
|
|
200
|
+
return res.json();
|
|
201
|
+
})()`);
|
|
202
|
+
// 解析 data...
|
|
203
|
+
return [];
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## 测试(必做)
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
npm run build # 语法检查
|
|
214
|
+
opencli list | grep mysite # 确认注册
|
|
215
|
+
opencli mysite mycommand --limit 3 -v # 实际运行
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 就这样,没了
|
|
221
|
+
|
|
222
|
+
写完文件 → build → run → 提交。有问题再看 [CLI-EXPLORER.md](./CLI-EXPLORER.md)。
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opencli-operate
|
|
3
|
+
description: Make websites accessible for AI agents. Navigate, click, type, extract, wait — using Chrome with existing login sessions. No LLM API key needed.
|
|
4
|
+
allowed-tools: Bash(opencli:*), Read, Edit, Write
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# OpenCLI — Make Websites Accessible for AI Agents
|
|
8
|
+
|
|
9
|
+
Control Chrome step-by-step via CLI. Reuses existing login sessions — no passwords needed.
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
opencli doctor # Verify extension + daemon connectivity
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Requires: Chrome running + OpenCLI Browser Bridge extension installed.
|
|
18
|
+
|
|
19
|
+
## Quickstart for AI Agents (1 step)
|
|
20
|
+
|
|
21
|
+
Point your AI agent to this file. It contains everything needed to operate browsers.
|
|
22
|
+
|
|
23
|
+
## Quickstart for Humans (3 steps)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g @jackwener/opencli # 1. Install
|
|
27
|
+
# Install extension from chrome://extensions # 2. Load extension
|
|
28
|
+
opencli operate open https://example.com # 3. Go!
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Core Workflow
|
|
32
|
+
|
|
33
|
+
1. **Navigate**: `opencli operate open <url>`
|
|
34
|
+
2. **Inspect**: `opencli operate state` → see elements with `[N]` indices
|
|
35
|
+
3. **Interact**: use indices — `click`, `type`, `select`, `keys`
|
|
36
|
+
4. **Wait**: `opencli operate wait selector ".loaded"` or `wait text "Success"`
|
|
37
|
+
5. **Verify**: `opencli operate get title` or `opencli operate screenshot`
|
|
38
|
+
6. **Repeat**: browser stays open between commands
|
|
39
|
+
7. **Save**: write a TS adapter to `~/.opencli/clis/<site>/<command>.ts`
|
|
40
|
+
|
|
41
|
+
## Commands
|
|
42
|
+
|
|
43
|
+
### Navigation
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
opencli operate open <url> # Open URL
|
|
47
|
+
opencli operate back # Go back
|
|
48
|
+
opencli operate scroll down # Scroll (up/down, --amount N)
|
|
49
|
+
opencli operate scroll up --amount 1000
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Inspect
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
opencli operate state # Elements with [N] indices
|
|
56
|
+
opencli operate screenshot [path.png] # Screenshot
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Get (structured data)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
opencli operate get title # Page title
|
|
63
|
+
opencli operate get url # Current URL
|
|
64
|
+
opencli operate get text <index> # Element text content
|
|
65
|
+
opencli operate get value <index> # Input/textarea value
|
|
66
|
+
opencli operate get html # Full page HTML
|
|
67
|
+
opencli operate get html --selector "h1" # Scoped HTML
|
|
68
|
+
opencli operate get attributes <index> # Element attributes
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Interact
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
opencli operate click <index> # Click element [N]
|
|
75
|
+
opencli operate type <index> "text" # Type into element [N]
|
|
76
|
+
opencli operate select <index> "option" # Select dropdown
|
|
77
|
+
opencli operate keys "Enter" # Press key (Enter, Escape, Tab, Control+a)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Wait
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
opencli operate wait selector ".loaded" # Wait for element
|
|
84
|
+
opencli operate wait selector ".spinner" --timeout 5000 # With timeout
|
|
85
|
+
opencli operate wait text "Success" # Wait for text
|
|
86
|
+
opencli operate wait time 3 # Wait N seconds
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Extract
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
opencli operate eval "document.title"
|
|
93
|
+
opencli operate eval "JSON.stringify([...document.querySelectorAll('h2')].map(e => e.textContent))"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Network (API Discovery)
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
opencli operate network # Show captured API requests (auto-captured since open)
|
|
100
|
+
opencli operate network --detail 3 # Show full response body of request #3
|
|
101
|
+
opencli operate network --all # Include static resources
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Sedimentation (Save as CLI)
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
opencli operate init hn/top # Generate adapter scaffold
|
|
108
|
+
opencli operate verify hn/top # Test the adapter
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Session
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
opencli operate close # Close automation window
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Example: Extract HN Stories
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
opencli operate open https://news.ycombinator.com
|
|
121
|
+
opencli operate state # See [1] a "Story 1", [2] a "Story 2"...
|
|
122
|
+
opencli operate eval "JSON.stringify([...document.querySelectorAll('.titleline a')].slice(0,5).map(a => ({title: a.textContent, url: a.href})))"
|
|
123
|
+
opencli operate close
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Example: Fill a Form
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
opencli operate open https://httpbin.org/forms/post
|
|
130
|
+
opencli operate state # See [3] input "Customer Name", [4] input "Telephone"
|
|
131
|
+
opencli operate type 3 "OpenCLI"
|
|
132
|
+
opencli operate type 4 "555-0100"
|
|
133
|
+
opencli operate get value 3 # Verify: "OpenCLI"
|
|
134
|
+
opencli operate close
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Saving as Reusable CLI — Complete Workflow
|
|
138
|
+
|
|
139
|
+
### Step-by-step sedimentation flow:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# 1. Explore the website
|
|
143
|
+
opencli operate open https://news.ycombinator.com
|
|
144
|
+
opencli operate state # Understand DOM structure
|
|
145
|
+
|
|
146
|
+
# 2. Discover APIs (crucial for high-quality adapters)
|
|
147
|
+
opencli operate eval "fetch('/api/...').then(r=>r.json())" # Trigger API calls
|
|
148
|
+
opencli operate network # See captured API requests
|
|
149
|
+
opencli operate network --detail 0 # Inspect response body
|
|
150
|
+
|
|
151
|
+
# 3. Generate scaffold
|
|
152
|
+
opencli operate init hn/top # Creates ~/.opencli/clis/hn/top.ts
|
|
153
|
+
|
|
154
|
+
# 4. Edit the adapter (fill in func logic)
|
|
155
|
+
# - If API found: use fetch() directly (Strategy.PUBLIC or COOKIE)
|
|
156
|
+
# - If no API: use page.evaluate() for DOM extraction (Strategy.UI)
|
|
157
|
+
|
|
158
|
+
# 5. Verify
|
|
159
|
+
opencli operate verify hn/top # Runs the adapter and shows output
|
|
160
|
+
|
|
161
|
+
# 6. If verify fails, edit and retry
|
|
162
|
+
# 7. Close when done
|
|
163
|
+
opencli operate close
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Example adapter:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// ~/.opencli/clis/hn/top.ts
|
|
170
|
+
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
171
|
+
|
|
172
|
+
cli({
|
|
173
|
+
site: 'hn',
|
|
174
|
+
name: 'top',
|
|
175
|
+
description: 'Top Hacker News stories',
|
|
176
|
+
domain: 'news.ycombinator.com',
|
|
177
|
+
strategy: Strategy.PUBLIC,
|
|
178
|
+
browser: false,
|
|
179
|
+
args: [{ name: 'limit', type: 'int', default: 5 }],
|
|
180
|
+
columns: ['rank', 'title', 'score', 'url'],
|
|
181
|
+
func: async (_page, kwargs) => {
|
|
182
|
+
const limit = Math.min(Math.max(1, kwargs.limit ?? 5), 50);
|
|
183
|
+
const resp = await fetch('https://hacker-news.firebaseio.com/v0/topstories.json');
|
|
184
|
+
const ids = await resp.json();
|
|
185
|
+
return Promise.all(
|
|
186
|
+
ids.slice(0, limit).map(async (id: number, i: number) => {
|
|
187
|
+
const item = await (await fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json`)).json();
|
|
188
|
+
return { rank: i + 1, title: item.title, score: item.score, url: item.url ?? '' };
|
|
189
|
+
})
|
|
190
|
+
);
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Save to `~/.opencli/clis/<site>/<command>.ts` → immediately available as `opencli <site> <command>`.
|
|
196
|
+
|
|
197
|
+
### Strategy Guide
|
|
198
|
+
|
|
199
|
+
| Strategy | When | browser: |
|
|
200
|
+
|----------|------|----------|
|
|
201
|
+
| `Strategy.PUBLIC` | Public API, no auth | `false` |
|
|
202
|
+
| `Strategy.COOKIE` | Needs login cookies | `true` |
|
|
203
|
+
| `Strategy.UI` | Direct DOM interaction | `true` |
|
|
204
|
+
|
|
205
|
+
**Always prefer API over UI** — if you discovered an API during browsing, use `fetch()` directly.
|
|
206
|
+
|
|
207
|
+
## Troubleshooting
|
|
208
|
+
|
|
209
|
+
| Error | Fix |
|
|
210
|
+
|-------|-----|
|
|
211
|
+
| "Browser not connected" | Run `opencli doctor` |
|
|
212
|
+
| "attach failed: chrome-extension://" | Disable 1Password temporarily |
|
|
213
|
+
| Element not found | `opencli operate scroll down` then `opencli operate state` |
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opencli-usage
|
|
3
|
+
description: "Use when running OpenCLI commands to interact with websites (Bilibili, Twitter, Reddit, Xiaohongshu, etc.), desktop apps (Cursor, Notion), or public APIs (HackerNews, arXiv). Covers installation, command reference, and output formats for 60+ adapters."
|
|
4
|
+
version: 1.6.0
|
|
5
|
+
author: jackwener
|
|
6
|
+
tags: [opencli, cli, browser, web, chrome-extension, cdp, bilibili, twitter, reddit, xiaohongshu, github, youtube, AI, agent, automation]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# OpenCLI Usage Guide
|
|
10
|
+
|
|
11
|
+
> Make any website or Electron App your CLI. Reuse Chrome login, zero risk, AI-powered discovery.
|
|
12
|
+
|
|
13
|
+
## Install & Run
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# npm global install (recommended)
|
|
17
|
+
npm install -g @jackwener/opencli
|
|
18
|
+
opencli <command>
|
|
19
|
+
|
|
20
|
+
# Or from source
|
|
21
|
+
cd ~/code/opencli && npm install
|
|
22
|
+
npx tsx src/main.ts <command>
|
|
23
|
+
|
|
24
|
+
# Update to latest
|
|
25
|
+
npm update -g @jackwener/opencli
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Prerequisites
|
|
29
|
+
|
|
30
|
+
Browser commands require:
|
|
31
|
+
1. Chrome browser running **(logged into target sites)**
|
|
32
|
+
2. **opencli Browser Bridge** Chrome extension installed (load `extension/` as unpacked in `chrome://extensions`)
|
|
33
|
+
3. No further setup needed — the daemon auto-starts on first browser command
|
|
34
|
+
|
|
35
|
+
> **Note**: You must be logged into the target website in Chrome before running commands. Tabs opened during command execution are auto-closed afterwards.
|
|
36
|
+
|
|
37
|
+
Public API commands (`hackernews`, `v2ex`) need no browser.
|
|
38
|
+
|
|
39
|
+
## Quick Lookup by Capability
|
|
40
|
+
|
|
41
|
+
| Capability | Platforms (partial list) | File |
|
|
42
|
+
|-----------|--------------------------|------|
|
|
43
|
+
| **search** | Bilibili, Twitter, Reddit, Xiaohongshu, Zhihu, YouTube, Google, arXiv, LinkedIn, Pixiv, etc. | browser.md / public-api.md |
|
|
44
|
+
| **hot/trending** | Bilibili, Twitter, Weibo, HackerNews, Reddit, V2EX, Xueqiu, Lobsters, Douban | browser.md / public-api.md |
|
|
45
|
+
| **feed/timeline** | Twitter, Reddit, Xiaohongshu, Xueqiu, Jike, Facebook, Instagram, Medium | browser.md |
|
|
46
|
+
| **user/profile** | Twitter, Reddit, Instagram, TikTok, Facebook, Bilibili, Pixiv | browser.md |
|
|
47
|
+
| **post/create** | Twitter, Jike | browser.md |
|
|
48
|
+
| **AI chat** | Grok, Doubao, Kimi, DeepSeek, Qwen, ChatGPT, Cursor, Codex | browser.md / desktop.md |
|
|
49
|
+
| **finance/stock** | Xueqiu, Yahoo Finance, Barchart, Sina Finance, Bloomberg | browser.md / public-api.md |
|
|
50
|
+
| **web scraping** | `opencli web read --url <url>` — any URL to Markdown | browser.md |
|
|
51
|
+
|
|
52
|
+
## Command Quick Reference
|
|
53
|
+
|
|
54
|
+
Usage: `opencli <site> <command> [args] [--limit N] [-f json|yaml|md|csv|table]`
|
|
55
|
+
|
|
56
|
+
### Browser-based (login required)
|
|
57
|
+
|
|
58
|
+
| Site | Commands |
|
|
59
|
+
|------|----------|
|
|
60
|
+
| **bilibili** | `hot` `search` `me` `favorite` `history` `feed` `user-videos` `subtitle` `dynamic` `ranking` `following` |
|
|
61
|
+
| **zhihu** | `hot` `search` `question` |
|
|
62
|
+
| **xiaohongshu** | `search` `notifications` `feed` `user` `creator-notes` `creator-note-detail` `creator-notes-summary` `creator-profile` `creator-stats` |
|
|
63
|
+
| **xueqiu** | `hot-stock` `stock` `watchlist` `feed` `hot` `search` `earnings-date` `fund-holdings` `fund-snapshot` |
|
|
64
|
+
| **twitter** | `trending` `bookmarks` `search` `profile` `timeline` `thread` `article` `follow` `unfollow` `bookmark` `unbookmark` `post` `like` `reply` `delete` `block` `unblock` `followers` `following` `notifications` `hide-reply` `download` `accept` `reply-dm` |
|
|
65
|
+
| **reddit** | `hot` `frontpage` `popular` `search` `subreddit` `read` `user` `user-posts` `user-comments` `upvote` `save` `comment` `subscribe` `saved` `upvoted` |
|
|
66
|
+
| **youtube** | `search` `video` `transcript` |
|
|
67
|
+
| **facebook** | `feed` `profile` `search` `friends` `groups` `events` `notifications` `memories` `add-friend` `join-group` |
|
|
68
|
+
| **instagram** | `explore` `profile` `search` `user` `followers` `following` `follow` `unfollow` `like` `unlike` `comment` `save` `unsave` `saved` |
|
|
69
|
+
| **tiktok** | `explore` `search` `profile` `user` `following` `follow` `unfollow` `like` `unlike` `comment` `save` `unsave` `live` `notifications` `friends` |
|
|
70
|
+
| **linkedin** | `search` `timeline` |
|
|
71
|
+
| **medium** | `feed` `search` `user` |
|
|
72
|
+
| **substack** | `feed` `search` `publication` |
|
|
73
|
+
| **sinablog** | `hot` `search` `article` `user` |
|
|
74
|
+
| **weibo** | `hot` |
|
|
75
|
+
| **boss** | `search` `detail` `recommend` `joblist` `greet` `batchgreet` `send` `chatlist` `chatmsg` `invite` `mark` `exchange` `resume` `stats` |
|
|
76
|
+
| **douban** | `search` `top250` `subject` `photos` `download` `marks` `reviews` |
|
|
77
|
+
| **pixiv** | `ranking` `search` `user` `illusts` `detail` `download` |
|
|
78
|
+
| **jike** | `feed` `search` `create` `like` `comment` `repost` `notifications` |
|
|
79
|
+
| **yahoo-finance** | `quote` |
|
|
80
|
+
| **barchart** | `quote` `options` `greeks` `flow` |
|
|
81
|
+
| **sinafinance** | `news` |
|
|
82
|
+
| **reuters** | `search` |
|
|
83
|
+
| **coupang** | `search` `add-to-cart` |
|
|
84
|
+
| **jd** | `item` |
|
|
85
|
+
| **smzdm** | `search` |
|
|
86
|
+
| **ctrip** | `search` |
|
|
87
|
+
| **weread** | `shelf` `search` `book` `highlights` `notes` `ranking` |
|
|
88
|
+
| **chaoxing** | `assignments` `exams` |
|
|
89
|
+
| **jimeng** | `generate` `history` |
|
|
90
|
+
| **yollomi** | `models` `generate` `video` `upload` `remove-bg` `edit` `background` `face-swap` `object-remover` `restore` `try-on` `upscale` |
|
|
91
|
+
| **web** | `read` — any URL to Markdown |
|
|
92
|
+
| **weixin** | `download` — 公众号 article to Markdown |
|
|
93
|
+
| **v2ex** (browser) | `daily` `me` `notifications` |
|
|
94
|
+
| **linux-do** (browser) | `categories` `category` |
|
|
95
|
+
| **bloomberg** (browser) | `news` — full article reader |
|
|
96
|
+
| **grok** | `ask` |
|
|
97
|
+
| **doubao** | `status` `new` `send` `read` `ask` |
|
|
98
|
+
| **kimi** | `status` `new` `ask` |
|
|
99
|
+
| **deepseek** | `status` `new` `ask` |
|
|
100
|
+
| **qwen** | `status` `new` `ask` |
|
|
101
|
+
|
|
102
|
+
### Desktop (CDP/Electron)
|
|
103
|
+
|
|
104
|
+
| Site | Commands |
|
|
105
|
+
|------|----------|
|
|
106
|
+
| **gh** | `repo` `pr` `issue` — passthrough to gh CLI |
|
|
107
|
+
| **cursor** | `status` `send` `read` `new` `dump` `composer` `model` `extract-code` `ask` `screenshot` `history` `export` |
|
|
108
|
+
| **codex** | `status` `send` `read` `new` `dump` `extract-diff` `model` `ask` `screenshot` `history` `export` |
|
|
109
|
+
| **chatgpt** | `status` `new` `send` `read` `ask` |
|
|
110
|
+
| **chatwise** | `status` `new` `send` `read` `ask` `model` `history` `export` `screenshot` |
|
|
111
|
+
| **notion** | `status` `search` `read` `new` `write` `sidebar` `favorites` `export` |
|
|
112
|
+
| **discord-app** | `status` `send` `read` `channels` `servers` `search` `members` |
|
|
113
|
+
| **doubao-app** | `status` `new` `send` `read` `ask` `screenshot` `dump` |
|
|
114
|
+
| **antigravity** | `status` `send` `read` `new` `dump` `extract-code` `model` `watch` |
|
|
115
|
+
|
|
116
|
+
### Public API (no browser)
|
|
117
|
+
|
|
118
|
+
| Site | Commands |
|
|
119
|
+
|------|----------|
|
|
120
|
+
| **hackernews** | `top` `new` `best` `ask` `show` `jobs` `search` `user` |
|
|
121
|
+
| **v2ex** (public) | `hot` `latest` `topic` `node` `nodes` `member` `user` `replies` |
|
|
122
|
+
| **bbc** | `news` |
|
|
123
|
+
| **lobsters** | `hot` `newest` `active` `tag` |
|
|
124
|
+
| **google** | `news` `search` `suggest` `trends` |
|
|
125
|
+
| **devto** | `top` `tag` `user` |
|
|
126
|
+
| **steam** | `top-sellers` |
|
|
127
|
+
| **apple-podcasts** | `top` `search` `episodes` |
|
|
128
|
+
| **arxiv** | `search` `paper` |
|
|
129
|
+
| **bloomberg** (RSS) | `main` `markets` `tech` `politics` `economics` `opinions` `industries` `businessweek` `feeds` |
|
|
130
|
+
| **dictionary** | `search` `synonyms` `examples` |
|
|
131
|
+
| **hf** | `top` |
|
|
132
|
+
| **stackoverflow** | `hot` `search` `bounties` |
|
|
133
|
+
| **xiaoyuzhou** | `podcast` `podcast-episodes` `episode` |
|
|
134
|
+
| **wikipedia** | `search` `summary` |
|
|
135
|
+
| **producthunt** | `today` `week` `month` `search` |
|
|
136
|
+
|
|
137
|
+
### Management
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
opencli list [-f json|yaml] # List all commands
|
|
141
|
+
opencli validate [site] # Validate adapter definitions
|
|
142
|
+
opencli doctor # Diagnose browser bridge
|
|
143
|
+
opencli explore <url> # AI-powered API discovery
|
|
144
|
+
opencli record <url> # Record API calls manually
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
All commands support: `--format` / `-f` with `table` `json` `yaml` `md` `csv`
|
|
148
|
+
|
|
149
|
+
## Related Skills
|
|
150
|
+
|
|
151
|
+
- **opencli-explorer** — Full guide for creating new adapters (API discovery, auth strategy, YAML/TS writing)
|
|
152
|
+
- **opencli-oneshot** — Quick 4-step template for adding a single command from a URL
|