Skip to content

Commit f2603c3

Browse files
authored
Add structured CLI automation outputs and bump to 0.1.35-rc.2 (#10)
1 parent 8cd472f commit f2603c3

9 files changed

Lines changed: 412 additions & 36 deletions

File tree

README.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,15 @@ Published package notes:
109109
## Commands
110110

111111
```bash
112+
rdt doctor --session demo
112113
rdt session open --url http://localhost:3000 --browser chromium --engine auto --session demo
113114
rdt session connect --ws-endpoint ws://127.0.0.1:3000/ --target-url localhost:3000 --session remote
114115
rdt session attach --cdp-url http://127.0.0.1:9222 --target-url localhost:3000 --session cdp
115116
rdt session doctor --session demo
116117
rdt tree get --session demo
118+
rdt tree stats --session demo --top 5
117119
rdt interact type --session demo --selector 'input[name="query"]' --text hello
118-
rdt node search App --session demo --snapshot <snapshotId>
120+
rdt node search App --session demo --snapshot <snapshotId> --structured
119121
rdt node inspect <nodeId> --session demo --snapshot <snapshotId>
120122
rdt profiler start --session demo
121123
rdt profiler stop --session demo
@@ -126,6 +128,7 @@ rdt profiler export --session demo --compress
126128
## Snapshot Semantics
127129

128130
- `tree get` returns a `snapshotId`.
131+
- `tree stats` returns the same `snapshotId` plus summary fields such as `rootCount`, `nodeCount`, `rootSummaries`, and `topLevelComponents`.
129132
- Node IDs are only meaningful within that snapshot.
130133
- The runtime currently keeps up to `5` snapshots in memory per session.
131134
- Agent-friendly recommended flow:
@@ -139,6 +142,7 @@ rdt profiler export --session demo --compress
139142
## Doctor
140143

141144
- `rdt session doctor --session <name>` reports runtime readiness and trust boundaries before a deeper investigation.
145+
- `rdt doctor --session <name>` is a first-class alias for the same command.
142146
- It also reports `enginePreference`, `selectedEngine`, `recommendedEngine`, `availableEngines`, and DevTools capability hints so agents know whether they are on a custom fallback or a DevTools-aligned path.
143147
- `sourceCapability` is reported separately from engine selection.
144148
- `_debugSource` is treated as an optional legacy source-mapping capability, not an engine-selection gate.
@@ -154,12 +158,15 @@ rdt profiler export --session demo --compress
154158

155159
- Use built-in `interact` commands before reaching for external Playwright helper scripts.
156160
- Current supported actions:
157-
- `rdt interact click --session <name> --selector <css>`
161+
- `rdt interact click --session <name> --selector <css> [--delivery auto|playwright|dom]`
158162
- `rdt interact type --session <name> --selector <css> --text <value>`
159163
- `rdt interact press --session <name> --key <name> [--selector <css>]`
160164
- `rdt interact wait --session <name> --ms <n>`
161165
- These commands execute through the same Playwright session that owns the current `rdt` browser page.
162166
- They target the first matching selector only and return structured action metadata plus trust-boundary fields.
167+
- `interact click` defaults to `--delivery auto`.
168+
- In `auto`, profiler-active clicks fall back to DOM dispatch and report `requestedDelivery`, `effectiveDelivery`, `profilerActive`, and `fallbackApplied`.
169+
- Use `--delivery playwright` to force Playwright pointer input, or `--delivery dom` to force DOM dispatch.
163170
- `click`, `type`, and `press` confirm that the action was dispatched. They do not guarantee that the page or React tree has fully settled afterward.
164171
- When profiling or triggering large rerenders, follow `interact` with an explicit verification step such as `interact wait`, `tree get`, `node inspect`, or a profiler read command.
165172

@@ -168,10 +175,10 @@ Example deterministic flow:
168175
```bash
169176
rdt tree get --session demo
170177
# => save snapshotId from output
171-
rdt node search App --session demo --snapshot <snapshotId>
178+
rdt node search App --session demo --snapshot <snapshotId> --structured
172179
rdt node inspect <nodeId> --session demo --snapshot <snapshotId>
173180
rdt node highlight <nodeId> --session demo --snapshot <snapshotId>
174-
rdt source reveal <nodeId> --session demo --snapshot <snapshotId>
181+
rdt source reveal <nodeId> --session demo --snapshot <snapshotId> --structured
175182
```
176183

177184
Snapshot recovery:
@@ -269,7 +276,11 @@ Use `node pick` when the agent knows the visible element but not the component n
269276
- `hooks` is a simplified serialized view of hook state from the inspected fiber.
270277
- `context` is a serialized view of current context dependencies for the inspected node.
271278
- `source` projects `_debugSource` when available; `null` is expected in many dev builds.
279+
- `source reveal --structured` returns `status`, `available`, `mode`, `reason`, and `source` so automation can distinguish unavailable source data from a successful source payload.
280+
- `source reveal` without `--structured` preserves the raw legacy behavior and may return literal `null`.
272281
- `dom` is the first host element summary used for CLI highlight and DOM-oriented inspection.
282+
- `node search --structured` wraps search results in `{ items, query, snapshotId, matchCount, runtimeWarnings }`.
283+
- When `node search --structured` returns `matchCount: 0`, `runtimeWarnings` explains that the component may be absent from the current snapshot rather than absent from the codebase.
273284
- Profiler summary fields are commit-oriented CLI metrics, not the full DevTools profiler session schema.
274285
- `profiler summary` and exported summaries explicitly report:
275286
- `measurementMode: "actual-duration" | "structural-only" | "mixed"`

docs/devtools-concept-mapping.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,18 @@ It is a maintenance aid for agents and contributors. It is not a commitment to r
3434
| `__REACT_DEVTOOLS_GLOBAL_HOOK__` shim | `src/runtime-script.js` | DevTools global hook | `rdt` uses the hook for renderer/root discovery, but does not speak the official frontend protocol. |
3535
| `state.roots` + `rootId` | `src/runtime-script.js` | Fiber roots / renderer root registry | `rdt` assigns CLI-friendly `root-*` ids per discovered root. |
3636
| `collectTree()` snapshot | `src/runtime-script.js` | Inspected tree payload | `rdt` serializes a tree for CLI use instead of streaming updates to a frontend. |
37+
| `tree stats` | `src/runtime-script.js` + `src/cli.js` | No direct public equivalent | Snapshot summary view for large trees; returns metadata without the full node dump. |
3738
| `snapshotId` | `src/runtime-script.js` | No direct public equivalent | Intentional divergence. This is a CLI-specific stability layer for follow-up commands. |
3839
| `node id` like `n68` | `src/runtime-script.js` | Element/fiber identity in inspector payloads | Snapshot-scoped only. Not intended to be globally stable across commits. |
3940
| `node inspect` payload | `src/runtime-script.js` | Inspected element details | Closest conceptual match to DevTools inspected element data. |
4041
| `ownerStack` | `src/runtime-script.js` | Owner chain / component stack | Serialized as lightweight `{id, displayName}` records. |
4142
| `hooks` | `src/runtime-script.js` | Hook inspection data | Derived from `memoizedState`; intentionally simpler than full DevTools hook typing. |
4243
| `context` | `src/runtime-script.js` | Context dependencies / inspected context values | Derived from fiber dependencies, serialized for CLI use. |
43-
| `source reveal` | `src/server.js` + `src/runtime-script.js` | View source / inspect source location | Depends on `_debugSource`; may legitimately return `null`. |
44+
| `source reveal` | `src/server.js` + `src/runtime-script.js` | View source / inspect source location | Raw mode may legitimately return `null`; structured mode reports source availability explicitly. |
4445
| `profiler` summary/export | `src/runtime-script.js` + `src/cli.js` | Profiler commit data | `rdt` keeps commit-oriented summaries and NDJSON export rather than full DevTools frontend state. |
4546
| `profiler compare` | `src/cli.js` | No direct public equivalent | CLI-side comparison of stored profiler artifacts or exported NDJSON files. |
4647
| `interact click|type|press|wait` | `src/server.js` | No direct public equivalent | Playwright-backed deterministic interaction helpers for agent workflows. |
48+
| `interact click --delivery` | `src/server.js` | No direct public equivalent | CLI-specific interaction contract for choosing Playwright pointer input vs DOM dispatch. |
4749
| `session doctor` | `src/server.js` + `src/runtime-script.js` | No direct public equivalent | CLI-specific preflight that reports trust boundaries, runtime readiness, Playwright resolution diagnostics, and helper import targets. |
4850

4951
## Intentional Divergences
@@ -72,6 +74,8 @@ It is a maintenance aid for agents and contributors. It is not a commitment to r
7274
- `hooks`: serialized hook state view, intentionally simplified.
7375
- `context`: serialized current context dependency values.
7476
- `source`: `_debugSource` projection when available; `null` is expected in many builds.
77+
- `source reveal --structured`: wraps source lookup in `{ status, available, mode, reason, source }`.
78+
- `mode`: source-capability mode, not engine mode. Current values describe whether `_debugSource` is available, removed by newer React runtimes, or stripped by the build.
7579
- `dom`: first host element descendant summary used for CLI-oriented highlight/reveal behavior.
7680

7781
### Profiler payload

docs/workflows.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ npm install -g react-devtool-cli
2323
```bash
2424
rdt session open --url http://localhost:3000 --browser chromium --engine auto --session demo
2525
rdt tree get --session demo
26-
rdt node search App --session demo --snapshot <snapshotId>
26+
rdt tree stats --session demo --top 5
27+
rdt node search App --session demo --snapshot <snapshotId> --structured
2728
rdt node inspect <nodeId> --session demo --snapshot <snapshotId>
2829
```
2930

@@ -40,11 +41,16 @@ Recommended flow:
4041

4142
```bash
4243
rdt tree get --session demo
43-
rdt node search App --session demo --snapshot <snapshotId>
44+
rdt tree stats --session demo --top 5
45+
rdt node search App --session demo --snapshot <snapshotId> --structured
4446
rdt node highlight <nodeId> --session demo --snapshot <snapshotId>
45-
rdt source reveal <nodeId> --session demo --snapshot <snapshotId>
47+
rdt source reveal <nodeId> --session demo --snapshot <snapshotId> --structured
4648
```
4749

50+
- `tree stats` is the lightweight summary path when `tree get --format json` is too heavy.
51+
- `node search --structured` keeps the default array-returning behavior opt-in while adding `matchCount` and `runtimeWarnings`.
52+
- `source reveal --structured` returns availability metadata instead of only raw `null`.
53+
4854
Recovery flow:
4955

5056
```bash
@@ -56,6 +62,7 @@ rdt node search App --session demo --snapshot <newSnapshotId>
5662
## Run `doctor` before deeper investigation
5763

5864
```bash
65+
rdt doctor --session demo
5966
rdt session doctor --session demo
6067
```
6168

@@ -71,11 +78,14 @@ Use it to confirm:
7178
Built-in interactions keep the investigation inside the same session instead of forcing separate helper scripts.
7279

7380
```bash
74-
rdt interact click --session demo --selector 'button.save'
81+
rdt interact click --session demo --selector 'button.save' --delivery auto
7582
rdt interact type --session demo --selector 'input[name="query"]' --text hello
7683
rdt interact wait --session demo --ms 500
7784
```
7885

86+
- `interact click --delivery auto` uses Playwright pointer input by default.
87+
- When the profiler is active, `auto` may fall back to DOM dispatch and reports the applied delivery in the response payload.
88+
7989
After interaction, verify the app settled by collecting a fresh tree or reading profiler output instead of assuming the UI state changed correctly.
8090

8191
## Profile a real update

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-devtool-cli",
3-
"version": "0.1.35-rc.1",
3+
"version": "0.1.35-rc.2",
44
"description": "Agent-first CLI for React component tree inspection, snapshot-aware node debugging, and profiler analysis through a Playwright-managed browser session.",
55
"license": "MIT",
66
"type": "module",

src/cli.js

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ function collectSnapshotPayload(options) {
9292
return options.snapshot ? { snapshotId: String(options.snapshot) } : {};
9393
}
9494

95+
function normalizeStructuredFlag(options) {
96+
return Boolean(options.structured);
97+
}
98+
9599
function resolveCommitId(positionals, options, message) {
96100
const commitId = positionals[0] ? String(positionals[0]) : (options.commit ? String(options.commit) : null);
97101
ensure(commitId, message, { code: "missing-commit-id" });
@@ -278,9 +282,14 @@ async function handleSessionCommand(command, options) {
278282
}
279283

280284
async function handleTreeCommand(command, options) {
281-
ensure(command === "get", "Only `rdt tree get` is supported.", { code: "unsupported-command" });
285+
ensure(command === "get" || command === "stats", "Only `rdt tree get` and `rdt tree stats` are supported.", {
286+
code: "unsupported-command",
287+
});
282288
ensure(options.session, "Missing required option --session", { code: "missing-session" });
283-
const response = await requestSession(options.session, "tree.get");
289+
const action = command === "stats" ? "tree.stats" : "tree.get";
290+
const response = await requestSession(options.session, action, {
291+
top: options.top ? Number(options.top) : undefined,
292+
});
284293
writeStdout(response.result, resolveFormat(options));
285294
}
286295

@@ -304,6 +313,7 @@ async function handleNodeCommand(command, positionals, options) {
304313
ensure(query, "Missing query for `rdt node search`.", { code: "missing-query" });
305314
const response = await requestSession(options.session, "node.search", {
306315
query,
316+
structured: normalizeStructuredFlag(options),
307317
...collectSnapshotPayload(options),
308318
});
309319
writeStdout(response.result, resolveFormat(options));
@@ -339,6 +349,7 @@ async function handleInteractCommand(command, options) {
339349
ensure(options.selector, "Missing required option --selector for `rdt interact click`.", { code: "missing-selector" });
340350
const response = await requestSession(options.session, "interact.click", {
341351
selector: String(options.selector),
352+
delivery: options.delivery ? String(options.delivery) : undefined,
342353
timeoutMs: options.timeoutMs ?? undefined,
343354
});
344355
writeStdout(response.result, resolveFormat(options));
@@ -732,11 +743,30 @@ async function handleSourceCommand(command, positionals, options) {
732743
ensure(nodeId, "Missing node id for `rdt source reveal`.", { code: "missing-node-id" });
733744
const response = await requestSession(options.session, "source.reveal", {
734745
nodeId,
746+
structured: normalizeStructuredFlag(options),
735747
...collectSnapshotPayload(options),
736748
});
737749
writeStdout(response.result, resolveFormat(options));
738750
}
739751

752+
export function normalizeCliPositionals(positionals) {
753+
const [resource, command, ...rest] = positionals;
754+
755+
if (resource === "doctor") {
756+
return {
757+
resource: "session",
758+
command: "doctor",
759+
rest: command ? [command, ...rest] : [],
760+
};
761+
}
762+
763+
return {
764+
resource,
765+
command,
766+
rest,
767+
};
768+
}
769+
740770
function printHelp() {
741771
process.stdout.write(`react-devtool-cli
742772
@@ -746,21 +776,23 @@ Recommended flow:
746776
3. Use rdt session attach only for Chromium CDP compatibility
747777
4. Use rdt tree/node/profiler commands for structured output
748778
5. For agent workflows, capture snapshotId from tree get and pass it to later node/source commands
749-
6. Use rdt doctor before profiling if helper scripts or Playwright resolution look suspicious
779+
6. Use rdt doctor (alias: rdt session doctor) before profiling if helper scripts or Playwright resolution look suspicious
750780
751781
Usage:
782+
rdt doctor --session <name> [--format json|yaml|pretty]
752783
rdt session open --url <url> [--browser chromium|firefox|webkit] [--engine auto|custom|devtools] [--channel <name>] [--device <name>] [--storage-state <path>] [--user-data-dir <path>] [--timeout <ms>] [--headless=false] [--session <name>]
753784
rdt session connect --ws-endpoint <url> [--browser chromium|firefox|webkit] [--engine auto|custom|devtools] [--target-url <substring>] [--timeout <ms>] [--session <name>]
754785
rdt session attach --cdp-url <url> [--engine auto|custom|devtools] [--target-url <substring>] [--timeout <ms>] [--session <name>]
755786
rdt session status --session <name>
756787
rdt session doctor --session <name> [--format json|yaml|pretty]
757788
rdt session close --session <name>
758789
rdt tree get --session <name> [--format json|yaml|pretty]
790+
rdt tree stats --session <name> [--top <n>] [--format json|yaml|pretty]
759791
rdt node inspect <id> --session <name> [--snapshot <id>] [--commit <id>]
760-
rdt node search <query> --session <name> [--snapshot <id>]
792+
rdt node search <query> --session <name> [--snapshot <id>] [--structured]
761793
rdt node highlight <id> --session <name> [--snapshot <id>]
762794
rdt node pick --session <name> [--timeout-ms 30000]
763-
rdt interact click --session <name> --selector <css> [--timeout-ms <ms>]
795+
rdt interact click --session <name> --selector <css> [--delivery auto|playwright|dom] [--timeout-ms <ms>]
764796
rdt interact type --session <name> --selector <css> --text <value> [--timeout-ms <ms>]
765797
rdt interact press --session <name> --key <name> [--selector <css>] [--timeout-ms <ms>]
766798
rdt interact wait --session <name> --ms <n>
@@ -773,7 +805,7 @@ Usage:
773805
rdt profiler flamegraph <id> --session <name> [--format json|pretty]
774806
rdt profiler compare --session <name> --left <profileId|file> --right <profileId|file> [--format json|yaml|pretty]
775807
rdt profiler export --session <name> [--output file.jsonl] [--compress]
776-
rdt source reveal <id> --session <name> [--snapshot <id>]
808+
rdt source reveal <id> --session <name> [--snapshot <id>] [--structured]
777809
778810
Snapshot behavior:
779811
- tree get returns snapshotId
@@ -795,7 +827,7 @@ export async function runCli(argv) {
795827
return;
796828
}
797829

798-
const [resource, command, ...rest] = positionals;
830+
const { resource, command, rest } = normalizeCliPositionals(positionals);
799831

800832
try {
801833
switch (resource) {

0 commit comments

Comments
 (0)