electron-app-cli.md
1 # 给新 Electron 应用生成 CLI 2 3 这篇文档是把一个新的 Electron 桌面应用接入 OpenCLI 的**中文入口指南**。 4 5 如果你需要更完整的背景和标准流程,继续看: 6 - [Chrome DevTools Protocol(中文)](/zh/advanced/cdp) 7 - [CLI-ifying Electron Applications(英文深度版)](/advanced/electron) 8 - [TypeScript 适配器开发指南(英文)](/developer/ts-adapter) 9 10 ## 这篇文档适合什么场景 11 12 当目标应用满足下面条件时,用这套流程: 13 - 应用是 **Electron**,或者至少能暴露可用的 **CDP(Chrome DevTools Protocol)** 端口 14 - 可以通过 `--remote-debugging-port=<port>` 启动 15 - 你希望控制的是桌面应用本身,而不是它背后的公开 HTTP API 16 17 如果应用**不是** Electron,或者不暴露 CDP,就不要硬套这套方案。那种情况应改用原生桌面自动化方案。可参考 [英文版说明](/advanced/electron#non-electron-pattern-applescript)。 18 19 ## 最短落地路径 20 21 ### 1. 先确认它是不是 Electron 22 23 macOS 下常见检查方式: 24 25 ```bash 26 ls /Applications/AppName.app/Contents/Frameworks/Electron\ Framework.framework 27 ``` 28 29 如果存在,通常就可以继续尝试 CDP。 30 31 ### 2. 带 CDP 端口启动应用 32 33 ```bash 34 /Applications/AppName.app/Contents/MacOS/AppName --remote-debugging-port=9222 35 ``` 36 37 然后把 OpenCLI 指到这个端口: 38 39 ```bash 40 export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9222" 41 ``` 42 43 ### 3. 先做 5 个基础命令 44 45 建议一个新 Electron 适配器先实现这 5 个命令: 46 47 - `status.ts` —— 确认 CDP 连通 48 - `dump.ts` —— 导出 DOM / snapshot,先做逆向再写逻辑 49 - `read.ts` —— 读取当前上下文 50 - `send.ts` —— 往真实编辑器里输入并发送 51 - `new.ts` —— 新建会话 / 标签页 / 文档 52 53 这是最稳妥的基线,因为它先把“能连上、能看见、能读、能写、能重置状态”这 5 件核心事情打通了。 54 55 ## 推荐开发顺序 56 57 ### 第一步:先做 `status` 58 59 目标不是功能,而是先证明: 60 - CDP 真的连上了 61 - 你连到的是对的窗口/标签页 62 - 应用当前页面确实可读 63 64 如果 `status` 都不稳定,先不要继续往下做。 65 66 ### 第二步:做 `dump` 67 68 **不要猜 selector。** 69 70 先把这些导出来: 71 - `document.body.innerHTML` 72 - accessibility snapshot 73 - 稳定属性:`data-testid`、`role`、`aria-*` 等 74 75 然后再决定: 76 - 消息列表在哪 77 - 输入框在哪 78 - 按钮在哪 79 - 当前会话容器在哪 80 81 ### 第三步:做 `read` 82 83 只读真正需要的区域,不要把整个页面文本都塞出来。 84 85 常见目标: 86 - 对话消息区 87 - 当前线程内容 88 - 当前编辑器历史 89 - 当前文档主区域 90 91 ### 第四步:做 `send` 92 93 很多 Electron 应用的输入框是 React 控制组件,直接改 `.value` 往往没用。 94 95 更稳妥的方式通常是: 96 - 先 focus 到可编辑区域 97 - 能用时优先 `document.execCommand('insertText', false, text)` 98 - 最后用真实按键提交,比如 `Enter`、`Meta+Enter` 99 100 ### 第五步:做 `new` 101 102 很多桌面应用的新建动作其实更适合走快捷键,而不是点按钮。 103 104 典型模式: 105 106 ```ts 107 const isMac = process.platform === 'darwin'; 108 await page.pressKey(isMac ? 'Meta+N' : 'Control+N'); 109 await page.wait(1); 110 ``` 111 112 ## 文件一般怎么放 113 114 一个 TypeScript 桌面适配器,通常结构是: 115 116 ```text 117 clis/<app>/status.ts 118 clis/<app>/dump.ts 119 clis/<app>/read.ts 120 clis/<app>/send.ts 121 clis/<app>/new.ts 122 clis/<app>/utils.ts 123 ``` 124 125 当基础能力稳定后,再继续加: 126 - `ask` 127 - `history` 128 - `model` 129 - `screenshot` 130 - `export` 131 132 ## 加完适配器后,还应该补什么文档 133 134 至少补这几项: 135 - `docs/adapters/desktop/` 下的适配器说明页 136 - 命令列表和示例 137 - 如何带 `--remote-debugging-port` 启动 138 - 需要哪些环境变量 139 - 平台限制和注意事项 140 141 可以参考这些现成文档: 142 - `docs/adapters/desktop/codex.md` 143 - `docs/adapters/desktop/chatwise.md` 144 - `docs/adapters/desktop/notion.md` 145 - `docs/adapters/desktop/discord.md` 146 147 ## 常见问题 148 149 ### CDP 能连,但命令不稳定 150 151 常见原因: 152 - 连错窗口或标签页 153 - 页面还没渲染完 154 - selector 是猜的,不是从 `dump` 里找出来的 155 - 输入框是受控组件,直接赋值不生效 156 157 ### 应用看起来像 Chromium,但就是不好控 158 159 有些桌面应用虽然嵌了 Chromium,但并不真正暴露可用的 CDP 接口。 160 这种情况不要强行走 Electron 方案,应该换到非 Electron 的桌面自动化方案。 161 162 ### 这个应用其实也有网页版本,还要不要做 Electron 适配器 163 164 如果网页版本已经足够稳定,浏览器适配器通常更简单。 165 只有当**桌面应用才是真正的集成面**时,再优先做 Electron 适配器。 166 167 ## 推荐阅读顺序 168 169 如果你从零开始: 170 171 1. 先看这篇 172 2. 再看 [CLI-ifying Electron Applications(英文深度版)](/advanced/electron) 173 3. 再看 [Chrome DevTools Protocol(中文)](/zh/advanced/cdp) 174 4. 再看 [TypeScript Adapter Guide(英文)](/developer/ts-adapter) 175 5. 最后找一个现成桌面适配器文档照着做 176 177 ## 最后一个实践建议 178 179 不要一上来就做很大的命令面。 180 181 先把下面 5 个做稳: 182 - `status` 183 - `dump` 184 - `read` 185 - `send` 186 - `new` 187 188 这 5 个稳定了,再往外扩,成本最低,返工也最少。