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
@@ -0,0 +1,136 @@
1
+ import { cliCommandMetas } from '@sootsim/skills/cli'
2
+ import {
3
+ renderCliCommandHelp,
4
+ renderCliGroupHelp,
5
+ renderCliIndexHelp,
6
+ } from '@sootsim/skills/cli/renderers'
7
+ import { formatFlagHelp } from 'sootsim-engine/settings/cli-flags'
8
+ import {
9
+ DEFAULT_SOOTSIM_BRIDGE_PORT,
10
+ DEFAULT_SOOTSIM_BRIDGE_URL,
11
+ } from '../src/bridge-constants'
12
+ import {
13
+ getRnxCommandAvailability,
14
+ getRnxFirstPositional,
15
+ getRnxCommandRegistration,
16
+ RNX_COMMAND_REGISTRY,
17
+ } from './command-registry'
18
+ import type { RnxBackendKind } from './command-contract'
19
+
20
+ export interface RnxHelpOptions {
21
+ backend: RnxBackendKind
22
+ command?: string | null
23
+ commandArgs?: string[]
24
+ prefer?: 'command' | 'verb'
25
+ group?: string | null
26
+ }
27
+
28
+ const HELP_CONTEXT = {
29
+ bridgePort: DEFAULT_SOOTSIM_BRIDGE_PORT,
30
+ defaultShellUrl: DEFAULT_SOOTSIM_BRIDGE_URL,
31
+ }
32
+
33
+ function backendLabel(command: string, args: readonly string[]): string {
34
+ const available = (['node', 'browser'] satisfies RnxBackendKind[]).filter(
35
+ (backend) => getRnxCommandAvailability(command, args, backend).available,
36
+ )
37
+ return `available backends: ${available.join(', ')}`
38
+ }
39
+
40
+ function renderWebHelp(): string {
41
+ return `rnx web — select or ensure the current branch's existing web preview
42
+
43
+ usage:
44
+ rnx web
45
+
46
+ The browser backend selects the Factory-owned web iframe. It never launches a
47
+ browser, host process, or Cloudflare runtime.`
48
+ }
49
+
50
+ function renderFactoryBrowserLeaves(command: string): string | null {
51
+ switch (command) {
52
+ case 'do':
53
+ return `Factory browser leaves:
54
+ rnx do navigate /route`
55
+ case 'shell':
56
+ return `Factory browser leaves:
57
+ rnx shell appearance light|dark`
58
+ case 'assert':
59
+ return `Factory browser leaves:
60
+ rnx assert find (--testid <id>|--text <text>|--role <role>) [--exists|--empty] [--contains <text>]`
61
+ case 'screenshot':
62
+ return `Factory browser leaves:
63
+ rnx screenshot
64
+ rnx screenshot ask <question>
65
+ rnx screenshot appearance light|dark /route --by <query-kind> --value <target>
66
+ rnx screenshot motion <task-id> /route --trigger-by <kind> --trigger-value <target> --result-by <kind> --result-value <target> [--duration-ms <100..2000>]`
67
+ default:
68
+ return null
69
+ }
70
+ }
71
+
72
+ function renderRootAvailability(backend: RnxBackendKind): string {
73
+ const visibleCommands = new Set([...cliCommandMetas.map((meta) => meta.id), 'web'])
74
+ const visibleRegistry = RNX_COMMAND_REGISTRY.filter((entry) =>
75
+ visibleCommands.has(entry.name),
76
+ )
77
+ const available = visibleRegistry
78
+ .filter((entry) => getRnxCommandAvailability(entry.name, [], backend).available)
79
+ .map((entry) => entry.name)
80
+ const unavailable = visibleRegistry
81
+ .filter((entry) => !getRnxCommandAvailability(entry.name, [], backend).available)
82
+ .map((entry) => entry.name)
83
+
84
+ return `backend availability (${backend}):
85
+ available: ${available.join(', ')}
86
+ unavailable: ${unavailable.join(', ')}
87
+
88
+ Run \`rnx <command> --help\` for leaf availability and usage.`
89
+ }
90
+
91
+ export function renderRnxHelp(options: RnxHelpOptions): string {
92
+ const command = options.command ?? null
93
+ const commandArgs = options.commandArgs ?? []
94
+ if (!command) {
95
+ return `${renderCliIndexHelp(HELP_CONTEXT, formatFlagHelp()).trimEnd()}
96
+
97
+ browser preview selector:
98
+ rnx web select the existing Factory web preview
99
+
100
+ ${renderRootAvailability(options.backend)}`
101
+ }
102
+
103
+ let body: string | null
104
+ if (command === 'web') {
105
+ body = renderWebHelp()
106
+ } else if (options.group === command && !options.prefer) {
107
+ body = renderCliGroupHelp(command, HELP_CONTEXT, formatFlagHelp())
108
+ } else {
109
+ const subVerb = getRnxFirstPositional(commandArgs)
110
+ const grouping = new Set(['do', 'get', 'debug', 'wait'])
111
+ const helpName = options.prefer === 'verb' && subVerb ? subVerb : command
112
+ body = renderCliCommandHelp(helpName, HELP_CONTEXT, {
113
+ prefer: options.prefer,
114
+ group: options.group,
115
+ })
116
+ if (!body && grouping.has(command)) {
117
+ body = renderCliGroupHelp(command, HELP_CONTEXT, formatFlagHelp())
118
+ }
119
+ }
120
+
121
+ if (!body) return `unknown command: ${command}`
122
+
123
+ const registration = getRnxCommandRegistration(command)
124
+ if (!registration) return body
125
+ const current = getRnxCommandAvailability(command, commandArgs, options.backend)
126
+ const currentLine = current.available
127
+ ? `${options.backend} backend: available`
128
+ : `${options.backend} backend: ${current.reason}`
129
+ const factoryLeaves =
130
+ options.backend === 'browser' ? renderFactoryBrowserLeaves(command) : null
131
+ return `${body.trimEnd()}
132
+
133
+ ${factoryLeaves ? `${factoryLeaves}\n\n` : ''}${backendLabel(command, commandArgs)}
134
+
135
+ ${currentLine}`
136
+ }
package/cli/help.ts CHANGED
@@ -1,61 +1,29 @@
1
- import {
2
- renderCliCommandHelp,
3
- renderCliGroupHelp,
4
- renderCliIndexHelp,
5
- } from '@sootsim/skills/cli/renderers'
6
- import { formatFlagHelp } from 'sootsim-engine/settings/cli-flags'
7
1
  import { BETA_TAGLINE, IS_BETA } from '../src/beta'
8
- import {
9
- DEFAULT_SOOTSIM_BRIDGE_PORT,
10
- DEFAULT_SOOTSIM_BRIDGE_URL,
11
- } from '../src/bridge-constants'
12
2
  import { getCliVersion } from '../src/cli-version'
13
3
  import { rnxPublicBrand } from '../src/public-brand'
4
+ import { renderRnxHelp } from './help-core'
14
5
  import { maybeHint } from './hints'
15
6
  import { getRuntimeSummary } from './runtime-summary'
16
7
 
17
- // header line shown at the top of `--help` so users can always tell what
18
- // they're running — the CLI npm version and the active engine runtime
19
- // version are independent, which is exactly the confusion `sootsim
20
- // upgrade` exists to clear up.
21
8
  function versionSummaryLine(): string {
22
9
  return `${rnxPublicBrand.commandName} CLI v${getCliVersion()} · ${getRuntimeSummary().primary}`
23
10
  }
24
11
 
25
- export function printHelp() {
26
- const base = renderCliIndexHelp(
27
- {
28
- bridgePort: DEFAULT_SOOTSIM_BRIDGE_PORT,
29
- defaultShellUrl: DEFAULT_SOOTSIM_BRIDGE_URL,
30
- },
31
- formatFlagHelp(),
32
- )
12
+ export function printHelp(): void {
33
13
  const betaLine = IS_BETA ? `\n${BETA_TAGLINE}\n` : ''
34
14
  console.log(
35
- `${versionSummaryLine()}\n${betaLine}${base}
36
- `,
15
+ `${versionSummaryLine()}\n${betaLine}${renderRnxHelp({ backend: 'node' })}\n`,
37
16
  )
38
- // once-ever nudge so users learn the clean teardown path before they need it.
39
- // the npm preuninstall hook runs the same teardown automatically when it
40
- // fires; this is the documented manual fallback.
41
17
  maybeHint('clean-uninstall')
42
18
  }
43
19
 
44
- // bare `sootsim` prints the registry-backed surface. setup/open own work.
45
-
46
- // print the help page for a grouping verb (do / get / debug / wait) built
47
- // entirely from the registry — no hardcoded strings. returns true if the
48
- // group was known, false if the caller should fall through.
49
20
  export function printGroupHelp(group: string): boolean {
50
- const output = renderCliGroupHelp(
21
+ const output = renderRnxHelp({
22
+ backend: 'node',
23
+ command: group,
51
24
  group,
52
- {
53
- bridgePort: DEFAULT_SOOTSIM_BRIDGE_PORT,
54
- defaultShellUrl: DEFAULT_SOOTSIM_BRIDGE_URL,
55
- },
56
- formatFlagHelp(),
57
- )
58
- if (!output) return false
25
+ })
26
+ if (output.startsWith('unknown command:')) return false
59
27
  console.log(`${output}\n`)
60
28
  return true
61
29
  }
@@ -63,18 +31,14 @@ export function printGroupHelp(group: string): boolean {
63
31
  export function printCommandHelp(
64
32
  name: string,
65
33
  options: { prefer?: 'command' | 'verb'; group?: string | null } = {},
66
- ) {
67
- const output = renderCliCommandHelp(
68
- name,
69
- {
70
- bridgePort: DEFAULT_SOOTSIM_BRIDGE_PORT,
71
- defaultShellUrl: DEFAULT_SOOTSIM_BRIDGE_URL,
72
- },
73
- options,
74
- )
75
- if (!output) {
76
- console.log(`unknown command: ${name}`)
77
- return
78
- }
34
+ ): void {
35
+ const command = options.group ?? name
36
+ const output = renderRnxHelp({
37
+ backend: 'node',
38
+ command,
39
+ commandArgs: options.group ? [name] : [],
40
+ prefer: options.prefer,
41
+ group: options.group,
42
+ })
79
43
  console.log(`${output}\n`)
80
44
  }
package/cli/hints.ts CHANGED
@@ -46,11 +46,11 @@ interface HintStateFile {
46
46
  const STATE_VERSION = 1 as const
47
47
 
48
48
  function identityStatePath(): string {
49
- return join(tmpdir(), `sootsim-cli-hints-${getCliIdentityKey()}.json`)
49
+ return join(tmpdir(), `rnx-cli-hints-${getCliIdentityKey()}.json`)
50
50
  }
51
51
 
52
52
  function globalStatePath(): string {
53
- return join(tmpdir(), `sootsim-cli-hints-global.json`)
53
+ return join(tmpdir(), `rnx-cli-hints-global.json`)
54
54
  }
55
55
 
56
56
  function readState(path: string): HintStateFile {
@@ -76,7 +76,7 @@ function writeState(path: string, state: HintStateFile) {
76
76
  }
77
77
 
78
78
  function modeFromEnv(): 'normal' | 'always' | 'off' {
79
- const v = (process.env.SOOTSIM_HINTS || '').toLowerCase()
79
+ const v = (process.env.RNX_HINTS || '').toLowerCase()
80
80
  if (v === 'off' || v === '0' || v === 'false') return 'off'
81
81
  if (v === 'always' || v === 'verbose') return 'always'
82
82
  return 'normal'
@@ -119,7 +119,7 @@ function shouldShow(id: string, frequency: HintFrequency): boolean {
119
119
  export function maybeHint(id: string, ...args: unknown[]): boolean {
120
120
  const spec = registry.get(id)
121
121
  if (!spec) {
122
- if (process.env.SOOTSIM_HINTS_DEBUG) {
122
+ if (process.env.RNX_HINTS_DEBUG) {
123
123
  console.error(` [hints] no hint registered for id "${id}"`)
124
124
  }
125
125
  return false
@@ -210,7 +210,7 @@ defineHint<[]>('clean-uninstall', {
210
210
  // hint documents the explicit daemon cleanup command.
211
211
  frequency: 'once-ever',
212
212
  render: () => [
213
- `to remove the background daemon and all ~/.sootsim data, run \`rnx daemon uninstall\`.`,
213
+ `to remove the background daemon and all ~/.rnx data, run \`rnx daemon uninstall\`.`,
214
214
  `the optional desktop app and its macOS preference plist are separate from the daemon.`,
215
215
  ],
216
216
  })
@@ -23,7 +23,7 @@ interface InspectNoticeState {
23
23
  export function getInspectNoticeStatePath() {
24
24
  return resolve(
25
25
  process.env[INSPECT_NOTICE_PATH_ENV] ||
26
- join(tmpdir(), 'sootsim-inspect-notice-state.json'),
26
+ join(tmpdir(), 'rnx-inspect-notice-state.json'),
27
27
  )
28
28
  }
29
29
 
package/cli/maestro-js.ts CHANGED
@@ -17,7 +17,7 @@
17
17
  // divergences (deliberate, sootsim-side ergonomics — keep this list short):
18
18
  // 1. envBinding is seeded from the full process.env, not just MAESTRO_*.
19
19
  // sootsim flows historically resolve `${SOOTSIM_*}` credentials from the
20
- // shell environment and `sootsim maestro --env K=V` writes process.env.
20
+ // shell environment and `rnx maestro --env K=V` writes process.env.
21
21
  // 2. a *bare identifier* template (`${NAME}`) that evaluates to undefined
22
22
  // throws a loud "missing variable" error instead of interpolating the
23
23
  // literal text "undefined" into a tap target or login form. complex
@@ -9,6 +9,7 @@ export type OutboundCategory =
9
9
  | 'local-development'
10
10
  | 'same-origin-runtime'
11
11
  | 'guest-app-network'
12
+ | 'release-delivery'
12
13
 
13
14
  export interface OutboundEndpointDeclaration {
14
15
  category: OutboundCategory
@@ -38,11 +39,18 @@ export const OUTBOUND_ENDPOINTS: Record<string, OutboundEndpointDeclaration> = {
38
39
  payload:
39
40
  'explicit auth, billing, preview, issue report, test, or generated-flow request; a stored login may refresh auth/subscription state',
40
41
  },
41
- npm_update_check: {
42
+ cli_delivery: {
42
43
  category: 'explicit-user-action',
43
- destination: 'https://registry.npmjs.org/rnxsim/latest',
44
+ destination:
45
+ 'https://r2.rnxsim.com/rnx-cli/channels/stable and the selected executable/checksum',
46
+ preConsent: false,
47
+ payload: 'requested CLI version, platform, and architecture only',
48
+ },
49
+ cli_release_publish: {
50
+ category: 'release-delivery',
51
+ destination: 'configured R2 origin and https://r2.rnxsim.com/rnx-cli',
44
52
  preConsent: false,
45
- payload: 'package update request only',
53
+ payload: 'release executables, checksums, version, and source identity',
46
54
  },
47
55
  release_notes: {
48
56
  category: 'explicit-user-action',
@@ -332,10 +340,20 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
332
340
  { category: 'contrast_user_action', count: 1 },
333
341
  'packages/sootsim/cli/commands/screenshots-capture.ts :: fetch :: `${apiOrigin}/api/sootsim/screenshot-decks?org=${encodeURIComponent(org)}&repo=${encodeURIComponent(repo)}`':
334
342
  { category: 'contrast_user_action', count: 1 },
335
- 'packages/sootsim/cli/commands/upgrade.ts :: fetch :: REGISTRY_LATEST_URL': {
336
- category: 'npm_update_check',
343
+ 'packages/sootsim/cli/commands/upgrade.ts :: fetch :: url': {
344
+ category: 'cli_delivery',
337
345
  count: 1,
338
346
  },
347
+ 'packages/sootsim/scripts/publish-cli-binaries.ts :: fetch :: `${url}?sha256=${digest}`':
348
+ {
349
+ category: 'cli_release_publish',
350
+ count: 1,
351
+ },
352
+ 'packages/sootsim/scripts/publish-cli-binaries.ts :: fetch :: `${publicOrigin}/${channelKey}?sourceSha=${sourceSha}`':
353
+ {
354
+ category: 'cli_release_publish',
355
+ count: 1,
356
+ },
339
357
  'packages/sootsim/cli/commands/upload.ts :: fetch :: url': {
340
358
  category: 'presigned_upload',
341
359
  count: 1,
package/cli/parse-args.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  // shared CLI argument parser — handles global flags, commands, and per-command flags
2
2
 
3
+ import { RNX_COMMAND_NAMES, RNX_NODE_COMMAND_NAMES } from './command-registry'
4
+
3
5
  export interface ParsedArgs {
4
6
  command: string | null
5
7
  commandArgs: string[]
@@ -7,6 +9,7 @@ export interface ParsedArgs {
7
9
  help: boolean
8
10
  version: boolean
9
11
  verbose: boolean
12
+ warnings: string[]
10
13
  }
11
14
 
12
15
  const GLOBAL_FLAGS: Record<
@@ -30,9 +33,9 @@ const GLOBAL_FLAGS: Record<
30
33
 
31
34
  // top-level verbs that route into runInspect. the surface is intentionally
32
35
  // tiny — everything else lives under one of the grouping verbs:
33
- // - `sootsim get <noun>` reads
34
- // - `sootsim do <action>` writes
35
- // - `sootsim debug <tool>` instrumentation (handled by runDebug)
36
+ // - `rnx get <noun>` reads
37
+ // - `rnx do <action>` writes
38
+ // - `rnx debug <tool>` instrumentation (handled by runDebug)
36
39
  // `describe` and `find` stay at root as the most common entrypoints.
37
40
  // `list` stays at root because it's a sim-management read.
38
41
  export const TOP_LEVEL_RUNTIME_COMMANDS = new Set([
@@ -47,9 +50,9 @@ export const TOP_LEVEL_RUNTIME_COMMANDS = new Set([
47
50
  'shell',
48
51
  ])
49
52
 
50
- // grouping verbs that take a sub-verb (`sootsim wait ready`,
51
- // `sootsim do tap-id`). agents and humans very often type the hyphenated
52
- // form (`sootsim wait-ready`, `sootsim do-tap-id`) — it reads as one
53
+ // grouping verbs that take a sub-verb (`rnx wait ready`,
54
+ // `rnx do tap-id`). agents and humans very often type the hyphenated
55
+ // form (`rnx wait-ready`, `rnx do-tap-id`) — it reads as one
53
56
  // command and matches the typed-tool names (rnx_wait_ready). bin.ts
54
57
  // normalizes `<verb>-<rest>` → `<verb> <rest>` for these so the intuitive
55
58
  // spelling just works instead of failing as "unknown command".
@@ -60,64 +63,9 @@ export const HYPHENATED_GROUPING_VERBS = new Set(['do', 'get', 'wait', 'shell',
60
63
  // `packages/sootsim-skills/src/cli/meta.ts` (or sit on the internal
61
64
  // allowlist in `test/sootsimCliRegistry.test.ts`), so help, website docs,
62
65
  // and agent skills can never drift from what the parser accepts.
63
- export const COMMANDS = new Set([
64
- 'detox',
65
- 'maestro',
66
- 'record',
67
- 'film',
68
- 'storage',
69
- 'permissions',
70
- 'perf',
71
- 'screenshot',
72
- 'state',
73
- 'reset',
74
- 'camera',
75
- 'mode',
76
- 'debug',
77
- 'timeline',
78
- 'what-happened',
79
- 'shell',
80
- 'assert',
81
- 'device',
82
- 'open',
83
- // platform entrypoints — start a simulator on that platform. the execution
84
- // environment (host, local box, cloud box) comes from the command context,
85
- // not from a separate spelling per place.
86
- 'ios',
87
- 'android',
88
- // the box environment: bare `box` is local, `box create` is cloud.
89
- 'box',
90
- 'list',
91
- 'use',
92
- 'claim',
93
- 'close',
94
- 'compat',
95
- 'report-issue',
96
- 'desktop',
97
- 'login',
98
- 'logout',
99
- 'auth',
100
- 'setup',
101
- 'serve',
102
- 'daemon',
103
- 'runtime',
104
- 'upgrade',
105
- 'version',
106
- 'skill',
107
- 'config',
108
- 'cleanup',
109
- // stage config-plugin fonts into a build's asset manifest (run.sh build path)
110
- 'app-fonts',
111
- // internal — not user-facing, spawned as a subprocess by electron main
112
- // and by `sootsim agent start`.
113
- 'agent-wrapper',
114
- // attached projects + local agent sessions.
115
- 'agent',
116
- ...TOP_LEVEL_RUNTIME_COMMANDS,
117
- ])
66
+ export const COMMANDS = new Set(RNX_NODE_COMMAND_NAMES)
118
67
 
119
- export function parseArgs(argv: string[]): ParsedArgs {
120
- const args = argv.slice(2)
68
+ export function parseRnxArgs(args: string[]): ParsedArgs {
121
69
  const result: ParsedArgs = {
122
70
  command: null,
123
71
  commandArgs: [],
@@ -125,6 +73,7 @@ export function parseArgs(argv: string[]): ParsedArgs {
125
73
  help: false,
126
74
  version: false,
127
75
  verbose: false,
76
+ warnings: [],
128
77
  }
129
78
 
130
79
  let i = 0
@@ -154,14 +103,14 @@ export function parseArgs(argv: string[]): ParsedArgs {
154
103
  const val = args[i + 1]
155
104
  if (val === undefined || val.startsWith('-')) {
156
105
  // missing value — treat as error, pass through
157
- console.error(` warning: ${arg} requires a value`)
106
+ result.warnings.push(` warning: ${arg} requires a value`)
158
107
  i++
159
108
  continue
160
109
  }
161
110
  if (def.type === 'number') {
162
111
  const num = Number(val)
163
112
  if (Number.isNaN(num)) {
164
- console.error(` warning: ${arg} requires a number, got "${val}"`)
113
+ result.warnings.push(` warning: ${arg} requires a number, got "${val}"`)
165
114
  i += 2
166
115
  continue
167
116
  }
@@ -193,7 +142,7 @@ export function parseArgs(argv: string[]): ParsedArgs {
193
142
  break
194
143
  }
195
144
  }
196
- if (COMMANDS.has(arg)) {
145
+ if (RNX_COMMAND_NAMES.has(arg)) {
197
146
  result.command = arg
198
147
  const rest = args.slice(i + 1)
199
148
  // strip leading -- separator if present
@@ -217,3 +166,7 @@ export function parseArgs(argv: string[]): ParsedArgs {
217
166
 
218
167
  return result
219
168
  }
169
+
170
+ export function parseArgs(argv: string[]): ParsedArgs {
171
+ return parseRnxArgs(argv.slice(2))
172
+ }
@@ -42,7 +42,7 @@ export interface RecordingEntitlementOptions {
42
42
  * origin stored in the shared desktop session. */
43
43
  originOverride?: string
44
44
  /** allow GitHub installation/action auth to record for pr preview uploads.
45
- * this is intentionally opt-in so local `sootsim record` stays tied to
45
+ * this is intentionally opt-in so local `rnx record` stays tied to
46
46
  * the user's paid/trial desktop entitlement. */
47
47
  allowGitHubAuth?: boolean
48
48
  }
package/cli/registry.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from '@sootsim/skills/cli'
2
+ export * from './command-registry'
@@ -99,7 +99,7 @@ export function resolveRunProvenance(): RunProvenance {
99
99
 
100
100
  const branch = contrastBranch ?? gitOutput('git rev-parse --abbrev-ref HEAD')
101
101
  // env slug wins when present; otherwise infer from the github remote so a
102
- // a plain local `sootsim maestro test --preview` still lands on its repo's dashboard.
102
+ // a plain local `rnx maestro test --preview` still lands on its repo's dashboard.
103
103
  const remote = envOwner ? null : ownerRepoFromGitRemote()
104
104
  return {
105
105
  owner: envOwner ?? remote?.owner ?? null,
@@ -0,0 +1,148 @@
1
+ import {
2
+ createRnxCommandInvocation,
3
+ getRnxCommandAvailability,
4
+ getRnxFirstPositional,
5
+ } from './command-registry'
6
+ import { renderRnxHelp } from './help-core'
7
+ import { resolveHiddenRuntimeAlias } from './hidden-runtime-alias'
8
+ import { parseRnxArgs } from './parse-args'
9
+ import type {
10
+ CommandArtifact,
11
+ CommandExecutionResult,
12
+ CommandWriter,
13
+ RunRnxCoreOptions,
14
+ SemanticInvocation,
15
+ } from './command-contract'
16
+
17
+ interface CapturedCommandWriter {
18
+ writer: CommandWriter
19
+ stdout: string[]
20
+ stderr: string[]
21
+ }
22
+
23
+ function createCapturedWriter(writer?: CommandWriter): CapturedCommandWriter {
24
+ const stdout: string[] = []
25
+ const stderr: string[] = []
26
+ return {
27
+ stdout,
28
+ stderr,
29
+ writer: {
30
+ stdout(text) {
31
+ stdout.push(text)
32
+ writer?.stdout(text)
33
+ },
34
+ stderr(text) {
35
+ stderr.push(text)
36
+ writer?.stderr(text)
37
+ },
38
+ },
39
+ }
40
+ }
41
+
42
+ function result(
43
+ captured: CapturedCommandWriter,
44
+ exitCode: number,
45
+ invocations: SemanticInvocation[] = [],
46
+ artifacts: CommandArtifact[] = [],
47
+ ): CommandExecutionResult {
48
+ return {
49
+ exitCode,
50
+ stdout: captured.stdout.join(''),
51
+ stderr: captured.stderr.join(''),
52
+ invocations,
53
+ artifacts,
54
+ }
55
+ }
56
+
57
+ export async function runRnxCore(
58
+ argv: string[],
59
+ options: RunRnxCoreOptions,
60
+ ): Promise<CommandExecutionResult> {
61
+ const captured = createCapturedWriter(options.writer)
62
+ const signal = options.signal ?? new AbortController().signal
63
+ let parsed = parseRnxArgs(argv)
64
+ for (const warning of parsed.warnings) captured.writer.stderr(`${warning}\n`)
65
+
66
+ if (!parsed.command && parsed.commandArgs.length > 0) {
67
+ parsed = resolveHiddenRuntimeAlias(parsed)
68
+ }
69
+
70
+ if (parsed.version) {
71
+ captured.writer.stderr(
72
+ 'rnx --version is unavailable in the browser backend; use the node backend.\n',
73
+ )
74
+ return result(captured, 1)
75
+ }
76
+
77
+ if (!parsed.command) {
78
+ if (parsed.commandArgs.length > 0) {
79
+ const attempted = getRnxFirstPositional(parsed.commandArgs) ?? parsed.commandArgs[0]
80
+ captured.writer.stderr(`unknown command: ${attempted}\n`)
81
+ return result(captured, 1)
82
+ }
83
+ captured.writer.stdout(`${renderRnxHelp({ backend: options.backend.kind })}\n`)
84
+ return result(captured, 0)
85
+ }
86
+
87
+ const command = parsed.command
88
+ const helpRequested =
89
+ parsed.help ||
90
+ parsed.commandArgs.includes('--help') ||
91
+ parsed.commandArgs.includes('-h')
92
+ if (helpRequested) {
93
+ const grouping = new Set(['do', 'get', 'debug', 'wait'])
94
+ const subVerb = getRnxFirstPositional(parsed.commandArgs)
95
+ captured.writer.stdout(
96
+ `${renderRnxHelp({
97
+ backend: options.backend.kind,
98
+ command,
99
+ commandArgs: parsed.commandArgs,
100
+ prefer: grouping.has(command) && subVerb ? 'verb' : undefined,
101
+ group: grouping.has(command) ? command : undefined,
102
+ })}\n`,
103
+ )
104
+ return result(captured, 0)
105
+ }
106
+
107
+ const availability = getRnxCommandAvailability(
108
+ command,
109
+ parsed.commandArgs,
110
+ options.backend.kind,
111
+ )
112
+ if (!availability.available) {
113
+ captured.writer.stderr(`${availability.reason ?? `rnx ${command} is unavailable`}\n`)
114
+ return result(captured, 1)
115
+ }
116
+
117
+ if (signal.aborted) {
118
+ captured.writer.stderr('rnx: command cancelled\n')
119
+ return result(captured, 1)
120
+ }
121
+
122
+ const invocation = createRnxCommandInvocation({
123
+ command,
124
+ args: parsed.commandArgs,
125
+ globalFlags: parsed.globalFlags,
126
+ })
127
+
128
+ try {
129
+ const execution = await options.backend.execute(invocation, {
130
+ writer: captured.writer,
131
+ signal,
132
+ })
133
+ return result(
134
+ captured,
135
+ execution.exitCode,
136
+ execution.invocations,
137
+ execution.artifacts,
138
+ )
139
+ } catch (error) {
140
+ const message = signal.aborted
141
+ ? 'command cancelled'
142
+ : error instanceof Error
143
+ ? error.message
144
+ : String(error)
145
+ captured.writer.stderr(`rnx: ${message}\n`)
146
+ return result(captured, 1)
147
+ }
148
+ }