@jackwener/opencli 1.0.1 → 1.0.4
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/.github/workflows/build-extension.yml +80 -0
- package/.github/workflows/ci.yml +6 -6
- package/.github/workflows/docs.yml +52 -0
- package/.github/workflows/e2e-headed.yml +2 -2
- package/.github/workflows/pkg-pr-new.yml +2 -2
- package/.github/workflows/release.yml +2 -5
- package/.github/workflows/security.yml +2 -2
- package/CDP.md +1 -1
- package/CDP.zh-CN.md +1 -1
- package/README.md +42 -34
- package/README.zh-CN.md +42 -34
- package/SKILL.md +3 -5
- package/dist/browser/cdp.d.ts +42 -0
- package/dist/browser/cdp.js +339 -0
- package/dist/browser/daemon-client.d.ts +3 -1
- package/dist/browser/daemon-client.js +4 -0
- package/dist/browser/dom-helpers.d.ts +20 -0
- package/dist/browser/dom-helpers.js +109 -0
- package/dist/browser/index.d.ts +3 -0
- package/dist/browser/index.js +4 -0
- package/dist/browser/mcp.d.ts +1 -0
- package/dist/browser/mcp.js +10 -5
- package/dist/browser/page.d.ts +7 -0
- package/dist/browser/page.js +39 -123
- package/dist/browser/utils.d.ts +10 -0
- package/dist/browser/utils.js +27 -0
- package/dist/browser.test.js +49 -1
- package/dist/build-manifest.js +3 -1
- package/dist/build-manifest.test.js +34 -0
- package/dist/capabilityRouting.d.ts +2 -0
- package/dist/capabilityRouting.js +30 -0
- package/dist/capabilityRouting.test.d.ts +1 -0
- package/dist/capabilityRouting.test.js +42 -0
- package/dist/chaoxing.d.ts +58 -0
- package/dist/chaoxing.js +225 -0
- package/dist/chaoxing.test.d.ts +1 -0
- package/dist/chaoxing.test.js +45 -0
- package/dist/cli-manifest.json +885 -48
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +234 -0
- package/dist/clis/antigravity/serve.d.ts +14 -0
- package/dist/clis/antigravity/serve.js +263 -0
- package/dist/clis/bilibili/download.js +4 -14
- package/dist/clis/boss/chatlist.d.ts +1 -0
- package/dist/clis/boss/chatlist.js +50 -0
- package/dist/clis/boss/chatmsg.d.ts +1 -0
- package/dist/clis/boss/chatmsg.js +73 -0
- package/dist/clis/boss/resume.d.ts +1 -0
- package/dist/clis/boss/resume.js +249 -0
- package/dist/clis/boss/send.d.ts +1 -0
- package/dist/clis/boss/send.js +176 -0
- package/dist/clis/chaoxing/assignments.d.ts +1 -0
- package/dist/clis/chaoxing/assignments.js +74 -0
- package/dist/clis/chaoxing/exams.d.ts +1 -0
- package/dist/clis/chaoxing/exams.js +74 -0
- package/dist/clis/chatgpt/ask.js +15 -14
- package/dist/clis/chatgpt/ax.d.ts +1 -0
- package/dist/clis/chatgpt/ax.js +78 -0
- package/dist/clis/chatgpt/read.js +5 -6
- package/dist/clis/hf/top.d.ts +1 -0
- package/dist/clis/hf/top.js +119 -0
- package/dist/clis/jike/comment.d.ts +1 -0
- package/dist/clis/jike/comment.js +107 -0
- package/dist/clis/jike/create.d.ts +1 -0
- package/dist/clis/jike/create.js +106 -0
- package/dist/clis/jike/feed.d.ts +1 -0
- package/dist/clis/jike/feed.js +67 -0
- package/dist/clis/jike/like.d.ts +1 -0
- package/dist/clis/jike/like.js +61 -0
- package/dist/clis/jike/notifications.d.ts +1 -0
- package/dist/clis/jike/notifications.js +169 -0
- package/dist/clis/jike/post.yaml +58 -0
- package/dist/clis/jike/repost.d.ts +1 -0
- package/dist/clis/jike/repost.js +103 -0
- package/dist/clis/jike/search.d.ts +1 -0
- package/dist/clis/jike/search.js +67 -0
- package/dist/clis/jike/shared.d.ts +19 -0
- package/dist/clis/jike/shared.js +25 -0
- package/dist/clis/jike/topic.yaml +52 -0
- package/dist/clis/jike/user.yaml +51 -0
- package/dist/clis/smzdm/search.js +28 -39
- package/dist/clis/stackoverflow/bounties.yaml +29 -0
- package/dist/clis/stackoverflow/hot.yaml +28 -0
- package/dist/clis/stackoverflow/search.yaml +32 -0
- package/dist/clis/stackoverflow/unanswered.yaml +28 -0
- package/dist/clis/twitter/download.js +6 -16
- package/dist/clis/twitter/post.js +9 -2
- package/dist/clis/twitter/search.js +14 -33
- package/dist/clis/xiaohongshu/download.d.ts +1 -1
- package/dist/clis/xiaohongshu/download.js +4 -4
- package/dist/clis/zhihu/download.js +3 -3
- package/dist/doctor.d.ts +7 -0
- package/dist/doctor.js +16 -0
- package/dist/download/index.d.ts +12 -8
- package/dist/download/index.js +11 -3
- package/dist/download/index.test.d.ts +1 -0
- package/dist/download/index.test.js +14 -0
- package/dist/engine.js +25 -14
- package/dist/explore.d.ts +1 -0
- package/dist/explore.js +48 -103
- package/dist/generate.js +1 -0
- package/dist/interceptor.js +3 -2
- package/dist/main.js +4 -193
- package/dist/output.d.ts +2 -1
- package/dist/output.js +3 -1
- package/dist/pipeline/executor.test.js +1 -0
- package/dist/pipeline/steps/download.js +14 -18
- package/dist/registry.d.ts +4 -3
- package/dist/registry.js +5 -2
- package/dist/runtime.d.ts +4 -1
- package/dist/runtime.js +2 -2
- package/dist/scripts/framework.d.ts +4 -0
- package/dist/scripts/framework.js +21 -0
- package/dist/scripts/interact.d.ts +4 -0
- package/dist/scripts/interact.js +20 -0
- package/dist/scripts/store.d.ts +9 -0
- package/dist/scripts/store.js +44 -0
- package/dist/synthesize.js +1 -1
- package/dist/types.d.ts +12 -0
- package/dist/verify.d.ts +6 -1
- package/dist/verify.js +54 -2
- package/docs/.vitepress/config.mts +193 -0
- package/docs/adapters/browser/apple-podcasts.md +28 -0
- package/docs/adapters/browser/bbc.md +26 -0
- package/docs/adapters/browser/bilibili.md +38 -0
- package/docs/adapters/browser/boss.md +28 -0
- package/docs/adapters/browser/coupang.md +28 -0
- package/docs/adapters/browser/ctrip.md +27 -0
- package/docs/adapters/browser/github.md +26 -0
- package/docs/adapters/browser/hackernews.md +26 -0
- package/docs/adapters/browser/linkedin.md +27 -0
- package/docs/adapters/browser/reddit.md +41 -0
- package/docs/adapters/browser/reuters.md +27 -0
- package/docs/adapters/browser/smzdm.md +27 -0
- package/docs/adapters/browser/twitter.md +47 -0
- package/docs/adapters/browser/v2ex.md +32 -0
- package/docs/adapters/browser/weibo.md +27 -0
- package/docs/adapters/browser/xiaohongshu.md +32 -0
- package/docs/adapters/browser/xiaoyuzhou.md +28 -0
- package/docs/adapters/browser/xueqiu.md +32 -0
- package/docs/adapters/browser/yahoo-finance.md +26 -0
- package/docs/adapters/browser/youtube.md +29 -0
- package/docs/adapters/browser/zhihu.md +30 -0
- package/docs/adapters/desktop/antigravity.md +46 -0
- package/docs/adapters/desktop/chatgpt.md +43 -0
- package/docs/adapters/desktop/chatwise.md +38 -0
- package/docs/adapters/desktop/codex.md +32 -0
- package/docs/adapters/desktop/cursor.md +33 -0
- package/docs/adapters/desktop/discord.md +28 -0
- package/docs/adapters/desktop/feishu.md +20 -0
- package/docs/adapters/desktop/neteasemusic.md +31 -0
- package/docs/adapters/desktop/notion.md +29 -0
- package/docs/adapters/desktop/wechat.md +28 -0
- package/docs/adapters/index.md +49 -0
- package/docs/advanced/cdp.md +103 -0
- package/docs/advanced/download.md +63 -0
- package/docs/advanced/electron.md +125 -0
- package/docs/advanced/remote-chrome.md +72 -0
- package/docs/developer/ai-workflow.md +66 -0
- package/docs/developer/architecture.md +90 -0
- package/docs/developer/contributing.md +136 -0
- package/docs/developer/testing.md +237 -0
- package/docs/developer/ts-adapter.md +87 -0
- package/docs/developer/yaml-adapter.md +108 -0
- package/docs/guide/browser-bridge.md +38 -0
- package/docs/guide/getting-started.md +56 -0
- package/docs/guide/installation.md +37 -0
- package/docs/guide/troubleshooting.md +56 -0
- package/docs/index.md +35 -0
- package/docs/zh/adapters/index.md +5 -0
- package/docs/zh/advanced/cdp.md +3 -0
- package/docs/zh/developer/contributing.md +24 -0
- package/docs/zh/guide/browser-bridge.md +25 -0
- package/docs/zh/guide/getting-started.md +40 -0
- package/docs/zh/guide/installation.md +37 -0
- package/docs/zh/index.md +29 -0
- package/extension/dist/background.js +386 -438
- package/extension/manifest.json +2 -2
- package/extension/package-lock.json +1156 -0
- package/extension/src/background.test.ts +151 -0
- package/extension/src/background.ts +124 -53
- package/extension/src/protocol.ts +3 -1
- package/package.json +7 -3
- package/src/browser/cdp.ts +367 -0
- package/src/browser/daemon-client.ts +7 -1
- package/src/browser/dom-helpers.ts +116 -0
- package/src/browser/index.ts +4 -0
- package/src/browser/mcp.ts +14 -6
- package/src/browser/page.ts +47 -124
- package/src/browser/utils.ts +27 -0
- package/src/browser.test.ts +56 -0
- package/src/build-manifest.test.ts +36 -0
- package/src/build-manifest.ts +2 -1
- package/src/capabilityRouting.test.ts +47 -0
- package/src/capabilityRouting.ts +28 -0
- package/src/chaoxing.test.ts +53 -0
- package/src/chaoxing.ts +268 -0
- package/src/cli.ts +205 -0
- package/src/clis/antigravity/SKILL.md +5 -0
- package/src/clis/antigravity/serve.ts +329 -0
- package/src/clis/bilibili/download.ts +4 -15
- package/src/clis/boss/chatlist.ts +50 -0
- package/src/clis/boss/chatmsg.ts +70 -0
- package/src/clis/boss/resume.ts +262 -0
- package/src/clis/boss/send.ts +193 -0
- package/src/clis/chaoxing/README.md +36 -0
- package/src/clis/chaoxing/README.zh-CN.md +35 -0
- package/src/clis/chaoxing/assignments.ts +88 -0
- package/src/clis/chaoxing/exams.ts +88 -0
- package/src/clis/chatgpt/ask.ts +14 -15
- package/src/clis/chatgpt/ax.ts +81 -0
- package/src/clis/chatgpt/read.ts +5 -7
- package/src/clis/hf/top.ts +141 -0
- package/src/clis/jike/comment.ts +113 -0
- package/src/clis/jike/create.ts +113 -0
- package/src/clis/jike/feed.ts +74 -0
- package/src/clis/jike/like.ts +65 -0
- package/src/clis/jike/notifications.ts +185 -0
- package/src/clis/jike/post.yaml +58 -0
- package/src/clis/jike/repost.ts +114 -0
- package/src/clis/jike/search.ts +74 -0
- package/src/clis/jike/shared.ts +36 -0
- package/src/clis/jike/topic.yaml +52 -0
- package/src/clis/jike/user.yaml +51 -0
- package/src/clis/smzdm/search.ts +30 -39
- package/src/clis/stackoverflow/bounties.yaml +29 -0
- package/src/clis/stackoverflow/hot.yaml +28 -0
- package/src/clis/stackoverflow/search.yaml +32 -0
- package/src/clis/stackoverflow/unanswered.yaml +28 -0
- package/src/clis/twitter/download.ts +6 -17
- package/src/clis/twitter/post.ts +9 -2
- package/src/clis/twitter/search.ts +15 -33
- package/src/clis/xiaohongshu/download.ts +4 -4
- package/src/clis/zhihu/download.ts +3 -3
- package/src/doctor.ts +18 -2
- package/src/download/index.test.ts +16 -0
- package/src/download/index.ts +22 -4
- package/src/engine.ts +20 -13
- package/src/explore.ts +54 -103
- package/src/generate.ts +1 -0
- package/src/interceptor.ts +3 -2
- package/src/main.ts +4 -180
- package/src/output.ts +15 -13
- package/src/pipeline/executor.test.ts +1 -0
- package/src/pipeline/steps/download.ts +14 -17
- package/src/registry.ts +9 -5
- package/src/runtime.ts +3 -2
- package/src/scripts/framework.ts +20 -0
- package/src/scripts/interact.ts +22 -0
- package/src/scripts/store.ts +40 -0
- package/src/synthesize.ts +1 -1
- package/src/types.ts +9 -0
- package/src/verify.ts +64 -3
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Notion
|
|
2
|
+
|
|
3
|
+
Control the **Notion Desktop App** from the terminal via Chrome DevTools Protocol (CDP).
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Launch with remote debugging port:
|
|
8
|
+
```bash
|
|
9
|
+
/Applications/Notion.app/Contents/MacOS/Notion --remote-debugging-port=9230
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Setup
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9230"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Commands
|
|
19
|
+
|
|
20
|
+
| Command | Description |
|
|
21
|
+
|---------|-------------|
|
|
22
|
+
| `opencli notion status` | Check CDP connection |
|
|
23
|
+
| `opencli notion search "query"` | Quick Find search (Cmd+P) |
|
|
24
|
+
| `opencli notion read` | Read the current page content |
|
|
25
|
+
| `opencli notion new "title"` | Create a new page (Cmd+N) |
|
|
26
|
+
| `opencli notion write "text"` | Append text to the current page |
|
|
27
|
+
| `opencli notion sidebar` | List pages from the sidebar |
|
|
28
|
+
| `opencli notion favorites` | List pages from the Favorites section |
|
|
29
|
+
| `opencli notion export` | Export page as Markdown |
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# WeChat (微信)
|
|
2
|
+
|
|
3
|
+
Control **WeChat Mac Desktop** from the terminal via AppleScript + Accessibility API.
|
|
4
|
+
|
|
5
|
+
> **Note:** WeChat is a native macOS app (not Electron), so CDP is not available. This adapter uses AppleScript keyboard simulation and clipboard operations.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
1. WeChat must be running and logged in
|
|
10
|
+
2. Terminal must have **Accessibility permission** (System Settings → Privacy & Security → Accessibility)
|
|
11
|
+
|
|
12
|
+
## Commands
|
|
13
|
+
|
|
14
|
+
| Command | Description |
|
|
15
|
+
|---------|-------------|
|
|
16
|
+
| `opencli wechat status` | Check if WeChat is running |
|
|
17
|
+
| `opencli wechat send "msg"` | Send message in the active chat (clipboard paste + Enter) |
|
|
18
|
+
| `opencli wechat read` | Read current chat content (Cmd+A → Cmd+C) |
|
|
19
|
+
| `opencli wechat search "keyword"` | Open search and type a query (Cmd+F) |
|
|
20
|
+
| `opencli wechat chats` | Switch to Chats tab (Cmd+1) |
|
|
21
|
+
| `opencli wechat contacts` | Switch to Contacts tab (Cmd+2) |
|
|
22
|
+
|
|
23
|
+
## Limitations
|
|
24
|
+
|
|
25
|
+
- **No CDP support** — WeChat is native Cocoa, not Electron
|
|
26
|
+
- `send` requires the correct conversation to be already open
|
|
27
|
+
- `read` captures whatever is visible via select-all + copy
|
|
28
|
+
- `search` types the query but cannot programmatically click results
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# All Adapters
|
|
2
|
+
|
|
3
|
+
Run `opencli list` for the live registry.
|
|
4
|
+
|
|
5
|
+
## Browser Adapters
|
|
6
|
+
|
|
7
|
+
| Site | Commands | Mode |
|
|
8
|
+
|------|----------|------|
|
|
9
|
+
| **[twitter](/adapters/browser/twitter)** | `trending` `bookmarks` `profile` `search` `timeline` `thread` `following` `followers` `notifications` `post` `reply` `delete` `like` `article` `follow` `unfollow` `bookmark` `unbookmark` `download` `accept` `reply-dm` | 🔐 Browser |
|
|
10
|
+
| **[reddit](/adapters/browser/reddit)** | `hot` `frontpage` `popular` `search` `subreddit` `read` `user` `user-posts` `user-comments` `upvote` `save` `comment` `subscribe` `saved` `upvoted` | 🔐 Browser |
|
|
11
|
+
| **[bilibili](/adapters/browser/bilibili)** | `hot` `search` `me` `favorite` `history` `feed` `subtitle` `dynamic` `ranking` `following` `user-videos` `download` | 🔐 Browser |
|
|
12
|
+
| **[zhihu](/adapters/browser/zhihu)** | `hot` `search` `question` `download` | 🔐 Browser |
|
|
13
|
+
| **[xiaohongshu](/adapters/browser/xiaohongshu)** | `search` `notifications` `feed` `me` `user` `download` | 🔐 Browser |
|
|
14
|
+
| **[xueqiu](/adapters/browser/xueqiu)** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` | 🔐 Browser |
|
|
15
|
+
| **[youtube](/adapters/browser/youtube)** | `search` `video` `transcript` | 🔐 Browser |
|
|
16
|
+
| **[v2ex](/adapters/browser/v2ex)** | `hot` `latest` `topic` `daily` `me` `notifications` | 🌐 / 🔐 |
|
|
17
|
+
| **[weibo](/adapters/browser/weibo)** | `hot` | 🔐 Browser |
|
|
18
|
+
| **[linkedin](/adapters/browser/linkedin)** | `search` | 🔐 Browser |
|
|
19
|
+
| **[coupang](/adapters/browser/coupang)** | `search` `add-to-cart` | 🔐 Browser |
|
|
20
|
+
| **[boss](/adapters/browser/boss)** | `search` `detail` | 🔐 Browser |
|
|
21
|
+
| **[ctrip](/adapters/browser/ctrip)** | `search` | 🔐 Browser |
|
|
22
|
+
| **[reuters](/adapters/browser/reuters)** | `search` | 🔐 Browser |
|
|
23
|
+
| **[smzdm](/adapters/browser/smzdm)** | `search` | 🔐 Browser |
|
|
24
|
+
|
|
25
|
+
## Public API Adapters
|
|
26
|
+
|
|
27
|
+
| Site | Commands | Mode |
|
|
28
|
+
|------|----------|------|
|
|
29
|
+
| **[hackernews](/adapters/browser/hackernews)** | `top` | 🌐 Public |
|
|
30
|
+
| **[github](/adapters/browser/github)** | `search` | 🌐 Public |
|
|
31
|
+
| **[bbc](/adapters/browser/bbc)** | `news` | 🌐 Public |
|
|
32
|
+
| **[apple-podcasts](/adapters/browser/apple-podcasts)** | `search` `episodes` `top` | 🌐 Public |
|
|
33
|
+
| **[xiaoyuzhou](/adapters/browser/xiaoyuzhou)** | `podcast` `podcast-episodes` `episode` | 🌐 Public |
|
|
34
|
+
| **[yahoo-finance](/adapters/browser/yahoo-finance)** | `quote` | 🌐 Public |
|
|
35
|
+
|
|
36
|
+
## Desktop Adapters
|
|
37
|
+
|
|
38
|
+
| App | Description | Commands |
|
|
39
|
+
|-----|-------------|----------|
|
|
40
|
+
| **[Cursor](/adapters/desktop/cursor)** | Control Cursor IDE | `status` `send` `read` `new` `dump` `composer` `model` `extract-code` `ask` `screenshot` `history` `export` |
|
|
41
|
+
| **[Codex](/adapters/desktop/codex)** | Drive OpenAI Codex CLI agent | `status` `send` `read` `new` `extract-diff` `model` `ask` `screenshot` `history` `export` |
|
|
42
|
+
| **[Antigravity](/adapters/desktop/antigravity)** | Control Antigravity Ultra | `status` `send` `read` `new` `dump` `extract-code` `model` `watch` |
|
|
43
|
+
| **[ChatGPT](/adapters/desktop/chatgpt)** | Automate ChatGPT macOS app | `status` `new` `send` `read` `ask` |
|
|
44
|
+
| **[ChatWise](/adapters/desktop/chatwise)** | Multi-LLM client | `status` `new` `send` `read` `ask` `model` `history` `export` `screenshot` |
|
|
45
|
+
| **[Notion](/adapters/desktop/notion)** | Search, read, write pages | `status` `search` `read` `new` `write` `sidebar` `favorites` `export` |
|
|
46
|
+
| **[Discord](/adapters/desktop/discord)** | Desktop messages & channels | `status` `send` `read` `channels` `servers` `search` `members` |
|
|
47
|
+
| **[Feishu](/adapters/desktop/feishu)** | 飞书/Lark via AppleScript | `status` `send` `read` `search` `new` |
|
|
48
|
+
| **[WeChat](/adapters/desktop/wechat)** | 微信 via AppleScript | `status` `send` `read` `search` `chats` `contacts` |
|
|
49
|
+
| **[NeteaseMusic](/adapters/desktop/neteasemusic)** | 网易云音乐 via CDP | `status` `playing` `play` `next` `prev` `search` `playlist` `like` `lyrics` `volume` |
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Connecting OpenCLI via CDP (Remote/Headless Servers)
|
|
2
|
+
|
|
3
|
+
If you cannot use the opencli Browser Bridge extension (e.g., in a remote headless server environment without a UI), OpenCLI provides an alternative: connecting directly to Chrome via **CDP (Chrome DevTools Protocol)**.
|
|
4
|
+
|
|
5
|
+
Because CDP binds to `localhost` by default for security reasons, accessing it from a remote server requires an additional networking tunnel.
|
|
6
|
+
|
|
7
|
+
This guide is broken down into three phases:
|
|
8
|
+
1. **Preparation**: Start Chrome with CDP enabled locally.
|
|
9
|
+
2. **Network Tunnels**: Expose that CDP port to your remote server using either **SSH Tunnels** or **Reverse Proxies**.
|
|
10
|
+
3. **Execution**: Run OpenCLI on your server.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Phase 1: Preparation (Local Machine)
|
|
15
|
+
|
|
16
|
+
First, you need to start a Chrome browser on your local machine with remote debugging enabled.
|
|
17
|
+
|
|
18
|
+
**macOS:**
|
|
19
|
+
```bash
|
|
20
|
+
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
|
|
21
|
+
--remote-debugging-port=9222 \
|
|
22
|
+
--user-data-dir="$HOME/chrome-debug-profile" \
|
|
23
|
+
--remote-allow-origins="*"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Linux:**
|
|
27
|
+
```bash
|
|
28
|
+
google-chrome \
|
|
29
|
+
--remote-debugging-port=9222 \
|
|
30
|
+
--user-data-dir="$HOME/chrome-debug-profile" \
|
|
31
|
+
--remote-allow-origins="*"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Windows:**
|
|
35
|
+
```cmd
|
|
36
|
+
"C:\Program Files\Google\Chrome\Application\chrome.exe" ^
|
|
37
|
+
--remote-debugging-port=9222 ^
|
|
38
|
+
--user-data-dir="%USERPROFILE%\chrome-debug-profile" ^
|
|
39
|
+
--remote-allow-origins="*"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
> **Note**: The `--remote-allow-origins="*"` flag is often required for modern Chrome versions to accept cross-origin CDP WebSocket connections (e.g. from reverse proxies like ngrok).
|
|
43
|
+
|
|
44
|
+
Once this browser instance opens, **log into the target websites you want to use** (e.g., bilibili.com, zhihu.com) so that the session contains the correct cookies.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Phase 2: Remote Access Methods
|
|
49
|
+
|
|
50
|
+
Once CDP is running locally on port `9222`, you must securely expose this port to your remote server. Choose one of the two methods below depending on your network conditions.
|
|
51
|
+
|
|
52
|
+
### Method A: SSH Tunnel (Recommended)
|
|
53
|
+
|
|
54
|
+
If your local machine has SSH access to the remote server, this is the most secure and straightforward method.
|
|
55
|
+
|
|
56
|
+
Run this command on your **Local Machine** to forward the remote server's port `9222` back to your local port `9222`:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
ssh -R 9222:localhost:9222 your-server-user@your-server-ip
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Leave this SSH session running in the background.
|
|
63
|
+
|
|
64
|
+
### Method B: Reverse Proxy (ngrok / frp / socat)
|
|
65
|
+
|
|
66
|
+
If you cannot establish a direct SSH connection (e.g., due to NAT or firewalls), you can use an intranet penetration tool like `ngrok`.
|
|
67
|
+
|
|
68
|
+
Run this command on your **Local Machine** to expose your local port `9222` to the public internet securely via ngrok:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
ngrok http 9222
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This will print a forwarding URL, such as `https://abcdef.ngrok.app`. **Copy this URL**.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Phase 3: Execution (Remote Server)
|
|
79
|
+
|
|
80
|
+
Now switch to your **Remote Server** where OpenCLI is installed.
|
|
81
|
+
|
|
82
|
+
Depending on the network tunnel method you chose in Phase 2, set the `OPENCLI_CDP_ENDPOINT` environment variable and run your commands.
|
|
83
|
+
|
|
84
|
+
### If you used Method A (SSH Tunnel):
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
export OPENCLI_CDP_ENDPOINT="http://localhost:9222"
|
|
88
|
+
opencli doctor # Verify connection
|
|
89
|
+
opencli bilibili hot --limit 5 # Test a command
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### If you used Method B (Reverse Proxy like ngrok):
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Use the URL you copied from ngrok earlier
|
|
96
|
+
export OPENCLI_CDP_ENDPOINT="https://abcdef.ngrok.app"
|
|
97
|
+
opencli doctor # Verify connection
|
|
98
|
+
opencli bilibili hot --limit 5 # Test a command
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
> *Tip: If you provide a standard HTTP/HTTPS CDP endpoint, OpenCLI requests the `/json` target list and picks the most likely inspectable app/page target automatically. If multiple app targets exist, you can further narrow selection with `OPENCLI_CDP_TARGET` (for example `antigravity` or `codex`).*
|
|
102
|
+
|
|
103
|
+
If you plan to use this setup frequently, you can persist the environment variable by adding the `export` line to your `~/.bashrc` or `~/.zshrc` on the server.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Download Support
|
|
2
|
+
|
|
3
|
+
OpenCLI supports downloading images, videos, and articles from supported platforms.
|
|
4
|
+
|
|
5
|
+
## Supported Platforms
|
|
6
|
+
|
|
7
|
+
| Platform | Content Types | Notes |
|
|
8
|
+
|----------|---------------|-------|
|
|
9
|
+
| **xiaohongshu** | Images, Videos | Downloads all media from a note |
|
|
10
|
+
| **bilibili** | Videos | Requires `yt-dlp` installed |
|
|
11
|
+
| **twitter** | Images, Videos | Downloads from user media tab or single tweet |
|
|
12
|
+
| **zhihu** | Articles (Markdown) | Exports articles with optional image download |
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
For video downloads from streaming platforms, install `yt-dlp`:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Install yt-dlp
|
|
20
|
+
pip install yt-dlp
|
|
21
|
+
# or
|
|
22
|
+
brew install yt-dlp
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage Examples
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Download images/videos from Xiaohongshu note
|
|
29
|
+
opencli xiaohongshu download --note_id abc123 --output ./xhs
|
|
30
|
+
|
|
31
|
+
# Download Bilibili video (requires yt-dlp)
|
|
32
|
+
opencli bilibili download --bvid BV1xxx --output ./bilibili
|
|
33
|
+
opencli bilibili download --bvid BV1xxx --quality 1080p
|
|
34
|
+
|
|
35
|
+
# Download Twitter media from user
|
|
36
|
+
opencli twitter download --username elonmusk --limit 20 --output ./twitter
|
|
37
|
+
|
|
38
|
+
# Download single tweet media
|
|
39
|
+
opencli twitter download --tweet-url "https://x.com/user/status/123" --output ./twitter
|
|
40
|
+
|
|
41
|
+
# Export Zhihu article to Markdown
|
|
42
|
+
opencli zhihu download --url "https://zhuanlan.zhihu.com/p/xxx" --output ./zhihu
|
|
43
|
+
|
|
44
|
+
# Export with local images
|
|
45
|
+
opencli zhihu download --url "https://zhuanlan.zhihu.com/p/xxx" --download-images
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Pipeline Step (YAML Adapters)
|
|
49
|
+
|
|
50
|
+
The `download` step can be used in YAML pipelines:
|
|
51
|
+
|
|
52
|
+
::: v-pre
|
|
53
|
+
```yaml
|
|
54
|
+
pipeline:
|
|
55
|
+
- fetch: https://api.example.com/media
|
|
56
|
+
- download:
|
|
57
|
+
url: ${{ item.imageUrl }}
|
|
58
|
+
dir: ./downloads
|
|
59
|
+
filename: ${{ item.title | sanitize }}.jpg
|
|
60
|
+
concurrency: 5
|
|
61
|
+
skip_existing: true
|
|
62
|
+
```
|
|
63
|
+
:::
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: How to CLI-ify and automate any Electron Desktop Application via CDP
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# CLI-ifying Electron Applications (Skill Guide)
|
|
6
|
+
|
|
7
|
+
Based on the successful automation of **Cursor**, **Codex**, **Antigravity**, **ChatWise**, **Notion**, and **Discord** desktop apps, this guide serves as the standard operating procedure (SOP) for adapting ANY Electron-based application into an OpenCLI adapter.
|
|
8
|
+
|
|
9
|
+
## Core Concept
|
|
10
|
+
|
|
11
|
+
Electron apps are essentially local Chromium browser instances. By exposing a debugging port (CDP — Chrome DevTools Protocol) at launch time, we can use the Browser Bridge to pierce through the UI layer, accessing and controlling all underlying state including React/Vue components and Shadow DOM.
|
|
12
|
+
|
|
13
|
+
> **Note:** Not all desktop apps are Electron. WeChat (native Cocoa) and Feishu/Lark (custom Lark Framework) embed Chromium but do NOT expose CDP. For those apps, use the AppleScript + clipboard approach instead (see [Non-Electron Pattern](#non-electron-pattern-applescript)).
|
|
14
|
+
|
|
15
|
+
### Launching the Target App
|
|
16
|
+
```bash
|
|
17
|
+
/Applications/AppName.app/Contents/MacOS/AppName --remote-debugging-port=9222
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Verifying Electron
|
|
21
|
+
```bash
|
|
22
|
+
# Check for Electron Framework in the app bundle
|
|
23
|
+
ls /Applications/AppName.app/Contents/Frameworks/Electron\ Framework.framework
|
|
24
|
+
# If this directory exists → Electron → CDP works
|
|
25
|
+
# If not → check for libEGL.dylib (embedded Chromium/CEF, CDP may not work)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## The 5-Command Pattern (CDP / Electron)
|
|
29
|
+
|
|
30
|
+
Every new Electron adapter should implement these 5 commands in `src/clis/<app_name>/`:
|
|
31
|
+
|
|
32
|
+
### 1. `status.ts` — Connection Test
|
|
33
|
+
```typescript
|
|
34
|
+
export const statusCommand = cli({
|
|
35
|
+
site: 'myapp',
|
|
36
|
+
name: 'status',
|
|
37
|
+
domain: 'localhost',
|
|
38
|
+
strategy: Strategy.UI,
|
|
39
|
+
browser: true, // Requires CDP connection
|
|
40
|
+
args: [],
|
|
41
|
+
columns: ['Status', 'Url', 'Title'],
|
|
42
|
+
func: async (page: IPage) => {
|
|
43
|
+
const url = await page.evaluate('window.location.href');
|
|
44
|
+
const title = await page.evaluate('document.title');
|
|
45
|
+
return [{ Status: 'Connected', Url: url, Title: title }];
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. `dump.ts` — Reverse Engineering Core
|
|
51
|
+
Modern app DOMs are huge and obfuscated. **Never guess selectors.** Dump first, then extract precise class names with AI or `grep`:
|
|
52
|
+
```typescript
|
|
53
|
+
const dom = await page.evaluate('document.body.innerHTML');
|
|
54
|
+
fs.writeFileSync('/tmp/app-dom.html', dom);
|
|
55
|
+
const snap = await page.snapshot({ interactive: false });
|
|
56
|
+
fs.writeFileSync('/tmp/app-snapshot.json', JSON.stringify(snap, null, 2));
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 3. `send.ts` — Advanced Text Injection
|
|
60
|
+
Electron apps often use complex rich-text editors (Monaco, Lexical, ProseMirror). Setting `.value` directly is ignored by React state.
|
|
61
|
+
|
|
62
|
+
**Best practice:** Use `document.execCommand('insertText')` to perfectly simulate real user input, fully piercing React state:
|
|
63
|
+
```javascript
|
|
64
|
+
const composer = document.querySelector('[contenteditable="true"]');
|
|
65
|
+
composer.focus();
|
|
66
|
+
document.execCommand('insertText', false, 'Hello');
|
|
67
|
+
```
|
|
68
|
+
Then submit with `await page.pressKey('Enter')`.
|
|
69
|
+
|
|
70
|
+
### 4. `read.ts` — Context Extraction
|
|
71
|
+
Don't extract the entire page text. Use `dump.ts` output to find the real "conversation container":
|
|
72
|
+
- Look for semantic selectors: `[role="log"]`, `[data-testid="conversation"]`, `[data-content-search-turn-key]`
|
|
73
|
+
- Format output as Markdown — readable by both humans and LLMs
|
|
74
|
+
|
|
75
|
+
### 5. `new.ts` — Keyboard Shortcuts
|
|
76
|
+
Many GUI actions respond to native shortcuts rather than button clicks:
|
|
77
|
+
```typescript
|
|
78
|
+
const isMac = process.platform === 'darwin';
|
|
79
|
+
await page.pressKey(isMac ? 'Meta+N' : 'Control+N');
|
|
80
|
+
await page.wait(1); // Wait for re-render
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Environment Variable
|
|
84
|
+
```bash
|
|
85
|
+
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9222"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Non-Electron Pattern (AppleScript)
|
|
89
|
+
|
|
90
|
+
For native macOS apps (WeChat, Feishu) that don't expose CDP:
|
|
91
|
+
```typescript
|
|
92
|
+
export const statusCommand = cli({
|
|
93
|
+
site: 'myapp',
|
|
94
|
+
strategy: Strategy.PUBLIC,
|
|
95
|
+
browser: false, // No browser needed
|
|
96
|
+
func: async (page: IPage | null) => {
|
|
97
|
+
const output = execSync("osascript -e 'application \"MyApp\" is running'", { encoding: 'utf-8' }).trim();
|
|
98
|
+
return [{ Status: output === 'true' ? 'Running' : 'Stopped' }];
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Core techniques:
|
|
104
|
+
- **status**: `osascript -e 'application "AppName" is running'`
|
|
105
|
+
- **send**: `pbcopy` → activate window → `Cmd+V` → `Enter`
|
|
106
|
+
- **read**: `Cmd+A` → `Cmd+C` → `pbpaste`
|
|
107
|
+
- **search**: Activate → `Cmd+F`/`Cmd+K` → `keystroke "query"`
|
|
108
|
+
|
|
109
|
+
## Pitfalls & Gotchas
|
|
110
|
+
|
|
111
|
+
1. **Port conflicts (EADDRINUSE)**: Only one app per port. Use unique ports: Codex=9222, ChatGPT=9224, Cursor=9226, ChatWise=9228, Notion=9230, Discord=9232
|
|
112
|
+
2. **IPage abstraction**: OpenCLI wraps the browser page as `IPage` (`src/types.ts`). Use `page.pressKey()` and `page.evaluate()`, NOT direct DOM APIs
|
|
113
|
+
3. **Timing**: Always add `await page.wait(0.5)` to `1.0` after DOM mutations. Returning too early disconnects prematurely
|
|
114
|
+
4. **AppleScript requires Accessibility**: Terminal app must be granted permission in System Settings → Privacy & Security → Accessibility
|
|
115
|
+
|
|
116
|
+
## Port Assignment Table
|
|
117
|
+
|
|
118
|
+
| App | Port | Mode |
|
|
119
|
+
|-----|------|------|
|
|
120
|
+
| Codex | 9222 | CDP |
|
|
121
|
+
| ChatGPT | 9224 | CDP / AppleScript |
|
|
122
|
+
| Cursor | 9226 | CDP |
|
|
123
|
+
| ChatWise | 9228 | CDP |
|
|
124
|
+
| Notion | 9230 | CDP |
|
|
125
|
+
| Discord App | 9232 | CDP |
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Remote Chrome
|
|
2
|
+
|
|
3
|
+
Run OpenCLI on a server or headless environment by connecting to a remote Chrome instance.
|
|
4
|
+
|
|
5
|
+
## Use Cases
|
|
6
|
+
|
|
7
|
+
- Running CLI commands on a remote server
|
|
8
|
+
- CI/CD automation with headed browser
|
|
9
|
+
- Shared team browser sessions
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
### 1. Start Chrome on the Remote Machine
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# On the remote machine (or your Mac)
|
|
17
|
+
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
|
|
18
|
+
--remote-debugging-port=9222
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 2. SSH Tunnel (If Needed)
|
|
22
|
+
|
|
23
|
+
If the remote Chrome is on a different machine, create an SSH tunnel:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# On your local machine or server
|
|
27
|
+
ssh -L 9222:127.0.0.1:9222 user@remote-host
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
::: warning
|
|
31
|
+
Use `127.0.0.1` instead of `localhost` in the SSH command to avoid IPv6 resolution issues that can cause timeouts.
|
|
32
|
+
:::
|
|
33
|
+
|
|
34
|
+
### 3. Configure OpenCLI
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9222"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 4. Verify
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Test the connection
|
|
44
|
+
curl http://127.0.0.1:9222/json/version
|
|
45
|
+
|
|
46
|
+
# Run a diagnostic
|
|
47
|
+
opencli doctor
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## CI/CD Integration
|
|
51
|
+
|
|
52
|
+
For CI/CD environments, use a real Chrome instance with `xvfb`:
|
|
53
|
+
|
|
54
|
+
::: v-pre
|
|
55
|
+
```yaml
|
|
56
|
+
steps:
|
|
57
|
+
- uses: browser-actions/setup-chrome@latest
|
|
58
|
+
id: setup-chrome
|
|
59
|
+
- run: |
|
|
60
|
+
xvfb-run --auto-servernum \
|
|
61
|
+
${{ steps.setup-chrome.outputs.chrome-path }} \
|
|
62
|
+
--remote-debugging-port=9222 &
|
|
63
|
+
```
|
|
64
|
+
:::
|
|
65
|
+
|
|
66
|
+
Set the browser executable path:
|
|
67
|
+
::: v-pre
|
|
68
|
+
```yaml
|
|
69
|
+
env:
|
|
70
|
+
OPENCLI_BROWSER_EXECUTABLE_PATH: ${{ steps.setup-chrome.outputs.chrome-path }}
|
|
71
|
+
```
|
|
72
|
+
:::
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# AI Workflow
|
|
2
|
+
|
|
3
|
+
OpenCLI is designed with AI agents in mind. This guide covers the AI-native discovery and code generation tools.
|
|
4
|
+
|
|
5
|
+
## Quick Mode (One-Shot)
|
|
6
|
+
|
|
7
|
+
Generate a single command for a specific page URL — just a URL + one-line goal, 4 steps done:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
opencli generate https://example.com --goal "trending"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This runs: explore → synthesize → register in one shot.
|
|
14
|
+
|
|
15
|
+
For the complete one-shot workflow details, see [CLI-ONESHOT.md](https://github.com/jackwener/opencli/blob/main/CLI-ONESHOT.md).
|
|
16
|
+
|
|
17
|
+
## Full Mode (Explorer Workflow)
|
|
18
|
+
|
|
19
|
+
### Step 1: Deep Explore
|
|
20
|
+
|
|
21
|
+
Discover APIs, infer capabilities, and detect framework:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
opencli explore https://example.com --site mysite
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Outputs to `.opencli/explore/<site>/`:
|
|
28
|
+
- `manifest.json` — Site metadata
|
|
29
|
+
- `endpoints.json` — Discovered API endpoints
|
|
30
|
+
- `capabilities.json` — Inferred capabilities
|
|
31
|
+
- `auth.json` — Authentication strategy details
|
|
32
|
+
|
|
33
|
+
### Step 2: Synthesize
|
|
34
|
+
|
|
35
|
+
Generate YAML adapters from explore artifacts:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
opencli synthesize mysite
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Step 3: Strategy Cascade
|
|
42
|
+
|
|
43
|
+
Auto-probe authentication strategies: `PUBLIC → COOKIE → HEADER`:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
opencli cascade https://api.example.com/data
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Step 4: Validate & Test
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
opencli validate # Validate generated YAML
|
|
53
|
+
opencli <site> <command> --limit 3 -f json # Test the command
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 5-Tier Authentication Strategy
|
|
57
|
+
|
|
58
|
+
The explorer uses a decision tree to determine the best authentication approach:
|
|
59
|
+
|
|
60
|
+
1. **PUBLIC** — No auth, direct API call
|
|
61
|
+
2. **COOKIE** — Reuse Chrome session cookies
|
|
62
|
+
3. **HEADER** — Custom auth headers
|
|
63
|
+
4. **BROWSER** — Full browser automation
|
|
64
|
+
5. **CDP** — Chrome DevTools Protocol for Electron apps
|
|
65
|
+
|
|
66
|
+
For the complete browser exploration workflow and debugging guide, see [CLI-EXPLORER.md](https://github.com/jackwener/opencli/blob/main/CLI-EXPLORER.md).
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
OpenCLI is built on a **Dual-Engine Architecture** that supports both declarative YAML pipelines and programmatic TypeScript adapters.
|
|
4
|
+
|
|
5
|
+
## High-Level Architecture
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────────────────┐
|
|
9
|
+
│ opencli CLI │
|
|
10
|
+
│ (Commander.js entry point) │
|
|
11
|
+
├─────────────────────────────────────────────────────┤
|
|
12
|
+
│ Engine Layer │
|
|
13
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │
|
|
14
|
+
│ │ Registry │ │ Dynamic │ │ Output │ │
|
|
15
|
+
│ │ (commands) │ │ Loader │ │ Formatter │ │
|
|
16
|
+
│ └──────────────┘ └──────────────┘ └────────────┘ │
|
|
17
|
+
├─────────────────────────────────────────────────────┤
|
|
18
|
+
│ Adapter Layer │
|
|
19
|
+
│ ┌─────────────────┐ ┌──────────────────────────┐ │
|
|
20
|
+
│ │ YAML Pipeline │ │ TypeScript Adapters │ │
|
|
21
|
+
│ │ (declarative) │ │ (browser/desktop/AI) │ │
|
|
22
|
+
│ └─────────────────┘ └──────────────────────────┘ │
|
|
23
|
+
├─────────────────────────────────────────────────────┤
|
|
24
|
+
│ Connection Layer │
|
|
25
|
+
│ ┌─────────────────┐ ┌──────────────────────────┐ │
|
|
26
|
+
│ │ Browser Bridge │ │ CDP (Chrome DevTools) │ │
|
|
27
|
+
│ │ (Extension+WS) │ │ (Electron apps) │ │
|
|
28
|
+
│ └─────────────────┘ └──────────────────────────┘ │
|
|
29
|
+
└─────────────────────────────────────────────────────┘
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Core Modules
|
|
33
|
+
|
|
34
|
+
### Registry (`src/registry.ts`)
|
|
35
|
+
Central command registry. All adapters register their commands via the `cli()` function with metadata: site, name, description, domain, strategy, args, columns.
|
|
36
|
+
|
|
37
|
+
### Engine (`src/engine.ts`)
|
|
38
|
+
Command discovery and execution engine. Discovers commands from the registry, parses arguments, executes the appropriate adapter, and routes output through the formatter.
|
|
39
|
+
|
|
40
|
+
### Browser (`src/browser.ts`)
|
|
41
|
+
Manages connections to Chrome via the Browser Bridge WebSocket daemon. Handles JSON-RPC messaging, tab management, and extension/standalone mode switching.
|
|
42
|
+
|
|
43
|
+
### Pipeline (`src/pipeline/`)
|
|
44
|
+
The YAML pipeline engine. Processes declarative steps:
|
|
45
|
+
- **fetch** — HTTP requests with cookie/header strategies
|
|
46
|
+
- **map** — Data transformation with template expressions
|
|
47
|
+
- **limit** — Result truncation
|
|
48
|
+
- **filter** — Conditional filtering
|
|
49
|
+
- **download** — Media download support
|
|
50
|
+
|
|
51
|
+
### Output (`src/output.ts`)
|
|
52
|
+
Unified output formatting: `table`, `json`, `yaml`, `md`, `csv`.
|
|
53
|
+
|
|
54
|
+
## Authentication Strategies
|
|
55
|
+
|
|
56
|
+
OpenCLI uses a 3-tier authentication strategy:
|
|
57
|
+
|
|
58
|
+
| Strategy | How It Works | When to Use |
|
|
59
|
+
|----------|-------------|-------------|
|
|
60
|
+
| `public` | Direct HTTP fetch, no auth | Public APIs (HackerNews, BBC) |
|
|
61
|
+
| `cookie` | Reuse Chrome cookies via Browser Bridge | Logged-in sites (Bilibili, Zhihu) |
|
|
62
|
+
| `header` | Custom auth headers | API-key based services |
|
|
63
|
+
|
|
64
|
+
## Directory Structure
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
src/
|
|
68
|
+
├── main.ts # Entry point
|
|
69
|
+
├── engine.ts # Command execution engine
|
|
70
|
+
├── registry.ts # Command registry
|
|
71
|
+
├── browser.ts # Browser Bridge connection
|
|
72
|
+
├── output.ts # Output formatting
|
|
73
|
+
├── doctor.ts # Diagnostic tool
|
|
74
|
+
├── pipeline/ # YAML pipeline engine
|
|
75
|
+
│ ├── runner.ts
|
|
76
|
+
│ ├── template.ts
|
|
77
|
+
│ ├── transform.ts
|
|
78
|
+
│ └── steps/
|
|
79
|
+
│ ├── fetch.ts
|
|
80
|
+
│ ├── map.ts
|
|
81
|
+
│ ├── limit.ts
|
|
82
|
+
│ ├── filter.ts
|
|
83
|
+
│ └── download.ts
|
|
84
|
+
└── clis/ # Site adapters
|
|
85
|
+
├── twitter/
|
|
86
|
+
├── reddit/
|
|
87
|
+
├── bilibili/
|
|
88
|
+
├── cursor/
|
|
89
|
+
└── ...
|
|
90
|
+
```
|