rnxsim 0.1.368 → 0.1.370

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 (256) hide show
  1. package/cli/auth.ts +2 -1
  2. package/cli/bin.ts +283 -273
  3. package/cli/commands/app-fonts.ts +3 -2
  4. package/cli/commands/assert.ts +8 -7
  5. package/cli/commands/auth.ts +2 -1
  6. package/cli/commands/box/checkout-plane.ts +49 -16
  7. package/cli/commands/compat.ts +93 -4
  8. package/cli/commands/config.ts +2 -1
  9. package/cli/commands/control.ts +37 -33
  10. package/cli/commands/daemon.ts +22 -21
  11. package/cli/commands/debug.ts +17 -15
  12. package/cli/commands/detect.ts +11 -7
  13. package/cli/commands/detox.ts +5 -4
  14. package/cli/commands/device.ts +6 -5
  15. package/cli/commands/electron.ts +6 -5
  16. package/cli/commands/flow.ts +12 -11
  17. package/cli/commands/inspect/find.ts +2 -1
  18. package/cli/commands/inspect/keyboard.ts +2 -1
  19. package/cli/commands/inspect/sleep.ts +2 -1
  20. package/cli/commands/inspect/wait-event.ts +4 -3
  21. package/cli/commands/inspect/wait-idle.ts +2 -1
  22. package/cli/commands/inspect/wait-ready.ts +3 -2
  23. package/cli/commands/inspect/wait-selector.ts +4 -3
  24. package/cli/commands/inspect/wait.ts +2 -1
  25. package/cli/commands/inspect.ts +82 -80
  26. package/cli/commands/install-desktop.ts +5 -4
  27. package/cli/commands/login.ts +3 -2
  28. package/cli/commands/mode.ts +2 -1
  29. package/cli/commands/record.ts +38 -37
  30. package/cli/commands/runtime.ts +9 -8
  31. package/cli/commands/screenshot-layers.ts +4 -3
  32. package/cli/commands/screenshot-mode.ts +2 -1
  33. package/cli/commands/screenshot.ts +8 -7
  34. package/cli/commands/screenshots-capture.ts +2 -1
  35. package/cli/commands/serve.ts +5 -4
  36. package/cli/commands/shell-boolean-mode.ts +2 -1
  37. package/cli/commands/skills.ts +11 -10
  38. package/cli/commands/telemetry.ts +2 -1
  39. package/cli/commands/three-mode.ts +2 -1
  40. package/cli/commands/timeline.ts +4 -3
  41. package/cli/commands/upload.ts +14 -13
  42. package/cli/commands/what-happened.ts +2 -1
  43. package/cli/recording-access.ts +6 -5
  44. package/cli/run-rnx.ts +140 -0
  45. package/dist-cli/bin.js +6 -6
  46. package/dist-cli/chunks/{agent-GXCQMYV4.js → agent-3R4424LW.js} +2 -2
  47. package/dist-cli/chunks/{agent-wrapper-Y3PQAL6I.js → agent-wrapper-4PPWZWSY.js} +2 -2
  48. package/dist-cli/chunks/app-fonts-KYXB6CXQ.js +4 -0
  49. package/dist-cli/chunks/{assert-BSRQBRH7.js → assert-7EZOWGYQ.js} +11 -11
  50. package/dist-cli/chunks/auth-L7M36H6C.js +12 -0
  51. package/dist-cli/chunks/{beta-R4IZ5SWO.js → beta-FKAF6YWJ.js} +2 -2
  52. package/dist-cli/chunks/{box-2NQYYY3B.js → box-5Y5VBMHV.js} +62 -62
  53. package/dist-cli/chunks/{camera-ER66WWAX.js → camera-XHF2RPFG.js} +2 -2
  54. package/dist-cli/chunks/{chunk-UBH2BWCY.js → chunk-2FOGXVOK.js} +2 -2
  55. package/dist-cli/chunks/{chunk-7B22IPSC.js → chunk-3BG6UCQY.js} +2 -2
  56. package/dist-cli/chunks/{chunk-IXRVFQMT.js → chunk-3SOPYG7S.js} +2 -2
  57. package/dist-cli/chunks/{chunk-7V3S2DY2.js → chunk-3UXXYJVD.js} +1 -1
  58. package/dist-cli/chunks/{chunk-3MPFC3DS.js → chunk-5BR33NAZ.js} +1 -1
  59. package/dist-cli/chunks/{chunk-BWJOLJOK.js → chunk-5RKRVS5A.js} +2 -2
  60. package/dist-cli/chunks/{chunk-WVVAYLWZ.js → chunk-64JAEJ6N.js} +1 -1
  61. package/dist-cli/chunks/{chunk-GXHCJRKE.js → chunk-6A6L3VJR.js} +2 -2
  62. package/dist-cli/chunks/chunk-6GPS7U4X.js +74 -0
  63. package/dist-cli/chunks/{chunk-JHYXRORU.js → chunk-6S5LJV2O.js} +2 -2
  64. package/dist-cli/chunks/{chunk-TOE5O6JE.js → chunk-6W4HIWC7.js} +2 -2
  65. package/dist-cli/chunks/{chunk-ESVUVW3R.js → chunk-72S5FCBY.js} +2 -2
  66. package/dist-cli/chunks/{chunk-TC6DNQL6.js → chunk-7C7TJYZ3.js} +2 -2
  67. package/dist-cli/chunks/{chunk-M7COA4BE.js → chunk-AALKIAUZ.js} +1 -1
  68. package/dist-cli/chunks/{chunk-CKNNO6ZG.js → chunk-ARMXC3C3.js} +25 -25
  69. package/dist-cli/chunks/chunk-AVJBT5LF.js +4 -0
  70. package/dist-cli/chunks/chunk-BMIJZNKD.js +28 -0
  71. package/dist-cli/chunks/{chunk-FSPZY4AI.js → chunk-C7BA5CCM.js} +2 -2
  72. package/dist-cli/chunks/{chunk-EHA65UVJ.js → chunk-CMVRTZ5G.js} +2 -2
  73. package/dist-cli/chunks/chunk-D24EOJ4C.js +24 -0
  74. package/dist-cli/chunks/{chunk-3XMEIZEV.js → chunk-D2GZASRV.js} +1 -1
  75. package/dist-cli/chunks/{chunk-3S2J6IVC.js → chunk-DHYTRCIP.js} +2 -2
  76. package/dist-cli/chunks/{chunk-QMVBWZH2.js → chunk-DMHSD6YJ.js} +2 -2
  77. package/dist-cli/chunks/{chunk-NGWUGNPV.js → chunk-DUXHYPBP.js} +2 -2
  78. package/dist-cli/chunks/{chunk-4FLQYRGN.js → chunk-DXV37CJN.js} +1 -1
  79. package/dist-cli/chunks/{chunk-T2MGLXY5.js → chunk-EOIBLKZO.js} +2 -2
  80. package/dist-cli/chunks/{chunk-PNBQBBG5.js → chunk-EQ3OE2AV.js} +1 -1
  81. package/dist-cli/chunks/{chunk-WFAFAGMG.js → chunk-EWSWOWXK.js} +2 -2
  82. package/dist-cli/chunks/{chunk-HKQXGCQT.js → chunk-FA75F34Z.js} +1 -1
  83. package/dist-cli/chunks/{chunk-NERY6HGZ.js → chunk-FK4JSTZ3.js} +2 -2
  84. package/dist-cli/chunks/{chunk-NPSPWMBO.js → chunk-GJRLPJQL.js} +2 -2
  85. package/dist-cli/chunks/{chunk-TPIPKXJL.js → chunk-GRO74J2X.js} +1 -1
  86. package/dist-cli/chunks/chunk-H5X5FJ63.js +99 -0
  87. package/dist-cli/chunks/chunk-HEKHLQ3B.js +497 -0
  88. package/dist-cli/chunks/chunk-HQQTS2CB.js +30 -0
  89. package/dist-cli/chunks/{chunk-Q65KH25G.js → chunk-I52NT6VG.js} +1 -1
  90. package/dist-cli/chunks/{chunk-AUPJX4KI.js → chunk-IDLFVRPN.js} +1 -1
  91. package/dist-cli/chunks/{chunk-LAKWOJ5Y.js → chunk-JZLDHPB7.js} +2 -2
  92. package/dist-cli/chunks/{chunk-WJQB6AXZ.js → chunk-LIMWG54N.js} +1 -1
  93. package/dist-cli/chunks/{chunk-TE645QCO.js → chunk-LUOHRBJG.js} +1 -1
  94. package/dist-cli/chunks/{chunk-DJSPNOF6.js → chunk-LXPHL6FO.js} +2 -2
  95. package/dist-cli/chunks/{chunk-ECXDCED5.js → chunk-MDCY532E.js} +2 -2
  96. package/dist-cli/chunks/{chunk-4VA2ISWX.js → chunk-NJMU5BN6.js} +1 -1
  97. package/dist-cli/chunks/{chunk-RRALQ4WM.js → chunk-NR2V2ONN.js} +2 -2
  98. package/dist-cli/chunks/{chunk-SHMLYTNH.js → chunk-NTC46LSA.js} +2 -2
  99. package/dist-cli/chunks/{chunk-X5MXQB3L.js → chunk-O6QLKSAM.js} +10 -10
  100. package/dist-cli/chunks/{chunk-LPAOOJIW.js → chunk-OJZHECGH.js} +1 -1
  101. package/dist-cli/chunks/chunk-OTFTMGAL.js +7 -0
  102. package/dist-cli/chunks/{chunk-QKOY7UW5.js → chunk-PAUEZO6F.js} +2 -2
  103. package/dist-cli/chunks/{chunk-WXRDFUR7.js → chunk-PIZXOXBL.js} +2 -2
  104. package/dist-cli/chunks/{chunk-WF2CRNYF.js → chunk-PNOENVMJ.js} +1 -1
  105. package/dist-cli/chunks/{chunk-FDAFSRQE.js → chunk-Q4MRJ6PO.js} +2 -2
  106. package/dist-cli/chunks/{chunk-SSUPPM6K.js → chunk-RRX52O37.js} +1 -1
  107. package/dist-cli/chunks/{chunk-E6XYIIJK.js → chunk-U63T6LIQ.js} +1 -1
  108. package/dist-cli/chunks/{chunk-OZJMWTGA.js → chunk-UFVAAWGZ.js} +1 -1
  109. package/dist-cli/chunks/{chunk-GS5VUDCF.js → chunk-VVQCZ42C.js} +1 -1
  110. package/dist-cli/chunks/{chunk-MCO7V4VN.js → chunk-WFQHT4QD.js} +2 -2
  111. package/dist-cli/chunks/{chunk-JFGW75UL.js → chunk-WPV4H5S4.js} +2 -2
  112. package/dist-cli/chunks/{chunk-OXCDE3DD.js → chunk-X6WQ4YWE.js} +1 -1
  113. package/dist-cli/chunks/{chunk-FVODUDPS.js → chunk-YIZGNT7A.js} +1 -1
  114. package/dist-cli/chunks/{chunk-MGOAQHMO.js → chunk-Z2VBSNFI.js} +2 -2
  115. package/dist-cli/chunks/{chunk-GFWUIGGY.js → chunk-Z3DENGXW.js} +2 -2
  116. package/dist-cli/chunks/{cleanup-WHGLBAJ2.js → cleanup-MXMMJ7JW.js} +2 -2
  117. package/dist-cli/chunks/cli-version-MLS55UTY.js +4 -0
  118. package/dist-cli/chunks/compat-E6KE5KDI.js +23 -0
  119. package/dist-cli/chunks/config-QSLLVZDS.js +13 -0
  120. package/dist-cli/chunks/{connect-N4FV3DDV.js → connect-QE4VU6GB.js} +2 -2
  121. package/dist-cli/chunks/control-XD5F6K5T.js +4 -0
  122. package/dist-cli/chunks/daemon-UN5SE2JO.js +4 -0
  123. package/dist-cli/chunks/{debug-AHEK43AJ.js → debug-5FG3MBJS.js} +20 -20
  124. package/dist-cli/chunks/desktop-5EZX7NX5.js +31 -0
  125. package/dist-cli/chunks/detox-WJGQP5TM.js +52 -0
  126. package/dist-cli/chunks/device-D7LKCAMS.js +18 -0
  127. package/dist-cli/chunks/{diagnose-WDP3CVIX.js → diagnose-A3W6ZTGA.js} +2 -2
  128. package/dist-cli/chunks/{disk-cleanup-JRT5MKFW.js → disk-cleanup-BDRHX5ZG.js} +2 -2
  129. package/dist-cli/chunks/{do-chain-7FDMO56C.js → do-chain-RUJNRPPF.js} +2 -2
  130. package/dist-cli/chunks/drivers-3NJ5RL6X.js +4 -0
  131. package/dist-cli/chunks/{env-YIBOMB24.js → env-U67SQVTV.js} +2 -2
  132. package/dist-cli/chunks/{film-R3EQADMG.js → film-XC6UAQ3V.js} +3 -3
  133. package/dist-cli/chunks/flow-FHZZD3P6.js +4 -0
  134. package/dist-cli/chunks/help-BYYDUSXF.js +4 -0
  135. package/dist-cli/chunks/{hidden-runtime-alias-6M4UERRQ.js → hidden-runtime-alias-7S2TNZXG.js} +2 -2
  136. package/dist-cli/chunks/{home-paths-QJNOHZJO.js → home-paths-LMO5LB4F.js} +2 -2
  137. package/dist-cli/chunks/inspect-RQCTWDCC.js +4 -0
  138. package/dist-cli/chunks/install-desktop-GOWXCQUE.js +4 -0
  139. package/dist-cli/chunks/login-JIU42S4C.js +26 -0
  140. package/dist-cli/chunks/{logout-VNJX2IEW.js → logout-JTAWQXZO.js} +2 -2
  141. package/dist-cli/chunks/{maestro-SQS2OS2D.js → maestro-TYBQYOGB.js} +3 -3
  142. package/dist-cli/chunks/{maestro-generate-GWVPISG5.js → maestro-generate-YLAGWVKE.js} +3 -3
  143. package/dist-cli/chunks/mode-DV24ZRZ6.js +26 -0
  144. package/dist-cli/chunks/{optional-demo-registry-L3LRBQHG.js → optional-demo-registry-JZH66VIM.js} +2 -2
  145. package/dist-cli/chunks/{perf-XLPC4UKR.js → perf-LXXJ4EAX.js} +2 -2
  146. package/dist-cli/chunks/{permissions-QRHWVMDP.js → permissions-KAOVZUPW.js} +2 -2
  147. package/dist-cli/chunks/{platform-F47URZNB.js → platform-KW35446W.js} +3 -3
  148. package/dist-cli/chunks/privacy-MIFE72CG.js +4 -0
  149. package/dist-cli/chunks/record-EK3ETFHZ.js +72 -0
  150. package/dist-cli/chunks/report-issue-NW5PCAZF.js +29 -0
  151. package/dist-cli/chunks/reset-RZ4O5AFJ.js +4 -0
  152. package/dist-cli/chunks/resolve-target-7R5BNYMM.js +4 -0
  153. package/dist-cli/chunks/runtime-MZHLSRS6.js +4 -0
  154. package/dist-cli/chunks/{screenshot-command-RK7IJHVK.js → screenshot-command-TQSPTFT2.js} +11 -11
  155. package/dist-cli/chunks/screenshot-layers-IZP3L3AQ.js +20 -0
  156. package/dist-cli/chunks/screenshots-capture-K7LJOVAE.js +42 -0
  157. package/dist-cli/chunks/{serve-UBXNGLNP.js → serve-MMX4WXXG.js} +18 -18
  158. package/dist-cli/chunks/setup-YFP3KEQZ.js +4 -0
  159. package/dist-cli/chunks/{sim-client-VTKFEDJX.js → sim-client-KLAYIFOC.js} +2 -2
  160. package/dist-cli/chunks/skills-N4D3POIS.js +50 -0
  161. package/dist-cli/chunks/{state-273XJPUE.js → state-ES6TFQZF.js} +2 -2
  162. package/dist-cli/chunks/{storage-RTDFWIY7.js → storage-52DR5V2C.js} +2 -2
  163. package/dist-cli/chunks/store-HOL45WCI.js +4 -0
  164. package/dist-cli/chunks/telemetry-BV6OTYPF.js +4 -0
  165. package/dist-cli/chunks/timeline-NRVNB5JR.js +24 -0
  166. package/dist-cli/chunks/{upgrade-R74NVHKG.js → upgrade-LNED5YQ2.js} +2 -2
  167. package/dist-cli/chunks/upload-RXKHFIBU.js +4 -0
  168. package/dist-cli/chunks/{version-RTFCYQZ7.js → version-VEF2DYGG.js} +2 -2
  169. package/dist-cli/chunks/{web-35SSKBRU.js → web-CGDE6S73.js} +2 -2
  170. package/dist-cli/chunks/welcome-FT2AMUWW.js +5 -0
  171. package/dist-cli/chunks/what-happened-FSIDWL32.js +25 -0
  172. package/dist-cli/chunks/{ws-bridge-JXQUAWFA.js → ws-bridge-QXFQLRE7.js} +2 -2
  173. package/dist-lib/agent-daemon-client.cjs +1 -1
  174. package/dist-lib/agent-events.cjs +1 -1
  175. package/dist-lib/agent-identity.cjs +1 -1
  176. package/dist-lib/agent-sessions.cjs +1 -1
  177. package/dist-lib/attached-projects.cjs +1 -1
  178. package/dist-lib/auth/shared-session.cjs +1 -1
  179. package/dist-lib/backend-origin.cjs +1 -1
  180. package/dist-lib/beta.cjs +1 -1
  181. package/dist-lib/beta.mjs +1 -1
  182. package/dist-lib/bridge-constants.cjs +1 -1
  183. package/dist-lib/bridge-contract-input.cjs +1 -1
  184. package/dist-lib/bridge-contract-input.mjs +1 -1
  185. package/dist-lib/bridge-contract.cjs +1 -1
  186. package/dist-lib/bridge-contract.mjs +1 -1
  187. package/dist-lib/cli-constants.cjs +1 -1
  188. package/dist-lib/config.cjs +1 -1
  189. package/dist-lib/detox/index.cjs +1 -1
  190. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  191. package/dist-lib/home-paths.cjs +1 -1
  192. package/dist-lib/host/bridge-host.cjs +1 -1
  193. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  194. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  195. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  196. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  197. package/dist-lib/host/websocket-proxy.cjs +1 -1
  198. package/dist-lib/index.cjs +1 -1
  199. package/dist-lib/jump-to-source-babel.cjs +1 -1
  200. package/dist-lib/menu.cjs +1 -1
  201. package/dist-lib/menu.mjs +1 -1
  202. package/dist-lib/metro-production-bundle.cjs +1 -1
  203. package/dist-lib/metro-production-bundle.mjs +1 -1
  204. package/dist-lib/metro.cjs +1 -1
  205. package/dist-lib/profiles.cjs +1 -1
  206. package/dist-lib/public-brand.cjs +1 -1
  207. package/dist-lib/react-native-host-modules.cjs +2 -1
  208. package/dist-lib/react-native-host-modules.mjs +2 -1
  209. package/dist-lib/render-mode.cjs +1 -1
  210. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  211. package/dist-lib/sdk.cjs +1 -1
  212. package/dist-lib/sdk.mjs +1 -1
  213. package/dist-lib/skills.cjs +560 -48
  214. package/dist-lib/vite.cjs +1 -1
  215. package/package.json +1 -1
  216. package/src/react-native-host-modules.ts +1 -0
  217. package/dist-cli/chunks/app-fonts-MDD3W4VN.js +0 -4
  218. package/dist-cli/chunks/auth-SLPHDPCF.js +0 -12
  219. package/dist-cli/chunks/chunk-2YK5J2D2.js +0 -24
  220. package/dist-cli/chunks/chunk-42TLK75A.js +0 -497
  221. package/dist-cli/chunks/chunk-57LITN73.js +0 -7
  222. package/dist-cli/chunks/chunk-T4ZZ26A2.js +0 -28
  223. package/dist-cli/chunks/chunk-UXROQPIN.js +0 -30
  224. package/dist-cli/chunks/chunk-YSHJ3LMQ.js +0 -74
  225. package/dist-cli/chunks/chunk-YYPTSF6W.js +0 -99
  226. package/dist-cli/chunks/cli-version-DMXIXBIM.js +0 -4
  227. package/dist-cli/chunks/compat-MGBKGYGQ.js +0 -20
  228. package/dist-cli/chunks/config-TRDOMP4T.js +0 -13
  229. package/dist-cli/chunks/control-5GRBZVYK.js +0 -4
  230. package/dist-cli/chunks/daemon-MBT5E3ZC.js +0 -4
  231. package/dist-cli/chunks/desktop-LDRIXOVV.js +0 -31
  232. package/dist-cli/chunks/detox-6HAKYISO.js +0 -52
  233. package/dist-cli/chunks/device-QM3S7OVU.js +0 -18
  234. package/dist-cli/chunks/drivers-AJL2EVXH.js +0 -4
  235. package/dist-cli/chunks/flow-BDAA6BWL.js +0 -4
  236. package/dist-cli/chunks/help-5EJD6LJF.js +0 -4
  237. package/dist-cli/chunks/inspect-S3LR3R2A.js +0 -4
  238. package/dist-cli/chunks/install-desktop-GXE6K7BJ.js +0 -4
  239. package/dist-cli/chunks/login-ISWDW4WU.js +0 -26
  240. package/dist-cli/chunks/mode-3URDGBZB.js +0 -26
  241. package/dist-cli/chunks/privacy-BF23T67T.js +0 -4
  242. package/dist-cli/chunks/record-2DN3OUE5.js +0 -72
  243. package/dist-cli/chunks/report-issue-D3BQPSLU.js +0 -29
  244. package/dist-cli/chunks/reset-T5CNZ7D3.js +0 -4
  245. package/dist-cli/chunks/resolve-target-KAAS274S.js +0 -4
  246. package/dist-cli/chunks/runtime-AQJDBR3X.js +0 -4
  247. package/dist-cli/chunks/screenshot-layers-DP2QKSMN.js +0 -20
  248. package/dist-cli/chunks/screenshots-capture-MA7P3FUT.js +0 -42
  249. package/dist-cli/chunks/setup-GH7OW4GC.js +0 -4
  250. package/dist-cli/chunks/skills-HPK25R4B.js +0 -50
  251. package/dist-cli/chunks/store-DLKNNM4L.js +0 -4
  252. package/dist-cli/chunks/telemetry-7CWDXEOO.js +0 -4
  253. package/dist-cli/chunks/timeline-IF2PGK7C.js +0 -24
  254. package/dist-cli/chunks/upload-3JFFVCZ4.js +0 -4
  255. package/dist-cli/chunks/welcome-N5V352SE.js +0 -5
  256. package/dist-cli/chunks/what-happened-WXTP6EPR.js +0 -25
@@ -27,6 +27,7 @@ import { tmpdir } from 'os'
27
27
  import { dirname, join, resolve } from 'path'
28
28
  import { findDesktopCompanion } from '../desktop-companion'
29
29
  import { confirm } from '../prompt'
30
+ import { rnxExit } from '../run-rnx'
30
31
  import { accent, bold, failure, muted, success, withSpinner } from '../ui'
31
32
 
32
33
  const DOWNLOAD_BASE = 'https://contrast.dev/api/electron-release'
@@ -274,7 +275,7 @@ examples:
274
275
  rnx desktop install
275
276
  rnx desktop install --yes
276
277
  `)
277
- process.exit(0)
278
+ rnxExit(0)
278
279
  }
279
280
 
280
281
  const skipConfirm =
@@ -300,7 +301,7 @@ examples:
300
301
  console.error(
301
302
  ' Supported: darwin-arm64, darwin-x64, linux-x64, linux-arm64, win32-x64',
302
303
  )
303
- process.exit(1)
304
+ rnxExit(1)
304
305
  }
305
306
 
306
307
  console.log(` ${bold('Desktop app')}`)
@@ -347,7 +348,7 @@ examples:
347
348
  ' network blocked the request. Check your connection and try again later.',
348
349
  )
349
350
  console.error(' The CLI and daemon work without the desktop app. Run `rnx --help`.')
350
- process.exit(1)
351
+ rnxExit(1)
351
352
  }
352
353
 
353
354
  if (process.stdout.isTTY) process.stdout.write('\n')
@@ -374,7 +375,7 @@ examples:
374
375
  } else {
375
376
  console.error(` Keeping the download at ${downloadPath} for manual installation.`)
376
377
  }
377
- process.exit(1)
378
+ rnxExit(1)
378
379
  }
379
380
 
380
381
  console.log()
@@ -6,6 +6,7 @@ import {
6
6
  writeSharedDesktopAuthSession,
7
7
  } from '../../src/auth/shared-session'
8
8
  import { rnxPublicBrand } from '../../src/public-brand'
9
+ import { rnxExit } from '../run-rnx'
9
10
 
10
11
  const REMOTE_DEFAULT_ORIGIN = process.env.SOOTSIM_AUTH_ORIGIN || 'https://contrast.dev'
11
12
 
@@ -141,7 +142,7 @@ function isLocalOrigin(origin: string): boolean {
141
142
  export async function runLogin(args: string[]) {
142
143
  if (args.includes('--help') || args.includes('-h')) {
143
144
  printHelp()
144
- process.exit(0)
145
+ rnxExit(0)
145
146
  }
146
147
 
147
148
  const mutableArgs = [...args]
@@ -269,7 +270,7 @@ export async function runLogin(args: string[]) {
269
270
 
270
271
  if (!result.ok) {
271
272
  console.error(` login failed: ${result.error}`)
272
- process.exit(1)
273
+ rnxExit(1)
273
274
  }
274
275
 
275
276
  writeSharedDesktopAuthSession({
@@ -1,3 +1,4 @@
1
+ import { rnxExit } from '../run-rnx'
1
2
  import { runScreenshotMode } from './screenshot-mode'
2
3
  import { runThreeMode } from './three-mode'
3
4
 
@@ -45,7 +46,7 @@ export async function runMode(args: string[], opts: ModeOptions): Promise<void>
45
46
  const sub = findSubcommand(args)
46
47
  if (!sub) {
47
48
  printHelp()
48
- process.exit(1)
49
+ rnxExit(1)
49
50
  }
50
51
 
51
52
  const rest = withoutSubcommand(args, sub.index)
@@ -18,6 +18,7 @@ import { getCliIdentityKey } from '../current-sim'
18
18
  import { openUrl } from '../open-url'
19
19
  import { ensureCliRecordingEntitlement } from '../recording-access'
20
20
  import { resolveRunProvenance } from '../run-registry'
21
+ import { rnxExit } from '../run-rnx'
21
22
  import {
22
23
  checkSimHealth,
23
24
  createBridgeFromParsed,
@@ -86,7 +87,7 @@ async function evalCaptureStep<T>(
86
87
  ` the capture lock auto-releases, so simply retry the recording.\n` +
87
88
  ` if it persists, recover the sim with \`rnx close --sim <id>\`.`,
88
89
  )
89
- process.exit(1)
90
+ rnxExit(1)
90
91
  }
91
92
  // a leaked/contended render-host streaming session surfaces as an
92
93
  // engine-side error delivered over the WS bridge. on the gif/video
@@ -107,12 +108,12 @@ async function evalCaptureStep<T>(
107
108
  )}s — retry then, or recover now with\n` +
108
109
  ` \`rnx close --sim <id>\` and reopen the sim.`,
109
110
  )
110
- process.exit(1)
111
+ rnxExit(1)
111
112
  }
112
113
  // never let any other capture-eval rejection escape as an unhandled
113
114
  // promise (raw stack + false exit 0). surface it and exit non-zero.
114
115
  console.error(` ${step} failed: ${msg}`)
115
- process.exit(1)
116
+ rnxExit(1)
116
117
  }
117
118
  }
118
119
 
@@ -172,7 +173,7 @@ function readRepoScope(args: string[]): RepoScope {
172
173
  const repo = valueOf(args, '--repo')?.trim()
173
174
  if ((owner && !repo) || (!owner && repo)) {
174
175
  console.error(' --owner and --repo must be provided together')
175
- process.exit(1)
176
+ rnxExit(1)
176
177
  }
177
178
  return owner && repo ? { owner, repo } : null
178
179
  }
@@ -236,7 +237,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
236
237
  const formatArg = valueOf(args, '--format') as OutputFormat | undefined
237
238
  if (formatArg && !['webm', 'mp4', 'gif', 'png'].includes(formatArg)) {
238
239
  console.error(` invalid --format "${formatArg}" — expected webm | mp4 | gif | png`)
239
- process.exit(1)
240
+ rnxExit(1)
240
241
  }
241
242
  const outputArg = valueOf(args, '--output')
242
243
  const durationSec = Number(valueOf(args, '--duration') ?? '10')
@@ -244,7 +245,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
244
245
  console.error(
245
246
  ` invalid --duration "${valueOf(args, '--duration')}" — expected a positive number of seconds`,
246
247
  )
247
- process.exit(1)
248
+ rnxExit(1)
248
249
  }
249
250
  // upper bound: a fat-fingered `--duration 99999` (≈27.7h) otherwise
250
251
  // started a runaway recording with no warning (QA F23-3). 600s mirrors
@@ -258,7 +259,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
258
259
  console.error(
259
260
  ` invalid --duration "${valueOf(args, '--duration')}" — exceeds the ${MAX_DURATION_SEC}s (10m) maximum`,
260
261
  )
261
- process.exit(1)
262
+ rnxExit(1)
262
263
  }
263
264
  const fps = Number(valueOf(args, '--fps') ?? '30')
264
265
  const framesArg = valueOf(args, '--frames')
@@ -271,7 +272,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
271
272
  console.error(
272
273
  ` invalid --frames "${framesArg}" — expected a positive integer count`,
273
274
  )
274
- process.exit(1)
275
+ rnxExit(1)
275
276
  }
276
277
  }
277
278
  const openAfter = args.includes('--open')
@@ -285,7 +286,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
285
286
  console.error(
286
287
  ' --lockstep works with `record start` / `record stop` (stateful mode) — atomic --duration is wall-clock and cannot bound a virtual-time capture',
287
288
  )
288
- process.exit(1)
289
+ rnxExit(1)
289
290
  }
290
291
 
291
292
  const durationMs = Math.max(100, Math.round(durationSec * 1000))
@@ -342,7 +343,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
342
343
  ` start failed: recording store refused to start (${mode})` +
343
344
  (started.error ? `: ${started.error}` : ''),
344
345
  )
345
- process.exit(1)
346
+ rnxExit(1)
346
347
  }
347
348
  console.log(` recording ${mode} for ${durationSec}s`)
348
349
  await new Promise((r) => setTimeout(r, durationMs))
@@ -401,7 +402,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
401
402
  })
402
403
  if (!start.ok || !start.requestId) {
403
404
  console.error(` frame capture start failed: ${start.error ?? 'unknown error'}`)
404
- process.exit(1)
405
+ rnxExit(1)
405
406
  }
406
407
  await new Promise((r) => setTimeout(r, durationMs))
407
408
  const deadline = Date.now() + Math.max(5_000, durationMs)
@@ -418,19 +419,19 @@ export async function runRecord(args: string[], opts: RecordOptions) {
418
419
  })
419
420
  if (!result) {
420
421
  console.error(' frame capture result missing')
421
- process.exit(1)
422
+ rnxExit(1)
422
423
  }
423
424
  if (result.done) {
424
425
  if (!result.ok) {
425
426
  console.error(` frame capture failed: ${result.error ?? 'unknown error'}`)
426
- process.exit(1)
427
+ rnxExit(1)
427
428
  }
428
429
  frames = result.frames ?? []
429
430
  break
430
431
  }
431
432
  if (Date.now() >= deadline) {
432
433
  console.error(' frame capture timed out')
433
- process.exit(1)
434
+ rnxExit(1)
434
435
  }
435
436
  await new Promise((r) => setTimeout(r, 100))
436
437
  }
@@ -457,7 +458,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
457
458
  )
458
459
  if (!result) {
459
460
  console.error(' gif capture returned no frames')
460
- process.exit(1)
461
+ rnxExit(1)
461
462
  }
462
463
  writeFileSync(out, Buffer.from(result.data, 'base64'))
463
464
  console.log(` saved: ${out} (${formatBytes(result.size)})`)
@@ -503,7 +504,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
503
504
  ' `rnx close --sim <id>` then reopen the sim.',
504
505
  )
505
506
  }
506
- process.exit(1)
507
+ rnxExit(1)
507
508
  }
508
509
 
509
510
  console.log(` recording ${format} for ${durationSec}s → ${out}`)
@@ -524,12 +525,12 @@ export async function runRecord(args: string[], opts: RecordOptions) {
524
525
  )
525
526
  if (!stopResult.ok) {
526
527
  console.error(` stop failed: ${stopResult.error ?? 'unknown error'}`)
527
- process.exit(1)
528
+ rnxExit(1)
528
529
  }
529
530
 
530
531
  if (!stopResult.size) {
531
532
  console.error(' recorder returned an empty blob — nothing written')
532
- process.exit(1)
533
+ rnxExit(1)
533
534
  }
534
535
 
535
536
  await downloadBlob(bridge, out)
@@ -564,7 +565,7 @@ async function probeSim(bridge: WsBridge, code: string): Promise<boolean> {
564
565
  ' loaded an app (or its page is unresponsive). run `rnx list`\n' +
565
566
  ' and target a sim with a loaded app via --sim <id>.',
566
567
  )
567
- process.exit(1)
568
+ rnxExit(1)
568
569
  }
569
570
  throw err
570
571
  }
@@ -576,7 +577,7 @@ async function assertRecorderAvailable(bridge: WsBridge) {
576
577
  console.error(
577
578
  ' window.__sootsimRecorder missing — is rnx engine running in this sim?',
578
579
  )
579
- process.exit(1)
580
+ rnxExit(1)
580
581
  }
581
582
  }
582
583
 
@@ -598,7 +599,7 @@ async function assertTabVisibleForCapture(bridge: WsBridge) {
598
599
  ' bring the chrome window to the foreground (un-minimize / switch to\n' +
599
600
  ' its tab) or run the recording in headless playwright, then retry.',
600
601
  )
601
- process.exit(1)
602
+ rnxExit(1)
602
603
  }
603
604
  }
604
605
 
@@ -693,7 +694,7 @@ function parseMode(raw: string | undefined): RecordMode {
693
694
  if (!raw) return 'video'
694
695
  if (raw === 'video' || raw === 'live' || raw === 'combined') return raw
695
696
  console.error(` invalid --mode "${raw}" — expected video | live | combined`)
696
- process.exit(1)
697
+ rnxExit(1)
697
698
  }
698
699
 
699
700
  function recordingStatePath(): string {
@@ -745,7 +746,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
745
746
  console.error(
746
747
  ` recording already in progress (started ${existing.startedAt}, sim ${existing.simId ?? '?'}). run \`rnx record stop\` first, or \`rnx record cancel\` to discard.`,
747
748
  )
748
- process.exit(1)
749
+ rnxExit(1)
749
750
  }
750
751
 
751
752
  const parsed = parseBridgeCliArgs(args, {
@@ -773,7 +774,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
773
774
  console.error(
774
775
  ` record start only supports webm or mp4 (got: ${formatArg}). for gif/png use atomic mode: rnx record --format ${formatArg} --duration <s>`,
775
776
  )
776
- process.exit(1)
777
+ rnxExit(1)
777
778
  }
778
779
  const fps = Number(valueOf(args, '--fps') ?? '30')
779
780
  const repoScope = readRepoScope(args)
@@ -817,7 +818,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
817
818
  ` start failed: recording store refused to start (${mode})` +
818
819
  (started.error ? `: ${started.error}` : ''),
819
820
  )
820
- process.exit(1)
821
+ rnxExit(1)
821
822
  }
822
823
  } else {
823
824
  await assertRecorderAvailable(bridge)
@@ -825,7 +826,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
825
826
  const lockstep = args.includes('--lockstep')
826
827
  if (lockstep && format !== 'mp4') {
827
828
  console.error(' --lockstep requires --format mp4 (webm is realtime-clocked)')
828
- process.exit(1)
829
+ rnxExit(1)
829
830
  }
830
831
  const startOpts: {
831
832
  format: string
@@ -841,7 +842,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
841
842
  })
842
843
  if (!result.ok) {
843
844
  console.error(` start failed: ${result.error ?? 'unknown error'}`)
844
- process.exit(1)
845
+ rnxExit(1)
845
846
  }
846
847
  }
847
848
  writeRecordingState({
@@ -872,7 +873,7 @@ async function recordPreludeStart(args: string[], opts: RecordOptions) {
872
873
  console.error(
873
874
  ` recording already in progress (started ${existing.startedAt}, sim ${existing.simId ?? '?'}). run \`rnx record stop\` first, or \`rnx record cancel\` to discard.`,
874
875
  )
875
- process.exit(1)
876
+ rnxExit(1)
876
877
  }
877
878
 
878
879
  const parsed = parseBridgeCliArgs(args, {
@@ -907,7 +908,7 @@ async function recordPreludeStart(args: string[], opts: RecordOptions) {
907
908
  typeof reason === 'string' && reason ? ` (${reason})` : ''
908
909
  }`,
909
910
  )
910
- process.exit(1)
911
+ rnxExit(1)
911
912
  }
912
913
  console.log(
913
914
  ' recording preview prelude — run `rnx record start --mode combined` when the visible proof segment is ready',
@@ -1133,7 +1134,7 @@ async function recordStop(args: string[], opts: RecordOptions) {
1133
1134
  const state = readRecordingState()
1134
1135
  if (!state) {
1135
1136
  console.error(' no recording in progress. start one with `rnx record start`.')
1136
- process.exit(1)
1137
+ rnxExit(1)
1137
1138
  }
1138
1139
 
1139
1140
  const parsed = parseBridgeCliArgs(args, {
@@ -1180,12 +1181,12 @@ async function recordStop(args: string[], opts: RecordOptions) {
1180
1181
  if (!stopResult.ok) {
1181
1182
  console.error(` stop failed: ${stopResult.error ?? 'unknown error'}`)
1182
1183
  clearRecordingState()
1183
- process.exit(1)
1184
+ rnxExit(1)
1184
1185
  }
1185
1186
  if (!stopResult.size) {
1186
1187
  console.error(' recorder returned an empty blob — nothing written')
1187
1188
  clearRecordingState()
1188
- process.exit(1)
1189
+ rnxExit(1)
1189
1190
  }
1190
1191
  await downloadBlob(bridge, out)
1191
1192
  clearRecordingState()
@@ -1212,7 +1213,7 @@ async function assertStoreBridgesAvailable(bridge: WsBridge) {
1212
1213
  console.error(
1213
1214
  ' SootSim.bridges.startRecording missing — is rnx engine running in this sim?',
1214
1215
  )
1215
- process.exit(1)
1216
+ rnxExit(1)
1216
1217
  }
1217
1218
  }
1218
1219
 
@@ -1246,7 +1247,7 @@ async function assertGuestBundleLoaded(bridge: WsBridge, mode: RecordMode) {
1246
1247
  ` photos/settings/home has none). open a metro/guest app first, or\n` +
1247
1248
  ` use \`--mode video\` for a local screen recording with no upload.`,
1248
1249
  )
1249
- process.exit(1)
1250
+ rnxExit(1)
1250
1251
  }
1251
1252
  }
1252
1253
 
@@ -1309,7 +1310,7 @@ async function injectPreviewSessionAuth(
1309
1310
  ' build without CLI-injected preview auth. reload the sim or open a\n' +
1310
1311
  ' fresh one (`rnx open --new`); if it persists, update rnx.',
1311
1312
  )
1312
- process.exit(1)
1313
+ rnxExit(1)
1313
1314
  }
1314
1315
  }
1315
1316
 
@@ -1384,11 +1385,11 @@ function handleStoreUploadResult(
1384
1385
  ) {
1385
1386
  if (result.uploadError) {
1386
1387
  console.error(` upload failed: ${result.uploadError}`)
1387
- process.exit(1)
1388
+ rnxExit(1)
1388
1389
  }
1389
1390
  if (!result.previewUrl) {
1390
1391
  console.error(' upload returned no preview URL')
1391
- process.exit(1)
1392
+ rnxExit(1)
1392
1393
  }
1393
1394
  console.log(` preview: ${result.previewUrl}`)
1394
1395
  // the preview id is content-addressed (shareId = hash of the bundle), so
@@ -27,6 +27,7 @@ import {
27
27
  sootsimRuntime,
28
28
  } from '../../src/runtime-delivery'
29
29
  import { resolveSootSimAppConfig } from '../app-config'
30
+ import { rnxExit } from '../run-rnx'
30
31
  import { fetchRuntimeReleaseNotes, formatRuntimeReleaseNotes } from '../runtime-notes'
31
32
  import { resolveDefaultBridgePort } from '../ws-bridge'
32
33
 
@@ -56,7 +57,7 @@ export async function runRuntime(args: string[], opts: RuntimeOptions = {}) {
56
57
  default:
57
58
  console.error(` unknown runtime subcommand: ${sub}`)
58
59
  printHelp()
59
- process.exit(1)
60
+ rnxExit(1)
60
61
  }
61
62
  }
62
63
 
@@ -120,7 +121,7 @@ async function runtimeInstall(args: string[], opts: RuntimeOptions) {
120
121
  return result
121
122
  } catch (err) {
122
123
  console.error(` ${describeError(err)}`)
123
- process.exit(1)
124
+ rnxExit(1)
124
125
  }
125
126
  }
126
127
 
@@ -234,14 +235,14 @@ async function runtimeUse(args: string[]) {
234
235
  const version = args[0]
235
236
  if (!version) {
236
237
  console.error(` usage: rnx runtime use <version>`)
237
- process.exit(1)
238
+ rnxExit(1)
238
239
  }
239
240
  const installed = sootsimRuntime.listInstalled()
240
241
  if (!installed.includes(version)) {
241
242
  console.error(` version ${version} is not installed`)
242
243
  console.error(` installed: ${installed.join(', ') || '(none)'}`)
243
244
  console.error(` run \`rnx runtime install ${version}\` first`)
244
- process.exit(1)
245
+ rnxExit(1)
245
246
  }
246
247
  await activateVersion(version)
247
248
  }
@@ -252,7 +253,7 @@ async function runtimeRemove(args: string[]) {
252
253
  const version = args[0]
253
254
  if (!version) {
254
255
  console.error(` usage: rnx runtime remove <version>`)
255
- process.exit(1)
256
+ rnxExit(1)
256
257
  }
257
258
  const active = readActiveRuntime()
258
259
  if (active === version) {
@@ -260,11 +261,11 @@ async function runtimeRemove(args: string[]) {
260
261
  console.error(
261
262
  ` switch with \`rnx runtime use <other>\` first, or install another version`,
262
263
  )
263
- process.exit(1)
264
+ rnxExit(1)
264
265
  }
265
266
  if (readLiveRuntimeVersions().includes(version)) {
266
267
  console.error(` cannot remove runtime ${version} while a project is using it`)
267
- process.exit(1)
268
+ rnxExit(1)
268
269
  }
269
270
  const dir = runtimeDir(version)
270
271
  if (!fs.existsSync(dir)) {
@@ -291,7 +292,7 @@ async function runtimeWhich() {
291
292
  async function runtimeNotes(args: string[]) {
292
293
  if (args.length > 0) {
293
294
  console.error(` usage: rnx runtime notes`)
294
- process.exit(1)
295
+ rnxExit(1)
295
296
  }
296
297
  const { config } = await resolveSootSimAppConfig()
297
298
  const version = config?.runtimeVersion ?? readActiveRuntime()
@@ -11,6 +11,7 @@ import { mkdirSync, writeFileSync } from 'fs'
11
11
  import { resolve } from 'path'
12
12
  import { devices } from 'sootsim-engine/settings'
13
13
  import { buildResolveRectEval, type SampleRect } from '../browser-evals'
14
+ import { rnxExit } from '../run-rnx'
14
15
  import { callInBridge, createBridgeFromParsed, parseBridgeCliArgs } from '../ws-bridge'
15
16
  import { inspectWaitReady, waitReadyReason } from './inspect/core'
16
17
 
@@ -40,13 +41,13 @@ output:
40
41
  layer-<id>.png each subtree rendered alone on a transparent frame
41
42
  manifest.json device metrics + logical rect per layer
42
43
  `)
43
- process.exit(0)
44
+ rnxExit(0)
44
45
  }
45
46
 
46
47
  const idsArg = args.find((_, i) => args[i - 1] === '--ids')
47
48
  if (!idsArg) {
48
49
  console.error(' --ids is required (comma-separated testIDs)')
49
- process.exit(1)
50
+ rnxExit(1)
50
51
  }
51
52
  const testIds = idsArg
52
53
  .split(',')
@@ -54,7 +55,7 @@ output:
54
55
  .filter(Boolean)
55
56
  if (testIds.length === 0) {
56
57
  console.error(' --ids resolved to an empty list')
57
- process.exit(1)
58
+ rnxExit(1)
58
59
  }
59
60
  const outDirArg = args.find((_, i) => args[i - 1] === '--out-dir')
60
61
  const outDir = resolve(process.cwd(), outDirArg ?? '/tmp/sootsim-layers')
@@ -6,6 +6,7 @@
6
6
  // wraps the existing `toggle-screenshot-mode` shell action so the CLI
7
7
  // stays behavior-compatible with the menu item / keyboard shortcut.
8
8
 
9
+ import { rnxExit } from '../run-rnx'
9
10
  import { runShellBooleanMode, type ShellBooleanModeOptions } from './shell-boolean-mode'
10
11
 
11
12
  export async function runScreenshotMode(args: string[], opts: ShellBooleanModeOptions) {
@@ -26,7 +27,7 @@ examples:
26
27
  rnx mode screenshot on
27
28
  rnx mode screenshot off
28
29
  `)
29
- process.exit(0)
30
+ rnxExit(0)
30
31
  }
31
32
 
32
33
  await runShellBooleanMode(args, opts, {
@@ -13,6 +13,7 @@ import { launchReapedChrome } from '../../../../scripts/lib/reap-browser'
13
13
  import { DEFAULT_SOOTSIM_BRIDGE_PORT } from '../../src/bridge-constants'
14
14
  import { composeFramedScreenshot } from '../../src/screenshots/frame-compose'
15
15
  import { buildResolveRectEval, type SampleRect } from '../browser-evals'
16
+ import { rnxExit } from '../run-rnx'
16
17
  import {
17
18
  callInBridge,
18
19
  checkSimHealth,
@@ -64,7 +65,7 @@ examples:
64
65
  rnx screenshot --area 0,200,393,400 --output hero.png
65
66
  rnx screenshot --id loginButton --output button.png
66
67
  `)
67
- process.exit(0)
68
+ rnxExit(0)
68
69
  }
69
70
 
70
71
  const unknown = findUnknownFlags(args)
@@ -77,7 +78,7 @@ examples:
77
78
  )
78
79
  }
79
80
  console.error(' run `rnx screenshot --help` for the list of supported flags')
80
- process.exit(1)
81
+ rnxExit(1)
81
82
  }
82
83
 
83
84
  const gallery = args.includes('--gallery')
@@ -89,7 +90,7 @@ examples:
89
90
  if (gallery || themes) {
90
91
  if (withFrame) {
91
92
  console.error(' --with-frame is not supported with --gallery / --themes')
92
- process.exit(1)
93
+ rnxExit(1)
93
94
  }
94
95
  // these still go through the playwright-backed path — the bridge can't
95
96
  // crawl routes on its own yet.
@@ -102,7 +103,7 @@ examples:
102
103
  ) {
103
104
  console.error(' --with-frame only supports full-screen capture for now')
104
105
  console.error(' remove --area / --id / --text, or capture raw and compose later')
105
- process.exit(1)
106
+ rnxExit(1)
106
107
  }
107
108
 
108
109
  // share the standard bridge arg parser so --sim / --port / saved sims
@@ -132,7 +133,7 @@ examples:
132
133
  console.error(
133
134
  ` screenshot failed: ${err instanceof Error ? err.message : String(err)}`,
134
135
  )
135
- process.exit(1)
136
+ rnxExit(1)
136
137
  }
137
138
  return
138
139
  }
@@ -140,7 +141,7 @@ examples:
140
141
  if (withFrame) {
141
142
  console.error(' --with-frame requires a running rnx bridge')
142
143
  console.error(' open the app in a live sim first, then rerun the command')
143
- process.exit(1)
144
+ rnxExit(1)
144
145
  }
145
146
 
146
147
  if (rect) {
@@ -148,7 +149,7 @@ examples:
148
149
  console.error(
149
150
  ' start one with `rnx serve`, `rnx desktop`, or your project dev server',
150
151
  )
151
- process.exit(1)
152
+ rnxExit(1)
152
153
  }
153
154
 
154
155
  await runPlaywrightScreenshot(args, opts)
@@ -25,6 +25,7 @@ import { chromium, type Frame, type Page } from 'playwright-core'
25
25
  import { launchReapedChromeScoped } from '../../../../scripts/lib/reap-browser'
26
26
  import { rnxPublicBrand } from '../../src/public-brand'
27
27
  import { resolveCliAuth, type CliAuth } from '../auth'
28
+ import { rnxExit } from '../run-rnx'
28
29
 
29
30
  const HELP = `
30
31
  rnx screenshot appstore capture — headlessly capture + upload App Store slides
@@ -128,7 +129,7 @@ function resolveSessionAuth(): { token: string; origin: string } {
128
129
  '\n rnx screenshot appstore capture needs a logged-in session.\n' +
129
130
  ' run `rnx login` first (the captured slides upload to that account).\n\n',
130
131
  )
131
- process.exit(1)
132
+ rnxExit(1)
132
133
  }
133
134
 
134
135
  function isLoopback(hostname: string): boolean {
@@ -15,6 +15,7 @@ import {
15
15
  readDaemonLockfile,
16
16
  } from '../../src/home-paths'
17
17
  import { SootSimBridgeHost } from '../../src/host/bridge-host'
18
+ import { rnxExit } from '../run-rnx'
18
19
  import { resolveDefaultUploadOrigin } from './upload'
19
20
 
20
21
  interface ServeOptions {
@@ -41,7 +42,7 @@ examples:
41
42
  rnx serve
42
43
  rnx serve --port 7668 --quiet
43
44
  `)
44
- process.exit(0)
45
+ rnxExit(0)
45
46
  }
46
47
 
47
48
  const portArgIdx = args.indexOf('--port')
@@ -51,7 +52,7 @@ examples:
51
52
  : (opts.port ?? DEFAULT_SOOTSIM_BRIDGE_PORT)
52
53
  if (Number.isNaN(port)) {
53
54
  console.error(` invalid --port value: ${args[portArgIdx + 1]}`)
54
- process.exit(1)
55
+ rnxExit(1)
55
56
  }
56
57
  const quiet = args.includes('--quiet') || args.includes('-q')
57
58
 
@@ -64,7 +65,7 @@ examples:
64
65
  ` an rnx bridge is already running (pid ${existingLock.pid}, port ${existingLock.bridgePort})`,
65
66
  )
66
67
  console.error(` stop it with 'rnx daemon stop' first`)
67
- process.exit(1)
68
+ rnxExit(1)
68
69
  }
69
70
 
70
71
  ensureSootsimHome()
@@ -116,7 +117,7 @@ examples:
116
117
  try {
117
118
  await host.close()
118
119
  } catch {}
119
- process.exit(0)
120
+ rnxExit(0)
120
121
  }
121
122
  process.on('SIGINT', () => shutdown('SIGINT'))
122
123
  process.on('SIGTERM', () => shutdown('SIGTERM'))
@@ -1,3 +1,4 @@
1
+ import { rnxExit } from '../run-rnx'
1
2
  import { callInBridge, createBridgeFromParsed, parseBridgeCliArgs } from '../ws-bridge'
2
3
 
3
4
  export type ShellBooleanModeAction = 'on' | 'off' | 'toggle'
@@ -23,7 +24,7 @@ export function parseShellBooleanModeAction(args: string[]): ShellBooleanModeAct
23
24
  const action = args[0]?.toLowerCase() ?? 'toggle'
24
25
  if (action !== 'on' && action !== 'off' && action !== 'toggle') {
25
26
  console.error(` unknown argument: "${action}" (expected on | off | toggle)`)
26
- process.exit(1)
27
+ rnxExit(1)
27
28
  }
28
29
  return action
29
30
  }