.agents/skills/agent-browser-electron/SKILL.md
Inspect Electron renderer windows reliably when agent-browser alone is not enough to tell which CDP target maps to which visible app window.
Prefer raw CDP target discovery over guessing from tab list, then use agent-browser --cdp <port> tab stable tab IDs to interact with the renderer target you want.
Use raw CDP target discovery because agent-browser is operating as a convenience layer on top of Chrome DevTools Protocol, and that layer can hide or flatten details that matter in Electron.
Raw /json/list is the source of truth for CDP target discovery because it exposes Chromium's target inventory without extra interpretation. It is not the same thing as Electron's BrowserWindow.getAllWindows().
In Electron, that distinction matters because:
BrowserWindow instances can share the same URLagent-browser tab list may show only a subset of targets or present them with reduced metadataagent-browser can keep you attached to a previous renderer unless you reset and verifyIn practice, the higher-level tab list view is useful for quick browsing, but not reliable enough for window-to-target mapping when:
http://localhost:5173/#/Use curl http://127.0.0.1:<port>/json/list first whenever correct target selection matters. Treat agent-browser as the interaction client after target discovery, not as the only discovery source.
If /json/list does not contain a window that the user says exists, do not assume agent-browser hid it. First consider that the window may not have been created yet, may not have loaded a renderer route yet, or may not currently be exposed as a CDP target. Trigger the window from the app UI or Electron main-process action, then enumerate /json/list again.
The CDP port is project- and run-command-specific. Do not assume 9222, 9250, or any other value is universal. If an Electron process is running but no CDP port responds, tell the user to relaunch the app with the project's remote-debug environment variables or launch flags.
For AIRI stage-tamagotchi on POSIX shells:
APP_REMOTE_DEBUG=true APP_REMOTE_DEBUG_PORT=9250 pnpm dev:tamagotchi
For Windows PowerShell:
$env:APP_REMOTE_DEBUG = "true"
$env:APP_REMOTE_DEBUG_PORT = "9250"
pnpm dev:tamagotchi
For Windows Git Bash:
APP_REMOTE_DEBUG=true APP_REMOTE_DEBUG_PORT=9250 pnpm dev:tamagotchi
Adjust the port to match what the user actually started. If the project uses a different mechanism, inspect its Electron launch code before giving command advice.
If the app uses lazy window creation, agent-browser cannot inspect a window that has not been created yet. Open it from the app UI or trigger its Electron-side open handler first.
agent-browser --cdp <port> tab.curl -sS http://127.0.0.1:<port>/json/list
Read these fields:
titleurltypewebSocketDebuggerUrlUse /json/version if you need to confirm the port is a Chromium/Electron CDP endpoint or need the browser-level debugger URL:
curl -sS http://127.0.0.1:<port>/json/version
Common patterns:
http://localhost:5173/#/chat while the main window is http://localhost:5173/#/.http://localhost:5173/#/; in that case use screenshots, snapshots, and Electron app knowledge to disambiguate.agent-browser and switch with stable tab IDs.agent-browser --cdp <port> tab
agent-browser --cdp <port> tab t2
Do not use positional integers. If agent-browser tab prints [t2], switch with tab t2.
agent-browser --cdp <port> get url
agent-browser --cdp <port> get title
agent-browser --cdp <port> snapshot -i
agent-browser close --all
agent-browser connect <webSocketDebuggerUrl>
agent-browser get url
If needed:
agent-browser --cdp <port> screenshot /tmp/electron-target.png --annotate
agent-browser --cdp <port> console
agent-browser --cdp <port> errors
Use this order when the Electron app has multiple windows:
curl /json/listworker targets unless the task is specifically about workersDevTools page targets unless debugging DevTools itselfagent-browser --cdp <port> tabagent-browser --cdp <port> tab t3agent-browser --cdp <port> get urlagent-browser --cdp <port> snapshot -iIn apps/stage-tamagotchi, some windows are lazy-created. The main window loads /#/; settings loads /#/settings; chat loads /#/chat; BeatSync loads /beat-sync.html.
The 9250 examples below assume the app was started by the person running it with:
APP_REMOTE_DEBUG=true APP_REMOTE_DEBUG_PORT=9250 pnpm dev:tamagotchi
That port is not intrinsic to AIRI or Electron. It depends on the current command and environment. Most stage-tamagotchi code lives under apps/stage-tamagotchi; inspect that app's Electron startup and window code when the port, routes, or remote-debug behavior differ.
Relevant files:
apps/stage-tamagotchi/src/main/windows/chat/index.tsapps/stage-tamagotchi/src/main/windows/main/index.tsapps/stage-tamagotchi/src/main/libs/electron/window-manager/reusable.tsapps/stage-tamagotchi/src/renderer/components/stage-islands/controls-island/index.vueThat means:
chatWindow()http://localhost:5173/#/settings and http://localhost:5173/#/chatagent-browser stable tab IDs, switch, and verify with get urlExample:
curl -sS http://127.0.0.1:9250/json/list
agent-browser --cdp 9250 tab
agent-browser --cdp 9250 tab t4
agent-browser --cdp 9250 get url
agent-browser --cdp 9250 snapshot -i
If settings or chat is missing, start from the main window:
agent-browser --cdp 9250 tab t2
agent-browser --cdp 9250 snapshot -i
# Click the main window control that opens the panel or launcher.
# In AIRI this is the arrow-up control in the bottom-right controls island.
# Re-snapshot after every click because refs are stale after UI changes.
agent-browser --cdp 9250 click '[i-solar\:alt-arrow-up-line-duotone]'
agent-browser --cdp 9250 snapshot -i
Then open the desired entry from the expanded controls and enumerate again:
agent-browser --cdp 9250 click '[i-solar\:settings-minimalistic-outline]'
agent-browser --cdp 9250 click '[i-solar\:chat-line-line-duotone]'
curl -sS http://127.0.0.1:9250/json/list
agent-browser --cdp 9250 tab
If the controls island is visible but the accessibility refs or CSS icon click do not expand it, inspect the Vue component as a diagnostic fallback. AIRI currently nests tooltip trigger buttons around icon buttons, so a CDP click can report success while landing on the wrapper instead of the Vue ControlButton listener. This fallback is for automation/debugging only; do not use it as evidence that end-user clicking works.
agent-browser --cdp 9250 eval '(() => {
const icon = document.querySelector("[i-solar\\:alt-arrow-up-line-duotone]")
let controls = icon.__vueParentComponent
for (let i = 0; i < 10; i++) controls = controls.parent
controls.devtoolsRawSetupState.expanded.value = true
controls.proxy.$nextTick()
return controls.devtoolsRawSetupState.expanded.value
})()'
Expected verification for chat:
agent-browser --cdp 9250 get url returns http://localhost:5173/#/chatExpected verification for settings:
agent-browser --cdp 9250 get url returns http://localhost:5173/#/settingsagent-browser tab omits or flattens the target you need: use raw /json/list./json/list and browser-level target discovery both omit the window: the renderer target is not currently exposed. Trigger the window creation/loading path, then enumerate again.connect <webSocketDebuggerUrl> appears to succeed but later commands still point at another renderer: switch with agent-browser --cdp <port> tab tN, or run agent-browser close --all, reconnect, and verify with get url.eval returns {} for object values: prefer get url, get title, snapshot -i, or primitive-only eval return values.