9b395f5cc3
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
Build Chrome Extension / build (push) Has been cancelled
Trigger Website Rebuild (Docs Updated) / dispatch (push) Has been cancelled
200 lines
5.5 KiB
Markdown
200 lines
5.5 KiB
Markdown
---
|
|
description: How to turn a new Electron desktop app into an OpenCLI adapter
|
|
---
|
|
|
|
# Add a New Electron App CLI
|
|
|
|
This guide is the **fast entry point** for turning a new Electron desktop application into an OpenCLI adapter.
|
|
|
|
If you want the full background and deeper SOP, read:
|
|
- [CLI-ifying Electron Applications](/advanced/electron)
|
|
- [Chrome DevTools Protocol](/advanced/cdp)
|
|
- [TypeScript Adapter Guide](/developer/ts-adapter)
|
|
|
|
## When to use this guide
|
|
|
|
Use this workflow when the target app:
|
|
- is built with **Electron**, or at least exposes a working **Chrome DevTools Protocol (CDP)** endpoint
|
|
- can be launched with `--remote-debugging-port=<port>`
|
|
- should be automated through its real UI instead of a public HTTP API
|
|
|
|
If the app is **not** Electron and does **not** expose CDP, use the native desktop automation pattern instead. See [CLI-ifying Electron Applications](/advanced/electron#non-electron-pattern-applescript).
|
|
|
|
## The shortest path
|
|
|
|
### 1. Confirm the app is Electron
|
|
|
|
Typical macOS check:
|
|
|
|
```bash
|
|
ls /Applications/AppName.app/Contents/Frameworks/Electron\ Framework.framework
|
|
```
|
|
|
|
If Electron is present, the next step is usually to launch the app with a debugging port.
|
|
|
|
### 2. Launch it with CDP enabled
|
|
|
|
```bash
|
|
/Applications/AppName.app/Contents/MacOS/AppName --remote-debugging-port=<unique-port>
|
|
```
|
|
|
|
Then point OpenCLI at that CDP endpoint:
|
|
|
|
```bash
|
|
export OPENCLI_CDP_ENDPOINT="http://127.0.0.1:<unique-port>"
|
|
```
|
|
|
|
### 3. Start with the 5-command pattern
|
|
|
|
For a new Electron adapter, implement these commands first in `clis/<app>/`:
|
|
|
|
- `status.js` — verify the app is reachable through CDP
|
|
- `dump.js` — inspect DOM and snapshot structure before guessing selectors
|
|
- `read.js` — extract the visible context you actually need
|
|
- `send.js` — inject text and submit through the real editor
|
|
- `new.js` — create a new session, tab, thread, or document
|
|
|
|
This is the standard baseline because it gives you:
|
|
- a connection check
|
|
- a reverse-engineering tool
|
|
- one read path
|
|
- one write path
|
|
- one session reset path
|
|
|
|
The full rationale and examples are in [CLI-ifying Electron Applications](/advanced/electron).
|
|
|
|
## Recommended implementation workflow
|
|
|
|
### Step 1: Build `status`
|
|
|
|
Goal: prove CDP connectivity before touching app-specific logic.
|
|
|
|
Typical checks:
|
|
- current URL
|
|
- document title
|
|
- app shell presence
|
|
|
|
If `status` is unstable, stop there and fix connectivity first.
|
|
|
|
### Step 2: Build `dump`
|
|
|
|
Do **not** guess selectors from the rendered UI.
|
|
|
|
Dump:
|
|
- `document.body.innerHTML`
|
|
- accessibility snapshot
|
|
- any stable attributes such as `data-testid`, `role`, `aria-*`, framework-specific markers
|
|
|
|
Use the dump to identify real containers, buttons, composers, and conversation regions.
|
|
|
|
### Step 3: Build `read`
|
|
|
|
Target only the app region that matters.
|
|
|
|
Good targets:
|
|
- message list
|
|
- editor history
|
|
- visible thread content
|
|
- selected document panel
|
|
|
|
Avoid dumping the entire page text into the final command output.
|
|
|
|
### Step 4: Build `send`
|
|
|
|
Most Electron apps use React-style controlled editors, so direct `.value = ...` assignments are often ignored.
|
|
|
|
Prefer editor-aware input patterns such as:
|
|
- focus the editable region
|
|
- use `document.execCommand('insertText', false, text)` when applicable
|
|
- use real key presses like `Enter`, `Meta+Enter`, or app-specific shortcuts
|
|
|
|
### Step 5: Build `new`
|
|
|
|
Many desktop apps rely on keyboard shortcuts for “new chat”, “new tab”, or “new note”.
|
|
|
|
Typical pattern:
|
|
|
|
```ts
|
|
const isMac = process.platform === 'darwin';
|
|
await page.pressKey(isMac ? 'Meta+N' : 'Control+N');
|
|
await page.wait(1);
|
|
```
|
|
|
|
## Where to put files
|
|
|
|
For a desktop adapter, the usual layout is:
|
|
|
|
```text
|
|
clis/<app>/status.js
|
|
clis/<app>/dump.js
|
|
clis/<app>/read.js
|
|
clis/<app>/send.js
|
|
clis/<app>/new.js
|
|
clis/<app>/utils.js
|
|
```
|
|
|
|
If the app grows beyond the baseline, add higher-level commands such as:
|
|
- `ask`
|
|
- `history`
|
|
- `model`
|
|
- `screenshot`
|
|
- `export`
|
|
|
|
## What to document when you add a new app
|
|
|
|
When the adapter is ready, also add:
|
|
|
|
- an adapter doc under `docs/adapters/desktop/`
|
|
- command list and examples
|
|
- launch instructions with `--remote-debugging-port`
|
|
- any required environment variables
|
|
- platform-specific caveats
|
|
|
|
Examples to study:
|
|
- `docs/adapters/desktop/codex.md`
|
|
- `docs/adapters/desktop/chatwise.md`
|
|
- `docs/adapters/desktop/discord.md`
|
|
|
|
## Common failure modes
|
|
|
|
### CDP endpoint exists, but commands are flaky
|
|
|
|
Usually one of these:
|
|
- the wrong window/tab is selected
|
|
- the app has not finished rendering
|
|
- selectors were guessed instead of discovered from `dump`
|
|
- the editor is controlled and ignores direct value assignment
|
|
|
|
### The app is Chromium-based but not truly controllable
|
|
|
|
Some desktop apps embed Chromium but do not expose a usable CDP surface.
|
|
In that case, switch to the non-Electron desktop automation approach instead of forcing the Electron pattern.
|
|
|
|
### You already have a browser workflow and wonder whether to reuse it
|
|
|
|
If the app exposes a normal web URL and the browser flow is enough, a browser adapter is usually simpler.
|
|
Use an Electron adapter only when the desktop app is the real integration surface.
|
|
|
|
## Recommended reading order
|
|
|
|
If you are starting from zero:
|
|
|
|
1. This page
|
|
2. [CLI-ifying Electron Applications](/advanced/electron)
|
|
3. [Chrome DevTools Protocol](/advanced/cdp)
|
|
4. [TypeScript Adapter Guide](/developer/ts-adapter)
|
|
5. One concrete desktop adapter doc under `docs/adapters/desktop/`
|
|
|
|
## Practical rule
|
|
|
|
Do not start with a large feature surface.
|
|
|
|
Start with:
|
|
- `status`
|
|
- `dump`
|
|
- `read`
|
|
- `send`
|
|
- `new`
|
|
|
|
Once those are stable, extend outward.
|