@jackwener/opencli 1.0.5 → 1.0.6
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 +8 -0
- package/README.md +10 -10
- package/dist/bilibili.js +4 -2
- package/docs/.vitepress/config.mts +1 -0
- package/package.json +1 -1
- package/src/bilibili.ts +4 -2
- package/src/clis/antigravity/README.md +3 -46
- package/src/clis/chaoxing/README.md +2 -24
- package/src/clis/chatgpt/README.md +3 -42
- package/src/clis/chatwise/README.md +3 -36
- package/src/clis/codex/README.md +3 -32
- package/src/clis/cursor/README.md +3 -31
- package/src/clis/discord-app/README.md +2 -25
- package/src/clis/feishu/README.md +2 -17
- package/src/clis/neteasemusic/README.md +3 -29
- package/src/clis/notion/README.md +2 -26
- package/src/clis/wechat/README.md +2 -25
- package/CDP.md +0 -103
- package/CDP.zh-CN.md +0 -103
- package/CLI-ELECTRON.md +0 -125
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.0.6](https://github.com/jackwener/opencli/compare/v1.0.5...v1.0.6) (2026-03-20)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* use %20 instead of + for spaces in Bilibili WBI signed requests ([#126](https://github.com/jackwener/opencli/issues/126)) ([4cabca1](https://github.com/jackwener/opencli/commit/4cabca12dfa6ca027b938b80ee6b940b5e89ea5c)), closes [#125](https://github.com/jackwener/opencli/issues/125)
|
package/README.md
CHANGED
|
@@ -150,16 +150,16 @@ Each desktop adapter has its own detailed documentation with commands reference,
|
|
|
150
150
|
|
|
151
151
|
| App | Description | Doc |
|
|
152
152
|
|-----|-------------|-----|
|
|
153
|
-
| **Cursor** | Control Cursor IDE — Composer, chat, code extraction | [
|
|
154
|
-
| **Codex** | Drive OpenAI Codex CLI agent headlessly | [
|
|
155
|
-
| **Antigravity** | Control Antigravity Ultra from terminal | [
|
|
156
|
-
| **ChatGPT** | Automate ChatGPT macOS desktop app | [
|
|
157
|
-
| **ChatWise** | Multi-LLM client (GPT-4, Claude, Gemini) | [
|
|
158
|
-
| **Notion** | Search, read, write Notion pages | [
|
|
159
|
-
| **Discord** | Discord Desktop — messages, channels, servers | [
|
|
160
|
-
| **Feishu** | 飞书/Lark Desktop via AppleScript | [
|
|
161
|
-
| **WeChat** | 微信 Desktop via AppleScript + Accessibility | [
|
|
162
|
-
| **NeteaseMusic** | 网易云音乐 Desktop via CEF/CDP | [
|
|
153
|
+
| **Cursor** | Control Cursor IDE — Composer, chat, code extraction | [Doc](./docs/adapters/desktop/cursor.md) |
|
|
154
|
+
| **Codex** | Drive OpenAI Codex CLI agent headlessly | [Doc](./docs/adapters/desktop/codex.md) |
|
|
155
|
+
| **Antigravity** | Control Antigravity Ultra from terminal | [Doc](./docs/adapters/desktop/antigravity.md) |
|
|
156
|
+
| **ChatGPT** | Automate ChatGPT macOS desktop app | [Doc](./docs/adapters/desktop/chatgpt.md) |
|
|
157
|
+
| **ChatWise** | Multi-LLM client (GPT-4, Claude, Gemini) | [Doc](./docs/adapters/desktop/chatwise.md) |
|
|
158
|
+
| **Notion** | Search, read, write Notion pages | [Doc](./docs/adapters/desktop/notion.md) |
|
|
159
|
+
| **Discord** | Discord Desktop — messages, channels, servers | [Doc](./docs/adapters/desktop/discord.md) |
|
|
160
|
+
| **Feishu** | 飞书/Lark Desktop via AppleScript | [Doc](./docs/adapters/desktop/feishu.md) |
|
|
161
|
+
| **WeChat** | 微信 Desktop via AppleScript + Accessibility | [Doc](./docs/adapters/desktop/wechat.md) |
|
|
162
|
+
| **NeteaseMusic** | 网易云音乐 Desktop via CEF/CDP | [Doc](./docs/adapters/desktop/neteasemusic.md) |
|
|
163
163
|
|
|
164
164
|
## Download Support
|
|
165
165
|
|
package/dist/bilibili.js
CHANGED
|
@@ -47,7 +47,9 @@ export async function wbiSign(page, params) {
|
|
|
47
47
|
for (const key of Object.keys(allParams).sort()) {
|
|
48
48
|
sorted[key] = String(allParams[key]).replace(/[!'()*]/g, '');
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
// Bilibili WBI verification expects %20 for spaces, not + (URLSearchParams default).
|
|
51
|
+
// Using + causes signature mismatch → CORS-blocked error response → TypeError: Failed to fetch.
|
|
52
|
+
const query = new URLSearchParams(sorted).toString().replace(/\+/g, '%20');
|
|
51
53
|
const wRid = await md5(query + mixinKey);
|
|
52
54
|
sorted.w_rid = wRid;
|
|
53
55
|
return sorted;
|
|
@@ -58,7 +60,7 @@ export async function apiGet(page, path, opts = {}) {
|
|
|
58
60
|
if (opts.signed) {
|
|
59
61
|
params = await wbiSign(page, params);
|
|
60
62
|
}
|
|
61
|
-
const qs = new URLSearchParams(Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)])));
|
|
63
|
+
const qs = new URLSearchParams(Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)]))).toString().replace(/\+/g, '%20');
|
|
62
64
|
const url = `${baseUrl}${path}?${qs}`;
|
|
63
65
|
return fetchJson(page, url);
|
|
64
66
|
}
|
package/package.json
CHANGED
package/src/bilibili.ts
CHANGED
|
@@ -60,7 +60,9 @@ export async function wbiSign(
|
|
|
60
60
|
for (const key of Object.keys(allParams).sort()) {
|
|
61
61
|
sorted[key] = String(allParams[key]).replace(/[!'()*]/g, '');
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
// Bilibili WBI verification expects %20 for spaces, not + (URLSearchParams default).
|
|
64
|
+
// Using + causes signature mismatch → CORS-blocked error response → TypeError: Failed to fetch.
|
|
65
|
+
const query = new URLSearchParams(sorted).toString().replace(/\+/g, '%20');
|
|
64
66
|
const wRid = await md5(query + mixinKey);
|
|
65
67
|
sorted.w_rid = wRid;
|
|
66
68
|
return sorted;
|
|
@@ -78,7 +80,7 @@ export async function apiGet(
|
|
|
78
80
|
}
|
|
79
81
|
const qs = new URLSearchParams(
|
|
80
82
|
Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)])),
|
|
81
|
-
);
|
|
83
|
+
).toString().replace(/\+/g, '%20');
|
|
82
84
|
const url = `${baseUrl}${path}?${qs}`;
|
|
83
85
|
return fetchJson(page, url);
|
|
84
86
|
}
|
|
@@ -1,48 +1,5 @@
|
|
|
1
|
-
# Antigravity
|
|
1
|
+
# Antigravity Adapter
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Control **Antigravity Ultra** from the terminal via Chrome DevTools Protocol (CDP).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Turn your local Antigravity desktop application into a programmable AI node via Chrome DevTools Protocol (CDP). This allows you to compose complex LLM workflows entirely through the terminal by manipulating the actual UI natively, bypassing any API restrictions.
|
|
8
|
-
|
|
9
|
-
## Prerequisites
|
|
10
|
-
|
|
11
|
-
Start the Antigravity desktop app with the Chrome DevTools `remote-debugging-port` flag:
|
|
12
|
-
|
|
13
|
-
\`\`\`bash
|
|
14
|
-
# Start Antigravity in the background
|
|
15
|
-
/Applications/Antigravity.app/Contents/MacOS/Electron \
|
|
16
|
-
--remote-debugging-port=9224
|
|
17
|
-
\`\`\`
|
|
18
|
-
|
|
19
|
-
*(Note: Depending on your installation, the executable might be named differently, e.g., \`Antigravity\` instead of \`Electron\`.)*
|
|
20
|
-
|
|
21
|
-
Next, set the target port in your terminal session to tell OpenCLI where to connect:
|
|
22
|
-
|
|
23
|
-
\`\`\`bash
|
|
24
|
-
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9224"
|
|
25
|
-
\`\`\`
|
|
26
|
-
|
|
27
|
-
## Available Commands
|
|
28
|
-
|
|
29
|
-
### \`opencli antigravity status\`
|
|
30
|
-
Check the Chromium CDP connection. Returns the current window title and active internal URL.
|
|
31
|
-
|
|
32
|
-
### \`opencli antigravity send <message>\`
|
|
33
|
-
Send a text prompt to the AI. Automatically locates the Lexical editor input box, types the prompt securely, and hits Enter.
|
|
34
|
-
|
|
35
|
-
### \`opencli antigravity read\`
|
|
36
|
-
Scrape the entire current conversation history block as pure text. Useful for feeding the context to another script.
|
|
37
|
-
|
|
38
|
-
### \`opencli antigravity new\`
|
|
39
|
-
Click the "New Conversation" button to instantly clear the UI state and start fresh.
|
|
40
|
-
|
|
41
|
-
### \`opencli antigravity extract-code\`
|
|
42
|
-
Extract any multi-line code blocks from the current conversation view. Ideal for automated script extraction (e.g. \`opencli antigravity extract-code > script.sh\`).
|
|
43
|
-
|
|
44
|
-
### \`opencli antigravity model <name>\`
|
|
45
|
-
Quickly target and switch the active LLM engine. Example: \`opencli antigravity model claude\` or \`opencli antigravity model gemini\`.
|
|
46
|
-
|
|
47
|
-
### \`opencli antigravity watch\`
|
|
48
|
-
A long-running, streaming process that continuously polls the Antigravity UI for chat updates and outputs them in real-time to standard output.
|
|
5
|
+
📖 **Full documentation**: [docs/adapters/desktop/antigravity](../../../docs/adapters/desktop/antigravity.md)
|
|
@@ -2,35 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
View your Chaoxing assignments and exams from the terminal by reusing your Chrome login session.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
1. Chrome must be running and already logged into Chaoxing (`i.chaoxing.com`).
|
|
8
|
-
2. The opencli Browser Bridge extension must be installed.
|
|
5
|
+
📖 **Full documentation**: See commands and usage below.
|
|
9
6
|
|
|
10
7
|
## Commands
|
|
11
8
|
|
|
12
9
|
| Command | Description |
|
|
13
10
|
|---------|-------------|
|
|
14
11
|
| `opencli chaoxing assignments` | List assignments across all courses |
|
|
15
|
-
| `opencli chaoxing assignments --course "数学"` | Filter by course name (fuzzy match) |
|
|
16
|
-
| `opencli chaoxing assignments --status pending` | Filter: `all` / `pending` / `submitted` / `graded` |
|
|
17
12
|
| `opencli chaoxing exams` | List exams across all courses |
|
|
18
|
-
| `opencli chaoxing exams --course "数学"` | Filter by course name |
|
|
19
|
-
| `opencli chaoxing exams --status upcoming` | Filter: `all` / `upcoming` / `ongoing` / `finished` |
|
|
20
|
-
|
|
21
|
-
## How It Works
|
|
22
|
-
|
|
23
|
-
Chaoxing has no flat API for listing assignments/exams. The adapter follows the same
|
|
24
|
-
flow a student would in the browser:
|
|
25
|
-
|
|
26
|
-
1. Establish session via the interaction page
|
|
27
|
-
2. Fetch enrolled course list (`backclazzdata` JSON API)
|
|
28
|
-
3. Enter each course via `stucoursemiddle` redirect (obtains session `enc`)
|
|
29
|
-
4. Click the 作业/考试 tab and capture the iframe URL
|
|
30
|
-
5. Navigate to that URL and parse the DOM
|
|
31
|
-
|
|
32
|
-
## Limitations
|
|
33
13
|
|
|
34
|
-
|
|
35
|
-
- Does not submit homework or exams
|
|
36
|
-
- If Chaoxing changes page structure, the DOM parser may need updates
|
|
14
|
+
Supports `--course` and `--status` filters. Requires Chrome logged into `i.chaoxing.com` with Browser Bridge extension installed.
|
|
@@ -1,44 +1,5 @@
|
|
|
1
|
-
# ChatGPT
|
|
1
|
+
# ChatGPT Adapter
|
|
2
2
|
|
|
3
|
-
Control the **ChatGPT macOS Desktop App**
|
|
3
|
+
Control the **ChatGPT macOS Desktop App** from the terminal via AppleScript or CDP.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The current built-in commands use native AppleScript automation — no extra launch flags needed.
|
|
8
|
-
|
|
9
|
-
### Prerequisites
|
|
10
|
-
1. Install the official [ChatGPT Desktop App](https://openai.com/chatgpt/mac/) from OpenAI.
|
|
11
|
-
2. Grant **Accessibility permissions** to your terminal app (Terminal / iTerm / Warp) in **System Settings → Privacy & Security → Accessibility**. This is required for System Events keystroke simulation.
|
|
12
|
-
|
|
13
|
-
### Commands
|
|
14
|
-
- `opencli chatgpt status`: Check if the ChatGPT app is currently running.
|
|
15
|
-
- `opencli chatgpt new`: Activate ChatGPT and press `Cmd+N` to start a new conversation.
|
|
16
|
-
- `opencli chatgpt send "message"`: Copy your message to clipboard, activate ChatGPT, paste, and submit.
|
|
17
|
-
- `opencli chatgpt read`: Copy the last AI response via `Cmd+Shift+C` and return it as text.
|
|
18
|
-
|
|
19
|
-
## Approach 2: CDP (Advanced, Electron Debug Mode)
|
|
20
|
-
|
|
21
|
-
ChatGPT Desktop is also an Electron app and can be launched with a remote debugging port for deeper automation via CDP:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
/Applications/ChatGPT.app/Contents/MacOS/ChatGPT \
|
|
25
|
-
--remote-debugging-port=9224
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Then set the endpoint:
|
|
29
|
-
```bash
|
|
30
|
-
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9224"
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
> **Note**: The CDP approach enables future advanced commands like DOM inspection, model switching, and code extraction — similar to the Cursor and Codex adapters.
|
|
34
|
-
|
|
35
|
-
## How It Works
|
|
36
|
-
|
|
37
|
-
- **AppleScript mode**: Uses `osascript` and `pbcopy`/`pbpaste` for clipboard-based text transfer. No remote debugging port needed.
|
|
38
|
-
- **CDP mode**: Connects via Chrome DevTools Protocol to the Electron renderer process for direct DOM manipulation.
|
|
39
|
-
|
|
40
|
-
## Limitations
|
|
41
|
-
|
|
42
|
-
- macOS only (AppleScript dependency)
|
|
43
|
-
- AppleScript mode requires Accessibility permissions
|
|
44
|
-
- `read` command copies the last response — earlier messages need manual scroll
|
|
5
|
+
📖 **Full documentation**: [docs/adapters/desktop/chatgpt](../../../docs/adapters/desktop/chatgpt.md)
|
|
@@ -1,38 +1,5 @@
|
|
|
1
|
-
# ChatWise Adapter
|
|
1
|
+
# ChatWise Adapter
|
|
2
2
|
|
|
3
|
-
Control the **ChatWise Desktop App**
|
|
3
|
+
Control the **ChatWise Desktop App** (multi-LLM client) from the terminal via CDP.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
1. Install [ChatWise](https://chatwise.app/).
|
|
8
|
-
2. Launch with remote debugging port:
|
|
9
|
-
```bash
|
|
10
|
-
/Applications/ChatWise.app/Contents/MacOS/ChatWise \
|
|
11
|
-
--remote-debugging-port=9228
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Setup
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9228"
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Commands
|
|
21
|
-
|
|
22
|
-
### Diagnostics
|
|
23
|
-
- `opencli chatwise status`: Check CDP connection status.
|
|
24
|
-
- `opencli chatwise screenshot`: Export DOM + accessibility snapshot.
|
|
25
|
-
|
|
26
|
-
### Chat
|
|
27
|
-
- `opencli chatwise new`: Start a new conversation (`Cmd+N`).
|
|
28
|
-
- `opencli chatwise send "message"`: Send a message to the active chat.
|
|
29
|
-
- `opencli chatwise read`: Read the current conversation.
|
|
30
|
-
- `opencli chatwise ask "prompt"`: Send + wait for response + return it (one-shot).
|
|
31
|
-
|
|
32
|
-
### AI Features
|
|
33
|
-
- `opencli chatwise model`: Get the current AI model.
|
|
34
|
-
- `opencli chatwise model gpt-4`: Switch to a different model.
|
|
35
|
-
|
|
36
|
-
### Organization
|
|
37
|
-
- `opencli chatwise history`: List conversations from the sidebar.
|
|
38
|
-
- `opencli chatwise export`: Export conversation as Markdown.
|
|
5
|
+
📖 **Full documentation**: [docs/adapters/desktop/chatwise](../../../docs/adapters/desktop/chatwise.md)
|
package/src/clis/codex/README.md
CHANGED
|
@@ -1,34 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Codex Adapter
|
|
2
2
|
|
|
3
|
-
Control the **OpenAI Codex Desktop App**
|
|
4
|
-
Because Codex is built on Electron, OpenCLI can directly drive its internal UI, automate slash commands, and manipulate its AI agent threads.
|
|
3
|
+
Control the **OpenAI Codex Desktop App** via Chrome DevTools Protocol (CDP).
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
1. You must have the official OpenAI Codex app installed.
|
|
9
|
-
2. Launch it via the terminal and expose the remote debugging port:
|
|
10
|
-
```bash
|
|
11
|
-
# macOS
|
|
12
|
-
/Applications/Codex.app/Contents/MacOS/Codex --remote-debugging-port=9222
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Setup
|
|
16
|
-
|
|
17
|
-
Export the CDP endpoint in your shell:
|
|
18
|
-
```bash
|
|
19
|
-
export OPENCLI_CODEX_CDP_ENDPOINT="http://127.0.0.1:9222"
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Commands
|
|
23
|
-
|
|
24
|
-
### Diagnostics
|
|
25
|
-
- `opencli codex status`: Checks connection and reads the current active window URL/title.
|
|
26
|
-
- `opencli codex dump`: Dumps the full UI DOM and Accessibility tree into `/tmp` (ideal for building AI automation tools on top of it).
|
|
27
|
-
|
|
28
|
-
### Agent Manipulation
|
|
29
|
-
- `opencli codex new`: Simulates `Cmd+N` to start a completely fresh and isolated Git Worktree thread context.
|
|
30
|
-
- `opencli codex send "message"`: Robustly finds the active Thread Composer and injects your text.
|
|
31
|
-
- *Pro-tip*: You can trigger internal shortcuts by sending them, e.g., `opencli codex send "/review"` or `opencli codex send "$imagegen draw a cat"`.
|
|
32
|
-
- `opencli codex read`: Extracts the entire current thread history and AI reasoning logs into readable text.
|
|
33
|
-
- `opencli codex extract-diff`: Automatically scrapes any visual Patch chunks and Code Diffs the AI generated inside the review UI.
|
|
34
|
-
- `opencli codex model`: Get the currently active AI model.
|
|
5
|
+
📖 **Full documentation**: [docs/adapters/desktop/codex](../../../docs/adapters/desktop/codex.md)
|
|
@@ -1,33 +1,5 @@
|
|
|
1
|
-
# Cursor Adapter
|
|
1
|
+
# Cursor Adapter
|
|
2
2
|
|
|
3
|
-
Control the **Cursor IDE** from the terminal via Chrome DevTools Protocol (CDP).
|
|
3
|
+
Control the **Cursor IDE** from the terminal via Chrome DevTools Protocol (CDP).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
1. Install [Cursor](https://cursor.sh/).
|
|
8
|
-
2. Launch it with the remote debugging port:
|
|
9
|
-
```bash
|
|
10
|
-
/Applications/Cursor.app/Contents/MacOS/Cursor --remote-debugging-port=9226
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Setup
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9226"
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Commands
|
|
20
|
-
|
|
21
|
-
### Diagnostics
|
|
22
|
-
- `opencli cursor status`: Check CDP connection status.
|
|
23
|
-
- `opencli cursor dump`: Dump the full DOM and Accessibility snapshot to `/tmp/cursor-dom.html` and `/tmp/cursor-snapshot.json`.
|
|
24
|
-
|
|
25
|
-
### Chat Manipulation
|
|
26
|
-
- `opencli cursor new`: Press `Cmd+N` to start a new file/tab.
|
|
27
|
-
- `opencli cursor send "message"`: Inject text into the active Composer/Chat input and submit.
|
|
28
|
-
- `opencli cursor read`: Extract the full conversation history from the active chat panel.
|
|
29
|
-
|
|
30
|
-
### AI Features
|
|
31
|
-
- `opencli cursor composer "prompt"`: Open the Composer panel (`Cmd+I`) and send a prompt for inline AI editing.
|
|
32
|
-
- `opencli cursor model`: Get the currently active AI model (e.g., `claude-4.5-sonnet`).
|
|
33
|
-
- `opencli cursor extract-code`: Extract all code blocks from the current conversation.
|
|
5
|
+
📖 **Full documentation**: [docs/adapters/desktop/cursor](../../../docs/adapters/desktop/cursor.md)
|
|
@@ -1,28 +1,5 @@
|
|
|
1
|
-
# Discord
|
|
1
|
+
# Discord Adapter
|
|
2
2
|
|
|
3
3
|
Control the **Discord Desktop App** from the terminal via Chrome DevTools Protocol (CDP).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Launch with remote debugging port:
|
|
8
|
-
```bash
|
|
9
|
-
/Applications/Discord.app/Contents/MacOS/Discord --remote-debugging-port=9232
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## Setup
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9232"
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Commands
|
|
19
|
-
|
|
20
|
-
| Command | Description |
|
|
21
|
-
|---------|-------------|
|
|
22
|
-
| `discord status` | Check CDP connection |
|
|
23
|
-
| `discord send "message"` | Send a message in the active channel |
|
|
24
|
-
| `discord read` | Read recent messages |
|
|
25
|
-
| `discord channels` | List channels in the current server |
|
|
26
|
-
| `discord servers` | List all joined servers |
|
|
27
|
-
| `discord search "query"` | Search messages (Cmd+F) |
|
|
28
|
-
| `discord members` | List online members |
|
|
5
|
+
📖 **Full documentation**: [docs/adapters/desktop/discord](../../../docs/adapters/desktop/discord.md)
|
|
@@ -1,20 +1,5 @@
|
|
|
1
|
-
# Feishu (飞书/Lark)
|
|
1
|
+
# Feishu (飞书/Lark) Adapter
|
|
2
2
|
|
|
3
3
|
Control **Feishu/Lark Desktop** from the terminal via AppleScript.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Prerequisites
|
|
8
|
-
|
|
9
|
-
1. Feishu/Lark must be running and logged in
|
|
10
|
-
2. Terminal must have **Accessibility permission**
|
|
11
|
-
|
|
12
|
-
## Commands
|
|
13
|
-
|
|
14
|
-
| Command | Description |
|
|
15
|
-
|---------|-------------|
|
|
16
|
-
| `feishu status` | Check if Feishu/Lark is running |
|
|
17
|
-
| `feishu send "msg"` | Send message in active chat (paste + Enter) |
|
|
18
|
-
| `feishu read` | Read current chat (Cmd+A → Cmd+C) |
|
|
19
|
-
| `feishu search "query"` | Global search (Cmd+K) |
|
|
20
|
-
| `feishu new` | New message/document (Cmd+N) |
|
|
5
|
+
📖 **Full documentation**: [docs/adapters/desktop/feishu](../../../docs/adapters/desktop/feishu.md)
|
|
@@ -1,31 +1,5 @@
|
|
|
1
|
-
# NeteaseMusic
|
|
1
|
+
# NeteaseMusic (网易云音乐) Adapter
|
|
2
2
|
|
|
3
|
-
Control **NeteaseMusic**
|
|
3
|
+
Control **NeteaseMusic** from the terminal via Chrome DevTools Protocol (CDP/CEF).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Launch with remote debugging port:
|
|
8
|
-
```bash
|
|
9
|
-
/Applications/NeteaseMusic.app/Contents/MacOS/NeteaseMusic --remote-debugging-port=9234
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## Setup
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9234"
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Commands
|
|
19
|
-
|
|
20
|
-
| Command | Description |
|
|
21
|
-
|---------|-------------|
|
|
22
|
-
| `neteasemusic status` | Check CDP connection |
|
|
23
|
-
| `neteasemusic playing` | Current song info (title, artist, album) |
|
|
24
|
-
| `neteasemusic play` | Play / Pause toggle |
|
|
25
|
-
| `neteasemusic next` | Skip to next song |
|
|
26
|
-
| `neteasemusic prev` | Go to previous song |
|
|
27
|
-
| `neteasemusic search "query"` | Search songs, artists |
|
|
28
|
-
| `neteasemusic playlist` | Show current playback queue |
|
|
29
|
-
| `neteasemusic like` | Like / unlike current song |
|
|
30
|
-
| `neteasemusic lyrics` | Get lyrics of current song |
|
|
31
|
-
| `neteasemusic volume [0-100]` | Get or set volume |
|
|
5
|
+
📖 **Full documentation**: [docs/adapters/desktop/neteasemusic](../../../docs/adapters/desktop/neteasemusic.md)
|
|
@@ -1,29 +1,5 @@
|
|
|
1
|
-
# Notion
|
|
1
|
+
# Notion Adapter
|
|
2
2
|
|
|
3
3
|
Control the **Notion Desktop App** from the terminal via Chrome DevTools Protocol (CDP).
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
| `notion status` | Check CDP connection |
|
|
23
|
-
| `notion search "query"` | Quick Find search (Cmd+P) |
|
|
24
|
-
| `notion read` | Read the current page content |
|
|
25
|
-
| `notion new "title"` | Create a new page (Cmd+N) |
|
|
26
|
-
| `notion write "text"` | Append text to the current page |
|
|
27
|
-
| `notion sidebar` | List pages from the sidebar |
|
|
28
|
-
| `notion favorites` | List pages from the Favorites section |
|
|
29
|
-
| `notion export` | Export page as Markdown |
|
|
5
|
+
📖 **Full documentation**: [docs/adapters/desktop/notion](../../../docs/adapters/desktop/notion.md)
|
|
@@ -1,28 +1,5 @@
|
|
|
1
|
-
# WeChat (微信)
|
|
1
|
+
# WeChat (微信) Adapter
|
|
2
2
|
|
|
3
3
|
Control **WeChat Mac Desktop** from the terminal via AppleScript + Accessibility API.
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
| `wechat status` | Check if WeChat is running |
|
|
17
|
-
| `wechat send "msg"` | Send message in the active chat (clipboard paste + Enter) |
|
|
18
|
-
| `wechat read` | Read current chat content (Cmd+A → Cmd+C) |
|
|
19
|
-
| `wechat search "keyword"` | Open search and type a query (Cmd+F) |
|
|
20
|
-
| `wechat chats` | Switch to Chats tab (Cmd+1) |
|
|
21
|
-
| `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
|
|
5
|
+
📖 **Full documentation**: [docs/adapters/desktop/wechat](../../../docs/adapters/desktop/wechat.md)
|
package/CDP.md
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
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.
|
package/CDP.zh-CN.md
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# 通过 CDP 远程连接 OpenCLI (服务器/无头环境)
|
|
2
|
-
|
|
3
|
-
如果你无法使用 opencli Browser Bridge 浏览器扩展(例如:在无界面的远程服务器上运行 OpenCLI 时),OpenCLI 提供了备选方案:通过连接 **CDP (Chrome DevTools Protocol,即 Chrome 开发者工具协议)** 来直接控制本地 Chrome。
|
|
4
|
-
|
|
5
|
-
出于安全考虑,CDP 默认仅绑定在 `localhost` 的本地端口。所以,若是想让**远程服务器**调用本地的 CDP 服务,我们需要依靠一层额外的网络隧道。
|
|
6
|
-
|
|
7
|
-
本指南将整个过程拆分为三个阶段:
|
|
8
|
-
1. **阶段一:准备工作**(在本地启动允许 CDP 调试的 Chrome)。
|
|
9
|
-
2. **阶段二:建立网络隧道**(通过 **SSH反向隧道** 或 **反向代理工具**,将本地的 CDP 端口暴露给服务器)。
|
|
10
|
-
3. **阶段三:执行命令**(在服务器端运行 OpenCLI)。
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## 阶段一:准备工作 (本地电脑)
|
|
15
|
-
|
|
16
|
-
首先,你需要在你的本地电脑上,通过命令行参数启动一个开启了远程调试端口的 Chrome 实例。
|
|
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
|
-
> **注意**:此处增加的 `--remote-allow-origins="*"` 参数对于较新版本的 Chrome 来说通常是[必需的],以允许来自反向代理(如 ngrok)的跨域 WebSocket 连接请求。
|
|
43
|
-
|
|
44
|
-
待这个新的浏览器实例打开后,**手工登录那些你打算使用的网站**(如 bilibili.com、zhihu.com 等),这可以让该浏览器的运行资料(Profile)保留上这些网站登录用的 Cookie。
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## 阶段二:建立网络隧道
|
|
49
|
-
|
|
50
|
-
现在你的本地已经有了一个监听在 `9222` 端口的 CDP 服务,接下来,选择以下任意一种方式将其实际暴露给你的远端服务器。
|
|
51
|
-
|
|
52
|
-
### 方法 A:SSH 反向端口转发 (推荐)
|
|
53
|
-
|
|
54
|
-
如果你的本地电脑可以直连远程服务器的 SSH,那么这是最简单且最安全的做法。
|
|
55
|
-
|
|
56
|
-
在你的 **本地电脑** 终端上直接运行这条 ssh 命令,将远程服务器的 `9222` 端口反向映射回本地的 `9222` 端口:
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
ssh -R 9222:localhost:9222 your-server-user@your-server-ip
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
保持此 SSH 会话在后台运行即可。
|
|
63
|
-
|
|
64
|
-
### 方法 B:反向代理 / 内网穿透 (ngrok / frp / socat)
|
|
65
|
-
|
|
66
|
-
如果因为 NAT 或防火墙等因素导致无法直连 SSH 服务器,你可以使用 `ngrok` 等内网穿透工具。
|
|
67
|
-
|
|
68
|
-
在 **本地电脑** 运行 ngrok 将本地的 `9222` 端口暴露到公网:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
ngrok http 9222
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
此时终端里会打印出一段专属的转发 URL 地址(如:`https://abcdef.ngrok.app`)。**复制这一段 URL 地址备用**。
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
## 阶段三:执行命令 (远程服务器)
|
|
79
|
-
|
|
80
|
-
现在,所有的准备工作已结束。请切换到你已安装好 OpenCLI 的 **远程服务器** 终端上。
|
|
81
|
-
|
|
82
|
-
根据你在上方阶段二所选择的隧道方案,在终端中配置对应的 `OPENCLI_CDP_ENDPOINT` 环境变量:
|
|
83
|
-
|
|
84
|
-
### 若使用 方法 A (SSH 反向隧道):
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
export OPENCLI_CDP_ENDPOINT="http://localhost:9222"
|
|
88
|
-
opencli doctor # 查看并验证连接是否通畅
|
|
89
|
-
opencli bilibili hot --limit 5 # 执行目标命令
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### 若使用 方法 B (Ngrok 等反向代理):
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
# 将刚刚使用 ngrok 得到的地址填入这里
|
|
96
|
-
export OPENCLI_CDP_ENDPOINT="https://abcdef.ngrok.app"
|
|
97
|
-
opencli doctor # 查看并验证连接是否通畅
|
|
98
|
-
opencli bilibili hot --limit 5 # 执行目标命令
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
> *Tip: 如果你填写的是一个普通 HTTP/HTTPS 的 CDP 地址,OpenCLI 会自动请求 `/json` target 列表,并挑选最可能的 app/page target;如果同一个端口下暴露了多个应用 target,还可以通过 `OPENCLI_CDP_TARGET`(例如 `antigravity`、`codex`)进一步缩小匹配范围。*
|
|
102
|
-
|
|
103
|
-
如果你想在此服务器上永久启用该配置,可以将对应的 `export` 语句追加进入你的 `~/.bashrc` 或 `~/.zshrc` 配置文件中。
|
package/CLI-ELECTRON.md
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
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 |
|