packages/builtin-skills/src/verify/surfaces/electron.md
Use this surface for desktop-only behavior — native windows, IPC / main-process
code, tray/menu, auto-update, OS integration, or a packaged-only path. That code
doesn't exist in a plain web page, so web.md can't prove it. You drive
the running app's renderer over CDP with agent-browser
(../references/agent-browser.md).
For a change that behaves identically in a browser, prefer web.md — it's lighter and cloud-portable. Use Electron only when the criterion calls out the desktop shell.
agent-browser --cdp 9222 snapshot -i
agent-browser --cdp 9222 get url # sanity-check you attached to the app
agent-browser --cdp 9222 screenshot ./proof/desktop-state.png
If the app exposes a global state handle, eval it to assert behavior (discover the actual global name from the app — don't assume one):
agent-browser --cdp 9222 eval --stdin << 'EVALEOF'
(function () {
// example shape — replace with the app's real global / selectors
var s = window.__APP_STATE__ && window.__APP_STATE__();
return JSON.stringify({ route: location.hash || location.pathname, ready: !!s });
})()
EVALEOF
# install an interceptor before exercising the feature
agent-browser --cdp 9222 eval --stdin << 'EVALEOF'
(function () {
window.__ERRORS__ = [];
var orig = console.error;
console.error = function () {
window.__ERRORS__.push(Array.from(arguments).map(String).join(' '));
orig.apply(console, arguments);
};
return 'installed';
})()
EVALEOF
# ... drive the feature ...
agent-browser --cdp 9222 eval "JSON.stringify(window.__ERRORS__)" # → text evidence
Dev builds often auto-open DevTools, which hijacks the CDP target. Symptom:
get url returns a devtools://… URL instead of the app. Fix: close the
DevTools target and reconnect:
DT_ID=$(curl -s http://localhost:9222/json/list | python3 -c "import json,sys; ts=json.load(sys.stdin); print(next(t['id'] for t in ts if t['type']=='page' and t['url'].startswith('devtools://')))")
curl -s "http://localhost:9222/json/close/$DT_ID" > /dev/null
agent-browser close --all && agent-browser --cdp 9222 get url
Clean up all processes when done. pkill -f "Electron" only kills the main
process; helper processes (GPU, renderer, network) survive. Prefer the app's own
stop command or kill by the project's electron binary path.
Don't resize the window after load — many apps trigger a full reload on resize, invalidating refs and state.
Electron runs on Linux but has no true headless mode — it needs a display server.
In a headless/cloud environment, wrap the launch with xvfb-run (virtual
framebuffer). Everything CDP-based keeps working under Xvfb (connection, snapshots,
eval, agent-browser screenshot — captured from the renderer, not the OS screen).
What does NOT work: OS-window capture (screencapture), osascript, and native
screen recording — all macOS-only. Keep evidence CDP-based to stay cloud-portable
(see ../references/evidence.md).