rnxsim 0.1.376 → 0.1.378

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/README.md +28 -25
  2. package/cli/app-config.ts +9 -12
  3. package/cli/app-fonts.ts +3 -3
  4. package/cli/app-project.ts +8 -8
  5. package/cli/auth.ts +7 -9
  6. package/cli/bin.ts +16 -31
  7. package/cli/bridge-flow-runner.ts +3 -3
  8. package/cli/browser-backend.ts +44 -0
  9. package/cli/command-contract.ts +221 -0
  10. package/cli/command-registry.ts +291 -0
  11. package/cli/commands/agent-wrapper.ts +2 -2
  12. package/cli/commands/app-fonts.ts +2 -2
  13. package/cli/commands/assert.ts +3 -3
  14. package/cli/commands/auth.ts +1 -1
  15. package/cli/commands/box/cloud-box.ts +1 -1
  16. package/cli/commands/box/plane-share.ts +2 -2
  17. package/cli/commands/box.ts +4 -6
  18. package/cli/commands/compat.ts +1 -1
  19. package/cli/commands/config.ts +2 -2
  20. package/cli/commands/control.ts +29 -29
  21. package/cli/commands/cpu-profile.ts +7 -7
  22. package/cli/commands/daemon-mac-app.ts +7 -7
  23. package/cli/commands/daemon.ts +10 -10
  24. package/cli/commands/debug.ts +11 -11
  25. package/cli/commands/detox.ts +13 -13
  26. package/cli/commands/diagnose.ts +6 -6
  27. package/cli/commands/do-chain.ts +1 -2
  28. package/cli/commands/electron.ts +1 -3
  29. package/cli/commands/film.ts +3 -3
  30. package/cli/commands/flow.ts +43 -43
  31. package/cli/commands/inspect/count.ts +1 -1
  32. package/cli/commands/inspect/describe.ts +1 -1
  33. package/cli/commands/inspect/env.ts +2 -2
  34. package/cli/commands/inspect/get-layout.ts +1 -1
  35. package/cli/commands/inspect/keyboard.ts +1 -1
  36. package/cli/commands/inspect/list.ts +1 -1
  37. package/cli/commands/inspect/memory.ts +1 -1
  38. package/cli/commands/inspect/resolve-target.ts +1 -1
  39. package/cli/commands/inspect/screens.ts +1 -1
  40. package/cli/commands/inspect/tree.ts +1 -1
  41. package/cli/commands/inspect/url.ts +1 -1
  42. package/cli/commands/inspect/wait-event.ts +5 -5
  43. package/cli/commands/inspect.ts +34 -34
  44. package/cli/commands/install-desktop.ts +3 -3
  45. package/cli/commands/login.ts +6 -6
  46. package/cli/commands/maestro-generate.ts +5 -5
  47. package/cli/commands/maestro.ts +5 -5
  48. package/cli/commands/profile.ts +1 -1
  49. package/cli/commands/record.ts +9 -9
  50. package/cli/commands/runtime.ts +18 -18
  51. package/cli/commands/screenshot-command.ts +1 -1
  52. package/cli/commands/screenshot-layers.ts +5 -5
  53. package/cli/commands/screenshot-mode.ts +1 -1
  54. package/cli/commands/screenshot.ts +8 -8
  55. package/cli/commands/screenshots-capture.ts +5 -5
  56. package/cli/commands/serve.ts +3 -3
  57. package/cli/commands/setup.ts +20 -12
  58. package/cli/commands/skills.ts +5 -5
  59. package/cli/commands/slides.ts +1 -1
  60. package/cli/commands/telemetry.ts +1 -1
  61. package/cli/commands/three-mode.ts +1 -1
  62. package/cli/commands/timeline.ts +8 -8
  63. package/cli/commands/upgrade.ts +116 -131
  64. package/cli/commands/upload.ts +12 -12
  65. package/cli/commands/version.ts +7 -7
  66. package/cli/commands/what-happened.ts +9 -9
  67. package/cli/current-sim.ts +3 -3
  68. package/cli/desktop-companion.ts +1 -1
  69. package/cli/drivers/playwright.ts +9 -9
  70. package/cli/drivers/registry.ts +1 -1
  71. package/cli/drivers/types.ts +1 -1
  72. package/cli/flow-file.ts +2 -2
  73. package/cli/flow-session.ts +1 -1
  74. package/cli/help-core.ts +136 -0
  75. package/cli/help.ts +17 -53
  76. package/cli/hints.ts +5 -5
  77. package/cli/inspect-notice-state.ts +1 -1
  78. package/cli/maestro-js.ts +1 -1
  79. package/cli/outbound-endpoints.ts +23 -5
  80. package/cli/parse-args.ts +19 -66
  81. package/cli/recording-access.ts +1 -1
  82. package/cli/registry.ts +1 -0
  83. package/cli/run-registry.ts +1 -1
  84. package/cli/run-rnx-core.ts +148 -0
  85. package/cli/run-rnx.ts +6 -9
  86. package/cli/runtime-notes.ts +3 -3
  87. package/cli/standalone.ts +4 -0
  88. package/cli/ws-bridge.ts +8 -8
  89. package/detox/config-loader.ts +2 -2
  90. package/detox/index.ts +8 -8
  91. package/detox/jest-preset.cjs +1 -1
  92. package/detox/navigation.ts +2 -2
  93. package/dist-lib/agent-daemon-client.cjs +5 -5
  94. package/dist-lib/agent-events.cjs +1 -1
  95. package/dist-lib/agent-identity.cjs +2 -2
  96. package/dist-lib/agent-sessions.cjs +10 -10
  97. package/dist-lib/attached-projects.cjs +6 -6
  98. package/dist-lib/auth/shared-session.cjs +6 -6
  99. package/dist-lib/backend-origin.cjs +1 -1
  100. package/dist-lib/beta.cjs +1 -1
  101. package/dist-lib/beta.mjs +1 -1
  102. package/dist-lib/bridge-constants.cjs +1 -1
  103. package/dist-lib/bridge-contract-input.cjs +1 -1
  104. package/dist-lib/bridge-contract-input.mjs +1 -1
  105. package/dist-lib/bridge-contract.cjs +1 -1
  106. package/dist-lib/bridge-contract.mjs +1 -1
  107. package/dist-lib/cli-constants.cjs +1 -1
  108. package/dist-lib/config.cjs +25 -25
  109. package/dist-lib/detox/index.cjs +73 -31
  110. package/dist-lib/detox/jest-preset.cjs +1 -1
  111. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  112. package/dist-lib/home-paths.cjs +29 -29
  113. package/dist-lib/host/bridge-host.cjs +128 -49
  114. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  115. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  116. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  117. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  118. package/dist-lib/host/websocket-proxy.cjs +1 -1
  119. package/dist-lib/index.cjs +14 -14
  120. package/dist-lib/jump-to-source-babel.cjs +1 -1
  121. package/dist-lib/menu.cjs +1 -1
  122. package/dist-lib/menu.mjs +1 -1
  123. package/dist-lib/metro-production-bundle.cjs +1 -1
  124. package/dist-lib/metro-production-bundle.mjs +1 -1
  125. package/dist-lib/metro.cjs +8 -8
  126. package/dist-lib/profiles.cjs +12 -12
  127. package/dist-lib/public-brand.cjs +1 -1
  128. package/dist-lib/react-native-host-modules.cjs +1 -1
  129. package/dist-lib/react-native-host-modules.mjs +1 -1
  130. package/dist-lib/render-mode.cjs +1 -1
  131. package/dist-lib/scripts/dev-server-scanner.cjs +8 -8
  132. package/dist-lib/sdk.cjs +1 -1
  133. package/dist-lib/sdk.mjs +1 -1
  134. package/dist-lib/skills.cjs +329 -160
  135. package/dist-lib/vite.cjs +9 -9
  136. package/package.json +4 -11
  137. package/scripts/dev-server-scanner.ts +2 -2
  138. package/scripts/optional-demo-registry.ts +1 -1
  139. package/skills/contrast/SKILL.md +3 -3
  140. package/skills/rnx-debug/SKILL.md +1 -1
  141. package/skills/rnx-test/SKILL.md +2 -2
  142. package/src/agent-identity.ts +1 -1
  143. package/src/agent-sessions.ts +7 -5
  144. package/src/cli-version.ts +12 -4
  145. package/src/config.ts +26 -28
  146. package/src/disk-cleanup.ts +11 -11
  147. package/src/home-paths.ts +28 -28
  148. package/src/host/bridge-host.ts +16 -16
  149. package/src/metro-plugin.ts +2 -2
  150. package/src/profiles.ts +2 -2
  151. package/src/runtime-assets.ts +7 -7
  152. package/src/runtime-delivery.ts +13 -13
  153. package/src/screenshots/orchestrate.ts +1 -1
  154. package/src/screenshots/schema.ts +2 -2
  155. package/src/skills/builtin/a11y-review.ts +2 -2
  156. package/src/skills/builtin/compat-check.ts +2 -2
  157. package/src/skills/builtin/maestro-test.ts +2 -2
  158. package/src/skills/builtin/perf-profile.ts +2 -2
  159. package/src/skills/builtin/screenshot-all.ts +2 -2
  160. package/src/skills/builtin/visual-diff.ts +2 -2
  161. package/src/skills/registry.ts +8 -8
  162. package/src/skills/types.ts +1 -1
  163. package/src/vite-plugin-one.ts +3 -3
  164. package/src/vite-plugin.ts +15 -2
  165. package/dist-cli/bin.js +0 -15
  166. package/dist-cli/chunks/agent-H42FCKFF.js +0 -48
  167. package/dist-cli/chunks/agent-wrapper-BBZKTZS6.js +0 -17
  168. package/dist-cli/chunks/app-fonts-43VXIKF4.js +0 -4
  169. package/dist-cli/chunks/assert-IXOLVO5Z.js +0 -49
  170. package/dist-cli/chunks/auth-KFMFB6FU.js +0 -12
  171. package/dist-cli/chunks/beta-5AO3SJB7.js +0 -4
  172. package/dist-cli/chunks/box-ZHM66L6K.js +0 -1730
  173. package/dist-cli/chunks/camera-FNJVFCDQ.js +0 -33
  174. package/dist-cli/chunks/chunk-37MCSPTE.js +0 -71
  175. package/dist-cli/chunks/chunk-3PEMSUAQ.js +0 -30
  176. package/dist-cli/chunks/chunk-4TQ5HOK3.js +0 -7
  177. package/dist-cli/chunks/chunk-5YZYDEMI.js +0 -4
  178. package/dist-cli/chunks/chunk-6CV3R3XD.js +0 -15
  179. package/dist-cli/chunks/chunk-7LGK5XU6.js +0 -4
  180. package/dist-cli/chunks/chunk-7R2TK2NY.js +0 -4
  181. package/dist-cli/chunks/chunk-7VZZQQEE.js +0 -497
  182. package/dist-cli/chunks/chunk-AFOVILIL.js +0 -130
  183. package/dist-cli/chunks/chunk-BEU7CD7E.js +0 -9
  184. package/dist-cli/chunks/chunk-CE4JQJ6Y.js +0 -6
  185. package/dist-cli/chunks/chunk-CIE6CZXL.js +0 -142
  186. package/dist-cli/chunks/chunk-CSJ7L7ZL.js +0 -312
  187. package/dist-cli/chunks/chunk-CWCQP53A.js +0 -27
  188. package/dist-cli/chunks/chunk-DCS5FK5N.js +0 -7
  189. package/dist-cli/chunks/chunk-DEV3E3MV.js +0 -4
  190. package/dist-cli/chunks/chunk-DGJMIVZM.js +0 -5
  191. package/dist-cli/chunks/chunk-DGX3MN65.js +0 -5
  192. package/dist-cli/chunks/chunk-DNPQMTW5.js +0 -4
  193. package/dist-cli/chunks/chunk-DOVBJBVD.js +0 -5
  194. package/dist-cli/chunks/chunk-DPBJ3S3J.js +0 -3
  195. package/dist-cli/chunks/chunk-FVZBGPCU.js +0 -4
  196. package/dist-cli/chunks/chunk-GDKMOIUT.js +0 -4
  197. package/dist-cli/chunks/chunk-GIF2NJCS.js +0 -32
  198. package/dist-cli/chunks/chunk-GZE57ORL.js +0 -4
  199. package/dist-cli/chunks/chunk-H3U56DKI.js +0 -24
  200. package/dist-cli/chunks/chunk-HZLOYAPH.js +0 -4
  201. package/dist-cli/chunks/chunk-J2IKAEU2.js +0 -4
  202. package/dist-cli/chunks/chunk-JXAXYK7W.js +0 -11
  203. package/dist-cli/chunks/chunk-KJE2O2GK.js +0 -4
  204. package/dist-cli/chunks/chunk-KMNVDZZI.js +0 -423
  205. package/dist-cli/chunks/chunk-LC3QRIRB.js +0 -10
  206. package/dist-cli/chunks/chunk-LGFTAQYC.js +0 -4
  207. package/dist-cli/chunks/chunk-LQMUA5IY.js +0 -4
  208. package/dist-cli/chunks/chunk-MFIQTWC5.js +0 -4
  209. package/dist-cli/chunks/chunk-MGALNF2F.js +0 -7
  210. package/dist-cli/chunks/chunk-MLBZZHOY.js +0 -4
  211. package/dist-cli/chunks/chunk-NNRF7GIB.js +0 -107
  212. package/dist-cli/chunks/chunk-NORLYTTO.js +0 -7
  213. package/dist-cli/chunks/chunk-P6KVGV3H.js +0 -14
  214. package/dist-cli/chunks/chunk-PAJTUK33.js +0 -4
  215. package/dist-cli/chunks/chunk-QELIC5XP.js +0 -4
  216. package/dist-cli/chunks/chunk-QRDF33WD.js +0 -11
  217. package/dist-cli/chunks/chunk-R76BA7C7.js +0 -535
  218. package/dist-cli/chunks/chunk-RVEB4CZ2.js +0 -4
  219. package/dist-cli/chunks/chunk-SK4M7NXT.js +0 -5
  220. package/dist-cli/chunks/chunk-SKMG5DD7.js +0 -5
  221. package/dist-cli/chunks/chunk-TEESPOYR.js +0 -4
  222. package/dist-cli/chunks/chunk-TH2UFGVP.js +0 -4
  223. package/dist-cli/chunks/chunk-TLP3T3VO.js +0 -4
  224. package/dist-cli/chunks/chunk-TZUABDIJ.js +0 -38
  225. package/dist-cli/chunks/chunk-UB2W6OQM.js +0 -99
  226. package/dist-cli/chunks/chunk-UYVXALPB.js +0 -506
  227. package/dist-cli/chunks/chunk-VQDYFFIG.js +0 -5
  228. package/dist-cli/chunks/chunk-VWCNJPCJ.js +0 -5
  229. package/dist-cli/chunks/chunk-VZIK4WIS.js +0 -74
  230. package/dist-cli/chunks/chunk-W3FNXAQP.js +0 -4
  231. package/dist-cli/chunks/chunk-XCDNVNP3.js +0 -4
  232. package/dist-cli/chunks/chunk-XSVILA4Z.js +0 -4
  233. package/dist-cli/chunks/chunk-XUTJ7ZWD.js +0 -4
  234. package/dist-cli/chunks/chunk-YTXY3MHW.js +0 -4
  235. package/dist-cli/chunks/chunk-ZF7PVX44.js +0 -28
  236. package/dist-cli/chunks/chunk-ZSSG7OR7.js +0 -4
  237. package/dist-cli/chunks/cleanup-MLOK2OZA.js +0 -25
  238. package/dist-cli/chunks/cli-version-OBNR366V.js +0 -4
  239. package/dist-cli/chunks/compat-SHMFSKU7.js +0 -23
  240. package/dist-cli/chunks/config-TPEAEUJ2.js +0 -13
  241. package/dist-cli/chunks/connect-3LEXWTE5.js +0 -4
  242. package/dist-cli/chunks/control-Z3FWA6BO.js +0 -4
  243. package/dist-cli/chunks/daemon-RSVYSC65.js +0 -4
  244. package/dist-cli/chunks/debug-GUVAK2KR.js +0 -200
  245. package/dist-cli/chunks/desktop-OOP2PTKP.js +0 -31
  246. package/dist-cli/chunks/detox-C2ILVBEC.js +0 -52
  247. package/dist-cli/chunks/device-NXIQQJWR.js +0 -18
  248. package/dist-cli/chunks/diagnose-2JBGYE5L.js +0 -43
  249. package/dist-cli/chunks/disk-cleanup-VURWJYQV.js +0 -4
  250. package/dist-cli/chunks/do-chain-DJ4UQC7A.js +0 -5
  251. package/dist-cli/chunks/drivers-JMA2OIKU.js +0 -4
  252. package/dist-cli/chunks/env-KTNPKEZR.js +0 -4
  253. package/dist-cli/chunks/film-DCPS7EID.js +0 -74
  254. package/dist-cli/chunks/flow-4DZ7B2OA.js +0 -4
  255. package/dist-cli/chunks/help-34CJMQY2.js +0 -4
  256. package/dist-cli/chunks/hidden-runtime-alias-HHT2C7WE.js +0 -4
  257. package/dist-cli/chunks/home-paths-KTPGCPMS.js +0 -4
  258. package/dist-cli/chunks/inspect-JF5WYJRD.js +0 -4
  259. package/dist-cli/chunks/install-desktop-ZIC4CDXI.js +0 -4
  260. package/dist-cli/chunks/login-TTJAOI2Q.js +0 -26
  261. package/dist-cli/chunks/logout-ERAQ6SKW.js +0 -4
  262. package/dist-cli/chunks/maestro-W46QCF77.js +0 -108
  263. package/dist-cli/chunks/maestro-generate-VBLM3MTU.js +0 -36
  264. package/dist-cli/chunks/mode-ZEDZK7R7.js +0 -26
  265. package/dist-cli/chunks/optional-demo-registry-ZUTPSVYQ.js +0 -4
  266. package/dist-cli/chunks/perf-YVT2WXT4.js +0 -48
  267. package/dist-cli/chunks/permissions-L7VVDHFP.js +0 -13
  268. package/dist-cli/chunks/platform-7TJOU2FB.js +0 -6
  269. package/dist-cli/chunks/privacy-57UOTB5J.js +0 -4
  270. package/dist-cli/chunks/record-VXG37P7U.js +0 -72
  271. package/dist-cli/chunks/report-issue-WNNOBZHC.js +0 -29
  272. package/dist-cli/chunks/reset-H5NBFE5U.js +0 -4
  273. package/dist-cli/chunks/resolve-target-57TK5WLE.js +0 -4
  274. package/dist-cli/chunks/runtime-QU2NIF2K.js +0 -4
  275. package/dist-cli/chunks/screenshot-command-AN56TTG7.js +0 -159
  276. package/dist-cli/chunks/screenshot-layers-3W5R7DB2.js +0 -20
  277. package/dist-cli/chunks/screenshots-capture-6AWJY7XZ.js +0 -42
  278. package/dist-cli/chunks/serve-GLYO5Q7J.js +0 -56
  279. package/dist-cli/chunks/setup-UA2HLD7S.js +0 -4
  280. package/dist-cli/chunks/sim-client-5C2RDQQO.js +0 -4
  281. package/dist-cli/chunks/skills-EYXWBRNQ.js +0 -50
  282. package/dist-cli/chunks/state-REJ7W6K3.js +0 -14
  283. package/dist-cli/chunks/storage-CFMDHI3V.js +0 -37
  284. package/dist-cli/chunks/store-XMCUA45G.js +0 -4
  285. package/dist-cli/chunks/telemetry-FBL3NAKB.js +0 -4
  286. package/dist-cli/chunks/timeline-HMCHN5FO.js +0 -24
  287. package/dist-cli/chunks/upgrade-2QSPAA3P.js +0 -7
  288. package/dist-cli/chunks/upload-DUQBKZYV.js +0 -4
  289. package/dist-cli/chunks/version-IOA6QFGB.js +0 -6
  290. package/dist-cli/chunks/web-NCGUYVCJ.js +0 -4
  291. package/dist-cli/chunks/welcome-QYGSQCWQ.js +0 -5
  292. package/dist-cli/chunks/what-happened-YTOUK4LO.js +0 -25
  293. package/dist-cli/chunks/ws-bridge-OF4OZARG.js +0 -4
  294. package/scripts/postinstall.cjs +0 -3
  295. package/scripts/preuninstall.cjs +0 -118
package/README.md CHANGED
@@ -10,7 +10,7 @@ React Native simulator.
10
10
  contains **no rendering code**. The canvas engine (CanvasKit renderer, Yoga
11
11
  layout, iOS/Android shell chrome, Electron shell) lives in the private
12
12
  `sootsim-engine` workspace package and is shipped at runtime as a versioned
13
- tarball, fetched from the contrast.dev CDN and unpacked into `~/.sootsim`.
13
+ tarball, fetched from the contrast.dev CDN and unpacked into `~/.rnx`.
14
14
 
15
15
  What this package gives you:
16
16
 
@@ -87,7 +87,7 @@ graph TD
87
87
  ENGINESHIM["sootsim-engine react-native shim"]
88
88
  end
89
89
  SKILLS["rnxsim/skills registry.ts (builtin skills)"]
90
- subgraph fs["~/.sootsim (home-paths.ts)"]
90
+ subgraph fs["~/.rnx (home-paths.ts)"]
91
91
  RTDIR["runtimes/<version>/ (engine assets)"]
92
92
  LOCK["daemon.json lockfile"]
93
93
  CFG["config.json"]
@@ -149,7 +149,7 @@ Electron is the native desktop surface.
149
149
 
150
150
  **The daemon is one process** — `SootSimBridgeHost` (`src/host/bridge-host.ts`).
151
151
  `rnx serve` runs it in the foreground; the background daemon is the *same
152
- process* wrapped with autostart and the `~/.sootsim/daemon.json` lockfile. It is
152
+ process* wrapped with autostart and the `~/.rnx/daemon.json` lockfile. It is
153
153
  an HTTP+WS hub: sims register over WS, CLI clients connect to drive them, and
154
154
  the host forwards each command to the targeted sim and relays the reply back. It
155
155
  also serves the engine runtime over HTTP (with a self-update route), exposes
@@ -159,7 +159,7 @@ localhost. The `AgentHost` extension owns one FIFO reader per agent session and
159
159
  fans agent events out to every subscriber.
160
160
 
161
161
  During source development, each Vite bridge owns one
162
- `~/.sootsim/dev-bridges/<port>.json` heartbeat record. CLI defaults select the
162
+ `~/.rnx/dev-bridges/<port>.json` heartbeat record. CLI defaults select the
163
163
  current `PORT_OFFSET`, then the current checkout, then the canonical `:7668`
164
164
  bridge, so concurrent worktrees cannot replace or delete one another's address.
165
165
 
@@ -175,7 +175,7 @@ bridge always addresses the **shell worker**, never an undifferentiated sim.
175
175
  and **`rnxsim/metro`** plugins do one thing: serve the installed runtime at
176
176
  `/__soot/` so an app's own dev server can host the sim shell. Both accept an
177
177
  opt-in `open` option that launches a named Electron window when the dev server
178
- starts (skipped when `CI` or `SOOTSIM_NO_OPEN` is set).
178
+ starts (skipped when `CI` or `RNX_NO_OPEN` is set).
179
179
  - The internal **`sootsim()`** plugin (`src/vite-plugin.ts`) is a separate, much
180
180
  larger RN-resolution / native-stub plugin: it aliases `react-native` to the
181
181
  engine shim and native packages to `@sootsim/compat` stubs, applies worklets
@@ -196,20 +196,21 @@ bridge always addresses the **shell worker**, never an undifferentiated sim.
196
196
  | SootSimBridgeHost (serve/daemon) | The bridge process (`rnx serve`, or autostarted as the daemon via launchd/systemd). HTTP+WS hub on `:7668`: relays commands between CLI clients and registered sims; also serves runtime HTTP, `/__server-scan`, and fetch/WS proxies. | `src/host/bridge-host.ts`, `cli/commands/serve.ts`, `cli/commands/daemon.ts`, `src/home-paths.ts` |
197
197
  | AgentHost + sessions | Agent-routing extension of the host: owns the single FIFO reader per agent session and fans `agent:event`/`session-status` pushes to every WS subscriber. Backed by agent-sessions + attached-projects stores. | `src/host/agent-host.ts`, `src/agent-sessions.ts`, `src/attached-projects.ts`, `src/agent-daemon-client.ts` |
198
198
  | host proxies + dev-server scan | Host-side helpers so a cross-origin tenant worker can reach local dev servers and same-origin APIs: `/__server-scan` discovers running metro/expo/vxrn/one servers; fetch + websocket proxies relay guest-app network through the daemon. | `src/host/fetch-proxy-handler.ts`, `src/host/websocket-proxy.ts`, `scripts/dev-server-scanner.ts`, `src/dev-bundle-resolution.ts` |
199
- | runtime delivery + rnx home | Versioned engine runtime management. The shared machinery owns manifest fetch, sha256 verification, channels, and auto-update. rnx binds it to `https://contrast.dev` and `~/.sootsim/runtimes/<version>`. A repo can select `runtimeVersion` without changing the machine default. | `src/runtime-delivery.ts`, `packages/contrast-runtime-delivery/`, `src/home-paths.ts`, `src/runtime-assets.ts`, `scripts/postinstall.cjs` |
200
- | `rnxsim/vite` + `rnxsim/metro` (runtime serving) | Published bundler plugins. Both serve the installed engine runtime at `/__soot/` from `~/.sootsim/runtimes/<version>` so an app's own dev server can host the sim shell; either plugin can opt into a named Electron window. | `src/vite-plugin-one.ts`, `src/metro-plugin.ts`, `src/runtime-assets.ts` |
199
+ | runtime delivery + rnx home | Versioned engine runtime management. The shared machinery owns manifest fetch, sha256 verification, channels, and auto-update. rnx binds it to `https://contrast.dev` and `~/.rnx/runtimes/<version>`. A repo can select `runtimeVersion` without changing the machine default. | `src/runtime-delivery.ts`, `packages/contrast-runtime-delivery/`, `src/home-paths.ts`, `src/runtime-assets.ts` |
200
+ | `rnxsim/vite` + `rnxsim/metro` (runtime serving) | Published bundler plugins. Both serve the installed engine runtime at `/__soot/` from `~/.rnx/runtimes/<version>` so an app's own dev server can host the sim shell; either plugin can opt into a named Electron window. | `src/vite-plugin-one.ts`, `src/metro-plugin.ts`, `src/runtime-assets.ts` |
201
201
  | `sootsim()` vite resolver plugin (internal) | The large RN-resolution / native-stub vite plugin: aliases `react-native` to the engine shim, native packages to `@sootsim/compat` stubs, applies worklets/babel transforms, and instantiates `SootSimBridgeHost` in its dev server. Distinct from the published `rnxsim/vite` export. | `src/vite-plugin.ts`, `src/worklets-babel.ts`, `packages/compat/src/stub-manifest.ts` |
202
202
  | skills registry | rnx agent skills (`rnx-setup`, `rnx-debug`, `rnx-test`, `rnx-visual`, and the generated `contrast` index) installable with `rnx skill`. | `skills/*.md`, `src/skills/registry.ts`, `src/skills/types.ts` |
203
203
 
204
204
  ## Getting started
205
205
 
206
206
  ```sh
207
- npx rnxsim # open ConnectRN and choose a running app in the simulator
207
+ curl -fsSL https://rnxsim.com/install.sh | sh
208
+ rnx # open ConnectRN and choose a running app in the simulator
208
209
  rnx open /settings # dispatch a React Native deep link into that app
209
210
  ```
210
211
 
211
212
  Start Metro, Expo, One, or another supported React Native development server
212
- the way you normally do, then run `npx rnxsim` from any directory. The simulator
213
+ the way you normally do, then run `rnx` from any directory. The simulator
213
214
  opens ConnectRN, which shows the available local apps and lets you connect one.
214
215
  Pass a target to `rnx open <port-or-url>` when a script or agent needs an explicit
215
216
  selection.
@@ -223,10 +224,10 @@ requested target. Use `rnx do reload` when the target has not changed.
223
224
  Reserve `--new` for a genuinely concurrent sim; repeated new browser trees
224
225
  consume memory and CPU on shared machines.
225
226
 
226
- There is no required global or per-app install. Optional global installs can
227
- use `npm install --global rnxsim`, `bun add --global rnxsim`, or
228
- `pnpm add --global rnxsim`. Start your Metro, Expo, or One dev server the way you
229
- already do, then open it from the CLI. There is no iOS native build in the inner loop; Metro alone is
227
+ The public installer places one standalone `rnx` executable in `~/.local/bin`.
228
+ The `rnxsim` npm package contains bundler plugins and library exports, not a CLI
229
+ binary. Start your Metro, Expo, or One dev server the way you already do, then
230
+ open it from the CLI. There is no iOS native build in the inner loop; Metro alone is
230
231
  enough. The manifest bundle path and query remain authoritative. When both the
231
232
  discovery request and manifest target are loopback addresses, RNX keeps the
232
233
  loopback host that answered discovery so an IPv6-only listener is not reopened
@@ -259,7 +260,7 @@ enforced network contract is in [`specs/rnx-privacy.md`](../../specs/rnx-privacy
259
260
 
260
261
  To uninstall the machine daemon and cached runtimes, run
261
262
  `rnx daemon uninstall`. It stops current and legacy launchd / systemd
262
- services, removes daemon logs, and removes `~/.sootsim/` (runtimes, profiles,
263
+ services, removes daemon logs, and removes `~/.rnx/` (runtimes, profiles,
263
264
  recordings, and lockfiles). It does not remove the optional
264
265
  `/Applications/rnx.app` desktop bundle or macOS preference plist. To inspect
265
266
  existing disk usage before uninstalling, run `rnx cleanup`; add `--apply`
@@ -366,7 +367,7 @@ uses about 267 MiB, so the browser remains the recommended first-run path and
366
367
  Electron is an opt-in desktop upgrade. The notarized CLI install did not produce
367
368
  a Gatekeeper prompt on a clean profile. A Mac that previously ran an unsigned
368
369
  development Electron build against the same user-data directory may ask for
369
- one-time Keychain approval. `SOOTSIM_NO_OPEN=1` keeps the server headless. The
370
+ one-time Keychain approval. `RNX_NO_OPEN=1` keeps the server headless. The
370
371
  Metro wrapper also has two independent non-window opt-ins.
371
372
  `devServer` serves the RNX shell from the Metro process. `productionBundles`
372
373
  lets explicitly marked production bundle requests use the RNX host
@@ -442,8 +443,8 @@ rnx debug snapshot before
442
443
  # reproduce the transition
443
444
  rnx debug snapshot after
444
445
  rnx debug diff before after
445
- rnx screenshot --with-frame --output /tmp/sootsim-framed.png
446
- rnx record --duration 5 --output /tmp/sootsim-anim.mp4
446
+ rnx screenshot --with-frame --output /tmp/rnx-framed.png
447
+ rnx record --duration 5 --output /tmp/rnx-anim.mp4
447
448
  ```
448
449
 
449
450
  `rnx screenshot --with-frame` composes the real rnx shell device chrome
@@ -486,7 +487,7 @@ compose:
486
487
  ```
487
488
 
488
489
  ```sh
489
- rnx screenshot appstore --plan .sootsim/app-store.yaml
490
+ rnx screenshot appstore --plan .rnx/app-store.yaml
490
491
  ```
491
492
 
492
493
  The plan runner can reuse a visible sim for capture (`--sim a9`), stop after
@@ -533,10 +534,10 @@ rnx's CDN origin (default `https://contrast.dev`, overridable in
533
534
  them to the shared delivery machinery in `@contrast/runtime-delivery` — an
534
535
  internal workspace package the CLI bundles, so a published install has it
535
536
  inlined. That machinery fetches `runtimes/manifest.json` + the runtime tarball,
536
- verifies its sha256, and unpacks it under `~/.sootsim`:
537
+ verifies its sha256, and unpacks it under `~/.rnx`:
537
538
 
538
539
  ```
539
- ~/.sootsim/
540
+ ~/.rnx/
540
541
  ├── runtimes/
541
542
  │ ├── <active>/ unpacked engine assets (served at /__soot/)
542
543
  │ └── <rollback>/ previous version for rollback
@@ -561,7 +562,7 @@ Per-repo configuration is optional. Every installed-runtime `rnx open`
561
562
  serves its selected version from a version-specific localhost origin, so a
562
563
  background activation cannot mix an already loaded shell with chunks from the
563
564
  next runtime. Without config, each new open selects the active stable version.
564
- When `sootsim.config.ts` sets `runtimeVersion`, `rnx open` installs that
565
+ When `rnx.config.ts` sets `runtimeVersion`, `rnx open` installs that
565
566
  version without changing the machine default. App config, native-linked fonts,
566
567
  and splash assets all resolve from the project root advertised by the selected
567
568
  development server. Bare Metro, which has no Expo manifest project root, uses
@@ -582,13 +583,15 @@ recordings.
582
583
 
583
584
  ## Development and building
584
585
 
585
- This package is part of the Contrast monorepo. To build the published CLI bundle:
586
+ This package is part of the Contrast monorepo. To build the standalone executable
587
+ for the current platform:
586
588
 
587
589
  ```sh
588
- bun run build:cli
590
+ bun run build:cli-binary
589
591
  ```
590
592
 
591
- The output is `dist-cli/bin.js` a single esbuild output published as the
592
- `rnx` (and `rnxsim`) npm bin. Library exports build to `dist-lib/` (consumed via the
593
+ The output is `dist-bin/rnx-<platform>-<arch>`. `dist-cli/bin.js` remains a
594
+ repository build artifact for tests and internal tooling and is not published
595
+ as an npm executable. Library exports build to `dist-lib/` (consumed via the
593
596
  `exports` map: `.`, `./vite`, `./metro`, `./sdk`, `./skills`, `./detox`, and the
594
597
  host/agent helpers). `bun run pack:smoke` validates the publishable tarball.
package/cli/app-config.ts CHANGED
@@ -4,7 +4,7 @@ import { isValidRuntimeVersion } from '@contrast/runtime-delivery'
4
4
  import { createJiti } from 'jiti'
5
5
  import { rnxPublicBrand } from '../src/public-brand'
6
6
  import { resolveAppProject, type ResolvedAppProject } from './app-project'
7
- import type { SootSimConfig } from '../src/config'
7
+ import type { RNXConfig } from '../src/config'
8
8
 
9
9
  const require = createRequire(import.meta.url)
10
10
 
@@ -15,7 +15,7 @@ function isOptionalRecord(value: unknown): boolean {
15
15
  )
16
16
  }
17
17
 
18
- function isSootSimConfig(value: unknown): value is SootSimConfig {
18
+ function isRNXConfig(value: unknown): value is RNXConfig {
19
19
  if (!value || typeof value !== 'object' || Array.isArray(value)) return false
20
20
  const runtimeVersion = Reflect.get(value, 'runtimeVersion')
21
21
  const network = Reflect.get(value, 'network')
@@ -34,10 +34,7 @@ function isSootSimConfig(value: unknown): value is SootSimConfig {
34
34
  )
35
35
  }
36
36
 
37
- function resolveConfigReplacementFiles(
38
- config: SootSimConfig,
39
- configPath: string,
40
- ): SootSimConfig {
37
+ function resolveConfigReplacementFiles(config: RNXConfig, configPath: string): RNXConfig {
41
38
  if (!config.modules) return config
42
39
  const configDir = path.dirname(configPath)
43
40
  return {
@@ -53,9 +50,9 @@ function resolveConfigReplacementFiles(
53
50
  }
54
51
  }
55
52
 
56
- export async function loadSootSimAppConfig(
53
+ export async function loadRNXAppConfig(
57
54
  project: ResolvedAppProject | null,
58
- ): Promise<SootSimConfig | undefined> {
55
+ ): Promise<RNXConfig | undefined> {
59
56
  if (!project?.configPath) return undefined
60
57
  try {
61
58
  const jiti = createJiti(import.meta.url, {
@@ -67,7 +64,7 @@ export async function loadSootSimAppConfig(
67
64
  },
68
65
  })
69
66
  const loaded: unknown = await jiti.import(project.configPath, { default: true })
70
- if (!isSootSimConfig(loaded)) {
67
+ if (!isRNXConfig(loaded)) {
71
68
  throw new Error('the default export must be an rnx config object')
72
69
  }
73
70
  return resolveConfigReplacementFiles(loaded, project.configPath)
@@ -77,9 +74,9 @@ export async function loadSootSimAppConfig(
77
74
  }
78
75
  }
79
76
 
80
- export async function resolveSootSimAppConfig(
77
+ export async function resolveRNXAppConfig(
81
78
  startDir: string = process.cwd(),
82
- ): Promise<{ project: ResolvedAppProject | null; config: SootSimConfig | undefined }> {
79
+ ): Promise<{ project: ResolvedAppProject | null; config: RNXConfig | undefined }> {
83
80
  const project = resolveAppProject(startDir)
84
- return { project, config: await loadSootSimAppConfig(project) }
81
+ return { project, config: await loadRNXAppConfig(project) }
85
82
  }
package/cli/app-fonts.ts CHANGED
@@ -260,9 +260,9 @@ export function discoverNativeLinkedAppFonts(opts: {
260
260
 
261
261
  // resolve a metro dev server's project root. expo serves a manifest at the
262
262
  // server origin carrying `extra.expoClient._internal.projectRoot` — the absolute
263
- // dir of the app being served. the local `sootsim open <port>` path runs from the
263
+ // dir of the app being served. the local `rnx open <port>` path runs from the
264
264
  // CLI's cwd, which almost never owns the bundle being opened (e.g.
265
- // `sootsim open 8081` run from ~/soot against a 3pc metro), so scanning cwd for
265
+ // `rnx open 8081` run from ~/soot against a 3pc metro), so scanning cwd for
266
266
  // font declarations finds nothing.
267
267
  //
268
268
  // a bare react-native packager serves no such manifest, so the same resolver
@@ -355,7 +355,7 @@ export type FetchedAppFont = {
355
355
  // fetch every config-plugin font declared on an engine `?appFonts=` wire.
356
356
  // these typefaces live in the native binary, never in the metro bundle's
357
357
  // __packager_asset graph, so neither asset capture nor recorded fetches see
358
- // them — both the preview (`sootsim record upload`) and build (`sootsim app-fonts
358
+ // them — both the preview (`rnx record upload`) and build (`rnx app-fonts
359
359
  // stage`) paths backfill by re-fetching the declared urls off the still-live
360
360
  // metro. one implementation so both pipelines store identical bytes + keys.
361
361
  export async function fetchAppFontFiles(
@@ -9,11 +9,11 @@ export const EXPO_APP_CONFIG_NAMES = [
9
9
  'app.json',
10
10
  ] as const
11
11
 
12
- export const SOOTSIM_APP_CONFIG_NAMES = [
13
- 'sootsim.config.ts',
14
- 'sootsim.config.js',
15
- 'sootsim.config.mjs',
16
- 'sootsim.config.cjs',
12
+ export const RNX_APP_CONFIG_NAMES = [
13
+ 'rnx.config.ts',
14
+ 'rnx.config.js',
15
+ 'rnx.config.mjs',
16
+ 'rnx.config.cjs',
17
17
  ] as const
18
18
 
19
19
  export interface ResolvedAppProject {
@@ -35,8 +35,8 @@ export function findExpoAppConfig(dir: string): string | null {
35
35
  return firstNamedFile(dir, EXPO_APP_CONFIG_NAMES)
36
36
  }
37
37
 
38
- export function findSootSimAppConfig(dir: string): string | null {
39
- return firstNamedFile(dir, SOOTSIM_APP_CONFIG_NAMES)
38
+ export function findRNXAppConfig(dir: string): string | null {
39
+ return firstNamedFile(dir, RNX_APP_CONFIG_NAMES)
40
40
  }
41
41
 
42
42
  export function resolveAppProject(projectRoot: string): ResolvedAppProject | null {
@@ -47,7 +47,7 @@ export function resolveAppProject(projectRoot: string): ResolvedAppProject | nul
47
47
  return null
48
48
  }
49
49
 
50
- const configPath = findSootSimAppConfig(appDir)
50
+ const configPath = findRNXAppConfig(appDir)
51
51
  if (
52
52
  !configPath &&
53
53
  !findExpoAppConfig(appDir) &&
package/cli/auth.ts CHANGED
@@ -1,7 +1,7 @@
1
- // sootsim cli auth resolution for cloud-hitting commands.
1
+ // rnx cli auth resolution for cloud-hitting commands.
2
2
  //
3
3
  // priority order (first match wins):
4
- // 1. RNX_API_KEY, or SOOTSIM_API_KEY if that is unset — ci path
4
+ // 1. RNX_API_KEY — ci path
5
5
  // 2. CONTRAST_INSTALLATION_TOKEN/GITHUB_TOKEN + repo env — github action
6
6
  // preview uploads from the Contrast runner, no extra secret
7
7
  // 3. desktop session token from shared desktop auth (`rnx login`)
@@ -11,7 +11,7 @@
11
11
  import { readSharedDesktopAuthSession } from '../src/auth/shared-session'
12
12
  import { rnxExit } from './run-rnx'
13
13
 
14
- export type CliApiKeyEnvName = 'RNX_API_KEY' | 'SOOTSIM_API_KEY'
14
+ export type CliApiKeyEnvName = 'RNX_API_KEY'
15
15
 
16
16
  export type CliAuth =
17
17
  | { kind: 'api-key'; secret: string; source: 'env'; envName: CliApiKeyEnvName }
@@ -93,15 +93,13 @@ function resolveGitHubActionsAuth(): CliAuth | null {
93
93
  }
94
94
 
95
95
  function isCliApiKeySecret(secret: string): boolean {
96
- return secret.startsWith('sk_rnx_') || secret.startsWith('sk_sootsim_')
96
+ return secret.startsWith('sk_rnx_')
97
97
  }
98
98
 
99
99
  function readApiKeyFromEnv(): { secret: string; envName: CliApiKeyEnvName } | null {
100
- for (const envName of ['RNX_API_KEY', 'SOOTSIM_API_KEY'] as const) {
101
- const secret = process.env[envName]?.trim()
102
- if (secret && isCliApiKeySecret(secret)) return { secret, envName }
103
- }
104
- return null
100
+ const envName = 'RNX_API_KEY'
101
+ const secret = process.env[envName]?.trim()
102
+ return secret && isCliApiKeySecret(secret) ? { secret, envName } : null
105
103
  }
106
104
 
107
105
  export function resolveCliAuth(): CliAuth | null {
package/cli/bin.ts CHANGED
@@ -9,6 +9,7 @@
9
9
  import { rnxPublicBrand } from '../src/public-brand'
10
10
  import { parseArgs, TOP_LEVEL_RUNTIME_COMMANDS } from './parse-args'
11
11
  import { RnxExit } from './run-rnx'
12
+ import { IS_STANDALONE } from './standalone'
12
13
 
13
14
  // `./help` is loaded lazily (only on help paths) — it statically pulls the full
14
15
  // CLI registry renderers and engine settings, which would otherwise add ~400ms
@@ -54,28 +55,8 @@ function handleTopLevelError(err: unknown): never {
54
55
  process.on('unhandledRejection', handleTopLevelError)
55
56
  process.on('uncaughtException', handleTopLevelError)
56
57
 
57
- // set to `true` by build-cli-binary.ts via esbuild define. in the standalone
58
- // binary, commands that rely on vite / electron / playwright from the user's
59
- // node_modules can't run — gate them with a friendly message rather than
60
- // letting the dynamic import fail with a confusing module-not-found error.
61
- declare const __SOOTSIM_STANDALONE__: boolean | undefined
62
- const IS_STANDALONE =
63
- typeof __SOOTSIM_STANDALONE__ !== 'undefined' && __SOOTSIM_STANDALONE__
64
-
65
- const STANDALONE_BLOCKED_COMMANDS = new Set(['desktop'])
66
-
67
- function exitIfStandaloneBlocked(cmd: string): void {
68
- if (!IS_STANDALONE || !STANDALONE_BLOCKED_COMMANDS.has(cmd)) return
69
- process.stderr.write(
70
- ` ${rnxPublicBrand.commandName} ${cmd} isn't available in the standalone binary —\n` +
71
- ` it needs vite / electron / playwright from a project's node_modules.\n` +
72
- ` run the npm package instead:\n` +
73
- ` ${rnxPublicBrand.commandName} ${cmd}\n`,
74
- )
75
- process.exit(1)
76
- }
77
-
78
58
  let parsed = parseArgs(process.argv)
59
+ for (const warning of parsed.warnings) process.stderr.write(`${warning}\n`)
79
60
 
80
61
  // runtime actions and reads also work as hidden root aliases. resolve only
81
62
  // after the normal parser declined the token, so a real top-level command
@@ -90,6 +71,8 @@ const isAutomaticCleanupWorker =
90
71
  parsed.commandArgs.length === 1 &&
91
72
  parsed.commandArgs[0] === '--automatic-worker'
92
73
  const isBareWelcome = !parsed.command && parsed.commandArgs.length === 0
74
+ const isReadOnlyInvocation =
75
+ parsed.version || parsed.help || parsed.commandArgs.includes('--dry-run')
93
76
 
94
77
  if (
95
78
  !isAutomaticCleanupWorker &&
@@ -109,7 +92,7 @@ if (
109
92
  // interactive command runs next prints it once (stderr, so --json stdout
110
93
  // stays parseable) and deletes it. the daemon/serve processes skip it so a
111
94
  // background process can't eat the notice before a human sees it.
112
- if (parsed.command !== 'serve' && parsed.command !== 'daemon') {
95
+ if (!isReadOnlyInvocation && parsed.command !== 'serve' && parsed.command !== 'daemon') {
113
96
  const { consumeRuntimeUpgradeNotice } = await import('../src/home-paths')
114
97
  const notice = consumeRuntimeUpgradeNotice()
115
98
  if (notice) {
@@ -126,6 +109,7 @@ async function scheduleAutomaticCleanup(): Promise<void> {
126
109
  if (automaticCleanupFinished) return
127
110
  automaticCleanupFinished = true
128
111
  if (
112
+ isReadOnlyInvocation ||
129
113
  parsed.command === 'cleanup' ||
130
114
  parsed.command === 'serve' ||
131
115
  parsed.command === 'agent-wrapper' ||
@@ -193,7 +177,7 @@ if (parsed.version) {
193
177
  console.log(`${rnxPublicBrand.commandName} v${getCliVersion()}${suffix}`)
194
178
  // runtime version on its own line — keeps the first line parseable while
195
179
  // surfacing the (independently-versioned) engine runtime users actually
196
- // render with. see `sootsim upgrade`.
180
+ // render with. see `rnx upgrade`.
197
181
  const { readActiveRuntime } = await import('../src/home-paths')
198
182
  const runtime = readActiveRuntime()
199
183
  console.log(runtime ? `runtime v${runtime}` : 'runtime not installed')
@@ -281,8 +265,8 @@ if (
281
265
  await exitWithFlush(await runReset(commandArgsWithSim, { port }))
282
266
  }
283
267
  // for grouping verbs, try to resolve per-verb help from the first
284
- // positional arg. e.g. `sootsim do tap --help` shows tap's help page,
285
- // not the generic `do` grouping page. bare `sootsim do --help` falls
268
+ // positional arg. e.g. `rnx do tap --help` shows tap's help page,
269
+ // not the generic `do` grouping page. bare `rnx do --help` falls
286
270
  // through to runInspect which has the full verb group listing.
287
271
  const isGroupingVerb =
288
272
  command === 'do' ||
@@ -312,12 +296,6 @@ if (
312
296
  }
313
297
  }
314
298
 
315
- // gate heavy commands in the standalone binary before any dynamic imports
316
- // fire. the imports themselves would also fail (vite / electron etc. are
317
- // kept external from the bundle), but the resulting module-not-found error
318
- // is much harder to act on than this targeted message.
319
- exitIfStandaloneBlocked(command)
320
-
321
299
  // the command modules stop by throwing RnxExit rather than ending the
322
300
  // process, because the same command has to run in a box shell and in
323
301
  // workerd, where process.exit() cancels the whole request. this is the
@@ -453,6 +431,13 @@ try {
453
431
  await exitWithFlush(typeof code === 'number' ? code : 0)
454
432
  }
455
433
 
434
+ case 'web': {
435
+ const { getRnxCommandAvailability } = await import('./command-registry')
436
+ const availability = getRnxCommandAvailability('web', parsed.commandArgs, 'node')
437
+ console.error(` ${availability.reason ?? 'rnx web is unavailable'}`)
438
+ await exitWithFlush(1)
439
+ }
440
+
456
441
  case 'box': {
457
442
  const { runBox } = await import('./commands/box')
458
443
  await exitWithFlush(await runBox(commandArgsWithSim, { port, verbose }))
@@ -432,7 +432,7 @@ export class SootSimBridgeFlowRunner {
432
432
  screenshotPathMode?: FlowScreenshotPathMode
433
433
  // flow-wide default for screenshot layers — applied to every
434
434
  // takeScreenshot step unless that step has its own `layers:`. set by
435
- // `sootsim maestro test --no-shell` to produce clean tenant-only captures
435
+ // `rnx maestro test --no-shell` to produce clean tenant-only captures
436
436
  // (useful when a stuck shell overlay would otherwise pollute the
437
437
  // demo asset set).
438
438
  screenshotLayers?: 'full' | 'tenant' | 'shell'
@@ -688,7 +688,7 @@ export class SootSimBridgeFlowRunner {
688
688
  const extension = videoMime.includes('mp4') ? 'mp4' : 'webm'
689
689
  const outputPath = path.join(
690
690
  this.opts.recordingOutputDir,
691
- `sootsim-${Date.now()}.${extension}`,
691
+ `rnx-${Date.now()}.${extension}`,
692
692
  )
693
693
  fs.writeFileSync(outputPath, Buffer.concat(chunks))
694
694
  return outputPath
@@ -1573,7 +1573,7 @@ export class SootSimBridgeFlowRunner {
1573
1573
  if (typeof tree === 'string') write('tree.txt', tree)
1574
1574
 
1575
1575
  // 6. console buffer + failed requests (captured by sootsim's native-globals
1576
- // hook / request recorder; same shape as `sootsim get errors` etc.).
1576
+ // hook / request recorder; same shape as `rnx get errors` etc.).
1577
1577
  const consoleBuf = await safeEval<{
1578
1578
  errors: unknown[]
1579
1579
  warnings: unknown[]
@@ -0,0 +1,44 @@
1
+ import type {
2
+ RnxBrowserOperations,
3
+ RnxCommandBackend,
4
+ RnxCommandInvocation,
5
+ RnxExecutionContext,
6
+ } from './command-contract'
7
+
8
+ export function createRnxBrowserBackend(
9
+ operations: RnxBrowserOperations,
10
+ ): RnxCommandBackend {
11
+ return {
12
+ kind: 'browser',
13
+ execute(invocation: RnxCommandInvocation, context: RnxExecutionContext) {
14
+ switch (invocation.family) {
15
+ case 'preview':
16
+ return operations.selectPreview(invocation, context)
17
+ case 'runtime':
18
+ return operations.readRuntime(invocation, context)
19
+ case 'tree':
20
+ return operations.inspectTree(invocation, context)
21
+ case 'layout':
22
+ return operations.inspectLayout(invocation, context)
23
+ case 'find':
24
+ return operations.find(invocation, context)
25
+ case 'wait':
26
+ return operations.wait(invocation, context)
27
+ case 'action':
28
+ return operations.act(invocation, context)
29
+ case 'screenshot':
30
+ return operations.screenshot(invocation, context)
31
+ case 'logs':
32
+ return operations.readLogs(invocation, context)
33
+ case 'network':
34
+ return operations.readNetwork(invocation, context)
35
+ case 'storage':
36
+ return operations.accessStorage(invocation, context)
37
+ case 'history':
38
+ return operations.readHistory(invocation, context)
39
+ case 'evidence':
40
+ return operations.collectEvidence(invocation, context)
41
+ }
42
+ },
43
+ }
44
+ }