# rdbg-debugger — Claude Code plugin

Drive the [rdbg](https://sundaymorning.app/rdbg/) Delphi remote
debugger from Claude Code. Set breakpoints, step, inspect VCL objects
through RTTI, capture window screenshots, simulate keyboard/mouse
input, and let an autonomous bug-hunter agent reproduce crashes
without human babysitting.

**Scope (v1):** local Windows debugging only. Claude Code runs on
Windows in the same interactive desktop as the daemon (typically
your RDP session). The plugin drives both `rdbgd64.exe` (Win64
targets) and `rdbgd32.exe` (Win32 targets) — the bridge picks the
right one per `launch` based on the target's PE machine type.
SSH-to-remote-Windows is a v2 feature.

---

## Prerequisites

1. **Windows 10+ x64** with Claude Code installed.
2. **rdbg 0.2 or later.** Earlier releases don't ship `rdbg-mcp.exe`.
   Download from [sundaymorning.app/rdbg/](https://sundaymorning.app/rdbg/assets/dl/)
   and unzip somewhere short and space-free, e.g. `C:\rdbg\`.
3. **Claude Code launched from inside your interactive RDP desktop**
   (Session 2+). The daemon needs DirectDraw / GDI from a real
   logged-in session; the plugin pre-checks this and refuses to
   auto-spawn from Session 0.

---

## Install

In Claude Code:

```
/plugin marketplace add https://sundaymorning.app/rdbg/.claude-plugin/marketplace.json
/plugin install rdbg-debugger@rdbg
```

Claude Code clones the plugin from
`https://sundaymorning.app/rdbg/rdbg-plugin.git` (a static-file
git mirror — no GitHub account or auth required) and prompts you
for configuration on first enable.

Defaults assume `C:\rdbg\bin\` for `rdbg-mcp.exe`, `rdbgd64.exe`,
and `rdbgd32.exe`. If you unzipped rdbg somewhere else, set
`rdbg_mcp_path`, `daemon_path_x64`, and `daemon_path_x86`
accordingly (use no-spaces paths). If you only debug one bitness,
leave the unused `daemon_path_*` blank — the bridge surfaces a
clear error if a launch needs a daemon you haven't configured.

That's it. Run `/rdbg:status` to confirm everything's connected.

**Updating.** Re-run `/plugin marketplace update rdbg` to pull a
new version published to the same git mirror.

**Manual download.** A versioned zip is published alongside the
git mirror at
[`assets/dl/rdbg-claude-plugin-latest.zip`](https://sundaymorning.app/rdbg/assets/dl/rdbg-claude-plugin-latest.zip)
for offline inspection / archival; Claude Code itself won't
install from a zip.

---

## What you get

### Tools (Claude calls these directly)

| Group | Tools |
|---|---|
| Process | `hello`, `status`, `list_processes`, `launch`, `attach`, `shutdown_daemon` |
| Sessions | `list_sessions`, `bind_session`, `release_session` |
| Control | `interrupt`, `detach`, `kill_session` |
| Stepping | `continue`, `step_over`, `step_into`, `run_to`, `set_rip` |
| Breakpoints | `set_breakpoint` (source / symbol / address), `clear_breakpoint`, `list_breakpoints` |
| Inspection | `get_registers`, `read` (memory / string / dyn_array), `get_self`, `inspect_object`, `inspect_locals`, `evaluate` |
| VCL | `get_main_form`, `find_vcl_for_hwnd`, `enumerate_vcl_tree` |
| GUI | `list_windows`, `capture_window`, `screenshot_desktop`, `post_message`, `send_keys`, `set_text_field`, `click_at`, `send_input` |
| Recording | `spy` (start / stop / status) |
| Exceptions | `set_exception_filter` |
| Events | `events` (with optional `filter:[]`) |

### Skills (auto-load when context matches)

- **`delphi-debugging-workflow`** — primary skill. The
  attach/launch/break/step/`events` rhythm.
- **`exception-triage`** — first-chance vs second-chance, frame
  walking, exception-object inspection.
- **`gui-bug-reproduction`** — demo-and-record vs autonomous
  reproduction.
- **`delphi-rtti-inspection`** — walking Delphi objects through
  RTTI without source.
- **`vcl-self-discovery`** — build a model of an unfamiliar VCL
  app's UI tree from RTTI alone, then drive it to find crashes.

### Subagent

- **`delphi-bug-hunter`** — autonomous bug-investigation agent.
  Give it a one-line bug report; it figures out reproduction,
  catches the exception, walks the stack, and returns a `.pas:line`
  diagnosis.

### Slash commands

- `/rdbg:status` — daemon connectivity + session diagnostics.
- `/rdbg:start-daemon` — instructions for launching the daemon
  manually (with `--allow-send-input` / `--enable-spy` flag tips).
- `/rdbg:install-help` — this README, surfaced in chat.

---

## Two daemons, one bridge

rdbg ships two daemons from one source graph:

| Binary         | Targets       | Conv. port | Spawn helper          |
|----------------|---------------|------------|-----------------------|
| `rdbgd64.exe`  | Win64 (PE32+) | 5902       | `spawn-daemon.cmd`    |
| `rdbgd32.exe`  | Win32 (PE32)  | 5903       | `spawn-daemon32.cmd`  |

The wire protocol is identical between the two; `hello` reports
`target_arch: "x64" | "x86"` and `daemon: "rdbgd64" | "rdbgd32"`.
WoW64 cross-bitness debug is **not** supported — pick the daemon
that matches your target.

You don't have to pick manually. The MCP bridge:

1. Connects to the `default_target_bitness` daemon at startup
   (defaults to `x64`).
2. On every `launch` tool call, peeks the target's PE machine
   type (file is local on the same Windows host as the daemon).
3. If the target's bitness disagrees with the connected daemon,
   disconnects, spawns the matching daemon (when
   `auto_start_daemon=true` and the matching `daemon_path_*`
   is configured), and reconnects on the new port.
4. Caches `daemon` + `target_arch` from `hello` so subsequent
   tool calls don't re-probe.

For `attach`, the daemon itself fail-fasts with a structured
`wrong_arch` error if you point a daemon at a process of the
wrong bitness — Claude sees the error and switches accordingly
on the next attempt.

## How the daemon stays alive across Claude restarts

With `auto_start_daemon=true`, both daemons are spawned
**detached** (`DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP |
CREATE_BREAKAWAY_FROM_JOB`) so they outlive the MCP server.
Closing Claude Code, reloading the plugin, or starting a new
session all leave the daemons running; the next MCP server
instance reconnects to whichever one is appropriate for the
next `launch`.

If you'd rather control the daemons yourself, set
`auto_start_daemon=false` and start them from
`/rdbg:start-daemon`'s instructions.

---

## Common workflows

### Diagnose a specific crash

> *"crashy.exe segfaults right after I click the button"*

The `delphi-bug-hunter` subagent will:
1. `launch` or `attach` to `crashy.exe`.
2. Set `kernelbase!RaiseException` as a catch-all exception BP.
3. Either drive the click via `click_at` (if a hypothesis is
   available) or ask you to demonstrate while `spy(start)`
   records.
4. On the resulting `exception` event, walk frames to the first
   `.pas:line` user-code frame and report the diagnosis.

### Find any crash in an unfamiliar app

> *"find any crash in inputtest.exe"*

The same subagent in self-discovery mode will:
1. `attach`, then `get_main_form` + `enumerate_vcl_tree` to map
   the UI in two round trips.
2. Set `set_exception_filter(first_chance=false)` to drop noise.
3. Walk the tree breadth-first, injecting nasty input via
   `set_text_field` (long strings, edge unicode, format-string
   characters, etc.) and `click_at`.
4. Surface the first input sequence that produces an exception.

### Inspect what's in a Delphi variable

The `delphi-rtti-inspection` skill auto-loads when you ask "what
is in this object". Claude reaches for `get_self` (when paused at
a method) or `inspect_object` (given an address) to walk
published properties + fields, then `read(kind=string)` to
materialize Delphi strings at addresses it discovers.

---

## Troubleshooting

**`/rdbg:status` shows the daemon as Session 0** — `capture_window`
will return blank pixels. The daemon must run inside your
interactive RDP desktop. If `rdbg-mcp.exe` was somehow spawned
from a non-interactive context, restart Claude Code from the RDP
desktop directly.

**`/mcp` shows `rdbg` red with "file not found"** — check
`rdbg_mcp_path` in the plugin config. Use the path browser; the
default `C:\rdbg\bin\rdbg-mcp.exe` requires you to have unzipped
rdbg to `C:\rdbg\`.

**Daemon already busy with another client** — `rdbgd64` serves
one client at a time. Close `rdbgui.exe` or any `rdbgc repl`
session first.

**`send_input` / `spy` returns "feature not enabled"** — the
daemon needs `--allow-send-input` and/or `--enable-spy` flags.
Either edit `daemon_args` in the plugin config (auto-spawn case)
or relaunch the daemon manually with those flags.

---

## Development

The plugin source lives in `claude-plugin/` of the
[rdbg repo](https://github.com/p0ssess3d/rdbg). To test locally
without going through a release zip:

```powershell
$src = "C:\path\to\rdbg\claude-plugin"
$dst = "$env:USERPROFILE\.claude\plugins\rdbg-debugger"
New-Item -Type SymbolicLink -Path $dst -Target $src
```

Edit files in `claude-plugin/` and run `/plugin reload-plugins`
to pick up changes.

---

## License

MIT. See `LICENSE` in the rdbg repo root.
