agentskills.codes
RE

Driving a running Reactor app via `mur devtools` — screenshot, inspect visual tree, click/type/scroll, read hook state. Use when diagnosing visible bugs (layout, contrast) or verifying a UI change landed.

Install

mkdir -p .claude/skills/reactor-devtools && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/16581" && unzip -o skill.zip -d .claude/skills/reactor-devtools && rm skill.zip

Installs to .claude/skills/reactor-devtools

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Driving a running Reactor app via `mur devtools` — screenshot, inspect visual tree, click/type/scroll, read hook state. Use when diagnosing visible bugs (layout, contrast) or verifying a UI change landed.
204 chars✓ has a “when” trigger

About this skill

Reactor Devtools — CLI-driven UI automation

The Reactor devtools let you look at a running debug-build app the way a user does (screenshots, rendered text, layout bounds) and drive it the way a user does (click, type, toggle, scroll). Always prefer the mur devtools CLI — every action composes with shell pipes and jq, each invocation is a complete audit record, and no MCP client setup is needed.

Under the hood the CLI talks JSON-RPC to a loopback HTTP endpoint the app exposes. The MCP endpoint is still available at http://127.0.0.1:PORT/mcp as a parity escape hatch, but reach for it only when the CLI can't express what you need (structured args the CLI flattens, or another MCP client that's already wired up).

Loopback-only — DEBUG builds only, never ship it. Auth is a per-launch bearer token written into the lockfile; the CLI applies it transparently during lockfile discovery, so you don't see it. Don't pass --endpoint for tool calls — without the token the server returns 401. --endpoint is only useful when you're crafting the Authorization: Bearer … header yourself (curl, custom client).

Getting mur on your PATH

mur resolves from PATH in both modes:

  • Skill kit (deployed): install-skill-kit.ps1 (shipped with the kit zip) prepends <install>/bin/<arch> to your user PATH.
  • Cloned repo (selfhost): dotnet build of src/Reactor.Cli automatically mirrors the output to <repo>/bin/<arch>/ (architecture is determined from RuntimeIdentifier). Add that directory to your PATH once.

If mur --version doesn't resolve, neither path was set up; commands below assume it does.

Attaching to a running app

The app author enables devtools capability in the app project, usually only for Debug builds:

<ItemGroup Condition="'$(Configuration)' == 'Debug'">
  <RuntimeHostConfigurationOption Include="Reactor.DevtoolsSupport"
                                  Value="true" Trim="true" />
</ItemGroup>

ReactorApp.Run takes no devtools: or preview: argument.

Prefer attaching to an app that's already running. Any devtools-enabled app writes a lockfile to %TEMP%/reactor-devtools/ on first render, and mur devtools <verb> discovers it automatically — no port, no config, no parsing stdout.

mur devtools session list --pretty   # confirm a session is up

Exit 0 with a row means you're good to go; every other verb will find it. Exit 4 means no live session — you need to launch one yourself (next section).

Launching an app yourself

Two launch modes, from simplest to most featured:

Plain dotnet run (the default)

dotnet run --project path/to/App.csproj -- --devtools run \
  > /tmp/app-stdout.log 2>&1 &

This is what you want in almost every AI session: spawn the app, drive it with mur devtools <verb>, call mur devtools shutdown when you're done. No supervisor machinery, no pinned port — the CLI finds the session via the lockfile regardless.

mur devtools <project> — the supervisor

Reach for this only when you need a stable MCP endpoint across reload cycles:

mur devtools path/to/App.csproj --mcp-port 54931

The supervisor pins the port (reload-proof) and catches the child's exit code 42 to rebuild and relaunch. Useful if you've wired an external MCP client to http://127.0.0.1:54931/mcp and want it to survive code edits. Overkill for one-shot automation.

Discovering the tool surface

mur devtools call tools/list --pretty    # names + input schemas
mur devtools call tools/list | jq '.tools[].name'

mur devtools --help lists every named verb with one-line descriptions.

CLI verb catalog

Each verb attaches to the running session via lockfile discovery; no flags needed when only one session is active. Pass --pretty to any verb for indented JSON.

VerbWhat it does
versionBuild tag + pid + port — confirm the app is the one you expect.
componentsClass names of every Component subclass; marks which is mounted.
switch <name>Swap the root component by class name. Invalidates all node ids.
reload [--component N]Rebuild + relaunch via the supervisor sentinel. Old ids dead.
shutdownClose the app cleanly (supervisor exits 0). Releases the build output file lock.
windowsActive window ids, titles, bounds, currently-mounted component.
windows.listSpec 036 §10. Per-window id, key, title, DIP size, DPI, state, isMain. Use this when you care about DPI / DIP size or the key column for UseOpenWindow-keyed lookups.
windows.activate <id>Activate (focus) a window. Returns { ok, id }.
windows.close <id>Close a window. Honors UseClosingGuard / Closing subscribers — returns { ok: false, cancelled: true, id } when a guard vetoed the close.
windows.open <Component> [--title T] [--width W] [--height H] [--key K]Open a new top-level window mounting an allowlisted Component. The component name is gated by the same allowlist as switchComponent; rejected names return unknown-component with the available list.
tree [--selector S] [--window W] [--view summary|full]Dump the visual tree as JSON. full adds layout/automation/visual fields.
screenshot [--selector S] [--out path]PNG of the window (or selector-cropped region). --out path.png writes to file; --out - streams bytes to stdout.
click <selector>UIA click. Prefers Invoke → Toggle → SelectionItem; returns via.
invoke / toggle / selectDirect UIA pattern access. select <container> <item> auto-expands ComboBoxes.
type <selector> <text> [--clear]Set text on a value-bearing control.
focus <selector>Programmatic focus on a Control.
scroll <selector> [--by H%,V%] [--to <item-selector>]Scroll by percentage deltas 0–100 (not pixels), or scroll an item into view.
expand <selector> / collapse <selector>ExpandCollapse pattern (ComboBox popup, TreeViewItem, Expander).
wait <selector> [--text X | --text-matches RE | --visible | --count N] [--timeout MS]Poll a predicate until satisfied or timeout.
state [--selector S]Dump every hook value (useState/useReducer/etc.) across mounted components.
logs [--tail N] [--since SEQ] [--filter RE] [--source stdout|stderr|debug|trace] [--follow]Drain captured Debug.WriteLine / Trace.WriteLine / Console.Out / Console.Error. Ring buffer installed at --devtools run startup — late-attaching agents still see startup output. --follow long-polls until Ctrl+C.
fire <Component>.<event> [--args JSON]Call a NAMED METHOD on a live component by reflection. Inline lambdas aren't reachable.
properties <selector> [--name PropName]Read dependency properties on an element. Omit --name to enumerate all DPs with values, types, and local-vs-default status. Supports attached properties via Grid.Row syntax.
set-property <selector> <name> <value>Set a dependency property. Value is parsed from string (Thickness, CornerRadius, Brush hex #RRGGBB, enums, bool, double, int).
resources [--selector S] [--scope element|window|app] [--filter RE]Browse ResourceDictionary entries. Walks element → ancestor elements → window → app (including MergedDictionaries and ThemeDictionaries).
set-resource <key> <value> [--scope app|window|element] [--selector S]Set or add a XAML resource. Reports whether the write replaced an existing entry or created a new shadowing entry.
styles <selector>Inspect the explicitly-assigned Style: TargetType, Setters (property + value), BasedOn chain. Returns hasStyle: false when only a default/theme style is active.
ancestors <selector>Walk the visual tree upward — returns type, name, and automationId for each ancestor up to the root.
call <tool|method> [--args JSON]Generic JSON-RPC passthrough — parity escape hatch.

Reference-graph overlay

The references tool (Spec 057) returns the app's reactive reference graph — descriptor.Reference/.ReferenceList, the binding.Reference bridge, and modifier edges like .LabeledBy/.DescribedBy/.FlowsTo/ .XYFocus* — as {from, to, label, slot, kind, resolved} edges keyed to the same node ids tree uses, plus diagnostics for cycles and unresolved (perpetually-null) references. Reach it through the generic passthrough:

mur devtools call references --pretty
mur devtools call references --args '{"selector":"#login-form"}'   # scope to a subtree

Use it to confirm an accessibility relationship (LabeledBy/DescribedBy) or an XYFocus* ring actually resolved to the control you expect, or to spot a reference that never resolved. Cycles are a supported topology and are reported informationally, not as errors. The same overlay also backs the References toggle in the VS Code live-preview panel.

Session management

mur devtools session list             # JSONL, one live session per line
mur devtools session list --pretty    # human table
mur devtools session clean            # GC stale lockfiles
mur devtools session clean --dry-run  # show what would be removed

Shared flags (before any verb)

  • --endpoint <url> — skip lockfile discovery and talk to this endpoint. Drops the bearer token — the CLI has no --token flag, so verbs hit the endpoint unauthenticated and get 401. Only useful with curl plus a hand-built Authorization header, not for mur devtools <verb> calls.
  • --pretty — indent JSON output.
  • --auto — loopback port scan (slow; use only when lockfile discovery fails).

Exit codes

CodeMeaning
0Success.
1Usage error (unknown flag, missing argument).
2Transport error (endpoint unreachable, timeout).
3Another devtools session is already active for this project.
4No live devtools session found.
5Tool returne

Content truncated.

Search skills

Search the agent skills registry