Files
jackwener__opencli/docs/zh/guide/electron-app-cli.md
jakevin 29c135b656 refactor(notion): replace built-in CDP adapter with external ntn CLI (#1559)
* refactor(notion): replace built-in CDP adapter with external ntn CLI

Notion has shipped an official CLI at https://ntn.dev. It uses the
public Notion API (blocks / databases / properties / comments) instead
of reverse-engineering the Desktop UI, so it survives Notion app
updates and exposes a wider command surface than the in-tree adapter
could.

Changes:
  - `src/external-clis.yaml` — register `ntn` as first-class external CLI
    (binary `ntn`, homepage ntn.dev, install via the shell-pipe script
    on mac/linux)
  - `clis/notion/` — entire directory removed (8 commands: status /
    search / read / new / write / sidebar / favorites / export)
  - `docs/adapters/desktop/notion.md` — removed
  - `docs/.vitepress/config.mts` — drop nav entry
  - `docs/adapters/index.md` — drop adapter row
  - `README.md` / `README.zh-CN.md` — drop notion from feature lines,
    drop adapter table row, add `ntn` to CLI hub examples
  - `docs/index.md` / `docs/zh/index.md` / `docs/guide/getting-started.md`
    — drop notion from electron-control feature copy
  - `skills/opencli-usage/SKILL.md` — drop notion from electron list
  - `cli-manifest.json` — rebuilt with --allow-removals=8

Migration for users:
  `curl -fsSL https://ntn.dev | bash`  (or `opencli external install ntn`)
  Then use `opencli ntn <command>` in place of `opencli notion <command>`.

Rationale: the in-tree adapter was reverse-engineered against Notion
Desktop CDP and shipped only 8 commands. The official CLI gives users
the full Notion API surface and reduces our maintenance burden to zero.
Same pattern as gh / obsidian / lark-cli / tg-cli / discord-cli / wx-cli.

Verification:
  - `npx tsc --noEmit` clean
  - `npx vitest run --project unit` → 1091/1 skipped
  - `npm run build` (with --allow-removals=8) — manifest 809 entries
  - grep notion in user-facing docs (README / docs / skills) — only
    descriptive mentions remain in non-blocking places (comparison /
    site-recon / electron how-to / design doc), no broken adapter
    references

* fix(notion): align ntn external migration

* docs(notion): clarify ntn manual install
2026-05-14 16:12:17 +08:00

5.1 KiB
Raw Permalink Blame History

给新 Electron 应用生成 CLI

这篇文档是把一个新的 Electron 桌面应用接入 OpenCLI 的中文入口指南

如果你需要更完整的背景和标准流程,继续看:

这篇文档适合什么场景

当目标应用满足下面条件时,用这套流程:

  • 应用是 Electron,或者至少能暴露可用的 CDPChrome DevTools Protocol 端口
  • 可以通过 --remote-debugging-port=<port> 启动
  • 你希望控制的是桌面应用本身,而不是它背后的公开 HTTP API

如果应用不是 Electron或者不暴露 CDP就不要硬套这套方案。那种情况应改用原生桌面自动化方案。可参考 英文版说明

最短落地路径

1. 先确认它是不是 Electron

macOS 下常见检查方式:

ls /Applications/AppName.app/Contents/Frameworks/Electron\ Framework.framework

如果存在,通常就可以继续尝试 CDP。

2. 带 CDP 端口启动应用

/Applications/AppName.app/Contents/MacOS/AppName --remote-debugging-port=9222

然后把 OpenCLI 指到这个端口:

export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:9222"

3. 先做 5 个基础命令

建议一个新 Electron 适配器先实现这 5 个命令:

  • status.ts —— 确认 CDP 连通
  • dump.ts —— 导出 DOM / snapshot先做逆向再写逻辑
  • read.ts —— 读取当前上下文
  • send.ts —— 往真实编辑器里输入并发送
  • new.ts —— 新建会话 / 标签页 / 文档

这是最稳妥的基线,因为它先把“能连上、能看见、能读、能写、能重置状态”这 5 件核心事情打通了。

推荐开发顺序

第一步:先做 status

目标不是功能,而是先证明:

  • CDP 真的连上了
  • 你连到的是对的窗口/标签页
  • 应用当前页面确实可读

如果 status 都不稳定,先不要继续往下做。

第二步:做 dump

不要猜 selector。

先把这些导出来:

  • document.body.innerHTML
  • accessibility snapshot
  • 稳定属性:data-testidrolearia-*

然后再决定:

  • 消息列表在哪
  • 输入框在哪
  • 按钮在哪
  • 当前会话容器在哪

第三步:做 read

只读真正需要的区域,不要把整个页面文本都塞出来。

常见目标:

  • 对话消息区
  • 当前线程内容
  • 当前编辑器历史
  • 当前文档主区域

第四步:做 send

很多 Electron 应用的输入框是 React 控制组件,直接改 .value 往往没用。

更稳妥的方式通常是:

  • 先 focus 到可编辑区域
  • 能用时优先 document.execCommand('insertText', false, text)
  • 最后用真实按键提交,比如 EnterMeta+Enter

第五步:做 new

很多桌面应用的新建动作其实更适合走快捷键,而不是点按钮。

典型模式:

const isMac = process.platform === 'darwin';
await page.pressKey(isMac ? 'Meta+N' : 'Control+N');
await page.wait(1);

文件一般怎么放

一个 TypeScript 桌面适配器,通常结构是:

clis/<app>/status.ts
clis/<app>/dump.ts
clis/<app>/read.ts
clis/<app>/send.ts
clis/<app>/new.ts
clis/<app>/utils.ts

当基础能力稳定后,再继续加:

  • ask
  • history
  • model
  • screenshot
  • export

加完适配器后,还应该补什么文档

至少补这几项:

  • docs/adapters/desktop/ 下的适配器说明页
  • 命令列表和示例
  • 如何带 --remote-debugging-port 启动
  • 需要哪些环境变量
  • 平台限制和注意事项

可以参考这些现成文档:

  • docs/adapters/desktop/codex.md
  • docs/adapters/desktop/chatwise.md
  • docs/adapters/desktop/discord.md

常见问题

CDP 能连,但命令不稳定

常见原因:

  • 连错窗口或标签页
  • 页面还没渲染完
  • selector 是猜的,不是从 dump 里找出来的
  • 输入框是受控组件,直接赋值不生效

应用看起来像 Chromium但就是不好控

有些桌面应用虽然嵌了 Chromium但并不真正暴露可用的 CDP 接口。 这种情况不要强行走 Electron 方案,应该换到非 Electron 的桌面自动化方案。

这个应用其实也有网页版本,还要不要做 Electron 适配器

如果网页版本已经足够稳定,浏览器适配器通常更简单。 只有当桌面应用才是真正的集成面时,再优先做 Electron 适配器。

推荐阅读顺序

如果你从零开始:

  1. 先看这篇
  2. 再看 CLI-ifying Electron Applications英文深度版
  3. 再看 Chrome DevTools Protocol中文
  4. 再看 TypeScript Adapter Guide英文
  5. 最后找一个现成桌面适配器文档照着做

最后一个实践建议

不要一上来就做很大的命令面。

先把下面 5 个做稳:

  • status
  • dump
  • read
  • send
  • new

这 5 个稳定了,再往外扩,成本最低,返工也最少。