@jackwener/opencli 1.0.3 → 1.0.5

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.
Files changed (190) hide show
  1. package/.github/workflows/build-extension.yml +21 -3
  2. package/.github/workflows/docs.yml +52 -0
  3. package/README.md +28 -28
  4. package/README.zh-CN.md +28 -28
  5. package/dist/browser/cdp.d.ts +16 -1
  6. package/dist/browser/cdp.js +124 -80
  7. package/dist/browser/daemon-client.d.ts +3 -1
  8. package/dist/browser/daemon-client.js +4 -0
  9. package/dist/browser/dom-helpers.d.ts +20 -0
  10. package/dist/browser/dom-helpers.js +109 -0
  11. package/dist/browser/mcp.d.ts +1 -0
  12. package/dist/browser/mcp.js +10 -5
  13. package/dist/browser/page.d.ts +7 -0
  14. package/dist/browser/page.js +37 -100
  15. package/dist/browser.test.js +7 -0
  16. package/dist/build-manifest.js +3 -1
  17. package/dist/build-manifest.test.js +34 -0
  18. package/dist/capabilityRouting.d.ts +2 -0
  19. package/dist/capabilityRouting.js +30 -0
  20. package/dist/capabilityRouting.test.d.ts +1 -0
  21. package/dist/capabilityRouting.test.js +42 -0
  22. package/dist/chaoxing.test.js +11 -4
  23. package/dist/cli-manifest.json +635 -1
  24. package/dist/cli.js +48 -8
  25. package/dist/clis/antigravity/serve.d.ts +14 -0
  26. package/dist/clis/antigravity/serve.js +263 -0
  27. package/dist/clis/bilibili/download.js +4 -14
  28. package/dist/clis/boss/resume.d.ts +1 -0
  29. package/dist/clis/boss/resume.js +249 -0
  30. package/dist/clis/hf/top.d.ts +1 -0
  31. package/dist/clis/hf/top.js +119 -0
  32. package/dist/clis/jike/comment.d.ts +1 -0
  33. package/dist/clis/jike/comment.js +107 -0
  34. package/dist/clis/jike/create.d.ts +1 -0
  35. package/dist/clis/jike/create.js +106 -0
  36. package/dist/clis/jike/feed.d.ts +1 -0
  37. package/dist/clis/jike/feed.js +67 -0
  38. package/dist/clis/jike/like.d.ts +1 -0
  39. package/dist/clis/jike/like.js +61 -0
  40. package/dist/clis/jike/notifications.d.ts +1 -0
  41. package/dist/clis/jike/notifications.js +169 -0
  42. package/dist/clis/jike/post.yaml +58 -0
  43. package/dist/clis/jike/repost.d.ts +1 -0
  44. package/dist/clis/jike/repost.js +103 -0
  45. package/dist/clis/jike/search.d.ts +1 -0
  46. package/dist/clis/jike/search.js +67 -0
  47. package/dist/clis/jike/shared.d.ts +19 -0
  48. package/dist/clis/jike/shared.js +25 -0
  49. package/dist/clis/jike/topic.yaml +52 -0
  50. package/dist/clis/jike/user.yaml +51 -0
  51. package/dist/clis/smzdm/search.js +28 -39
  52. package/dist/clis/stackoverflow/bounties.yaml +29 -0
  53. package/dist/clis/stackoverflow/hot.yaml +28 -0
  54. package/dist/clis/stackoverflow/search.yaml +32 -0
  55. package/dist/clis/stackoverflow/unanswered.yaml +28 -0
  56. package/dist/clis/twitter/download.js +6 -16
  57. package/dist/clis/xiaohongshu/download.js +3 -3
  58. package/dist/clis/zhihu/download.js +3 -3
  59. package/dist/doctor.d.ts +7 -0
  60. package/dist/doctor.js +16 -0
  61. package/dist/download/index.d.ts +12 -8
  62. package/dist/download/index.js +11 -3
  63. package/dist/download/index.test.d.ts +1 -0
  64. package/dist/download/index.test.js +14 -0
  65. package/dist/engine.js +5 -5
  66. package/dist/explore.d.ts +1 -0
  67. package/dist/explore.js +3 -3
  68. package/dist/generate.js +1 -0
  69. package/dist/interceptor.js +3 -2
  70. package/dist/output.d.ts +1 -0
  71. package/dist/output.js +3 -1
  72. package/dist/pipeline/executor.test.js +1 -0
  73. package/dist/pipeline/steps/download.js +14 -18
  74. package/dist/registry.d.ts +1 -0
  75. package/dist/registry.js +5 -2
  76. package/dist/runtime.d.ts +4 -1
  77. package/dist/runtime.js +2 -2
  78. package/dist/types.d.ts +12 -0
  79. package/dist/verify.d.ts +6 -1
  80. package/dist/verify.js +54 -2
  81. package/docs/.vitepress/config.mts +193 -0
  82. package/docs/adapters/browser/apple-podcasts.md +28 -0
  83. package/docs/adapters/browser/bbc.md +26 -0
  84. package/docs/adapters/browser/bilibili.md +38 -0
  85. package/docs/adapters/browser/boss.md +28 -0
  86. package/docs/adapters/browser/coupang.md +28 -0
  87. package/docs/adapters/browser/ctrip.md +27 -0
  88. package/docs/adapters/browser/github.md +26 -0
  89. package/docs/adapters/browser/hackernews.md +26 -0
  90. package/docs/adapters/browser/linkedin.md +27 -0
  91. package/docs/adapters/browser/reddit.md +41 -0
  92. package/docs/adapters/browser/reuters.md +27 -0
  93. package/docs/adapters/browser/smzdm.md +27 -0
  94. package/docs/adapters/browser/twitter.md +47 -0
  95. package/docs/adapters/browser/v2ex.md +32 -0
  96. package/docs/adapters/browser/weibo.md +27 -0
  97. package/docs/adapters/browser/xiaohongshu.md +32 -0
  98. package/docs/adapters/browser/xiaoyuzhou.md +28 -0
  99. package/docs/adapters/browser/xueqiu.md +32 -0
  100. package/docs/adapters/browser/yahoo-finance.md +26 -0
  101. package/docs/adapters/browser/youtube.md +29 -0
  102. package/docs/adapters/browser/zhihu.md +30 -0
  103. package/docs/adapters/desktop/antigravity.md +46 -0
  104. package/docs/adapters/desktop/chatgpt.md +43 -0
  105. package/docs/adapters/desktop/chatwise.md +38 -0
  106. package/docs/adapters/desktop/codex.md +32 -0
  107. package/docs/adapters/desktop/cursor.md +33 -0
  108. package/docs/adapters/desktop/discord.md +28 -0
  109. package/docs/adapters/desktop/feishu.md +20 -0
  110. package/docs/adapters/desktop/neteasemusic.md +31 -0
  111. package/docs/adapters/desktop/notion.md +29 -0
  112. package/docs/adapters/desktop/wechat.md +28 -0
  113. package/docs/adapters/index.md +49 -0
  114. package/docs/advanced/cdp.md +103 -0
  115. package/docs/advanced/download.md +63 -0
  116. package/docs/advanced/electron.md +125 -0
  117. package/docs/advanced/remote-chrome.md +72 -0
  118. package/docs/developer/ai-workflow.md +66 -0
  119. package/docs/developer/architecture.md +90 -0
  120. package/docs/developer/contributing.md +136 -0
  121. package/docs/developer/testing.md +237 -0
  122. package/docs/developer/ts-adapter.md +87 -0
  123. package/docs/developer/yaml-adapter.md +108 -0
  124. package/docs/guide/browser-bridge.md +38 -0
  125. package/docs/guide/getting-started.md +56 -0
  126. package/docs/guide/installation.md +37 -0
  127. package/docs/guide/troubleshooting.md +56 -0
  128. package/docs/index.md +35 -0
  129. package/docs/zh/adapters/index.md +5 -0
  130. package/docs/zh/advanced/cdp.md +3 -0
  131. package/docs/zh/developer/contributing.md +24 -0
  132. package/docs/zh/guide/browser-bridge.md +25 -0
  133. package/docs/zh/guide/getting-started.md +40 -0
  134. package/docs/zh/guide/installation.md +37 -0
  135. package/docs/zh/index.md +29 -0
  136. package/extension/dist/background.js +92 -52
  137. package/extension/package-lock.json +1156 -0
  138. package/extension/src/background.test.ts +151 -0
  139. package/extension/src/background.ts +122 -51
  140. package/extension/src/protocol.ts +3 -1
  141. package/package.json +7 -3
  142. package/src/browser/cdp.ts +154 -82
  143. package/src/browser/daemon-client.ts +7 -1
  144. package/src/browser/dom-helpers.ts +116 -0
  145. package/src/browser/mcp.ts +14 -6
  146. package/src/browser/page.ts +45 -100
  147. package/src/browser.test.ts +10 -0
  148. package/src/build-manifest.test.ts +36 -0
  149. package/src/build-manifest.ts +2 -1
  150. package/src/capabilityRouting.test.ts +47 -0
  151. package/src/capabilityRouting.ts +28 -0
  152. package/src/chaoxing.test.ts +12 -4
  153. package/src/cli.ts +30 -8
  154. package/src/clis/antigravity/serve.ts +329 -0
  155. package/src/clis/bilibili/download.ts +4 -15
  156. package/src/clis/boss/resume.ts +262 -0
  157. package/src/clis/hf/top.ts +141 -0
  158. package/src/clis/jike/comment.ts +113 -0
  159. package/src/clis/jike/create.ts +113 -0
  160. package/src/clis/jike/feed.ts +74 -0
  161. package/src/clis/jike/like.ts +65 -0
  162. package/src/clis/jike/notifications.ts +185 -0
  163. package/src/clis/jike/post.yaml +58 -0
  164. package/src/clis/jike/repost.ts +114 -0
  165. package/src/clis/jike/search.ts +74 -0
  166. package/src/clis/jike/shared.ts +36 -0
  167. package/src/clis/jike/topic.yaml +52 -0
  168. package/src/clis/jike/user.yaml +51 -0
  169. package/src/clis/smzdm/search.ts +30 -39
  170. package/src/clis/stackoverflow/bounties.yaml +29 -0
  171. package/src/clis/stackoverflow/hot.yaml +28 -0
  172. package/src/clis/stackoverflow/search.yaml +32 -0
  173. package/src/clis/stackoverflow/unanswered.yaml +28 -0
  174. package/src/clis/twitter/download.ts +6 -17
  175. package/src/clis/xiaohongshu/download.ts +3 -3
  176. package/src/clis/zhihu/download.ts +3 -3
  177. package/src/doctor.ts +18 -2
  178. package/src/download/index.test.ts +16 -0
  179. package/src/download/index.ts +22 -4
  180. package/src/engine.ts +4 -4
  181. package/src/explore.ts +4 -4
  182. package/src/generate.ts +1 -0
  183. package/src/interceptor.ts +3 -2
  184. package/src/output.ts +3 -1
  185. package/src/pipeline/executor.test.ts +1 -0
  186. package/src/pipeline/steps/download.ts +14 -17
  187. package/src/registry.ts +6 -2
  188. package/src/runtime.ts +3 -2
  189. package/src/types.ts +9 -0
  190. 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
+ ```