drive-desktop-applisted
Install: claude install-skill reticlehq/reticle
# Drive a desktop app and prove what happened
A desktop app reaches its backend over **IPC, not HTTP**. Patching `fetch`/`XHR` cannot see that, so a browser-shaped tool is blind to every backend call the app makes: the network log reads empty, an action has no in-flight request to settle on, and asserting on the network is vacuously true. That is a false green by construction.
**Reticle** observes the renderer _and_ the IPC boundary, so a desktop verdict means what a web one does. Not installed? `RETICLE_INSTALL_SOURCE=npx_skill npx @reticlehq/server@latest init`, then the [`install-and-verify`](https://github.com/reticlehq/reticle/blob/main/skills/install-and-verify/SKILL.md) skill.
## Electron: two lines, none in your app code
```ts
// vite.config.ts — desktop:true also runs the plugin for `vite build`, because a packaged
// renderer is a production build with no dev server
export default defineConfig({
base: './', // file:// needs relative asset paths
plugins: [react(), reticle({ desktop: true })],
});
```
```js
// electron/preload.cjs — FIRST line. This is what makes main-process IPC visible.
require('@reticlehq/electron/preload');
```
It **must** be in the preload and it must be first. `contextBridge.exposeInMainWorld` hands the renderer a deeply frozen object, so nothing in the page can instrument it afterwards. The preload is the last point where `ipcRenderer.invoke` is still writable, and the shim has to run before your preload captures its own reference.
A