/debug-ui
Drive and visually QA the dev-3.0 UI in a real browser (headless Chromium via agent-browser). Use when verifying a UI/UX change, reproducing a visual bug, taking screenshots of the running app, or self-QA before review. Triggers — "check the UI", "screenshot the app", "does this
Claude Code
$ npx -y skills add h0x91b/dev-3.0 --skill debug-ui --agent claude-code
Codex
$ npx skills add h0x91b/dev-3.0 --skill debug-ui -a codex -y
Cursor
$ npx skills add h0x91b/dev-3.0 --skill debug-ui -a cursor -y
Gemini CLI
$ npx skills add h0x91b/dev-3.0 --skill debug-ui -a gemini-cli -y
GitHub Copilot
$ npx skills add h0x91b/dev-3.0 --skill debug-ui -a github-copilot -y
OpenCode
$ npx skills add h0x91b/dev-3.0 --skill debug-ui -a opencode -y
Windsurf
$ npx skills add h0x91b/dev-3.0 --skill debug-ui -a windsurf -y
SKILL.md
debug-ui.SKILL.mdname: debug-ui
description: Drive and visually QA the dev-3.0 UI in a real browser (headless Chromium via agent-browser). Use when verifying a UI/UX change, reproducing a visual bug, taking screenshots of the running app, or self-QA before review. Triggers — "check the UI", "screenshot the app", "does this render", "QA this screen", "verify the UI change in a browser", "drive the app".
debug-ui — QA the dev-3.0 UI in a real browser
See and drive the running dev-3.0 UI in headless Chromium — click, type, screenshot, read console errors — instead of guessing whether a UI change works. No desktop/native dependency; it works the same in a plain terminal session.
This is **dev-internal tooling for the dev-3.0 repo** — NOT one of the skills dev3 ships to its users (those live in `src/bun/agent-skills.ts`).
Prerequisite: `agent-browser` on PATH
Check with `agent-browser --version`. If it is missing, install it once per machine, not in the project `setupScript` (that runs for every new worktree):
bun add -g agent-browser # or: npm i -g agent-browser
agent-browser install # downloads Chromium; on Linux add --with-deps for system libraries (needs sudo)
One rule before the flow: the app starts through `dev3 dev-server`, nothing else
Every QA run in this skill boots the app with `dev3 dev-server start` and takes it down with `dev3 dev-server stop`. **Never start the app any other way** — not a bare `bun run dev`, not `bun run dev --qa`, and not `dev3 pane run "bun run dev …"`. A pane run looks like a shortcut and costs you everything the dev-server owns: the port wait (`--wait`), `status` with its port conflicts, a verified stop that frees `DEV3_PORT0`, the Dev Server button in the task UI that shows the user what is running, and the `show-image` / `attention` routing rules below. If you need the app to behave differently (a throwaway board, an env flag), change what the dev-server runs — see "Scoped QA" — do not route around it.
The whole flow
This task's dev-server **is** the web UI: `bun run dev` serves the full app in local remote mode at a stable per-machine token and a CLI-derivable port — no separate `dev3 remote`. The loop is always the same four beats: **values → server → browser → clean up.**
# 1. Values. AGENT_BROWSER_SESSION isolates THIS task's browser from every other agent's —
# without it all agents share one global "default" session and stomp each other (see
# Gotchas). Derived from the always-present $DEV3_TASK_ID, so this exact line is
# copy-paste-safe at the top of ANY block that calls agent-browser.
export AGENT_BROWSER_SESSION="dev3-${DEV3_TASK_ID%%-*}"
CODE=$(cat "$HOME/.dev3.0/dev-web-access-code" 2>/dev/null || bun scripts/dev-web-code.ts)
PORT=${DEV3_PORT0:-$(dev3 dev-server status | grep -oE 'DEV3_PORT0=[0-9]+' | cut -d= -f2)}
# 2. Start a FRESH dev-server and wait for it to come up. (Skip the start only if one is
# already running for THIS task — but see the build-snapshot gotcha: stale code needs a
# restart, so when in doubt restart.)
dev3 dev-server start
until curl -sf "http://localhost:$PORT/?token=$CODE" >/dev/null; do sleep 2; done
# 3. Drive it. Every agent-browser call inherits AGENT_BROWSER_SESSION, so it all runs in
# this task's own session. (Load /agent-browser for the full command set.) The screenshot
# path is task-scoped too, so parallel agents never overwrite each other's PNG.
# `&streamer=on` is MANDATORY: it enables streamer mode (privacy masking), so screenshots
# can't leak the developer's real emails/accounts/paths/tunnel URLs (see Gotchas).
# Keep `set viewport` BEFORE `open`, and keep the width ≥ 1024 for desktop QA — the app's
# mobile gate reads `screen.width` (see Gotchas).
agent-browser set viewport 1440 900
agent-browser open "http://localhost:$PORT/?token=$CODE&streamer=on"
agent-browser wait --load networkidle
sleep 2 # networkidle can still land mid-render — let it settle
agent-browser snapshot -i -d 6 # prove it's DRIVABLE, not just screenshot-able
agent-browser screenshot "/tmp/dev3-ui-${DEV3_TASK_ID%%-*}.png" # then Read it back to look
agent-browser errors # confirm no console errors
# 4. Always clean up what you started. `close` closes only THIS session's browser.
agent-browser close
dev3 dev-server stop # the port frees a second or two later (graceful shutdown)That's it. `DEV3_REMOTE_PORT=${DEV3_PORT0:-0}` is wired into the repo's `dev` script and `portCount: 1` is committed in `.dev3/config.json`, so the dev app binds the exact port shown above (see [decision 093](../../../decisions/2026/06/30/dev-remote-port-from-pool.md)).
Linux without a display: the dev-server goes headless
On Linux with no `DISPLAY`/`WAYLAND_DISPLAY`, or without `libwebkit2gtk-4.1` (WSL without WSLg, SSH, containers), the desktop window cannot open. `bun run dev` detects that and serves the same UI through `dev3 remote`, run from source, on the same port and access code. The flow above does not change: `agent-browser` only ever talked to the web server. The pane prints `[dev] headless (<reason>)` when this happens.
- **Headless defaults to the scoped `seeded` board**, because the real `~/.dev3.0` usually
belongs to an installed `dev3 remote` on the same machine. `--env DEV3_QA_SCOPE=0` opts back into the real board.
- **Headless on request** where the window could open:
`dev3 dev-server start --wait --env DEV3_DEV_HEADLESS=1`.
- **What it cannot show:** the native window, the application menu and OS notifications.
Everything rendered in the page is the same code.
Scoped QA: a throwaway board instead of the real one
`dev3 dev-server start` boots a full dev3 instance on **your real board** — another task's "Branch Merged — mark completed?" dialog is live and clickable in your browser, and another task's terminal is reachable by navigation. It stays t
Read more
name: debug-ui description: Drive and visually QA the dev-3.0 UI in a real browser (headless Chromium via agent-browser). Use when verifying a UI/UX change, reproducing a visual bug, taking screenshots of the running app, or self-QA before review. Triggers — "check the UI", "screenshot the app", "does this render", "QA this screen", "verify the UI change in a browser", "drive the app".
debug-ui — QA the dev-3.0 UI in a real browser
See and drive the running dev-3.0 UI in headless Chromium — click, type, screenshot, read console errors — instead of guessing whether a UI change works. No desktop/native dependency; it works the same in a plain terminal session.
This is **dev-internal tooling for the dev-3.0 repo** — NOT one of the skills dev3 ships to its users (those live in `src/bun/agent-skills.ts`).
Prerequisite: `agent-browser` on PATH
Check with `agent-browser --version`. If it is missing, install it once per machine, not in the project `setupScript` (that runs for every new worktree):
bun add -g agent-browser # or: npm i -g agent-browser agent-browser install # downloads Chromium; on Linux add --with-deps for system libraries (needs sudo)
One rule before the flow: the app starts through `dev3 dev-server`, nothing else
Every QA run in this skill boots the app with `dev3 dev-server start` and takes it down with `dev3 dev-server stop`. **Never start the app any other way** — not a bare `bun run dev`, not `bun run dev --qa`, and not `dev3 pane run "bun run dev …"`. A pane run looks like a shortcut and costs you everything the dev-server owns: the port wait (`--wait`), `status` with its port conflicts, a verified stop that frees `DEV3_PORT0`, the Dev Server button in the task UI that shows the user what is running, and the `show-image` / `attention` routing rules below. If you need the app to behave differently (a throwaway board, an env flag), change what the dev-server runs — see "Scoped QA" — do not route around it.
The whole flow
This task's dev-server **is** the web UI: `bun run dev` serves the full app in local remote mode at a stable per-machine token and a CLI-derivable port — no separate `dev3 remote`. The loop is always the same four beats: **values → server → browser → clean up.**
# 1. Values. AGENT_BROWSER_SESSION isolates THIS task's browser from every other agent's —
# without it all agents share one global "default" session and stomp each other (see
# Gotchas). Derived from the always-present $DEV3_TASK_ID, so this exact line is
# copy-paste-safe at the top of ANY block that calls agent-browser.
export AGENT_BROWSER_SESSION="dev3-${DEV3_TASK_ID%%-*}"
CODE=$(cat "$HOME/.dev3.0/dev-web-access-code" 2>/dev/null || bun scripts/dev-web-code.ts)
PORT=${DEV3_PORT0:-$(dev3 dev-server status | grep -oE 'DEV3_PORT0=[0-9]+' | cut -d= -f2)}
# 2. Start a FRESH dev-server and wait for it to come up. (Skip the start only if one is
# already running for THIS task — but see the build-snapshot gotcha: stale code needs a
# restart, so when in doubt restart.)
dev3 dev-server start
until curl -sf "http://localhost:$PORT/?token=$CODE" >/dev/null; do sleep 2; done
# 3. Drive it. Every agent-browser call inherits AGENT_BROWSER_SESSION, so it all runs in
# this task's own session. (Load /agent-browser for the full command set.) The screenshot
# path is task-scoped too, so parallel agents never overwrite each other's PNG.
# `&streamer=on` is MANDATORY: it enables streamer mode (privacy masking), so screenshots
# can't leak the developer's real emails/accounts/paths/tunnel URLs (see Gotchas).
# Keep `set viewport` BEFORE `open`, and keep the width ≥ 1024 for desktop QA — the app's
# mobile gate reads `screen.width` (see Gotchas).
agent-browser set viewport 1440 900
agent-browser open "http://localhost:$PORT/?token=$CODE&streamer=on"
agent-browser wait --load networkidle
sleep 2 # networkidle can still land mid-render — let it settle
agent-browser snapshot -i -d 6 # prove it's DRIVABLE, not just screenshot-able
agent-browser screenshot "/tmp/dev3-ui-${DEV3_TASK_ID%%-*}.png" # then Read it back to look
agent-browser errors # confirm no console errors
# 4. Always clean up what you started. `close` closes only THIS session's browser.
agent-browser close
dev3 dev-server stop # the port frees a second or two later (graceful shutdown)That's it. `DEV3_REMOTE_PORT=${DEV3_PORT0:-0}` is wired into the repo's `dev` script and `portCount: 1` is committed in `.dev3/config.json`, so the dev app binds the exact port shown above (see [decision 093](../../../decisions/2026/06/30/dev-remote-port-from-pool.md)).
Linux without a display: the dev-server goes headless
On Linux with no `DISPLAY`/`WAYLAND_DISPLAY`, or without `libwebkit2gtk-4.1` (WSL without WSLg, SSH, containers), the desktop window cannot open. `bun run dev` detects that and serves the same UI through `dev3 remote`, run from source, on the same port and access code. The flow above does not change: `agent-browser` only ever talked to the web server. The pane prints `[dev] headless (<reason>)` when this happens.
- **Headless defaults to the scoped `seeded` board**, because the real `~/.dev3.0` usually
belongs to an installed `dev3 remote` on the same machine. `--env DEV3_QA_SCOPE=0` opts back into the real board.
- **Headless on request** where the window could open:
`dev3 dev-server start --wait --env DEV3_DEV_HEADLESS=1`.
- **What it cannot show:** the native window, the application menu and OS notifications.
Everything rendered in the page is the same code.
Scoped QA: a throwaway board instead of the real one
`dev3 dev-server start` boots a full dev3 instance on **your real board** — another task's "Branch Merged — mark completed?" dialog is live and clickable in your browser, and another task's terminal is reachable by navigation. It stays t
Mission control for the One Person Studio — run a fleet of AI coding agents in parallel without losing your mind. Kanban + git worktrees + tmux for Claude Code, Codex, Gemini CLI, OpenCode and any shell agent. Not an IDE.
Other skills on dev-30.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about debug-ui.
- Which coding agents can use debug-ui?
- debug-ui installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

