stim 1.35.0 → 1.37.0

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 (167) hide show
  1. package/README.md +3 -1
  2. package/dist/{acquire-artifact-0E_iw7Rf.mjs → acquire-artifact-zBUbPuDP.mjs} +20 -4
  3. package/dist/{act-CyxFP8Vj.mjs → act-BGAFjY8f.mjs} +21 -21
  4. package/dist/{activity-BQpJpAjA.mjs → activity-CdpXXSq2.mjs} +6 -6
  5. package/dist/{agent-device-usage-output-BoOC3ZF9.mjs → agent-device-usage-output-D0582GHy.mjs} +5 -5
  6. package/dist/{android-YRb1UzSy.mjs → android-BBwLpxRh.mjs} +51 -40
  7. package/dist/{android-B2DSKg-A.mjs → android-BPBARZMR.mjs} +2 -2
  8. package/dist/{android-Iq0M2t2d.mjs → android-CGctfYpv.mjs} +7 -7
  9. package/dist/{android-CjcJE7uA.mjs → android-CaSsewbu.mjs} +5 -5
  10. package/dist/android-cas-compiler.mjs +1 -1
  11. package/dist/{android-cas-Dhcjkys1.mjs → android-cas-p8gna03x.mjs} +4 -4
  12. package/dist/{android-image-DFk26aY6.mjs → android-image-DY8KxK2m.mjs} +3 -3
  13. package/dist/{android-project-DhO6el8N.d.mts → android-project-v_1nej_x.d.mts} +3 -1
  14. package/dist/api.d.mts +30 -9
  15. package/dist/api.mjs +36 -28
  16. package/dist/{apk-signed-tail-CPpA-3vu.mjs → apk-signed-tail-BMv-KLcB.mjs} +2 -2
  17. package/dist/{artifact-2NIRz6SC.mjs → artifact-BrNZTZtA.mjs} +44 -15
  18. package/dist/{artifact-BG4h_WTC.mjs → artifact-BsimBWxG.mjs} +37 -15
  19. package/dist/{artifact-platform-DqCWUieN.mjs → artifact-platform-BaGL1i1X.mjs} +1 -1
  20. package/dist/{auto-placement-CBdWa87P.mjs → auto-placement-CFKNrWLU.mjs} +7 -7
  21. package/dist/{browser-web-CNlRugJv.mjs → browser-web-YFsgCP_a.mjs} +15 -15
  22. package/dist/{build-CNE3Wo5-.mjs → build-DIhuoozz.mjs} +77 -28
  23. package/dist/{build-cache-_fkewiwH.mjs → build-cache-Dt-dhCJF.mjs} +6 -6
  24. package/dist/{build-plan-BSgR9yKo.mjs → build-plan-CgnLDof9.mjs} +7 -7
  25. package/dist/{cache-manifest-8JX9S1QJ.mjs → cache-manifest-BO0TIcPV.mjs} +1 -1
  26. package/dist/cache-manifest.mjs +1 -1
  27. package/dist/{cdp-C216kOAn.mjs → cdp-CgT47_9A.mjs} +1 -1
  28. package/dist/{chrome-C8sC5tdl.mjs → chrome-DL5znvmo.mjs} +1 -1
  29. package/dist/{cli-DK24VzHi.mjs → cli-BGUrlSH3.mjs} +21 -20
  30. package/dist/cli.mjs +1 -1
  31. package/dist/{client-Dy0eJJtz.mjs → client-DU6dnGX1.mjs} +7 -7
  32. package/dist/collector-run.mjs +7 -7
  33. package/dist/{command-output-CGxrQ3Bd.mjs → command-output-ByEmIwur.mjs} +1 -1
  34. package/dist/{config-BW0fAtoK.mjs → config-CNmN-ndb.mjs} +61 -12
  35. package/dist/{dependencies-IVl2Ga2D.mjs → dependencies-BozoTBqa.mjs} +102 -64
  36. package/dist/{dependency-state-mL5g4H6K.mjs → dependency-state-BQeC4FVn.mjs} +2 -2
  37. package/dist/{detached-entry-tfrgGVWb.mjs → detached-entry-VqFeEE9W.mjs} +1 -1
  38. package/dist/{dev-client-DDApoVvd.mjs → dev-client-3SQzMRXZ.mjs} +2 -2
  39. package/dist/{device-p_cp8IzW.mjs → device-BIg1iExg.mjs} +11 -11
  40. package/dist/{device-mOFYiHiw.mjs → device-DGMvzoZZ.mjs} +13 -13
  41. package/dist/{device-android-C-biM49_.mjs → device-android-CBat355q.mjs} +9 -9
  42. package/dist/{device-capacity-C0PiTyRb.mjs → device-capacity-DWUOvY13.mjs} +19 -19
  43. package/dist/device-host-worker.mjs +16 -16
  44. package/dist/{device-pool-nsMvt2X2.mjs → device-pool-B8IqZKqm.mjs} +3 -3
  45. package/dist/{device-provision-BYYJuRKZ.mjs → device-provision-DWAoSKEw.mjs} +10 -10
  46. package/dist/{doctor-RosbBfTV.mjs → doctor-Bknt0121.mjs} +24 -24
  47. package/dist/{doctor-BptE4PaK.mjs → doctor-CPzwqcXY.mjs} +15 -15
  48. package/dist/{doctor-BBAb8NLe.mjs → doctor-CxgR5vPi.mjs} +1 -1
  49. package/dist/{doctor-fingerprint-DqWvIhMb.mjs → doctor-fingerprint-Bo4z8YNP.mjs} +1 -1
  50. package/dist/doctor-fingerprint.mjs +1 -1
  51. package/dist/{doctor-watchman-CKOnCINh.mjs → doctor-watchman-CPE4C8KV.mjs} +5 -5
  52. package/dist/{eas-build-BxJdzQnF.mjs → eas-build-CwOXKJwa.mjs} +4 -4
  53. package/dist/{eas-fallback-DU2WDF8r.mjs → eas-fallback-Cnb12a50.mjs} +6 -6
  54. package/dist/{eas-session-ledger-DCUfh6m7.mjs → eas-session-ledger-TE1miVz5.mjs} +6 -6
  55. package/dist/{error-diagnostics-D6wlK-yX.mjs → error-diagnostics-CXTT3bYC.mjs} +10 -10
  56. package/dist/{exec-CGuDzt40.mjs → exec-L37dbiIb.mjs} +7 -1
  57. package/dist/{gc-BUkonUfz.mjs → gc-0jdcnDHs.mjs} +19 -19
  58. package/dist/{gc-CvMEytXz.mjs → gc-1ZLq1djg.mjs} +2 -2
  59. package/dist/{guide-BWozWG7D.mjs → guide-COxIANZu.mjs} +179 -86
  60. package/dist/{hosted-android-y6K3DKQT.mjs → hosted-android-D8JbIzgC.mjs} +4 -4
  61. package/dist/{hosted-client-Bb89P6an.mjs → hosted-client-BLwuXEZS.mjs} +7 -7
  62. package/dist/{hosted-logs-DYPsnWMF.mjs → hosted-logs-BWEQNJx_.mjs} +7 -7
  63. package/dist/{hosted-logs-sync-DfUJ2GpF.mjs → hosted-logs-sync-uWSrH2mf.mjs} +5 -5
  64. package/dist/{hosted-macos-DsEzYVY_.mjs → hosted-macos-BnCYAv1y.mjs} +6 -6
  65. package/dist/{hosted-native-C9xQYYFb.mjs → hosted-native-OBT2sJxn.mjs} +8 -8
  66. package/dist/{ios-Qam0bT9n.mjs → ios-2Qr4_Zu2.mjs} +1 -1
  67. package/dist/{ios-BCKxjpRp.mjs → ios-Bjz7aPLy.mjs} +8 -8
  68. package/dist/{ios-BdZdNsAj.mjs → ios-BveW7qK1.mjs} +16 -6
  69. package/dist/{ios-FhMkDfNC.mjs → ios-CGyx4PA7.mjs} +44 -34
  70. package/dist/{ios-device-DMOnaH5n.mjs → ios-device-ByrDWSpC.mjs} +3 -3
  71. package/dist/{ios-device-DLdEDWJj.mjs → ios-device-ygijU78G.mjs} +1 -1
  72. package/dist/{ios-project-PXBDoaii.mjs → ios-project-XHg87vyQ.mjs} +7 -7
  73. package/dist/{ios-signing-CCFNjjWU.mjs → ios-signing-CRYQ1W42.mjs} +3 -3
  74. package/dist/{ios-state-CWsBysyN.mjs → ios-state-enWc5P6U.mjs} +1 -1
  75. package/dist/{js-swap-07ikLRJJ.mjs → js-swap-C6vl3vEd.mjs} +60 -13
  76. package/dist/{launch-CTq5gBim.mjs → launch-f3RnbFW5.mjs} +48 -28
  77. package/dist/{lightened-DikgC3-S.mjs → lightened-Cdfmo8MO.mjs} +5 -5
  78. package/dist/{logs-YDMfEohb.mjs → logs-DAjxBF3c.mjs} +6 -6
  79. package/dist/{logs-DwI3Rkpf.mjs → logs-x3em2-oI.mjs} +7 -7
  80. package/dist/{macos-BoNM-l6f.mjs → macos-D_LAseN9.mjs} +22 -22
  81. package/dist/{macos-C_e9f5-5.mjs → macos-ZfpWlzBO.mjs} +1 -1
  82. package/dist/macos-run.mjs +1 -1
  83. package/dist/maintenance-run.mjs +6 -6
  84. package/dist/{metro-B5PVz0Wv.mjs → metro-TIQ1Wft-.mjs} +4 -4
  85. package/dist/{metro-request-2LmFpC1z.mjs → metro-request-DcUxyaq8.mjs} +2 -2
  86. package/dist/{named-ports-CA0nB9Yw.mjs → named-ports-BfEMi9bK.mjs} +3 -3
  87. package/dist/{native-android-Mv4YTrVN.mjs → native-android-COOrNDk2.mjs} +18 -18
  88. package/dist/{native-gradle-artifact-inputs-C_TU6wPq.mjs → native-gradle-artifact-inputs-B4Mwydmf.mjs} +5 -5
  89. package/dist/{native-runtime-oDqT4UES.mjs → native-runtime-UxUBU8up.mjs} +6 -6
  90. package/dist/{native-source-ChAGj7R1.mjs → native-source-D2ZfiQ6U.mjs} +1 -1
  91. package/dist/{native-xcode-inputs-DsozghTX.mjs → native-xcode-inputs-DUv7Q3ok.mjs} +3 -3
  92. package/dist/{native-xcode-ios-UXnH9NRY.mjs → native-xcode-ios-DXcteLVi.mjs} +18 -19
  93. package/dist/offload-worker.d.mts +1 -1
  94. package/dist/offload-worker.mjs +22 -22
  95. package/dist/{operation-exec-DKlBcKAL.mjs → operation-exec-DNynwpqO.mjs} +1 -1
  96. package/dist/{ownership-hC7xvvxF.mjs → ownership-CQTg6v1d.mjs} +3 -3
  97. package/dist/{page-Dj8IqvGM.mjs → page-CoN9al_x.mjs} +2 -2
  98. package/dist/{phone-reverses-B9WyCBKQ.mjs → phone-reverses-CHtco460.mjs} +4 -4
  99. package/dist/{placement-log-D0DZLcJk.mjs → placement-log-oQnELAvQ.mjs} +1 -1
  100. package/dist/{plan-placement-DqmLrWoX.mjs → plan-placement-45EOlIG1.mjs} +6 -6
  101. package/dist/{ports-C1_1Qgdy.mjs → ports-DKO7EUNt.mjs} +3 -3
  102. package/dist/{prebuild-BptrXmh_.mjs → prebuild-BKkj3OyL.mjs} +12 -12
  103. package/dist/{project-Dqqj3IkW.mjs → project-BCtQz48d.mjs} +16 -16
  104. package/dist/{pull-request-BpMTNkMB.mjs → pull-request-m8cMZ3aE.mjs} +2 -2
  105. package/dist/pull-requests.mjs +1 -1
  106. package/dist/{react-native-android-Bsm_o4A8.mjs → react-native-android-MI4ktuhL.mjs} +27 -31
  107. package/dist/{react-native-build-BTUcE926.mjs → react-native-build-dixAL2G8.mjs} +9 -9
  108. package/dist/{react-native-doctor-CfsCTKZt.mjs → react-native-doctor-CvkWincj.mjs} +6 -6
  109. package/dist/{react-native-ios-_cK2pjZn.mjs → react-native-ios-DF5otoBR.mjs} +17 -18
  110. package/dist/recorded-build-CGHGCO8m.mjs +76 -0
  111. package/dist/{recordings-AKZfsW2W.mjs → recordings-BcOzqFD1.mjs} +1 -1
  112. package/dist/{registration-DKjJGQ6p.mjs → registration-C-3PDR3X.mjs} +1 -1
  113. package/dist/{reload-DsTMtMDU.mjs → reload-DGWfNFwQ.mjs} +16 -16
  114. package/dist/{reload-CXgce4Yo.mjs → reload-DWxmO9dY.mjs} +1 -1
  115. package/dist/{remote-BsmYHUxH.mjs → remote-CV2jBcLv.mjs} +9 -9
  116. package/dist/remote-DWYGW2f5.mjs +158 -0
  117. package/dist/{result-DK6nTO-M.mjs → result-CWyxwPvZ.mjs} +23 -17
  118. package/dist/{run-N-BbRxnC.mjs → run-FZtMQgrx.mjs} +2 -2
  119. package/dist/{server-bare-BTlICuaX.mjs → server-bare-Ksh1NKeI.mjs} +2 -2
  120. package/dist/{server-command-Cu2w-UjB.mjs → server-command-BO2DIsJV.mjs} +5 -5
  121. package/dist/server-expo-9hQwyLze.mjs +2 -0
  122. package/dist/{server-expo-CjQwxvIi.mjs → server-expo-ZS9_WaNG.mjs} +3 -3
  123. package/dist/{settings-B5IBDfTx.mjs → settings-Ag4pbs0z.mjs} +5 -4
  124. package/dist/{settings-DcmVICCn.mjs → settings-TYrzDh8T.mjs} +2 -2
  125. package/dist/{settings-payload-BoiFMiFq.mjs → settings-payload-CUM0DYwz.mjs} +5 -5
  126. package/dist/{settings-write-B3LzEVwf.mjs → settings-write-D_9_IEx7.mjs} +6 -6
  127. package/dist/settings.schema.json +1 -1
  128. package/dist/{simslim-DKdJx0LL.mjs → simslim-BMgpTRWe.mjs} +2 -2
  129. package/dist/{slot-launch-DsQmPdlg.mjs → slot-launch-DW_29Bmu.mjs} +6 -6
  130. package/dist/{stage-Dqk0qvaI.mjs → stage-_8k8p7uq.mjs} +2 -2
  131. package/dist/{start-GkRBR1e3.mjs → start-CdgtOksb.mjs} +1 -1
  132. package/dist/{start-DIFiT2P5.mjs → start-CzBB5R7N.mjs} +12 -12
  133. package/dist/{state-CtmYTRWm.mjs → state-CfP-ccP8.mjs} +4 -4
  134. package/dist/{state-DSOUqO-o.mjs → state-DsrFh3yv.mjs} +2 -2
  135. package/dist/{stats-Dz08IopP.mjs → stats-BgTyuzib.mjs} +5 -5
  136. package/dist/{stats-report-BVRCqwWA.mjs → stats-report-Ci6TAfFm.mjs} +1 -1
  137. package/dist/{status-DhKv_e8a.mjs → status-Bcdy5eHt.mjs} +24 -24
  138. package/dist/{status-DTFhDnd1.mjs → status-C2PdxK6q.mjs} +1 -1
  139. package/dist/{status-Dost__Vn.mjs → status-C7Zzb-Eh.mjs} +1 -1
  140. package/dist/{status-watch-UecLnPQD.mjs → status-watch-DY0EZcmg.mjs} +5 -5
  141. package/dist/status-worker.mjs +1 -1
  142. package/dist/{stim-desktop-_WTria-r.mjs → stim-desktop-DWGAfaud.mjs} +2 -2
  143. package/dist/{stop-CcZISot5.mjs → stop-CbxsTKyZ.mjs} +5 -5
  144. package/dist/{stop-vRe6TQk5.mjs → stop-CkmBkNyg.mjs} +16 -16
  145. package/dist/{stop-QFOqgICJ.mjs → stop-iGkvEvDn.mjs} +2 -2
  146. package/dist/supervisor-run.mjs +15 -15
  147. package/dist/{support-DW575Dnx.mjs → support-CfYmOdQs.mjs} +76 -38
  148. package/dist/{support-CNqJDBrH.mjs → support-JZ4KRW0C.mjs} +7 -7
  149. package/dist/{swiftpm-artifact-inputs-DQTJTczX.mjs → swiftpm-artifact-inputs-C1rZDRDs.mjs} +4 -4
  150. package/dist/{swiftpm-macos-BKczZ0k9.mjs → swiftpm-macos-DRTjC7Ff.mjs} +11 -11
  151. package/dist/{toolchain-DRQyCvlp.mjs → toolchain-BeD7tbBW.mjs} +73 -9
  152. package/dist/{toolchain-BDlugtoh.mjs → toolchain-CNlKc9pH.mjs} +1 -1
  153. package/dist/trigger-Bp3lruF2.mjs +2 -0
  154. package/dist/{trigger-BtB4kbe0.mjs → trigger-G_gbfIVB.mjs} +2 -2
  155. package/dist/{warm-progress-q11Vdvhh.mjs → warm-progress-CJQ8tk5O.mjs} +6 -6
  156. package/dist/{web-TDWjHUT3.mjs → web-BXbmysa1.mjs} +9 -9
  157. package/dist/web-BcaySU05.mjs +2 -0
  158. package/dist/web-run.mjs +8 -8
  159. package/dist/windows-report.mjs +1 -1
  160. package/dist/{workspace-state-BdZ-QgmB.mjs → workspace-state-DOPXG2Gp.mjs} +3 -3
  161. package/dist/{workspaces-CY3KSdC0.mjs → workspaces-DCzDzydB.mjs} +15 -14
  162. package/dist/{worktree-D6myrQ2H.mjs → worktree-6ngObKkw.mjs} +1 -1
  163. package/dist/{worktree-fKKe8j5M.mjs → worktree-BAC43Kio.mjs} +27 -27
  164. package/package.json +7 -7
  165. package/dist/server-expo-DbSypdNl.mjs +0 -2
  166. package/dist/trigger-D8B7QR0q.mjs +0 -2
  167. package/dist/web-D1m1LKEz.mjs +0 -2
@@ -1,8 +1,8 @@
1
- import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-B5IBDfTx.mjs";
2
- import { i as findProjectRoot$1 } from "./project-Dqqj3IkW.mjs";
3
- import { h as RECENT_LAUNCH_MS } from "./eas-session-ledger-DCUfh6m7.mjs";
4
- import { o as guideStatus, t as WATCHMAN_NESTED_WORKTREES } from "./doctor-watchman-CKOnCINh.mjs";
5
- import "./status-watch-UecLnPQD.mjs";
1
+ import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-Ag4pbs0z.mjs";
2
+ import { i as findProjectRoot$1 } from "./project-BCtQz48d.mjs";
3
+ import { h as RECENT_LAUNCH_MS } from "./eas-session-ledger-TE1miVz5.mjs";
4
+ import { o as guideStatus, t as WATCHMAN_NESTED_WORKTREES } from "./doctor-watchman-CPE4C8KV.mjs";
5
+ import "./status-watch-DY0EZcmg.mjs";
6
6
  import { SETTINGS, SETTINGS_SCHEMA_URL, TUTORIAL_VERSION } from "@stim-cli/core/state";
7
7
  import chalk from "chalk";
8
8
  //#region src/guide/agent.ts
@@ -148,7 +148,7 @@ server.* or hosting.* for the user, or approve requests. Read stim guide setting
148
148
  Desktop access tickets and person-owned approval.
149
149
  Read stim guide settings to select a remote machine. Keep a requested named
150
150
  placement when recovering STIM_OFFLOAD_REFUSED: report its reason and remedy.
151
- When the user mentions slow builds, a busy machine or wanting updates away from the desk, tell them about Stim Desktop > Settings > Remote Machines > Add or Phones > Pair a Phone; see stim guide settings.
151
+ When the user mentions slow builds, a busy machine or wanting updates away from the desk, tell them about Stim Desktop > Settings > Remote Machines > Add (or stim remote add <machine> in their terminal) or Phones > Pair a Phone; see stim guide settings.
152
152
 
153
153
  Read stim guide lifecycle concurrency when a build waits on another workspace
154
154
  or a build call times out. A native build can outlive a shell timeout; if the
@@ -612,7 +612,19 @@ it never starts an EAS build. iOS simulatorApp selects the simulator viewer.
612
612
  remote selects the launch host using the CLI's existing placement and approval
613
613
  rules; remoteBuild independently selects where compilation runs. macOS requires
614
614
  a named hosting Mac; auto, eas and proxy are not supported there.
615
- All methods accept signal. run builds, installs and launches.
615
+ All methods accept signal. run builds, installs and launches. iOS and Android run
616
+ also accept recordedBuild: true, which installs and launches the app the last
617
+ build with the same scheme and configuration (or variant) recorded in this
618
+ workspace, without fingerprinting, building or replacing its JS, and refuses with
619
+ STIM_NO_RECORDED_BUILD when there is none. They also accept cleanAppState: true,
620
+ which before install uninstalls every other user app except XCUITest runners
621
+ (*.xctrunner) and clears the app's data
622
+ (iOS: defaults, data container and the simulator keychain; Android: pm clear),
623
+ whether or not the install is skipped, on a local simulator or emulator only: a
624
+ run placed on another machine or on EAS is not cleaned. Both refuse device, and
625
+ cleanAppState refuses a local simulator or emulator Stim does not own, with
626
+ STIM_BAD_ARG.
627
+ @stim-cli/ci sets both; the CLI and the private Desktop transport set neither.
616
628
  Web requires a running server, just like stim web.
617
629
 
618
630
  build produces an artifact without acquiring a device, starting a runtime, or
@@ -627,18 +639,25 @@ including when Desktop is not installed on the build machine. Opening it only
627
639
  navigates; it does not install or launch the built app.
628
640
 
629
641
  Build options:
630
- ios: scheme, configuration, arch (arm64, x86_64, all), buildCache, remoteBuild
631
- android: variant, abi (arm64-v8a, armeabi-v7a, x86, x86_64, all), buildCache, remoteBuild
642
+ ios: scheme, configuration, arch (arm64, x86_64, all), buildCache, remoteBuild, easProfile
643
+ android: variant, abi (arm64-v8a, armeabi-v7a, x86, x86_64, all), buildCache, remoteBuild, easProfile
632
644
  macos: remoteBuild
633
- An iOS build targets the simulator. A Debug build defaults to the host
634
- architecture (Android only while optimizations.android.targetAbiOnly is on, the
635
- default); Release defaults to all. macOS builds the configured Debug SwiftPM app.
645
+ An iOS build targets the simulator and defaults to the host architecture in
646
+ every configuration; arch all builds every architecture the project lists. An
647
+ Android Debug build defaults to the host ABI while
648
+ optimizations.android.targetAbiOnly is on, the default; Release defaults to all.
649
+ macOS builds the configured Debug SwiftPM app.
636
650
  Build results retain an owned appPath (iOS), apkPath (Android) or bundle (macOS)
637
- inside this workspace until worktree removal. Later builds keep earlier copies.
651
+ inside this workspace. An iOS or Android build also records its app in workspace
652
+ state for recordedBuild runs; the last build per scheme and configuration or
653
+ variant wins. A successful build removes the workspace's other copies for its
654
+ platform that no recorded build points to, so a copy lasts until a build replaces
655
+ its record (for macOS, until the next macOS build) or the worktree is removed.
656
+ Copy or export a result you need to keep before the next build. easProfile downloads a
657
+ completed EAS development build instead of compiling; it never starts an EAS build.
638
658
  A build leaves a running app's last build record and build log untouched; it
639
659
  writes its own build-artifact-<platform>.ndjson. No distribution archive or web build
640
- pipeline is inferred. Use @stim-cli/ci's buildCI to export a portable artifact and
641
- diagnostics for your CI provider.
660
+ pipeline is inferred. Use @stim-cli/ci's buildCI to record the build and, with exportPath, export a portable artifact for your CI provider.
642
661
 
643
662
  Unresolved native Metro cleanup keeps error.details.cause.retainedClaimRoots and
644
663
  STIM_CLAIM_UNAVAILABLE even after cancellation. Web cancellation stops pending
@@ -951,12 +970,14 @@ leased until <time>" for each one.`,
951
970
  the ios.scheme setting; absent for automatic selection;
952
971
  not the app URL scheme
953
972
  cacheKey the shared-build-cache key derived from it (the
954
- configuration is part of it: -release-sim vs
973
+ configuration is part of it: -release-sim-arm64 vs
955
974
  -debug-sim-arm64). A single-architecture simulator build
956
- ends in its architecture (-arm64 or -x86-64): a local Debug
957
- build compiles this machine's, a --remote build the remote
958
- host's. A local non-Debug simulator build compiles every
959
- architecture the project lists and has no suffix
975
+ ends in its architecture (-arm64 or -x86-64): a local build
976
+ compiles this machine's in every configuration, a --remote
977
+ build the remote host's (a React Native Release build
978
+ offloaded to a worker may also contain other
979
+ architectures). A build of every architecture the project
980
+ lists (stim build --arch all) has no suffix
960
981
  With --eas-profile, fingerprint is computed by EAS CLI using the selected
961
982
  profile/environment, and cacheKey identifies the EAS project and build ID
962
983
  separately from local native builds. cacheHit is "remote" for the EAS
@@ -1270,7 +1291,7 @@ leased until <time>" for each one.`,
1270
1291
  local: machine that approved this one but whose key no
1271
1292
  person confirmed, so nothing pinned it; fingerprint is the
1272
1293
  key's fingerprint to compare with the one stim-server setup
1273
- printed there, and only stim doctor --fix in a terminal asks.
1294
+ printed there, and only stim remote add or doctor --fix in a terminal asks.
1274
1295
  A local: entry has no dnsName. "outdated" means its
1275
1296
  stim-server speaks protocol 1; the finding names the
1276
1297
  stim-server service update command to run there.
@@ -1285,7 +1306,7 @@ leased until <time>" for each one.`,
1285
1306
  fits the pin; match is "exact", or "major" for the newest
1286
1307
  install of the pinned major not older than the pin), else null
1287
1308
  remoteMachines one { machine, state, diagnosis?, dnsName?, fingerprint?, deviceId?,
1288
- requestedAt?, expiresAt?, offloadable?, reasons?, problems?, capacity?, host? } per
1309
+ requestedAt?, tailnet?, expiresAt?, offloadable?, reasons?, problems?, capacity?, host? } per
1289
1310
  remote.machines entry, for its build approval; state is "approved", "pending", "not-asked",
1290
1311
  "revoked" (revoked or denied), "lapsed" (the request lapsed
1291
1312
  before approval), "key-changed", "key-unconfirmed" (as in
@@ -1297,6 +1318,10 @@ leased until <time>" for each one.`,
1297
1318
  (deviceHosts carries it too); the codes are
1298
1319
  tailscale-stopped, tailscale-logged-out, tailscale-unavailable
1299
1320
  (this machine's Tailscale), peer-not-found, peer-ambiguous,
1321
+ peer-wrong-tailnet (no peer is named so, and this Mac is
1322
+ signed in to another tailnet than the one it was on when it
1323
+ asked the machine for access; both are named; tailnet is
1324
+ { name, suffix?, id? }),
1300
1325
  peer-offline (with last seen), peer-no-answer (the connection
1301
1326
  got no reply and tailscale ping fails), route-missing (nothing accepts
1302
1327
  connections on the serve port), route-tls, route-http-error
@@ -1748,7 +1773,7 @@ RULES
1748
1773
  workspaceBuildOutputs { dir, projectRoot, inTreeDirs, bytes, idleDays,
1749
1774
  willClear, reason, detail } derived-data,
1750
1775
  gradle-build, android-cas, cache-provider,
1751
- macos/build, macos/<Product>.app and
1776
+ js-swap-tmp, macos/build, macos/<Product>.app and
1752
1777
  macos/staging-* of each workspace; inTreeDirs
1753
1778
  lists the project's android/app/build,
1754
1779
  android/build,
@@ -3842,6 +3867,11 @@ WHAT WRITES WHAT
3842
3867
  the run that pointed you at it. A build from the API's
3843
3868
  build() writes build-artifact-<platform>.ndjson
3844
3869
  instead, so it never replaces a run's transcript.
3870
+ A failed build also leaves a copy of its transcript next
3871
+ to the log, named <log>.failed (build-ios.ndjson.failed);
3872
+ the failure's log line points at it, and the next
3873
+ failed build of that log replaces it. \`logs\` does not
3874
+ read it.
3845
3875
 
3846
3876
  Only a dev server Stim hosted is captured. If you started the bundler
3847
3877
  yourself, the metro and client sources stay empty -- which is not a sign of a
@@ -3904,7 +3934,7 @@ Branch on the code, never on the message.`,
3904
3934
  on the host to enable handoff and native logs (hello features hosted-ios-data
3905
3935
  for iOS and hosted-android-data for Android).
3906
3936
  A name outside remote.machines is STIM_BAD_ARG. Missing or pending hosting
3907
- approval keeps the doctor --fix and stim-server setup remedies.`
3937
+ approval keeps the stim remote add and stim-server setup remedies.`
3908
3938
  },
3909
3939
  STIM_EAS_BUILD_MISSING: {
3910
3940
  summary: "no completed EAS development build matches; build only with session authorization",
@@ -4021,7 +4051,11 @@ Branch on the code, never on the message.`,
4021
4051
  summary: "xcodebuild or gradle failed; the Android missing-SDK and APK refusals",
4022
4052
  body: () => `STIM_BUILD_FAILED
4023
4053
  xcodebuild or gradle failed. The EXTRACTED diagnostics are printed (capped),
4024
- not the transcript. Read the log path on the next line for the rest.
4054
+ not the transcript. Read the log path on the next line for the rest: it names
4055
+ a copy of the failed transcript (<log>.failed) that the next build in the
4056
+ workspace does not overwrite. When xcodebuild names failed script phases,
4057
+ the first diagnostics are the phase names and the last error lines the
4058
+ script printed, ahead of the compiler diagnostics.
4025
4059
  Three Android refusals share this code without gradle itself failing:
4026
4060
  - NO ANDROID SDK, before gradle starts: nothing exists at the SDK path
4027
4061
  Stim resolves (ANDROID_HOME, else ANDROID_SDK_ROOT, else the default
@@ -4282,9 +4316,9 @@ fingerprint reads, such as .env.local. Make the named input agree on both Macs,
4282
4316
  for example by committing the lockfile pod install rewrote there; pairing does
4283
4317
  not change it.
4284
4318
 
4285
- Run stim doctor --fix to ask for build access if not paired. Check
4286
- stim settings get remote.machines. A person on the worker approves this machine
4287
- by running the stim-server setup command doctor --fix printed, with its ticket
4319
+ Run stim remote add <machine> to ask for build access if not approved. Check
4320
+ stim remote list. A person on the worker approves this machine
4321
+ by running the stim-server setup command stim remote add printed, with its ticket
4288
4322
  and expiry (guide settings). Agents never run setup or approve requests.
4289
4323
  Rerun with --remote-build auto or remote for placement with local fallback, or
4290
4324
  --remote-build local to keep the build here.
@@ -5166,6 +5200,16 @@ captured" (in metro.ndjson, bare RN)
5166
5200
  Stim's processes. For a legacy record, stop the server with the tool that
5167
5201
  started it before retrying. Never reconstruct ownership from a process
5168
5202
  name, port, or wall-clock timestamp.`
5203
+ },
5204
+ STIM_NO_RECORDED_BUILD: {
5205
+ summary: "a recordedBuild run found no recorded build for its selectors",
5206
+ body: () => `STIM_NO_RECORDED_BUILD
5207
+ The API run option \`recordedBuild: true\` (used by \`stim-ci run\`) installs the
5208
+ app the last build with the same iOS scheme and configuration, or Android
5209
+ variant, recorded in this workspace's state. None is recorded, or its app was
5210
+ removed. Nothing was started. Build first with the same selectors and the same
5211
+ Stim home (\`stim-ci build\`, or the API build), then run again. \`stim guide ci\`
5212
+ has the flow. \`stim ios\` and \`stim android\` never use it.`
5169
5213
  },
5170
5214
  STIM_BAD_ARG: {
5171
5215
  summary: "an argument, setting, directory, flavor, or device name refused before anything starts",
@@ -6177,23 +6221,47 @@ prerequisites. \`reload\` refuses because the app has no Metro runtime. Re-run
6177
6221
  \`stim android\` after an edit and use \`stim stop\` for scoped cleanup.`
6178
6222
  },
6179
6223
  ci: {
6180
- summary: "Run an app and tests through @stim-cli/ci with diagnostics and scoped cleanup",
6224
+ summary: "Build an app once, then install it and run tests through @stim-cli/ci with scoped cleanup",
6181
6225
  body: () => `CONTINUOUS INTEGRATION
6182
6226
 
6183
6227
  Install app dependencies and platform tools first. Use a dedicated checkout:
6184
6228
  cleanup stops that workspace, including resources created before a build fails.
6185
6229
 
6230
+ npx --yes --package @stim-cli/ci stim-ci build --platform ios --project ./app
6186
6231
  npx --yes --package @stim-cli/ci stim-ci run --platform ios --project ./app --timeout 1800 -- pnpm test:e2e
6187
6232
 
6188
6233
  Or install npm install --global @stim-cli/ci and use stim-ci directly.
6189
6234
  Platforms: ios, android, macos, web. Everything after -- is argv, not a shell.
6190
- --artifacts selects the result directory (a fresh temporary directory by default).
6235
+ build is the only step that compiles (or restores from the cache, or with
6236
+ --eas-profile downloads an EAS development build). It records the app for this
6237
+ checkout, platform and selectors (iOS scheme and configuration, Android variant)
6238
+ in workspace state under the Stim home; the last build for those selectors wins.
6239
+ run never builds, fingerprints or replaces JS: it installs and launches that
6240
+ recorded app as built and trusts it, then runs the test. A Debug app still gets
6241
+ Metro from run. With no recorded build for the selectors, run refuses with
6242
+ STIM_NO_RECORDED_BUILD and names the stim-ci build command. Build and run must
6243
+ share the Stim home (--home or STIM_HOME). macOS and web run unchanged: macOS
6244
+ run builds the app itself.
6245
+ Every iOS and Android run on this machine starts from clean app state, even when
6246
+ the install is skipped: it uninstalls every other user app except XCUITest runners
6247
+ (*.xctrunner), clears the app's defaults and data
6248
+ container and resets the simulator keychain on iOS, and runs pm clear on Android.
6249
+ A run that ios.remote or android.remote places on another machine or on EAS is
6250
+ not cleaned. build always compiles on this machine and ignores remote.build. An
6251
+ iOS build, and an Android Debug build, target this machine's architecture only;
6252
+ when run can land on
6253
+ another machine or on EAS, build with --arch all (iOS) or --abi all (Android).
6254
+ Plain stim ios and stim android clean only a device they adopt.
6255
+ build exports nothing unless --export <path> is given (an APK, or a tar.gz).
6256
+ --artifacts selects a directory for result, test and diagnostic files; without
6257
+ it none are written, no logs are copied and the action uploads nothing.
6191
6258
  An explicit artifacts directory must be empty; use a new directory per run.
6192
6259
  Stdout is one JSON result; progress and test output go to stderr.
6193
6260
 
6194
6261
  Tests receive STIM_CI_PLATFORM, STIM_CI_DEVICE_ID, STIM_CI_APP_ID,
6195
- STIM_CI_METRO_PORT, STIM_CI_ARTIFACTS_DIR and STIM_CI_RUN_RESULT. The last is
6196
- run.json with the exact public API result. Use that target and check app
6262
+ STIM_CI_METRO_PORT, STIM_CI_ARTIFACTS_DIR and STIM_CI_RUN_RESULT. The last two
6263
+ are empty without --artifacts; otherwise STIM_CI_RUN_RESULT is run.json with the
6264
+ exact public API result, whose facts carry the stable cache appPath. Use that target and check app
6197
6265
  readiness; launched can still be bundling or unverified.
6198
6266
 
6199
6267
  result.json preserves the test exit code even if diagnostics or cleanup fail.
@@ -6213,7 +6281,7 @@ CI=true alone does not change defaults, ownership or coordination. Persist only
6213
6281
  cache artifacts, not state, claims or device ledgers. Independent homes must
6214
6282
  not share a writable filesystem cache because its claims live in the home.
6215
6283
 
6216
- The programmatic runner is import { runCI } from '@stim-cli/ci'. See its package
6284
+ The programmatic API is import { buildCI, runCI } from '@stim-cli/ci'. See its package
6217
6285
  README for result types, cancellation, cache policy, and coordination findings.`
6218
6286
  },
6219
6287
  "hosted-android": {
@@ -6222,9 +6290,8 @@ README for result types, cancellation, cache policy, and coordination findings.`
6222
6290
 
6223
6291
  If Stim is not installed globally, replace stim with npx stim.
6224
6292
 
6225
- stim settings set remote.machines '["janics-mac-mini"]'
6226
- stim doctor --fix
6227
- stim doctor
6293
+ stim remote add janics-mac-mini
6294
+ stim remote list
6228
6295
  stim android --remote janics-mac-mini --device-profile pixel_7
6229
6296
  stim status --json
6230
6297
  stim reload android
@@ -6384,10 +6451,9 @@ and show records already copied here.`
6384
6451
 
6385
6452
  If Stim is not installed globally, replace stim with npx stim.
6386
6453
 
6387
- stim settings set remote.machines '["janics-mac-mini"]'
6388
- stim doctor --fix
6389
- # A person there runs the stim-server setup command doctor printed.
6390
- stim doctor
6454
+ stim remote add janics-mac-mini
6455
+ # A person there runs the stim-server setup command it printed.
6456
+ stim remote list
6391
6457
  stim ios --remote janics-mac-mini --device-type "iPhone 17 Pro" --runtime "iOS 27.0"
6392
6458
  stim status --json
6393
6459
  stim reload ios
@@ -7025,7 +7091,7 @@ result as proof instead of requiring an unrelated screenshot.`
7025
7091
  at adoption renamed for the adopting workspace, then, inside the boot
7026
7092
  the run pays anyway, \`simctl privacy reset all\` and
7027
7093
  \`simctl keychain reset\`; at install, every other user app
7028
- is uninstalled, and this workspace's app, when it is
7094
+ except XCUITest runners (*.xctrunner) is uninstalled, and this workspace's app, when it is
7029
7095
  installed, has its preferences domain deleted (an
7030
7096
  expo-dev-client app's is replaced by the two dev-menu-off
7031
7097
  keys, see \`guide facts devmenu\`) and its data
@@ -8184,16 +8250,18 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
8184
8250
 
8185
8251
  Warm copies installed dependencies, Pods, native output, and other ignored
8186
8252
  paths eligible under the source checkout's Git ignore rules, including .env
8187
- and local configuration. The source's nonempty
8188
- .worktreeexclude replaces its resolved worktree.exclude setting. Nested
8189
- registered worktrees and ignored entries named .DS_Store, .DerivedData,
8190
- .idea, .jj or .pnpm-store are not copied, and neither is
8191
- android/build/generated/autolinking. Warm never walks a copied directory, so
8192
- a .DS_Store or .idea inside a copied directory stays. Warm deletes only
8193
- these paths from the copy: .pnpm-store in a copied node_modules (pnpm
8194
- refills it from the network or its global store), the autolinking directory
8195
- under a copied android, android/build or android/build/generated (Gradle
8196
- regenerates it for the destination checkout on its next build), and the
8253
+ and local configuration. The source's nonempty .worktreeexclude replaces its
8254
+ resolved worktree.exclude setting. Nested registered worktrees and ignored
8255
+ entries named .DS_Store, .DerivedData, .idea, .jj or .pnpm-store are not
8256
+ copied, and neither are android/build/generated/autolinking and .expo/types.
8257
+ Warm never walks a copied directory, so a .DS_Store or .idea inside a copied
8258
+ directory stays. Warm deletes only these paths from the copy: .pnpm-store in
8259
+ a copied node_modules (pnpm refills it from the network or its global
8260
+ store), the autolinking directory under a copied android, android/build or
8261
+ android/build/generated (Gradle regenerates it for the destination checkout
8262
+ on its next build), types in a copied .expo (Expo Router's typed routes,
8263
+ possibly generated from the source's older routes; Expo regenerates them on
8264
+ the destination's first expo start), and the
8197
8265
  expo-modules-jsi/apple/.DerivedData Xcode build state, directly under
8198
8266
  node_modules or in the pnpm virtual store. An ignored directory that Git
8199
8267
  reports above those names (for example an app directory with no tracked
@@ -8201,9 +8269,9 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
8201
8269
  $STIM_HOME/trash and a detached, low-priority rm deletes them after warm
8202
8270
  returns (through the programmatic API, before the call resolves); when the
8203
8271
  rename is not possible (Windows, $STIM_HOME on another volume), warm deletes
8204
- them before it returns. Warm also skips paths
8205
- overlapping a nested destination worktree or below a symlink ancestor.
8206
- Tracked .idea settings come from Git and stay untouched by warm.
8272
+ them before it returns. Warm also skips paths overlapping a nested
8273
+ destination worktree or below a symlink ancestor. Tracked .idea settings
8274
+ come from Git and stay untouched by warm.
8207
8275
 
8208
8276
  A carried ios/Pods still names the source checkout's path in its generated
8209
8277
  files and in the checksum of a podspec that embeds that path (the
@@ -8688,6 +8756,9 @@ THE POOL: WHICH DEVICE AN ID-LESS \`--device\` PICKS
8688
8756
  alive on the device rather than by a bundle fetch. Device logs are still
8689
8757
  collected, so \`logs --errors\` answers "does it repro in release/Hermes
8690
8758
  bytecode".
8759
+ EAS and proxy adapters cannot verify a release or native process launch:
8760
+ launched stays "unverified" with a notice that process verification is
8761
+ unavailable. These adapters collect no device logs or native crash reports.
8691
8762
 
8692
8763
  On a release CACHE HIT the cached APK carries its BUILDER's baked-in JS, so
8693
8764
  it is never installed as-is. Stim copies it aside, regenerates this
@@ -8698,7 +8769,11 @@ THE POOL: WHICH DEVICE AN ID-LESS \`--device\` PICKS
8698
8769
  mmaps it), then zipaligns and re-signs with apksigner. The keystore defaults
8699
8770
  to android/app/debug.keystore with the standard password; android.keystore /
8700
8771
  android.keystorePassword override it (see \`guide settings\`). The cache
8701
- entry itself is never modified.
8772
+ entry itself is never modified. The bundler runs with TMPDIR set to the
8773
+ workspace's js-swap-tmp/, which holds Metro's default cache; Stim empties it
8774
+ when an EXPO_PUBLIC_ value, EXPO_NO_DOTENV, NODE_ENV or a .env* file in the
8775
+ project root differs from the previous swap's. A metro.config.js that sets
8776
+ its own cacheStores keeps its own cache location.
8702
8777
 
8703
8778
  AN EXPO-UPDATES APP GETS A FRESH EMBEDDED UPDATE. expo-updates launches the
8704
8779
  update with the newest commitTime for the binary's runtime version, and the
@@ -8750,13 +8825,16 @@ THE POOL: WHICH DEVICE AN ID-LESS \`--device\` PICKS
8750
8825
  skips Metro ENTIRELY: no gate, no port wiring, no dev-client deep link (a
8751
8826
  plain \`simctl launch\`), and the payload says \`metroPort: null\` --
8752
8827
  \`launched\` is verified by the app PROCESS staying alive, not by a bundle
8753
- fetch. The build cache keys on the configuration
8754
- (\`<fingerprint>-release-sim\`), and because a cached Release .app carries
8755
- its builder's baked-in JS, a cache hit regenerates THIS workspace's bundle
8828
+ fetch. The build cache keys on the configuration and this Mac's simulator
8829
+ architecture, the only one a local build compiles
8830
+ (\`<fingerprint>-release-sim-arm64\`), and because a cached Release .app
8831
+ carries its builder's baked-in JS, a cache hit regenerates THIS workspace's bundle
8756
8832
  (the project's own \`expo export:embed\` / \`react-native bundle\`, plus
8757
8833
  its own hermesc when Hermes is enabled) into a copy of the artifact,
8758
8834
  refreshes an expo-updates manifest as described above, re-signs it and
8759
- installs that; any swap failure falls back to a full build
8835
+ installs that. Like the Android swap, it bundles with a workspace-private
8836
+ default Metro cache that is emptied when the EXPO_PUBLIC_ values,
8837
+ EXPO_NO_DOTENV, NODE_ENV or .env* files change. Any swap failure falls back to a full build
8760
8838
  rather than ever installing stale JS. A simulator Release build can run on
8761
8839
  a remote machine (stim guide settings, remote.build), which bundles the JS
8762
8840
  of the checkout it synced, its gitignored .env.production files included,
@@ -10055,6 +10133,8 @@ THE ONE CASE GC WILL NOT REAP
10055
10133
  global, so \`worktree remove\` reclaims them along with everything else in
10056
10134
  the global workspace directory. Each build starts its transcript file over, so the log
10057
10135
  holds one run and a workspace you keep building in does not accumulate them.
10136
+ A failed build also leaves a copy of its transcript (<log>.failed) that the
10137
+ next failed build replaces; \`gc\` does not trim it, \`worktree remove\` does.
10058
10138
 
10059
10139
  Simulators are large and live in the CoreSimulator device set, not in your
10060
10140
  project. If the disk is filling up, Stim's own devices are usually not the
@@ -10074,7 +10154,7 @@ a changed value.
10074
10154
 
10075
10155
  WORKSPACE BUILD OUTPUTS
10076
10156
  Each workspace directory holds derived-data/, gradle-build/, android-cas/,
10077
- cache-provider/, macos/build, the staged macos/<Product>.app and macos/staging-*
10157
+ cache-provider/, js-swap-tmp/, macos/build, the staged macos/<Product>.app and macos/staging-*
10078
10158
  leftovers. The project's own android/app/build, android/build,
10079
10159
  android/.gradle and .build count with them when git ignores every file in
10080
10160
  the directory and tracks none; one that fails that check, or is not in a
@@ -10332,7 +10412,7 @@ KEYS STIM READS
10332
10412
  (simulator only). Committing
10333
10413
  { "ios": { "configuration": "Release" } } makes every
10334
10414
  \`stim ios\` in the app a release-shaped build:
10335
- embedded JS, no Metro, cache keyed -release-sim, and
10415
+ embedded JS, no Metro, cache keyed -release-sim-<arch>, and
10336
10416
  a JS-bundle swap on cache hits. The \`--configuration\`
10337
10417
  flag overrides this per invocation. Unset means Debug.
10338
10418
  ios.remote where the simulator runs, with the same meaning as
@@ -10998,11 +11078,12 @@ A remote machine approves this one when a person there runs
10998
11078
  \`stim-server setup\` with this machine's setup ticket (32 random bytes, 43
10999
11079
  base64url characters) in STIM_SETUP_TICKET. Stim Desktop's Add wizard makes the
11000
11080
  ticket and sets STIM_ACCESS_TICKET for one \`doctor --fix\` run; without it,
11001
- \`doctor --fix\` makes one and prints the setup command to run on the worker.
11081
+ \`stim remote add <machine>\` or \`doctor --fix\` makes one and prints the setup
11082
+ command to run on the worker.
11002
11083
  Agents never set STIM_ACCESS_TICKET, never run \`stim-server setup\`, never edit
11003
11084
  \`remote.*\`, \`server.*\` or \`hosting.*\` for the user, and never approve requests.
11004
11085
  Until setup approves, the worker answers unknown-secret and the entry stays
11005
- pending; every doctor run tries again. The first connection after approval pins
11086
+ pending; every \`stim remote list\` or doctor run tries again. The first connection after approval pins
11006
11087
  the worker's stim-server key in build-machines.json or device-host-machines.json,
11007
11088
  and every later connection must prove that key; the tailnet node and address
11008
11089
  never decide who the worker is. With --fix, a pending entry is replaced when
@@ -11018,8 +11099,8 @@ agents do not run them. \`stim guide facts doctor\` lists the codes.
11018
11099
  REMOTE MACHINES AND PHONE APP
11019
11100
  When the user mentions slow builds, a busy machine, a full disk or device limit, or
11020
11101
  wanting updates away from the desk, tell them about Stim Desktop > Settings >
11021
- Remote Machines > Add (another machine on the tailnet that builds for this one,
11022
- or a Mac that also hosts simulators) or Phones > Pair a Phone (the Stim phone
11102
+ Remote Machines > Add, or \`stim remote add <machine>\` in their terminal (another
11103
+ machine on the tailnet that builds for this one, or a Mac that also hosts simulators) or Phones > Pair a Phone (the Stim phone
11023
11104
  app). Stim Desktop also suggests these itself, at most once a day and never
11024
11105
  during a build. Agents only tell the user: they never run \`stim-server setup\`,
11025
11106
  never edit \`remote.*\`, \`server.*\` or \`hosting.*\` for the user, and never
@@ -11028,10 +11109,20 @@ approve requests.
11028
11109
  REMOTE MACHINES ARE MACHINE-LEVEL
11029
11110
  \`remote.machines\` names the remote machines this machine may build on and host owned
11030
11111
  simulator sessions on, by MagicDNS name with an optional serve port (default
11031
- 7443). Name each node and port once:
11112
+ 7443). Name each node and port once. From any directory:
11113
+
11114
+ stim remote add janics-mac-mini
11115
+ stim remote list
11116
+ stim remote remove janics-mac-mini
11032
11117
 
11033
- stim settings set remote.machines '["janics-mac-mini"]'
11034
- stim doctor --fix
11118
+ \`stim remote add\` appends the machine to the machine-scope list, keeping the
11119
+ entries already there, asks it for build and device-host approval and prints
11120
+ the setup command for it. \`stim remote list\` contacts every listed machine
11121
+ and reports both approvals; it asks nothing new. \`stim remote remove\` drops the
11122
+ entry and forgets this machine's credentials for it; the remote machine keeps
11123
+ its approval until a person there runs the \`stim-server devices revoke\`
11124
+ command it prints. Each takes --json. \`stim settings set remote.machines\`
11125
+ replaces the whole list.
11035
11126
 
11036
11127
  The order of \`remote.machines\` is the priority order for every workload: the
11037
11128
  build, simulator, emulator and macOS app each go to the first listed machine that
@@ -11059,16 +11150,15 @@ addresses are refused, and the running server applies a change within seconds.
11059
11150
  An interface name follows the interface onto whatever private network it
11060
11151
  joins, so name the address on a machine that moves between networks, and an
11061
11152
  interface only on a worker that stays put. Then the person runs the setup
11062
- command \`stim doctor --fix\` prints here:
11153
+ command \`stim remote add\` prints here:
11063
11154
 
11064
11155
  stim settings set server.lanAddresses '["10.0.0.92"]' # on the worker
11065
- stim settings set remote.machines '["local:10.0.0.92"]' # on this machine
11066
- stim doctor --fix
11156
+ stim remote add local:10.0.0.92 # on this machine
11067
11157
 
11068
11158
  Every connection runs Stim's Noise handshake, so plain WebSocket carries it
11069
11159
  without TLS, and the address never identifies anyone. Nothing on a local network
11070
11160
  vouches for the worker's key, so \`stim-server setup\` prints the worker's server
11071
- key fingerprint and \`stim doctor --fix\`, run by a person in a terminal, shows
11161
+ key fingerprint and \`stim remote list\`, run by a person in a terminal, shows
11072
11162
  the fingerprint the worker answered with and pins the key only after they
11073
11163
  confirm it matches. Until then the entry reports key-unconfirmed and is not
11074
11164
  used. Agents never answer that question. The printed setup command carries the
@@ -11135,8 +11225,8 @@ machine idle: wait for existing work to finish or stop the relevant sessions bef
11135
11225
  benchmarking. Agents change these settings only when the user asks them to.
11136
11226
 
11137
11227
  DEVICE HOSTING
11138
- Only \`doctor --fix\` asks for device-host access: it makes a setup ticket and
11139
- prints the command. A person approves by running \`stim-server setup\` on the
11228
+ Only \`stim remote add\` and \`doctor --fix\` ask for device-host access: they
11229
+ make a setup ticket and print the command. A person approves by running \`stim-server setup\` on the
11140
11230
  worker with that ticket: one ticket, one expiry, one record per capability for
11141
11231
  the key that holds the ticket, with a per-grant Y/n question (Enter approves) in a
11142
11232
  terminal or \`--yes\` otherwise. Agents never run \`stim-server setup\` or
@@ -11166,9 +11256,11 @@ Stim sends tokens only to the pinned node's own tailnet address,
11166
11256
  with its MagicDNS name for TLS and Host routing. A changed node refuses
11167
11257
  access, and uncertain replies or unreadable credentials preserve the pin.
11168
11258
  An invalid remote.machines setting reports an error and preserves every saved credential.
11169
- \`doctor --fix\` forgets entries removed from remote.machines; remove a
11170
- replaced machine, run it, then re-add the name to request a new approval.
11171
- A definite revoked or lapsed request can be requested again with --fix.
11259
+ \`stim remote remove\` forgets the credentials of the machine it removes, and
11260
+ \`doctor --fix\` forgets those of entries removed from remote.machines otherwise.
11261
+ For a replaced machine, run \`stim remote remove <machine>\`, then
11262
+ \`stim remote add <machine>\` to request a new approval. A definite revoked or
11263
+ lapsed request can be requested again with \`stim remote add\` or --fix.
11172
11264
  An in-progress approval inspection reports busy rather than replacing its
11173
11265
  pending token. \`stim macos --remote <placement>\` or \`macos.remote\` runs a macOS
11174
11266
  app on an approved remote Mac (stim guide macos), and \`ios.remote\` and
@@ -11197,10 +11289,11 @@ The same \`remote.machines\` list names the machines that may build for this one
11197
11289
  "remote": { "machines": ["janics-mac-mini"] }
11198
11290
  }
11199
11291
 
11200
- \`doctor --fix\`, run in any app directory, makes a setup ticket for each named
11201
- machine and prints the \`stim-server setup\` command a person runs on that
11202
- machine to approve this one, under the approval rule above. The next doctor run
11203
- pins the worker's stim-server key in $STIM_HOME/build-machines.json. A build grant is full access
11292
+ \`stim remote add <machine>\`, run in any directory, makes a setup ticket for
11293
+ that machine and prints the \`stim-server setup\` command a person runs on that
11294
+ machine to approve this one, under the approval rule above; \`doctor --fix\`,
11295
+ run in an app directory, does the same for every named machine. The next
11296
+ \`stim remote list\` or doctor run pins the worker's stim-server key in $STIM_HOME/build-machines.json. A build grant is full access
11204
11297
  to the account stim-server runs as: project code runs there unsandboxed, so it
11205
11298
  can grant itself read and control. Revoking it does not undo what that code
11206
11299
  already did. Grant it only to machines you trust.
@@ -11280,8 +11373,8 @@ files the native fingerprint hashes or the Expo config reads, such as .env.local
11280
11373
  and other Expo .env files, secrets included. Nothing under node_modules and no
11281
11374
  build output the fingerprint ignores is sent. A fingerprint-mismatch refusal
11282
11375
  names the sources that differ and the files pod install or prebuild rewrote there.
11283
- Run stim doctor --fix to ask for build access if not paired. A person on the
11284
- worker approves it by running the stim-server setup command doctor printed, with
11376
+ Run stim remote add <machine> to ask for build access if not approved. A person
11377
+ on the worker approves it by running the stim-server setup command it printed, with
11285
11378
  its ticket and expiry. Check stim settings get remote.machines,
11286
11379
  or rerun with --remote-build auto or --remote-build local. Ctrl-C cancels
11287
11380
  the remote build without a local xcodebuild, Gradle or SwiftPM compile.
@@ -12350,9 +12443,9 @@ ON ANOTHER MAC
12350
12443
 
12351
12444
  stim macos --remote <machine> or macos.remote builds the Debug app on this Mac and runs it on an
12352
12445
  approved remote Mac over the tailnet, without SSH. The Mac must be listed
12353
- in remote.machines and approved: stim doctor --fix makes a setup ticket, a
12354
- person on that Mac runs stim-server setup with that ticket and expiry (guide
12355
- settings), and stim doctor then pins that Mac's stim-server key. Stim goes ahead
12446
+ in remote.machines and approved: stim remote add <machine> adds it and makes a
12447
+ setup ticket, a person on that Mac runs stim-server setup with that ticket and
12448
+ expiry (guide settings), and stim remote list then pins that Mac's stim-server key. Stim goes ahead
12356
12449
  only with the stim-server that proves it holds that key.
12357
12450
  A refusal or an unreachable host fails the command; with a named Mac it never launches here
12358
12451
  instead.
@@ -1,7 +1,7 @@
1
- import { d as throwIfCancelled } from "./exec-CGuDzt40.mjs";
2
- import { l as call, u as connectHost } from "./hosted-client-Bb89P6an.mjs";
3
- import { a as requestHostedMetro } from "./metro-request-2LmFpC1z.mjs";
4
- import { a as stopHostedNative, i as prepareHostedNative, r as placeHostedNative } from "./hosted-native-C9xQYYFb.mjs";
1
+ import { d as throwIfCancelled } from "./exec-L37dbiIb.mjs";
2
+ import { l as call, u as connectHost } from "./hosted-client-BLwuXEZS.mjs";
3
+ import { a as requestHostedMetro } from "./metro-request-DcUxyaq8.mjs";
4
+ import { a as stopHostedNative, i as prepareHostedNative, r as placeHostedNative } from "./hosted-native-OBT2sJxn.mjs";
5
5
  //#region src/device-host/hosted-android.ts
6
6
  async function prepareHostedAndroid(machine, selectors, recorded, mode) {
7
7
  return await prepareHostedNative(machine, selectors, recorded, "android", false, mode);
@@ -1,7 +1,7 @@
1
- import { d as throwIfCancelled, l as cancellableSleep } from "./exec-CGuDzt40.mjs";
2
- import { K as resolveEndpoint, P as diagnoseConnectFailure } from "./config-BW0fAtoK.mjs";
3
- import { t as BuildConnection } from "./client-Dy0eJJtz.mjs";
4
- import { tt as configuredMachines } from "./support-DW575Dnx.mjs";
1
+ import { d as throwIfCancelled, l as cancellableSleep } from "./exec-L37dbiIb.mjs";
2
+ import { F as diagnoseConnectFailure, q as resolveEndpoint } from "./config-CNmN-ndb.mjs";
3
+ import { t as BuildConnection } from "./client-DU6dnGX1.mjs";
4
+ import { nt as configuredMachines } from "./support-CfYmOdQs.mjs";
5
5
  import { createHash } from "node:crypto";
6
6
  import { lstatSync, readFileSync, readdirSync, readlinkSync } from "node:fs";
7
7
  import { join } from "node:path";
@@ -28,7 +28,7 @@ function credentialRefusal(message, remedy = "Run stim doctor.") {
28
28
  function hostingCredential(machine) {
29
29
  const configured = configuredMachines();
30
30
  if (configured === null) throw credentialRefusal("remote.machines is invalid. Run stim guide settings and correct it.", "Run stim guide settings and correct remote.machines.");
31
- if (!configured.includes(machine)) throw Object.assign(/* @__PURE__ */ new Error(`${machine} is not in remote.machines. Add it with stim settings set remote.machines, then run stim doctor --fix to ask it for hosting access.`), { code: "STIM_BAD_ARG" });
31
+ if (!configured.includes(machine)) throw Object.assign(/* @__PURE__ */ new Error(`${machine} is not in remote.machines. Run stim remote add ${machine} to add it and ask it for hosting access.`), { code: "STIM_BAD_ARG" });
32
32
  let credentials;
33
33
  try {
34
34
  credentials = readDeviceHostMachines();
@@ -36,9 +36,9 @@ function hostingCredential(machine) {
36
36
  throw credentialRefusal("The hosting credentials are unreadable. Run stim doctor.");
37
37
  }
38
38
  const credential = credentials.find((each) => each.machine === machine);
39
- if (!credential) throw credentialRefusal(`This machine has not asked ${machine} for hosting access. Run stim doctor --fix.`, "Run stim doctor --fix.");
39
+ if (!credential) throw credentialRefusal(`This machine has not asked ${machine} for hosting access. Run stim remote add ${machine}.`, `Run stim remote add ${machine}.`);
40
40
  if (credential.state !== "approved") {
41
- const remedy = `A person on ${machine} runs the stim-server setup command stim doctor --fix printed; then run stim doctor.`;
41
+ const remedy = `A person on ${machine} runs the stim-server setup command stim remote add ${machine} printed; then run stim remote list.`;
42
42
  throw credentialRefusal(`${machine} has not confirmed hosting access for this machine. ${remedy}`, remedy);
43
43
  }
44
44
  return credential;
@@ -1,11 +1,11 @@
1
- import { t as getExecutor } from "./exec-CGuDzt40.mjs";
2
- import { E as workspaceDir, k as workspaceLogsDir$1 } from "./workspace-state-BdZ-QgmB.mjs";
3
- import { l as phaseLine } from "./command-output-CGxrQ3Bd.mjs";
4
- import { U as parseMachine$1, _t as validateDeviceSlot, ut as deviceSlotFileKey } from "./config-BW0fAtoK.mjs";
5
- import { n as macosDir } from "./state-DSOUqO-o.mjs";
6
- import { n as androidLogGroups, r as isAndroidCrashText } from "./android-B2DSKg-A.mjs";
1
+ import { t as getExecutor } from "./exec-L37dbiIb.mjs";
2
+ import { E as workspaceDir, k as workspaceLogsDir$1 } from "./workspace-state-DOPXG2Gp.mjs";
3
+ import { l as phaseLine } from "./command-output-ByEmIwur.mjs";
4
+ import { W as parseMachine$1, dt as deviceSlotFileKey, vt as validateDeviceSlot } from "./config-CNmN-ndb.mjs";
5
+ import { n as macosDir } from "./state-DsrFh3yv.mjs";
6
+ import { n as androidLogGroups, r as isAndroidCrashText } from "./android-BPBARZMR.mjs";
7
7
  import { c as readNdjsonGenerations$1, i as createNdjsonWriter } from "./ndjson-CrjIsGzw.mjs";
8
- import { l as call } from "./hosted-client-Bb89P6an.mjs";
8
+ import { l as call } from "./hosted-client-BLwuXEZS.mjs";
9
9
  import { mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
10
10
  import { dirname, join } from "node:path";
11
11
  import { LOG_ROTATE_BYTES, ambientWrite, withDirLockAsync } from "@stim-cli/core";
@@ -1,8 +1,8 @@
1
- import { l as phaseLine } from "./command-output-CGxrQ3Bd.mjs";
2
- import { n as pullHostedNativeLogs, r as readHostedNativeLogs, t as pullHostedMacosLogs } from "./hosted-logs-DYPsnWMF.mjs";
3
- import { u as connectHost } from "./hosted-client-Bb89P6an.mjs";
4
- import { n as readHostedIos, t as readHostedAndroid } from "./ios-state-CWsBysyN.mjs";
5
- import "./hosted-macos-DsEzYVY_.mjs";
1
+ import { l as phaseLine } from "./command-output-ByEmIwur.mjs";
2
+ import { n as pullHostedNativeLogs, r as readHostedNativeLogs, t as pullHostedMacosLogs } from "./hosted-logs-BWEQNJx_.mjs";
3
+ import { u as connectHost } from "./hosted-client-BLwuXEZS.mjs";
4
+ import { n as readHostedIos, t as readHostedAndroid } from "./ios-state-enWc5P6U.mjs";
5
+ import "./hosted-macos-BnCYAv1y.mjs";
6
6
  import { watch } from "node:fs";
7
7
  import { dirname, relative, resolve, sep } from "node:path";
8
8
  import { ambientWrite, configDir } from "@stim-cli/core";