---
name: gui-bug-reproduction
description: Use when the user wants to reproduce a GUI bug, asks about clicking, screenshots, "show me what the app looks like", interacting with a window, or testing a hypothesis by driving the UI. Covers two distinct modes — demo-and-record (user demonstrates, you replay) vs autonomous reproduction (you drive the UI yourself based on a hypothesis or documented steps).
---

# Reproducing GUI bugs with rdbg

rdbg gives you both *passive* (capture, observe) and *active*
(inject) tools. There are two clearly distinct workflows and
choosing between them deliberately matters.

## Workflow A — Demo-and-record (steps unclear)

When the user can't articulate the steps to reproduce, ask them
to demonstrate while the daemon records:

```
spy(action="start")
```

Tell the user: *"The debugger is recording your input. Please
reproduce the bug now, then tell me when you're done."* Wait for
the user to respond.

```
spy(action="stop")
```

The `spy_status` and the captured `input` events (drained via
`events(filter=["input"])`) carry mouse and keyboard events with
`hwnd`, `class`, `title`, and — crucially — `vcl_path`,
`vcl_class`, `vcl_instance`. Each `vcl_instance` is a Delphi
object address you can `inspect_object` to learn the control's
type, name, caption, and event handlers.

Replay the captured trace via `send_input` (raw HID) for
byte-perfect reproduction, or via `send_keys` + `click_at` for
a more structured replay.

## Workflow B — Autonomous reproduction (hypothesis or docs)

When the user provides steps or you have a hypothesis from
reading the source:

1. `list_windows` to find the target's top-level windows.
2. `find_vcl_for_hwnd(hwnd)` on the main window to bootstrap
   into the VCL tree (or `get_main_form` for the canonical
   main form directly).
3. `enumerate_vcl_tree(root=<form_addr>, max_depth=5)` to learn
   what controls exist and their handler symbols.
4. Drive the UI:
   - Buttons: `click_at(hwnd=<button_hwnd>)`.
   - Text fields: `set_text_field(hwnd=<edit_hwnd>, text="...")`
     — instant, no focus-loss races, much faster than
     `send_keys` for long input.
   - Menus: `click_at` on the menu item's HWND.
5. After **every** action, `capture_window(hwnd=<form_hwnd>)`
   to verify visible state matches what you expect.

If a step doesn't produce the expected state, **stop**. Capture
the screenshot, capture registers if you're paused, and replan
from there. Do not blindly repeat — you've discovered something.

## When to switch modes

If autonomous reproduction fails twice on the same step (e.g.
the click "lands" but the expected dialog doesn't appear), fall
back to demo-and-record. The user's hands likely do something
subtle you missed (timing, modifier keys, an intermediate
hover-over-then-click).

## Always pair injection with capture

```
click_at(hwnd=12345)
capture_window(hwnd=12345)   # confirm result
events(timeout_ms=500)       # drain any handler that fired
```

Skipping the capture/events drain after injection is the most
common reason fuzzing flows wedge — the handler may have raised
an exception or shown a modal dialog you didn't see.

## Modal dialogs and unexpected popups

`capture_window` only captures the HWND you ask for. A
`MessageBox` or modal dialog has its own HWND that you don't
know about ahead of time. After any input that *might* trigger
one:

```
screenshot_desktop(max_dimension=1024)
```

Catches everything visible on the desktop. Look for
unexpected windows, then `list_windows` to find their HWND and
deal with them (`click_at` on OK, or `post_message` with
`WM_CLOSE`).

## Blank screenshots

If `capture_window` returns a uniform-color PNG, the daemon
isn't seeing real pixels. Run `/rdbg:status` — the daemon is
probably in Session 0. The fix is to relaunch Claude Code from
inside your interactive RDP desktop; the plugin will spawn the
daemon in the right session.

## Hard rules for autonomous mode

- **Never click "Close", "Quit", "Exit", "Logout", "Delete",
  "Format", "Drop"** without confirming with the user first.
  These are usually destructive.
- **Never type into a field whose label or `Name` contains
  "password", "key", or "secret"** — fuzzing those leaks nothing
  useful and may lock real accounts.
- **Cap actions at ~50 per session** unless the user lifts the
  budget. Long autonomous loops can wedge the target.
