|
| 1 | +# ADE Desktop |
| 2 | + |
| 3 | +Electron client for ADE. The renderer is also runnable in a regular browser for fast UI iteration. |
| 4 | + |
| 5 | +## Surfaces |
| 6 | + |
| 7 | +| Surface | Command | `window.ade` source | Backend | |
| 8 | +|--------|---------|---------------------|---------| |
| 9 | +| **Desktop dev** | `npm run dev` (repo root) | Electron preload → main IPC → runtime socket | Full | |
| 10 | +| **Browser preview (mock)** | `npm run dev:vite` | `browserMock.ts` only | Synthetic demo data | |
| 11 | +| **Browser preview (live)** | `npm run dev:vite:live` | Mock + runtime bridge patches | Partial live (see below) | |
| 12 | + |
| 13 | +`apps/web` is the public marketing site. This document covers the **desktop renderer in a browser** (`localhost:5173`), not the marketing app. |
| 14 | + |
| 15 | +## How the browser preview works |
| 16 | + |
| 17 | +Opening `http://localhost:5173` without Electron loads the same React renderer as the desktop app, but there is no preload bridge. On startup: |
| 18 | + |
| 19 | +1. **`browserMock.ts`** (imported first in `main.tsx`) installs a full `window.ade` stub so the UI can render without crashing. It returns built-in demo data for PRs, lanes, sessions, git, and so on. |
| 20 | +2. **`attachBrowserRuntimeBridge()`** (called at the end of the mock install) probes `GET /ade-dev-rpc/health`. If the browser runtime bridge is running, it **patches** selected methods on top of the mock and dispatches `ade:runtime-bridge-ready`. |
| 21 | + |
| 22 | +```text |
| 23 | +Browser tab |
| 24 | + └─ window.ade (mock baseline) |
| 25 | + └─ patched methods → fetch /ade-dev-rpc/* |
| 26 | + └─ Vite proxy |
| 27 | + └─ browser-runtime-bridge.mjs (127.0.0.1:18765) |
| 28 | + └─ JSON-RPC → /tmp/ade-runtime-dev.sock |
| 29 | + └─ ade serve (same daemon as desktop dev) |
| 30 | +``` |
| 31 | + |
| 32 | +The mock stays the fallback for everything the bridge does not override. UI work that only reads mock data still works with `dev:vite` alone. |
| 33 | + |
| 34 | +## Launch |
| 35 | + |
| 36 | +### Mock-only (fast UI shell) |
| 37 | + |
| 38 | +From `apps/desktop`: |
| 39 | + |
| 40 | +```bash |
| 41 | +npm run dev:vite |
| 42 | +``` |
| 43 | + |
| 44 | +Optional: export SQLite snapshot so lanes, PRs, sessions, and run-tab config mirror a real project: |
| 45 | + |
| 46 | +```bash |
| 47 | +ADE_PROJECT_ROOT=/path/to/your/project npm run export:browser-mock-ade |
| 48 | +npm run dev:vite |
| 49 | +``` |
| 50 | + |
| 51 | +The export runs automatically (best-effort) before `dev:vite` via `predev:vite`. Output: |
| 52 | + |
| 53 | +`src/renderer/browser-mock-ade-snapshot.generated.json` |
| 54 | + |
| 55 | +That file is gitignored. It seeds **read-only** mock data from `.ade/ade.db` at export time. It does **not** include secrets (Linear tokens, API keys). |
| 56 | + |
| 57 | +### Live bridge (real Linear, sync, lanes) |
| 58 | + |
| 59 | +From `apps/desktop`: |
| 60 | + |
| 61 | +```bash |
| 62 | +ADE_PROJECT_ROOT=/path/to/your/project npm run dev:vite:live |
| 63 | +``` |
| 64 | + |
| 65 | +This script: |
| 66 | + |
| 67 | +1. Builds/refreshes the ADE CLI runtime if needed |
| 68 | +2. Ensures the dev runtime is listening on `/tmp/ade-runtime-dev.sock` (override with `ADE_DEV_RUNTIME_SOCKET_PATH`) |
| 69 | +3. Starts `browser-runtime-bridge.mjs` on `127.0.0.1:18765` (`ADE_BROWSER_BRIDGE_PORT` to override) |
| 70 | +4. Starts Vite on port 5173 with a proxy from `/ade-dev-rpc` → the bridge |
| 71 | + |
| 72 | +Open `http://localhost:5173` (or `http://127.0.0.1:5173`). |
| 73 | + |
| 74 | +**Lane worktrees:** if you run from `.ade/worktrees/<lane>`, set `ADE_PROJECT_ROOT` to the primary project checkout (where `.ade/ade.db` and secrets live), not the worktree path. Same rule as `npm run dev`. |
| 75 | + |
| 76 | +Skip runtime rebuild when the CLI is already fresh: |
| 77 | + |
| 78 | +```bash |
| 79 | +ADE_PROJECT_ROOT=/path/to/your/project npm run dev:vite:live -- --skip-runtime-build |
| 80 | +``` |
| 81 | + |
| 82 | +Bridge only (Vite already running): |
| 83 | + |
| 84 | +```bash |
| 85 | +ADE_PROJECT_ROOT=/path/to/your/project npm run dev:browser-bridge |
| 86 | +``` |
| 87 | + |
| 88 | +Verify the bridge: |
| 89 | + |
| 90 | +```bash |
| 91 | +curl -s http://127.0.0.1:18765/health | jq . |
| 92 | +``` |
| 93 | + |
| 94 | +## What the live bridge covers today |
| 95 | + |
| 96 | +When the bridge attaches, these `window.ade` methods call the real runtime instead of the mock: |
| 97 | + |
| 98 | +| Area | Methods | |
| 99 | +|------|---------| |
| 100 | +| **Project** | `app.getProject`, `app.getWindowSession` — real `projectRoot` / `projectId` from `projects.add` | |
| 101 | +| **Linear** | `cto.getLinearConnectionStatus`, `getLinearQuickView`, `getLinearIssuePickerData`, `searchLinearIssues`, `getLinearProjects`, `setLinearToken`, `clearLinearToken` | |
| 102 | +| **Sync / mobile** | `sync.getStatus`, `refreshDiscovery`, `listDevices`, `updateLocalDevice`, `connectToBrain`, `disconnectFromBrain`, `forgetDevice`, `getTransferReadiness`, `transferBrainToLocal`, `getPin`, `setPin`, `generatePin`, `clearPin` | |
| 103 | +| **Lanes** | `lanes.create`, `lanes.list` (e.g. Linear quick view → create lane) | |
| 104 | + |
| 105 | +Linear must already be connected in that project (Settings → Linear, or token in encrypted store under `.ade/secrets`). The bridge uses the same credentials as desktop dev. |
| 106 | + |
| 107 | +## Still mock-only in the browser |
| 108 | + |
| 109 | +Even with `dev:vite:live`, these stay on the mock until wired to the bridge or another backend: |
| 110 | + |
| 111 | +- Terminals / PTY / live chat sessions |
| 112 | +- PR list/detail/actions, git read/write, files on disk |
| 113 | +- Remote runtime connection UI (Electron IPC) |
| 114 | +- Computer use, App Control, iOS simulator, Mac VM |
| 115 | +- Agent chat send/receive, orchestration runs |
| 116 | +- Most settings persistence beyond Linear token via bridge |
| 117 | + |
| 118 | +For full product behavior, use **`npm run dev`** (Electron + preload). |
| 119 | + |
| 120 | +## Seeding mock data |
| 121 | + |
| 122 | +Three layers, from lightest to richest: |
| 123 | + |
| 124 | +1. **Built-in demo** — no setup; synthetic lanes, PRs, sessions in `browserMock.ts`. |
| 125 | +2. **Snapshot export** — `npm run export:browser-mock-ade` with `ADE_PROJECT_ROOT` set; replaces demo rows with data from `.ade/ade.db` and optional disk walks for the Files tab. |
| 126 | +3. **Live bridge** — real runtime for Linear, sync, and lane create/list; mock still backs everything else unless you also export a snapshot for read-only parity. |
| 127 | + |
| 128 | +Re-export the snapshot after local DB changes you want reflected in mock-only mode: |
| 129 | + |
| 130 | +```bash |
| 131 | +ADE_PROJECT_ROOT=/path/to/your/project npm run export:browser-mock-ade |
| 132 | +``` |
| 133 | + |
| 134 | +## Environment variables |
| 135 | + |
| 136 | +| Variable | Purpose | |
| 137 | +|----------|---------| |
| 138 | +| `ADE_PROJECT_ROOT` | Project opened by the bridge and snapshot export (primary checkout, not lane worktree) | |
| 139 | +| `ADE_DEV_RUNTIME_SOCKET_PATH` | Dev runtime socket (default `/tmp/ade-runtime-dev.sock`) | |
| 140 | +| `ADE_BROWSER_BRIDGE_PORT` | Bridge HTTP port (default `18765`) | |
| 141 | + |
| 142 | +## Related files |
| 143 | + |
| 144 | +| File | Role | |
| 145 | +|------|------| |
| 146 | +| `src/renderer/browserMock.ts` | Full `window.ade` stub for browser | |
| 147 | +| `src/renderer/browserRuntimeBridge.ts` | Patches live methods when bridge is up | |
| 148 | +| `scripts/browser-runtime-bridge.mjs` | HTTP → runtime JSON-RPC | |
| 149 | +| `scripts/dev-vite-live.mjs` | Orchestrates runtime + bridge + Vite | |
| 150 | +| `scripts/export-browser-mock-ade-snapshot.mjs` | SQLite → mock snapshot JSON | |
| 151 | +| `vite.config.ts` | Proxies `/ade-dev-rpc` to the bridge | |
| 152 | + |
| 153 | +## Validation |
| 154 | + |
| 155 | +```bash |
| 156 | +npm run typecheck |
| 157 | +npm run test:unit -- src/renderer/components/app/TopBar.test.tsx |
| 158 | +``` |
0 commit comments