stim 1.23.1 → 1.25.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 (174) hide show
  1. package/README.md +3 -2
  2. package/dist/{acquire-artifact-BzYRDgaP.mjs → acquire-artifact-zA4S7RHE.mjs} +2 -2
  3. package/dist/{act-vxiMwdf5.mjs → act-BbHS3oV8.mjs} +41 -26
  4. package/dist/{activity-BpWUPgUm.mjs → activity-BpjwrQXU.mjs} +6 -6
  5. package/dist/{agent-device-usage-output-CUlLsbRt.mjs → agent-device-usage-output-Bnkerfod.mjs} +5 -5
  6. package/dist/{android-DtfRGLcc.mjs → android-BGwuK3Mc.mjs} +75 -50
  7. package/dist/{android-CLi6DSiS.mjs → android-CNZgRC-4.mjs} +5 -5
  8. package/dist/{android-C7sVmyI9.mjs → android-Cjcj8MCw.mjs} +140 -46
  9. package/dist/{android-cas-ngferVq2.mjs → android-cas-BVqh2Zep.mjs} +3 -3
  10. package/dist/android-cas-compiler.mjs +1 -1
  11. package/dist/{android-project-DVWyCbWU.d.mts → android-project-CTYaETc0.d.mts} +6 -2
  12. package/dist/{android-DR5lZ2Az.mjs → android-saBeB4lr.mjs} +13 -3
  13. package/dist/api.d.mts +22 -5
  14. package/dist/api.mjs +32 -31
  15. package/dist/{artifact-Xvgibgzq.mjs → artifact-Co8zixVx.mjs} +19 -17
  16. package/dist/{artifact-DBI3DALs.mjs → artifact-DN8JNwqS.mjs} +18 -17
  17. package/dist/{artifact-platform-CXcmX_j3.mjs → artifact-platform-CMRc0M_r.mjs} +3 -3
  18. package/dist/{browser-web-BJN9ZHxB.mjs → browser-web-CCgZsHmI.mjs} +16 -17
  19. package/dist/{budget-3ivAK99e.mjs → budget-HyShrIpL.mjs} +149 -47
  20. package/dist/{build-Dv9s8Fz-.mjs → build-CAiw8Ezm.mjs} +33 -29
  21. package/dist/{build-cache-Dv7RN200.mjs → build-cache-CKCzxzxA.mjs} +172 -21
  22. package/dist/{build-plan-BmbdHQbr.mjs → build-plan-zCuHGlA8.mjs} +8 -7
  23. package/dist/{cache-manifest-DSeQjt-Q.mjs → cache-manifest-BPXRONJz.mjs} +1 -1
  24. package/dist/cache-manifest.mjs +1 -1
  25. package/dist/{ccache-CH2EWGPB.mjs → ccache-h1FKhZeg.mjs} +6 -6
  26. package/dist/{cdp-3fwICjzi.mjs → cdp-BG3FJCCx.mjs} +1 -1
  27. package/dist/{chrome-Bbw689-6.mjs → chrome-BvV8ssI3.mjs} +1 -1
  28. package/dist/{cli-BkK6Wr5i.mjs → cli-C4w607Pz.mjs} +20 -20
  29. package/dist/cli.mjs +1 -1
  30. package/dist/{client-B4MMzfo_.mjs → client-BQsmyp_-.mjs} +274 -39
  31. package/dist/collector-run.mjs +6 -6
  32. package/dist/{command-output-YKGWivpG.mjs → command-output-BBvS1H6v.mjs} +3 -2
  33. package/dist/{config-DlrsduwG.mjs → config-BZhXY15H.mjs} +3 -3
  34. package/dist/{created-devices-x9rN6bhs.mjs → created-devices-D2Aca-xu.mjs} +6 -2
  35. package/dist/{dependency-state-1I9KZT1Y.mjs → dependency-state-BwNCYG5Q.mjs} +2 -2
  36. package/dist/{detached-entry-BwNEtIrP.mjs → detached-entry-KmieOKgN.mjs} +1 -1
  37. package/dist/{dev-client-BFxiDpkf.mjs → dev-client-CHoXXZeg.mjs} +3 -3
  38. package/dist/{device-CiNYxqp6.mjs → device-B9FqTBYW.mjs} +81 -54
  39. package/dist/{device-B7ljwccX.mjs → device-F5-4z9ef.mjs} +16 -16
  40. package/dist/{device-capacity-DH0QsZYZ.mjs → device-capacity-ZYaRALv5.mjs} +20 -16
  41. package/dist/device-host-worker.mjs +17 -17
  42. package/dist/{device-ios-CbVDtDIy.mjs → device-ios-DkHBrmvH.mjs} +32 -50
  43. package/dist/{device-lease-run-DXPSwdbb.mjs → device-lease-run-ogEeJ62K.mjs} +6 -6
  44. package/dist/{device-pool-B4iOXIrD.mjs → device-pool-BIg8MU8l.mjs} +3 -3
  45. package/dist/{doctor-DRu-8ld6.mjs → doctor-A_Nr_fDe.mjs} +1 -1
  46. package/dist/{doctor-HUC1igzw.mjs → doctor-Bm8TVpGn.mjs} +37 -31
  47. package/dist/{doctor-fingerprint-DZLoYFVb.mjs → doctor-fingerprint-zlujA1Gs.mjs} +1 -1
  48. package/dist/doctor-fingerprint.mjs +1 -1
  49. package/dist/{doctor-C6t4Maue.mjs → doctor-k3P3PizH.mjs} +14 -14
  50. package/dist/{doctor-watchman-iGBpC6KM.mjs → doctor-watchman-BovI1y3-.mjs} +5 -5
  51. package/dist/{eas-build-DMWSSvxq.mjs → eas-build-CyDKNTBP.mjs} +4 -4
  52. package/dist/{eas-fallback-vKlrqxgE.mjs → eas-fallback-gaZi-dJL.mjs} +16 -15
  53. package/dist/{eas-session-ledger-BQF9Yyy9.mjs → eas-session-ledger-BMCA1gdO.mjs} +12 -8
  54. package/dist/{error-diagnostics-DYsjJIHz.mjs → error-diagnostics-B1Mj_-7h.mjs} +17 -42
  55. package/dist/{errors-ccaPc4ox.mjs → errors-DHm_U5gv.mjs} +2 -1
  56. package/dist/{exec-DEoAhcze.mjs → exec-VFRpu1iA.mjs} +116 -28
  57. package/dist/{gc-BW8E1uSC.mjs → gc-B9jcnmIk.mjs} +205 -28
  58. package/dist/{gc-dDE4QPVu.mjs → gc-eaz403W6.mjs} +2 -2
  59. package/dist/{guide-DYYEO3Wz.mjs → guide-DR0K0xW9.mjs} +328 -89
  60. package/dist/{hosted-android-xcfgCgSF.mjs → hosted-android-Bvb2-ZxD.mjs} +4 -4
  61. package/dist/{hosted-client-Bt-tndxV.mjs → hosted-client-rsRqysJc.mjs} +4 -4
  62. package/dist/{hosted-ios-y19jCYFF.mjs → hosted-ios-RtVcJH3u.mjs} +1 -1
  63. package/dist/{hosted-logs-DzJKzKlj.mjs → hosted-logs-CWKGYWNX.mjs} +11 -6
  64. package/dist/{hosted-macos-BJusKvqL.mjs → hosted-macos-d0pv9Tth.mjs} +7 -7
  65. package/dist/{hosted-native-BmQC6U_x.mjs → hosted-native-BxTizGU2.mjs} +58 -11
  66. package/dist/{idle-shutdown-CJmUOV5x.mjs → idle-shutdown-BIyfl0Zj.mjs} +10 -10
  67. package/dist/{ios-hcBpnEGk.mjs → ios-BQzvJlzw.mjs} +122 -17
  68. package/dist/{ios-CWjqfSm_.mjs → ios-BRVM8b0P.mjs} +81 -49
  69. package/dist/{ios-DTOYZGMJ.mjs → ios-Dvt97HgQ.mjs} +8 -8
  70. package/dist/{ios-xtlRHaeB.mjs → ios-ENC4sRPA.mjs} +1 -1
  71. package/dist/{ios-device-BXZ0c7Kb.mjs → ios-device-B6HK951C.mjs} +1 -1
  72. package/dist/{ios-device-DFGuwF4U.mjs → ios-device-CKSvk0bu.mjs} +3 -3
  73. package/dist/{ios-project-CSZYI1iu.mjs → ios-project-DCUDo06I.mjs} +5 -5
  74. package/dist/{ios-signing-BtAffm0A.mjs → ios-signing-4c_qXvQm.mjs} +2 -2
  75. package/dist/{ios-state-Dtw5K2aI.mjs → ios-state-CT9nV5SP.mjs} +15 -7
  76. package/dist/{js-swap-BSBHldmm.mjs → js-swap-Z9HbC4cj.mjs} +7 -6
  77. package/dist/{launch-D-zq8SHG.mjs → launch-D0lPvFFu.mjs} +49 -30
  78. package/dist/{launch-CP2wDCVd.mjs → launch-DscF1QfM.mjs} +52 -50
  79. package/dist/{logs-pNvA2hHK.mjs → logs-BsIRre8x.mjs} +16 -9
  80. package/dist/{logs-By5aw3g9.mjs → logs-Crs9y34Z.mjs} +8 -6
  81. package/dist/{macos-CPMahOC2.mjs → macos-CcUlJPMu.mjs} +1 -1
  82. package/dist/{macos-C67FZ2ft.mjs → macos-D477nfzH.mjs} +49 -42
  83. package/dist/macos-run.mjs +1 -1
  84. package/dist/maintenance-run.mjs +7 -7
  85. package/dist/{metro-DiXtA3Ty.mjs → metro-1pJgCX4U.mjs} +4 -4
  86. package/dist/{metro-gateway-CKZqKqx7.mjs → metro-gateway-Bp9gJQAN.mjs} +3 -4
  87. package/dist/{named-ports-DkEzOfzO.mjs → named-ports-BVbn8SvC.mjs} +3 -3
  88. package/dist/{native-android-_MWSs3PP.mjs → native-android-BvMizJn1.mjs} +17 -17
  89. package/dist/{native-gradle-artifact-inputs-DHFnmrVf.mjs → native-gradle-artifact-inputs-BJscK4vN.mjs} +5 -5
  90. package/dist/{native-run-Dv88i0aU.mjs → native-run-D5OJsGwA.mjs} +6 -6
  91. package/dist/{native-runtime-DBRfY_PN.mjs → native-runtime-B9w_Qyz3.mjs} +10 -9
  92. package/dist/{native-source-Y0yLhFyQ.mjs → native-source-D-4Dh4JU.mjs} +7 -4
  93. package/dist/{native-xcode-inputs-CqViUh3r.mjs → native-xcode-inputs-Cv4l-obn.mjs} +2 -2
  94. package/dist/{native-xcode-ios-vFgqL_yS.mjs → native-xcode-ios-DGrg90hE.mjs} +21 -20
  95. package/dist/offload-worker.d.mts +12 -4
  96. package/dist/offload-worker.mjs +78 -43
  97. package/dist/{operation-exec-BW0em61G.mjs → operation-exec-CUZifp6Z.mjs} +2 -25
  98. package/dist/{ownership-C5fo5Edb.mjs → ownership-jxxz-19m.mjs} +3 -3
  99. package/dist/{page-DBL2PiUU.mjs → page-CzEA_-5_.mjs} +2 -3
  100. package/dist/phone-reverses-CYb7RRAx.mjs +57 -0
  101. package/dist/{placement-log-BnGgJRRZ.mjs → placement-log-DjOXJRIH.mjs} +1 -1
  102. package/dist/{plan-placement-cr0fEU7b.mjs → plan-placement-BqKgKHCi.mjs} +3 -3
  103. package/dist/{ports-DpXjKkSV.mjs → ports-DtS1Amb0.mjs} +3 -3
  104. package/dist/{prebuild-BligW0QS.mjs → prebuild-JUaqOLpc.mjs} +14 -9
  105. package/dist/{project-DhCtQWWU.mjs → project-BiC68mIp.mjs} +21 -17
  106. package/dist/{pull-request-W1IuLXDt.mjs → pull-request-CbNlkFok.mjs} +2 -2
  107. package/dist/pull-requests.mjs +1 -1
  108. package/dist/{react-native-android-ZlhQfhvq.mjs → react-native-android-DRYqoJc4.mjs} +76 -32
  109. package/dist/{react-native-build-CelbTO_y.mjs → react-native-build-CwZB-agu.mjs} +23 -20
  110. package/dist/{react-native-doctor-LTIaP7lv.mjs → react-native-doctor-BCrytK7h.mjs} +10 -9
  111. package/dist/{react-native-ios-C5W0SA6f.mjs → react-native-ios-Cr1buNFo.mjs} +41 -24
  112. package/dist/{recordings-CQmfzAh7.mjs → recordings-BaoQ0t-J.mjs} +1 -1
  113. package/dist/{registration-BcRgF6Ox.mjs → registration-CN6nlhcD.mjs} +1 -1
  114. package/dist/{reload-QcwnYLYV.mjs → reload-Beftw2X3.mjs} +1 -1
  115. package/dist/{reload-COJWTbae.mjs → reload-FbSgMF8x.mjs} +144 -42
  116. package/dist/{remote-DR8qUERM.mjs → remote-BuZj6AyU.mjs} +16 -7
  117. package/dist/{result-utnBea7x.mjs → result-CR2vk2cj.mjs} +41 -18
  118. package/dist/{run-DidHghD1.mjs → run-BtzE09Dl.mjs} +2 -2
  119. package/dist/{selection-DSMbWEX2.mjs → selection-D5cxEl3t.mjs} +13 -7
  120. package/dist/{server-bare-CafzuyFB.mjs → server-bare-CH9X0RLn.mjs} +56 -4
  121. package/dist/{server-command-B9o92sLM.mjs → server-command-CaBbDNU2.mjs} +5 -5
  122. package/dist/server-expo-C16Zf2k7.mjs +2 -0
  123. package/dist/{server-expo-BXrWxNYh.mjs → server-expo-Ck8EIidM.mjs} +14 -9
  124. package/dist/{settings-C7O8A6ZI.mjs → settings-B5tCoq9N.mjs} +132 -39
  125. package/dist/{settings-PfJx8uK1.mjs → settings-DzH9mGQZ.mjs} +1 -1
  126. package/dist/{settings-write-Chuy7Cte.mjs → settings-write-n0zwfohx.mjs} +7 -7
  127. package/dist/settings.schema.json +51 -0
  128. package/dist/{simslim-BNckWpXi.mjs → simslim-BjxszUAb.mjs} +22 -7
  129. package/dist/{slot-launch-B7AuoWJv.mjs → slot-launch-QeuJMlnJ.mjs} +6 -6
  130. package/dist/{stage-C4u17aES.mjs → stage-D8xlRU2D.mjs} +2 -3
  131. package/dist/{start-BL_BsiWt.mjs → start-C1JLjkNw.mjs} +1 -1
  132. package/dist/{start-CU8mCPC7.mjs → start-YMpNwLhh.mjs} +75 -35
  133. package/dist/{state--smjFSTL.mjs → state-DMRNP7-4.mjs} +4 -4
  134. package/dist/{state-08I3hw3_.mjs → state-DPaM3u5K.mjs} +2 -2
  135. package/dist/{stats-CO6sK0Nh.mjs → stats-CP7STzZw.mjs} +5 -5
  136. package/dist/{stats-report-BzaPrRm6.mjs → stats-report-n2U5plhk.mjs} +1 -1
  137. package/dist/{status-_WPHzVft.mjs → status-CRLiJ-O_.mjs} +24 -24
  138. package/dist/{status-BRROykC8.mjs → status-Fect2w9R.mjs} +1 -1
  139. package/dist/{status-CrJutl6-.mjs → status-cNw6i0_t.mjs} +1 -1
  140. package/dist/{status-watch-BHFasOZN.mjs → status-watch-Bc2J4TZn.mjs} +5 -5
  141. package/dist/status-worker.mjs +1 -1
  142. package/dist/stim-clonefile.c +18 -0
  143. package/dist/{stim-desktop-D5OGpYZM.mjs → stim-desktop-DS0mzR8U.mjs} +2 -2
  144. package/dist/{stop-iuFHjUST.mjs → stop-Br7LKxBE.mjs} +2 -2
  145. package/dist/{stop-CR5689oB.mjs → stop-COP6PQqw.mjs} +5 -5
  146. package/dist/{stop-BJ06ipTZ.mjs → stop-Db9Kh-UA.mjs} +109 -56
  147. package/dist/supervisor-run.mjs +17 -17
  148. package/dist/{support-CbXPbUMJ.mjs → support-Cxj9CmII.mjs} +6 -6
  149. package/dist/{support-TWuQlHQo.mjs → support-qKcbgmI5.mjs} +14 -11
  150. package/dist/{swiftpm-artifact-inputs-DFcGsXDP.mjs → swiftpm-artifact-inputs-iY9fsmOc.mjs} +4 -4
  151. package/dist/{swiftpm-macos-DbwGCpZg.mjs → swiftpm-macos-Bp_sn9P4.mjs} +15 -14
  152. package/dist/{toolchain-XkA2PfJZ.mjs → toolchain-DB1aeqxO.mjs} +1 -1
  153. package/dist/{toolchain-B9hCFCQw.mjs → toolchain-VzLJzZ7O.mjs} +69 -37
  154. package/dist/trigger-BLsHgAGR.mjs +2 -0
  155. package/dist/{trigger-Cbyc41d_.mjs → trigger-CBMe2YLH.mjs} +2 -2
  156. package/dist/{warm-progress-CA3TgT3-.mjs → warm-progress-BV3ZPmcY.mjs} +6 -6
  157. package/dist/{web-DRF_oFXk.mjs → web-B4Yjyt1G.mjs} +12 -10
  158. package/dist/web-DS4UDWvf.mjs +2 -0
  159. package/dist/web-run.mjs +8 -9
  160. package/dist/windows-report.mjs +12 -1
  161. package/dist/windows-report.ps1 +1 -1
  162. package/dist/{workspace-state-U08dEzhG.mjs → workspace-state-CPSp3mav.mjs} +11 -4
  163. package/dist/{workspaces-e41xsjKr.mjs → workspaces-C9w4aeXF.mjs} +36 -32
  164. package/dist/{worktree-B4Nj3EGS.mjs → worktree-CclFIe1Z.mjs} +324 -99
  165. package/dist/{worktree-BEwxVwKF.mjs → worktree-Ct9Gk3KL.mjs} +1 -1
  166. package/dist/{xcode-Rq744mBF.mjs → xcode-CiIIDnuD.mjs} +42 -28
  167. package/package.json +7 -7
  168. package/shim/bundle-response.cjs +53 -1
  169. package/shim/bundle-response.d.cts +1 -1
  170. package/shim/expo-metro-config.cjs +23 -1
  171. package/dist/native-gradle-inputs-Dnh84Zbd.mjs +0 -211
  172. package/dist/server-expo-Ddr8cG_c.mjs +0 -2
  173. package/dist/trigger-yb_nFzPF.mjs +0 -2
  174. package/dist/web-kDE9Myoy.mjs +0 -2
@@ -1,8 +1,8 @@
1
- import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-C7O8A6ZI.mjs";
2
- import { i as findProjectRoot$1 } from "./project-DhCtQWWU.mjs";
3
- import { h as RECENT_LAUNCH_MS } from "./eas-session-ledger-BQF9Yyy9.mjs";
4
- import { o as guideStatus, t as WATCHMAN_NESTED_WORKTREES } from "./doctor-watchman-iGBpC6KM.mjs";
5
- import "./status-watch-BHFasOZN.mjs";
1
+ import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-B5tCoq9N.mjs";
2
+ import { i as findProjectRoot$1 } from "./project-BiC68mIp.mjs";
3
+ import { h as RECENT_LAUNCH_MS } from "./eas-session-ledger-BMCA1gdO.mjs";
4
+ import { o as guideStatus, t as WATCHMAN_NESTED_WORKTREES } from "./doctor-watchman-BovI1y3-.mjs";
5
+ import "./status-watch-Bc2J4TZn.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
@@ -191,13 +191,15 @@ RULES DURING THE LOOP
191
191
  - For stale Metro transforms or file-map state, use stim start --reset-cache.
192
192
  It restarts only this app's verified owned Metro, preserving devices and other
193
193
  apps' caches. See guide lifecycle for reset scope.
194
- - Reload is not part of the normal workflow. Use stim reload on an owned local
195
- simulator or emulator when an error screen remains after the fix, and on
194
+ - Reload is not part of the normal workflow. Use stim reload when an error
195
+ screen remains after the fix on an owned local simulator or emulator, a
196
+ physical device (an EAS Simulator session when its app connects to Metro), and on
196
197
  Android after a failed first bundle load. It reloads JavaScript and never
197
198
  restarts the app. An iOS app whose first bundle failed never connects to
198
199
  Metro, so reload cannot reach it and says to use the device's own Reload
199
- control. For a physical device that reached Metro, use agent-device metro
200
- reload with the reported port. The detected iOS Local Network first-load
200
+ control. With no owned launch recorded, reload goes through this workspace's
201
+ Metro to the apps connected to it, so an app that never connected is not
202
+ reached. The detected iOS Local Network first-load
201
203
  remedy uses UI automation instead because that app never established a Metro
202
204
  connection.
203
205
  - A successful stim reload confirms that the request was sent, not that new
@@ -482,12 +484,14 @@ refuses with STIM_CLAIM_UNAVAILABLE instead of cancellation or timeout. The
482
484
  child cleanup error names the launcher PID; unverifiable processes and descendants are left
483
485
  untouched. On POSIX, a launcher that exited before identity capture can only finish
484
486
  successfully once its process group is proven gone.
485
- After a termination request, cleanup waits at most one second for a child to
486
- close. Overall cleanup has a 35 second budget, including temporary-worktree
487
+ After a termination request, cleanup waits for a child to close, then for its
488
+ process group to exit: each wait is 5 seconds times the host's load per CPU,
489
+ from 5 to 15 seconds. Overall cleanup has a 35 second budget, including temporary-worktree
487
490
  removal; unfinished cleanup returns STIM_CLAIM_UNAVAILABLE and leaves unresolved
488
491
  resources in place. Credential refresh waits asynchronously and checks
489
492
  cancellation before writing.
490
493
  On Windows, report probes require the built-in Windows PowerShell for process-tree containment.
494
+ A probe's time limit counts only the probe itself; PowerShell's startup and exit each have their own 30 second limit.
491
495
 
492
496
  requestMachineAccess({ ticket?, signal? }) requests build and device-host access
493
497
  from configured remote machines without granting capabilities or repairing project
@@ -642,9 +646,10 @@ STIM_CLAIM_UNAVAILABLE, taking precedence over cancellation or callback failure;
642
646
  follow its remedy before retrying. Startup never retries automatically.
643
647
 
644
648
  reload({ platform?, signal?, beforeReload? }) requests a JavaScript reload in
645
- the live iOS/Android app or reloads the owned Chrome page. It returns the flat
646
- stim reload --json facts: platform, deviceId, deviceName, appId, metroPort,
647
- strategy, targets and reverseRestored. Choose ios, android or web when more
649
+ the live iOS/Android app (owned, on a physical device or in an EAS Simulator
650
+ session) or reloads the owned Chrome page. It returns the flat
651
+ stim reload --json facts: platform, deviceId, deviceName, appId (null for an
652
+ app Stim did not launch), metroPort, strategy, targets and reverseRestored. Choose ios, android or web when more
648
653
  than one platform is live. A request does not prove completion; verify the UI
649
654
  and inspect logs. A Metro broadcast can reach other connected clients.
650
655
  beforeReload(workspace) runs once after resolving the workspace and before
@@ -802,8 +807,10 @@ warns when gh is unavailable.
802
807
 
803
808
  status's remoteDevices lists each environment's recorded EAS Simulator
804
809
  session. The session is billable while it runs, and it makes the environment
805
- live. status reads only local records; it does not ask EAS whether the session
806
- is still running.
810
+ live. EAS stops it by itself after remote.easMaxDurationMinutes (default 30).
811
+ status reads only local records; it does not ask EAS whether the session is
812
+ still running, so a session EAS already stopped stays listed until the next
813
+ run replaces it or stop clears it.
807
814
 
808
815
  remoteDevices [{ platform, backend, sessionId, state, startedAt,
809
816
  webPreviewUrl }], empty when the workspace has none
@@ -983,8 +990,10 @@ leased until <time>" for each one.`,
983
990
  true Metro finished the bundle response, or an app
984
991
  without Metro (a release build, or a native
985
992
  Xcode or Gradle app) has a live process; then
986
- the app stayed alive through a three-second
987
- stability window.
993
+ the app stayed alive until its JavaScript
994
+ reported \`Running "<name>"\` (plus half a
995
+ second), or through a three-second stability
996
+ window when it did not.
988
997
  The command checks process liveness when the
989
998
  platform exposes it. Errors from that window
990
999
  are printed even when the app stays alive,
@@ -996,12 +1005,14 @@ leased until <time>" for each one.`,
996
1005
  bundle and the process, never a frame, and a
997
1006
  cold app can keep rendering for a minute or
998
1007
  more after this, which is why the stderr line
999
- reads \`bundle loaded, process alive, stable
1000
- for 3s -- the first screen may still be
1001
- rendering\`. Poll the UI before you trust a
1002
- screenshot. Optional app-declared readiness
1003
- adds a separate stderr readiness phase; it
1004
- does not change this field. See
1008
+ reads \`bundle loaded, process alive, app
1009
+ JavaScript running -- the first screen may
1010
+ still be rendering\` (\`stable for 3s\` when
1011
+ no \`Running\` log arrived). Poll the UI
1012
+ before you trust a screenshot. Optional
1013
+ app-declared readiness adds a separate
1014
+ stderr readiness phase; it does not change
1015
+ this field. See
1005
1016
  \`guide lifecycle readiness\`
1006
1017
  "bundling" the request DID arrive and Metro was still
1007
1018
  building or delivering when the bundle timeout closed.
@@ -1013,6 +1024,15 @@ leased until <time>" for each one.`,
1013
1024
  finishing
1014
1025
  "unverified" nothing was observed at all: usually a
1015
1026
  dev-client server picker awaiting a tap
1027
+ The wait for the app's bundle request is 20 seconds. On
1028
+ Expo, the dev client's manifest request (recorded in the
1029
+ metro log as manifest_request_started, _finished or _failed)
1030
+ counts as progress: the wait stays open while one is in
1031
+ flight and for 15 seconds after one was served, up to 60
1032
+ seconds after the launch, on any target (a new or adopted
1033
+ emulator already waits 60). A manifest is never launch
1034
+ evidence, so a launch that makes no bundle request is still
1035
+ "unverified". Bare React Native makes no manifest request.
1016
1036
  Neither "bundling" nor "unverified" is reported for an app
1017
1037
  whose process is gone when the bundle timeout closes: the
1018
1038
  run fails as FATAL, "the app process exited", with the
@@ -1131,10 +1151,15 @@ leased until <time>" for each one.`,
1131
1151
 
1132
1152
  platform "ios" | "android" | "web"
1133
1153
  deviceId the exact owned simulator UDID or emulator serial targeted;
1134
- for web, the owned Chrome's DevTools endpoint
1135
- deviceName the owned simulator or AVD name; for web, the Chrome version
1154
+ for web, the owned Chrome's DevTools endpoint; metro:<port>
1155
+ when the apps were reached through Metro alone
1156
+ deviceName the owned simulator or AVD name; for web, the Chrome version;
1157
+ "EAS Simulator session <id>" or "devices connected to
1158
+ Metro" when reached through Metro alone
1136
1159
  appId the live bundle id or Android package; for web, the URL the
1137
- owned page was on when Stim sent the reload
1160
+ owned page was on when Stim sent the reload; null when no
1161
+ launch is recorded (a physical device or EAS Simulator
1162
+ session) and Stim reloaded the apps connected to Metro
1138
1163
  metroPort the workspace's verified Metro port; for web, the reserved
1139
1164
  Metro port or null
1140
1165
  strategy how the reload was addressed.
@@ -1482,7 +1507,8 @@ RULES
1482
1507
  buildLock, buildSlot, deviceLease, easSession, worktree,
1483
1508
  cache, gradleVersion, tempLeftover (one "done" labelled
1484
1509
  with the TMPDIR it cleared, plus a "kept" or "failed" per
1485
- entry gc checked again or could not delete).
1510
+ entry gc checked again or could not delete), trash (the
1511
+ same, labelled with $STIM_HOME/trash).
1486
1512
  label is a device, path or cache name; id is the UDID,
1487
1513
  AVD name or path behind it, or null. Under --cache
1488
1514
  parked, a "done" parkedDevice was erased and stays
@@ -1707,10 +1733,23 @@ RULES
1707
1733
  kind is stim (stim-claim-*, stim-host-*,
1708
1734
  stim-fakehome-*, stim-hosted-macos-*,
1709
1735
  stim-server-*, stim-ws-* directories), xctrace
1710
- (instruments*.ktrace) or jest (Jest's
1736
+ (instruments*.ktrace), swiftpm
1737
+ (TemporaryDirectory.* directories) or jest (Jest's
1711
1738
  jest_<uid in base 36> cache, never deleted). deleteCount
1712
1739
  is what --delete removes. null with STIM_HOME
1713
1740
  set or any --cache scope
1741
+ trash { root, entries: [{ path, worktree, removedAt,
1742
+ bytes, willDelete, kept }] } | null ignored
1743
+ directories worktree remove moved out of a
1744
+ worktree into $STIM_HOME/trash before git
1745
+ removed it. bytes is null while a removal is
1746
+ deleting the entry. kept names the live or
1747
+ unresolved ownership claim, the missing or
1748
+ invalid trash.json, or the worktree that
1749
+ still exists, that keeps a directory;
1750
+ --delete deletes the rest, only remove-*
1751
+ entries with a valid trash.json. null when the
1752
+ trash is empty or under any --cache scope
1714
1753
  caches { name, dir, source, bytes, note, willEmpty,
1715
1754
  emptySkipped, scopedEmpty } alive, not
1716
1755
  garbage; willEmpty marks the ones --delete
@@ -2292,7 +2331,9 @@ RULES
2292
2331
  existed count their device time in prepare and install
2293
2332
 
2294
2333
  Only runs that record a last build are listed: a run that stops before
2295
- looking up a build, such as a bad flag, is not. Estimates (expectedMs) come from run statistics, not builds.
2334
+ looking up a build, such as a bad flag, is not. A run that builds or reuses
2335
+ an app and then fails at the device, install or launch step is listed as
2336
+ failed with its error code. Estimates (expectedMs) come from run statistics, not builds.
2296
2337
 
2297
2338
  done and total are counts, not a completion fraction: a target or task
2298
2339
  can take a second or ten minutes, and cached work finishes instantly.
@@ -2683,7 +2724,11 @@ HOSTED IOS METRO
2683
2724
  ios --remote <machine> keeps Metro local and needs no start --remote.
2684
2725
  The supervisor watches private gateway requests in workspace state, binds
2685
2726
  only this machine's Tailscale address and accepts only the pinned hosting peer
2686
- with a per-session secret. The host's bridge is loopback-only. Port and secret
2727
+ with a per-session secret. The host's bridge is loopback-only. For an Expo
2728
+ dev client it listens on this machine's Metro port, which the dev server
2729
+ writes into the manifest. ios --remote starts Metro on a port free on both
2730
+ Macs; a running Metro or a pin on a port the host uses refuses the run before
2731
+ the build. Port and secret
2687
2732
  stay in 0600 workspace state and never appear in status, JSON or logs.
2688
2733
  metro.tunnel and metro.publicUrl are ignored. Supervisor restart recreates
2689
2734
  the recorded gateway; stop or a stopped hosted session closes it. A recorded
@@ -2721,9 +2766,16 @@ TAILNET-ONLY METRO
2721
2766
 
2722
2767
  BUNDLE WARMUP
2723
2768
  After verifying Metro, \`stim ios\` and \`stim android\` prefetch the
2724
- platform's development bundle while native work continues. Expo supplies the
2725
- entry point and bundle options through its manifest; bare React Native uses
2726
- the standard index entry and development bundle options, including lazy loading.
2769
+ platform's development bundle while native work continues. The prefetch
2770
+ requests the URL of the app's most recent bundle request on that platform,
2771
+ read from this workspace's metro log, so it matches the app's entry point
2772
+ and options and does not ask Expo for its manifest. A recorded URL whose
2773
+ entry file no longer exists under the project root or its ancestors is
2774
+ skipped. Expo computes the
2775
+ runtime version fingerprint for every manifest request. Without a recorded
2776
+ request, Expo supplies the entry point and bundle options through its
2777
+ manifest, and bare React Native uses the standard index entry and
2778
+ development bundle options, including lazy loading.
2727
2779
  Warmup is enabled by default. Set optimizations.metroWarmup=false to disable
2728
2780
  it on the next ios/android command, using the machine or project settings.
2729
2781
  For custom entry points or bundle options, set metro.warmupUrl.ios and/or
@@ -2771,7 +2823,9 @@ REMOTE DEVICE BACKENDS
2771
2823
  are Apple silicon. The cache key ends in that architecture.
2772
2824
 
2773
2825
  The EAS backend needs eas-cli 21.6.0 or later and an account with EAS
2774
- Simulator access. An EAS session is billable. Stim prepares the app before
2826
+ Simulator access. An EAS session is billable; Stim has EAS stop each session
2827
+ it creates after remote.easMaxDurationMinutes (default 30), and a later run
2828
+ replaces a session that expired. Stim prepares the app before
2775
2829
  it creates or reconnects the session, so a failed build starts no session
2776
2830
  and the install follows the connection directly. EAS does not inherit the
2777
2831
  proxy credentials. Always tear the session down: \`stop\`,
@@ -3220,6 +3274,10 @@ serve bounded log queries.
3220
3274
  the safe direction: a client redbox that Fast Refresh already fixed keeps
3221
3275
  being reported until the next launch.
3222
3276
 
3277
+ RUN FAILURES. A run that builds or reuses an app and then fails before the app
3278
+ is running adds one build record with event run_failed, its code and the
3279
+ phase it failed in, so \`status\` and \`logs --errors\` agree.
3280
+
3223
3281
  OUTPUT. Every logs command, including --errors and --follow, shows full captured
3224
3282
  error, component and native stacks, with no frame or message-length limit.
3225
3283
  --errors shows the first 20 matching error records, plus stack context.
@@ -3345,7 +3403,15 @@ they stay in the local logs. These records carry no tokens.
3345
3403
 
3346
3404
  WHAT WRITES WHAT
3347
3405
  maintenance.ndjson workspace maintenance actions, failures and explaining skips
3348
- metro.ndjson the bundler, in every supervisor mode
3406
+ metro.ndjson the bundler, in every supervisor mode. Stim's
3407
+ middleware adds one record per bundle request
3408
+ (bundle_response_started, _progress, _finished,
3409
+ _failed; _started carries the request's path and
3410
+ query as url, which the next warmup prefetches)
3411
+ and, on Expo, one per dev-client manifest
3412
+ request (manifest_request_started, _finished,
3413
+ _failed: debug level, with platform and requestId;
3414
+ launch verification reads them as progress)
3349
3415
  client.ndjson in-app console logs and redboxes -- BARE PROJECTS ONLY.
3350
3416
  In expo-child and command-child mode everything the
3351
3417
  dev server prints lands in metro.ndjson with raw: true,
@@ -3557,6 +3623,10 @@ Branch on the code, never on the message.`,
3557
3623
  --system-image / --device-profile for Android when the offer names
3558
3624
  an unavailable choice. A session that exists stays recorded even if delivery
3559
3625
  fails: retry stim ios|android --remote <machine>, or run stim stop to reconcile it.
3626
+ An Expo dev client whose running or pinned Metro port is in use on the host
3627
+ refuses before the build: run stim stop, then stim ios --remote <machine>
3628
+ without stim start, so Stim starts Metro on a port free on both Macs, or pin
3629
+ one free on both Macs with metro.port or STIM_METRO_PORT.
3560
3630
  An unreachable stop keeps the placement; rerun stim stop when the host answers.
3561
3631
  To see why a host was slow or refused: stim logs --source placement (hosts checked and
3562
3632
  reason codes), stim logs --source build (remote_connect_failed, remote_request_failed),
@@ -3648,8 +3718,9 @@ Branch on the code, never on the message.`,
3648
3718
  \`pod install\` (iOS) or the gradle dependency sync (Android) failed. On iOS
3649
3719
  this runs only when Podfile.lock and Pods/Manifest.lock disagree, or Pods is
3650
3720
  absent -- which is exactly what a carried worktree produces.
3651
- WHICH POD COMMAND: when the project root has a Gemfile and a Gemfile.lock
3652
- that resolves cocoapods, pods go through bundler -- \`bundle check --dry-run\`,
3721
+ WHICH POD COMMAND: Stim takes the nearest Gemfile from the directory pod
3722
+ install runs in (ios/) up to the project root, as Bundler finds it. When its
3723
+ Gemfile.lock resolves cocoapods, pods go through bundler -- \`bundle check --dry-run\`,
3653
3724
  then \`bundle install\` only when that reports missing gems, then \`bundle exec
3654
3725
  pod install\` -- so the CocoaPods the lockfile pins is the one that writes
3655
3726
  Podfile.lock. Everything else gets plain \`pod install\`: no Gemfile, a Gemfile
@@ -3748,8 +3819,13 @@ Branch on the code, never on the message.`,
3748
3819
  leaves room for. A project with react-native-gesture-handler 3, whose
3749
3820
  shared shadow nodes have the longest known object path, fits a root of at
3750
3821
  most 24 characters for an x86_64 Debug build and 21 for arm64-v8a; other
3751
- projects fit 51 and 48. Refused BEFORE Gradle
3752
- runs -- a cache hit still installs -- because the build would otherwise
3822
+ projects fit 51 and 48. \`stim android\` on
3823
+ an emulator, local or --remote <backend>, refuses before it starts Metro
3824
+ or prepares the emulator, even when a cached build would have installed.
3825
+ That early refusal is skipped for a physical or hosted device, an EAS
3826
+ profile and when build machines are paired; a build that still runs here
3827
+ is refused before Gradle runs, so a cache hit there still installs.
3828
+ The build would otherwise
3753
3829
  fail deep inside ninja ("mkdir ... No such file or directory" or
3754
3830
  "Filename longer than 260 characters"). Move or clone the project under a
3755
3831
  short real path such as C:\\src\\<name> and run Stim there. A subst drive
@@ -3916,6 +3992,13 @@ Unlisted or unpaired names refuse at setup before consulting the cache, without
3916
3992
  a build record or failed-run stats. A listed paired name with a cache hit needs
3917
3993
  no build and does not contact the selected machine.
3918
3994
 
3995
+ A fingerprint-mismatch reason means the worker fingerprints the synced
3996
+ checkout differently. It names the sources that differ and the files pod
3997
+ install or prebuild rewrote there. Stim already sends the gitignored files the
3998
+ fingerprint reads, such as .env.local. Make the named input agree on both Macs,
3999
+ for example by committing the lockfile pod install rewrote there; pairing does
4000
+ not change it.
4001
+
3919
4002
  Run stim doctor --fix to ask for build access if not paired. Check
3920
4003
  stim settings get remote.machines. A person on the worker approves this machine
3921
4004
  by running the stim-server setup command doctor --fix printed, with its ticket
@@ -3959,6 +4042,11 @@ Rerun with --remote-build auto for normal placement and local fallback, or
3959
4042
  copying for the same reason. A copy without a claim would be invisible to a
3960
4043
  refresh starting after it, allowing the source dependencies to change while
3961
4044
  they are read.
4045
+ A report command such as \`gc\` reports it when it cannot confirm that a child
4046
+ it started has stopped, typically on a machine under heavy load. The child is
4047
+ left untouched. The remedy tells you what to check and which command to run
4048
+ again, and when the run held ownership claims it lists the exact \`rm\`
4049
+ command for each retained claim.
3962
4050
  Warm also reports this code for EACCES, EPERM, EROFS and ENOENT while taking a claim.
3963
4051
  The message names the claim path and original filesystem error. Restore write
3964
4052
  access to the existing claim store, checking parent permissions, symlink
@@ -4284,7 +4372,8 @@ so a Debug run on one is wired to a LAN origin instead of localhost.`,
4284
4372
  and \`adb devices\`, then retry after any other run finishes. Keep the AVD and
4285
4373
  its process locks while its state is unverified.
4286
4374
  On iOS a slow first boot is waited out for up to ten minutes while the
4287
- simulator reports Booting or Booted but bootstatus has not completed.
4375
+ simulator reports Booting or Booted but bootstatus has not completed, and
4376
+ then until SpringBoard has finished starting, which \`simctl launch\` needs.
4288
4377
  Booted alone does not end that wait. The failure names the udid and the wait.
4289
4378
  After boot, a process-spawn probe must finish within 30 seconds before
4290
4379
  installation. If it fails, the refusal includes observed host memory pressure
@@ -4457,14 +4546,19 @@ so a Debug run on one is wired to a LAN origin instead of localhost.`,
4457
4546
  proxy is selected. They never select the backend.`
4458
4547
  },
4459
4548
  STIM_REMOTE_EAS_UNAVAILABLE: {
4460
- summary: "--remote eas needs eas-cli 21.6.0 or later",
4549
+ summary: "--remote eas needs eas-cli 21.6.0 or later and an Expo app linked to an EAS project",
4461
4550
  body: () => `STIM_REMOTE_EAS_UNAVAILABLE
4462
4551
  \`--remote eas\` requires eas-cli 21.6.0 or later, the first release with
4463
4552
  the \`eas simulator:*\` commands Stim runs. Stim reads \`eas --version\` and
4464
4553
  refuses before any build or session work when eas-cli is missing, older, or
4465
4554
  reports no version. Upgrade it (\`npm install --global eas-cli@latest\`, or
4466
4555
  the project's eas-cli dependency). Proxy environment variables do not change
4467
- this selection and are not passed to EAS.`
4556
+ this selection and are not passed to EAS.
4557
+ It is also the code when EAS reports that the Expo app has no EAS project
4558
+ (no extra.eas.projectId), so no session was created. Link the app with
4559
+ \`eas init --id <project-id> --non-interactive\` or create a project with
4560
+ \`eas init --account <account-name> --non-interactive\`, then rerun. Rerunning
4561
+ \`stim ios\` or \`stim android\` without the link fails the same way.`
4468
4562
  },
4469
4563
  STIM_REMOTE_PLATFORM_MISMATCH: {
4470
4564
  summary: "the recorded remote session belongs to the other platform; stop, then rerun",
@@ -4548,12 +4642,17 @@ so a Debug run on one is wired to a LAN origin instead of localhost.`,
4548
4642
  aliases: ["STIM_RELOAD_UNOWNED", "STIM_RELOAD_PROBE_FAILED"],
4549
4643
  body: () => `STIM_RELOAD_STOPPED / STIM_RELOAD_UNOWNED / STIM_RELOAD_PROBE_FAILED
4550
4644
  The recorded app is gone, its exact device is not live and owned by this
4551
- workspace, or simctl/adb could not prove the process exists. For web,
4645
+ workspace, or Metro has no peer for the app and simctl/adb could not prove the
4646
+ process exists (a probe that times out alone does not stop the reload). For web,
4552
4647
  STOPPED means no owned Chrome is running (run stim web) and PROBE_FAILED
4553
4648
  that its identity could not be verified. A bare reload picks the Chrome page
4554
- only when no native launch is recorded. No launch or
4555
- device lifecycle action is taken; follow the printed platform-command or
4556
- process-probe remedy.`
4649
+ only when no native launch is recorded. Stim records launches only on owned
4650
+ local simulators and emulators. With none recorded, reload asks this
4651
+ workspace's Metro for its connected apps, which reaches an app on a physical
4652
+ device (--device) or an EAS Simulator session; STOPPED then means no app is
4653
+ connected to that Metro, so launch it or, for an Android phone, restore its
4654
+ adb reverse. No launch or device lifecycle action is taken; follow the
4655
+ printed platform-command or process-probe remedy.`
4557
4656
  },
4558
4657
  STIM_RELOAD_FAILED: {
4559
4658
  summary: "the reload failed; the remedy differs by shape -- read it before acting",
@@ -4704,6 +4803,13 @@ captured" (in metro.ndjson, bare RN)
4704
4803
  config -- lands THERE, not in supervisor.log). \`stim logs --errors\` has
4705
4804
  the full records. Fix that and run \`start\` again.
4706
4805
 
4806
+ A bind error on the reserved port ("listen EADDRINUSE ... :<port>") means
4807
+ another process, usually another Stim home, took the port after Stim chose
4808
+ it. \`start\` releases that reservation, reserves another free port and
4809
+ starts again, up to 3 attempts, and says so. A pinned metro.port and
4810
+ \`--remote\` starts are not retried. When all attempts fail, run \`start\`
4811
+ again.
4812
+
4707
4813
  "Cannot reuse or replace the recorded supervisor: ..."
4708
4814
  A live record has no verifiable OS process identity, or the workspace and
4709
4815
  registry records disagree. Nothing new was started; the old process is
@@ -5332,10 +5438,12 @@ hosting Mac keeps Metro local through a private bridge; see hosted-ios. Step 2 r
5332
5438
  Metro while other work happens.
5333
5439
 
5334
5440
  Each time Stim boots an owned local simulator or emulator, it mutes it: iOS
5335
- simulators to volume zero through Xcode's devicectl once SpringBoard has
5336
- finished starting, because SpringBoard resets the volume while it starts, and
5337
- Android 15 and later emulators to media volume zero. A device that is already
5338
- running keeps its volume. Turn sound on for one device with Sound (iOS) or
5441
+ simulators to volume zero through Xcode's devicectl, and Android 15 and later
5442
+ emulators to media volume zero. The iOS mute runs after SimSlim has applied its
5443
+ profile and once SpringBoard has finished starting, because both a SimSlim
5444
+ reboot and SpringBoard's startup reset the volume. A device that is already
5445
+ running keeps its volume, except that SimSlim reboots a running simulator whose
5446
+ profile changed. Turn sound on for one device with Sound (iOS) or
5339
5447
  Media sound (Android) in its Stim Desktop options; the choice lasts until that
5340
5448
  device next boots. Android 14 and older images have no shell command that can
5341
5449
  set media volume, so startup warns, as it does whenever a mute is not
@@ -5348,16 +5456,25 @@ not part of the normal workflow. It is the explicit recovery path when Fast
5348
5456
  Refresh cannot clear the current screen, and on Android after a failed first
5349
5457
  bundle load. It reloads JavaScript and never restarts the app. Use \`stim
5350
5458
  reload ios\` or \`stim reload android\` to select a platform when both owned
5351
- apps are live. For a physical device that reached Metro, use \`agent-device
5352
- metro reload --metro-port <reported-port>\`. The detected iOS Local Network
5459
+ apps are live. With no owned launch recorded, it reloads the apps connected to
5460
+ this workspace's Metro, such as one on a physical device (--device); an
5461
+ Android phone needs its adb reverse. An app in an EAS Simulator session may not
5462
+ connect to Metro through the tunnel; then reload finds no app and the way to
5463
+ restart it is stim ios|android --remote eas.
5464
+ The detected iOS Local Network
5353
5465
  first-load remedy uses agent-device UI automation because no Metro peer exists
5354
- yet. It never builds, installs, boots, or cold-launches. It acts only on a live
5355
- app on this workspace's owned local simulator or emulator, and refuses release
5356
- builds, stopped or unowned devices, a missing or foreign Metro, and an
5357
- ambiguous no-platform request. Every reload goes over this workspace's Metro
5466
+ yet. It never builds, installs, boots, or cold-launches. It acts on a live app
5467
+ on this workspace's owned local simulator or emulator, or on the apps connected
5468
+ to this workspace's Metro, and refuses release builds, stopped or unowned
5469
+ devices, a missing or foreign Metro, and an ambiguous no-platform request. Every reload goes over this workspace's Metro
5358
5470
  websocket, on both platforms. It never reopens a development-client URL,
5359
5471
  because that restarts the app rather than reloading its JavaScript.
5360
5472
 
5473
+ Before sending, Stim checks that the app process exists. The iOS probe
5474
+ (\`simctl spawn launchctl list\`) waits 5 seconds, scaled up with host load to at
5475
+ most 30. When the device tool still does not answer, Stim sends the reload anyway;
5476
+ \`STIM_RELOAD_PROBE_FAILED\` is then reported only if Metro finds no peer for the app after the reload fails.
5477
+
5361
5478
  An Android reload first lists \`adb reverse\` on each live owned emulator
5362
5479
  launched against this Metro and re-applies the Metro port's reverse where it is
5363
5480
  missing. adb ties a reverse to its transport, and a transport that drops and
@@ -5384,7 +5501,7 @@ dev menu.
5384
5501
  When Metro reports no peer for the app, Stim broadcasts a reload anyway before
5385
5502
  giving up, because matching is best-effort and an unmatched peer may still be
5386
5503
  this app. So verify the UI first: it may already have recovered. If it did not,
5387
- retry: a client reconnects every 2 seconds, which is also this probe's timeout,
5504
+ retry: a client reconnects every 2 seconds, which is also the Metro probe's timeout,
5388
5505
  so a single miss can be a reconnect window rather than an app that never
5389
5506
  connected. If it stays unreachable on iOS, an error in the first bundle leaves
5390
5507
  the app without a packager connection at all, and no retry will make it a peer.
@@ -5416,8 +5533,9 @@ does not restart initialization. Confirm the bundle request and expected UI.
5416
5533
 
5417
5534
  Debug Android launches on an owned emulator that the run creates, or whose
5418
5535
  adoption from the pool it finishes, get up to 60 seconds for bundle loading;
5419
- the verify phase names that budget. Existing emulators, remote targets, and physical devices keep the
5420
- 20-second budget.
5536
+ the verify phase names that budget. Existing emulators, remote targets, and physical devices get 20 seconds,
5537
+ extended up to 60 while an Expo dev client's manifest request is pending or was
5538
+ just served.
5421
5539
  Bundle delivery still requires the usual stability or app readiness check;
5422
5540
  an observed fatal error ends verification without waiting for the deadline.
5423
5541
 
@@ -5908,7 +6026,7 @@ is on PATH, the slot is default, no --runtime, --system-image or
5908
6026
  another platform or model, and a Debug run's Metro is reachable (not
5909
6027
  metro.tunnel off; on an Expo tunnel, run stim start --remote first). A recorded
5910
6028
  EAS session is not sticky: once this machine has room, auto runs here and the
5911
- session bills until stim stop. If any check fails, or the
6029
+ session bills until stim stop or remote.easMaxDurationMinutes. If any check fails, or the
5912
6030
  setting is off, auto runs here and may wait in the existing FIFO device
5913
6031
  slot queue; --no-wait and --wait 0 refuse with STIM_AT_CAPACITY. The placement
5914
6032
  line explains the decision, the skipped hosts and why EAS was not used
@@ -5958,6 +6076,12 @@ Stim builds or fetches before reserving, records the session immediately, then
5958
6076
  uploads the app on every run. React Native and Expo Debug keep Metro here; the supervisor owns a
5959
6077
  private gateway bound to this machine's Tailscale address, pinned to the host peer
5960
6078
  and protected by a per-session secret. The host exposes only a loopback bridge.
6079
+ For an Expo dev client the bridge listens on this machine's Metro port, because
6080
+ the dev server writes that port into the manifest's bundle URL. When this run
6081
+ starts Metro, it asks the host and picks a port free on both Macs, moving the
6082
+ recorded port if the host uses it. A running Metro or a metro.port pin on a port
6083
+ the host uses refuses before the build: run stim stop, then stim ios --remote
6084
+ <machine> without stim start, or pin a port free on both Macs.
5961
6085
  No start --remote is needed; metro.tunnel and metro.publicUrl are ignored.
5962
6086
  Debug requires a running supervisor with private gateway support before reserving
5963
6087
  a simulator. --no-metro-check refuses with STIM_BAD_ARG for hosted Debug runs.
@@ -6237,12 +6361,18 @@ Metro verification enabled, not release builds or --no-metro-check.
6237
6361
  a missing ready message, and a startup error. Retain the relevant output.
6238
6362
 
6239
6363
  Without an observed pending, Stim keeps its default 3-second stability window
6240
- after bundle delivery. Managed Metro servers report the native bundle response
6364
+ after bundle delivery. The window ends early, half a second after the app's
6365
+ React Native runtime logs \`Running "<name>"\` for this launch on either
6366
+ platform. A fatal record or an exited process before the window ends still
6367
+ fails the launch. An error after it, such as a first render that takes longer
6368
+ than that half second to throw, appears in \`stim logs --errors\`.
6369
+ Managed Metro servers report the native bundle response
6241
6370
  finishing; build-complete output alone does not close an observed request.
6242
6371
  Without response capture, Stim falls back to the build-complete marker.
6243
6372
  When Android reports queued JavaScript loading, Stim waits for a device
6244
6373
  JavaScript log before starting stability, bounded by the bundle timeout.
6245
- Pending must be observed before the stability window closes. It opts into
6374
+ Pending must be observed before the stability window closes, early end
6375
+ included, so log it before the root component renders. It opts into
6246
6376
  waiting for ready until 30 seconds after the same completion signal.
6247
6377
  Repeated pending messages never extend the deadline. Ready can end the wait
6248
6378
  early; an app error or process exit interrupts it. No ready means readiness
@@ -6745,9 +6875,10 @@ AN ARTIFACT THE DEVICE ALREADY HOLDS IS NOT INSTALLED AGAIN
6745
6875
  A RUNNING APP IS RESTARTED, LIKE XCODE'S RUN
6746
6876
  Before it launches, \`ios\` and \`android\` read the device's process list.
6747
6877
  When the app is already running, from an earlier run or after an install
6748
- that was skipped, Stim stops it and launches it fresh: \`simctl terminate\`
6749
- on a simulator, \`am force-stop\` on an emulator or an \`android --device\`
6750
- phone. The new process requests its bundle, so launch verification has real
6878
+ that was skipped, Stim stops it and launches it fresh: \`simctl launch
6879
+ --terminate-running-process\` on a simulator (a separate \`simctl
6880
+ terminate\` when the app opens through a URL), \`am force-stop\` on an
6881
+ emulator or an \`android --device\` phone. The new process requests its bundle, so launch verification has real
6751
6882
  evidence instead of an old process that fetched nothing. In-app state from
6752
6883
  the previous session does not survive. The launch line says so:
6753
6884
 
@@ -7043,8 +7174,11 @@ WHAT MAKES THE CACHE ACTUALLY HIT: .FINGERPRINTIGNORE
7043
7174
  BUILD is what breaks that, and it fails silently -- a cache that never hits
7044
7175
  looks exactly like a cache that is not there.
7045
7176
 
7046
- Stim ignores two paths a fresh checkout never has and no native build reads:
7047
- android/local.properties and android/.idea. A project does not repeat those.
7177
+ Stim ignores paths a fresh checkout never has and no native Debug build
7178
+ reads: android/local.properties, android/.idea, *.xcodeproj/xcuserdata, and,
7179
+ while a .gitignore pattern matches them (even when committed), the
7180
+ \`react-native bundle\` output ios/main.jsbundle and ios/assets. A project
7181
+ does not repeat those.
7048
7182
  Everything else is the project's call, including a lockfile whose checksums
7049
7183
  embed machine paths -- ignoring a path any project might read turns a slow
7050
7184
  build into a wrong one.
@@ -7479,11 +7613,18 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
7479
7613
  paths eligible under the source checkout's Git ignore rules, including .env
7480
7614
  and local configuration. The source's nonempty
7481
7615
  .worktreeexclude replaces its resolved worktree.exclude setting. Nested
7482
- registered worktrees, .DS_Store, .DerivedData, .idea, .jj, a project-local
7483
- .pnpm-store, and android/build/generated/autolinking caches are excluded,
7484
- including inside newly copied directories; pnpm refills its store from the
7485
- network or its global store. Gradle regenerates autolinking
7486
- for the destination checkout on its next build. Warm also skips paths
7616
+ registered worktrees and ignored entries named .DS_Store, .DerivedData,
7617
+ .idea, .jj or .pnpm-store are not copied, and neither is
7618
+ android/build/generated/autolinking. Warm never walks a copied directory, so
7619
+ a .DS_Store or .idea inside a copied directory stays. Warm deletes only
7620
+ these paths from the copy: .pnpm-store in a copied node_modules (pnpm
7621
+ refills it from the network or its global store), the autolinking directory
7622
+ under a copied android, android/build or android/build/generated (Gradle
7623
+ regenerates it for the destination checkout on its next build), and the
7624
+ expo-modules-jsi/apple/.DerivedData Xcode build state, directly under
7625
+ node_modules or in the pnpm virtual store. An ignored directory that Git
7626
+ reports above those names (for example an app directory with no tracked
7627
+ files) is copied as is. Warm also skips paths
7487
7628
  overlapping a nested destination worktree or below a symlink ancestor.
7488
7629
  Tracked .idea settings come from Git and stay untouched by warm.
7489
7630
 
@@ -7522,7 +7663,10 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
7522
7663
 
7523
7664
  Warm copies directly into the destination, without intermediate staging.
7524
7665
  Keep the source checkout and the linked worktree on the same volume to
7525
- retain copy-on-write cloning where supported. Cross-volume copies require
7666
+ retain copy-on-write cloning where supported. On macOS with the Command Line
7667
+ Tools, an ignored directory on the same APFS volume, such as node_modules or
7668
+ ios/Pods, is cloned in one step, so a large one takes seconds; elsewhere
7669
+ warm clones or copies file by file. Cross-volume copies require
7526
7670
  full file data; doctor reports that cost. STIM_TMPDIR and machine tempDir do
7527
7671
  not affect warming.
7528
7672
 
@@ -8005,6 +8149,24 @@ THE POOL: WHICH DEVICE AN ID-LESS \`--device\` PICKS
8005
8149
 
8006
8150
  { "ios": { "simslimProfile": ".simslim/dev.json" } }
8007
8151
 
8152
+ To slim every Stim-owned iOS simulator on a Mac without a profile per app,
8153
+ set it on the machine layer:
8154
+
8155
+ stim settings set ios.simslim on --scope machine
8156
+
8157
+ With \`ios.simslim\` on and no \`ios.simslimProfile\`, Stim runs
8158
+ \`simslim on <udid>\` with SimSlim's default categories. A project profile
8159
+ always applies in place of the defaults. A workspace, repo or committed
8160
+ \`ios.simslim off\` opts that app out and restores stock services on its
8161
+ simulator. The defaults disable push, StoreKit, iCloud, Safari sync, Mail,
8162
+ Calendar and Contacts services, among others; move an app that needs them
8163
+ to a profile that keeps those categories, or to \`off\`. A running or
8164
+ parked simulator is slimmed the next time Stim boots or adopts it, and an
8165
+ already slim simulator is left alone, so only the first slim reboots it.
8166
+ Without the \`simslim\` command, doctor reports it and \`stim ios\` boots
8167
+ the simulator unslimmed with a one-line note. Hosted simulators on a named
8168
+ Mac are never slimmed, whatever either Mac's setting says.
8169
+
8008
8170
  SimSlim 0.8 requires iOS 18.5 or newer. On each local \`stim ios\`,
8009
8171
  Stim reconciles that profile on the owned simulator before the app build.
8010
8172
  The first change can update services and reboot the simulator. A matching
@@ -8063,6 +8225,8 @@ HOST MEMORY PRESSURE AND STALLED SIMULATORS
8063
8225
  Watchman stim gc --delete --cache watchman
8064
8226
  Gradle or Kotlin daemon stim gc --delete --cache gradle-daemons
8065
8227
  Any other process is named with its size only; ask before quitting it.
8228
+ Boot does not wait for this read: the pressure message prints at once and the
8229
+ named processes follow on a second memory line when top finishes.
8066
8230
  Doctor skips this check when STIM_HOME is set: processes are machine-global.
8067
8231
 
8068
8232
  If pressure is elevated, free host memory before retrying. Use \`stim stop\`
@@ -8173,8 +8337,8 @@ DISK PRESSURE LEVELS
8173
8337
  android/build, android/.gradle and .build, at a project root, the
8174
8338
  worktree root, or apps/* and packages/*
8175
8339
  4. owned simulators and emulators of workspaces idle for the short window
8176
- 5. Stim temp directories and xctrace recordings in TMPDIR unmodified for
8177
- 24 hours, with gc --delete's checks (see stim guide cleanup gc)
8340
+ 5. Stim temp directories, xctrace recordings and SwiftPM temp directories
8341
+ in TMPDIR unmodified for 24 hours, with gc --delete's checks (see stim guide cleanup gc)
8178
8342
  Level 3:
8179
8343
  1. the Swift compilation cache, emptied whole under the same build rule;
8180
8344
  when a build keeps it, the last pass's blocked reasons name its size
@@ -8487,6 +8651,24 @@ LINKED WORKTREES
8487
8651
  has locked (unlock it first; --force does not override) and, without
8488
8652
  --force, uncommitted or unpushed work and initialized submodules. It then
8489
8653
  reclaims any owned resources it finds and removes the linked checkout.
8654
+ Before git removes it, the command renames the worktree's ignored
8655
+ directories (node_modules, ios/Pods, build outputs) into
8656
+ $STIM_HOME/trash/<entry>, so git removes a light tree, and a detached,
8657
+ low-priority rm deletes the entry after the command returns. Disk is freed
8658
+ when that rm finishes. Through the programmatic API (createStim), the entry
8659
+ is deleted before the call resolves. A directory that does not rename stays
8660
+ for git to delete as before; on Windows, or when $STIM_HOME is on another
8661
+ volume, nothing is renamed. When git refuses the removal, the directories
8662
+ are moved back. Each entry holds an ownership claim while the command or its
8663
+ rm uses it; gc reports every directory under trash with its size ("deleting"
8664
+ while a removal holds it) and, for an entry Stim wrote, its source worktree.
8665
+ gc --delete deletes only a remove-* entry with a valid trash.json whose
8666
+ claim is free and whose worktree path is gone, which finishes a removal that
8667
+ was interrupted, and keeps any other directory. An entry whose worktree path
8668
+ still exists, as after a removal killed between the rename and git, stays
8669
+ with the reason; if that worktree is the one the entry came from, run
8670
+ \`stim worktree remove\` on it to finish the removal.
8671
+ gc never moves the directories back.
8490
8672
  When git still refuses the removal, the kept ownership record no longer
8491
8673
  names the devices that were parked or deleted. A workspace that is in use
8492
8674
  (see IN USE below) keeps its directory, devices and registry entry, and the
@@ -8693,13 +8875,19 @@ TMPDIR LEFTOVERS
8693
8875
  under "TMPDIR leftovers", with their count, size and a remedy: Stim temp
8694
8876
  directories (stim-claim-*, stim-host-*, stim-fakehome-*,
8695
8877
  stim-hosted-macos-*, stim-server-*, stim-ws-*), xctrace recordings
8696
- (instruments*.ktrace) and Jest's jest_<uid in base 36> cache. \`gc --delete\` checks
8697
- them again and deletes a Stim temp directory or recording only when nothing
8698
- in it changed for 24 hours. It keeps a Stim temp directory that contains or
8878
+ (instruments*.ktrace), SwiftPM temp directories (TemporaryDirectory.* with a
8879
+ six-character suffix, left by swift and xcodebuild) and Jest's
8880
+ jest_<uid in base 36> cache. \`gc --delete\` checks them again and deletes a
8881
+ Stim temp directory, recording or SwiftPM temp directory only when nothing in
8882
+ it changed for 24 hours. It keeps a Stim temp directory that contains or
8699
8883
  sits inside a registered project, holds a live or unverifiable ownership
8700
8884
  claim or a .lock directory that is not a claim set, or cannot be listed. It
8701
- keeps a recording that cannot be read, and every recording while an xctrace
8702
- or Instruments process runs or the process list cannot be read. Jest's cache and every other entry
8885
+ keeps a recording or SwiftPM temp directory that cannot be read, every
8886
+ recording while an xctrace or Instruments process runs, and every SwiftPM
8887
+ temp directory while a swift or xcodebuild process runs, or when the process
8888
+ list cannot be read. Stim's own SwiftPM macOS builds run swift with the
8889
+ ambient TMPDIR, because SwiftPM keeps the locks for its shared caches there,
8890
+ so their temp directories land here too. Jest's cache and every other entry
8703
8891
  are never deleted. gc never follows a symlink and never acts outside TMPDIR.
8704
8892
  With STIM_HOME set it neither reports nor deletes them, because TMPDIR is
8705
8893
  shared by every Stim home. Automatic maintenance runs the same deletion at disk pressure
@@ -8800,6 +8988,9 @@ DEVICE LEASES
8800
8988
  its holder and expiry, including holders no config knows. \`stop\` and
8801
8989
  \`worktree remove\` release the leases of the workspace they act on, and
8802
8990
  nothing else deletes a lease file: never remove another workspace's.
8991
+ They also remove the \`adb reverse\` that an \`android --device\` run added
8992
+ for this workspace's Metro port on that phone, using the serial and port the
8993
+ run recorded in its workspace state; any other reverse on the phone stays.
8803
8994
 
8804
8995
  A device leaks when a project is abandoned WITHOUT either delete path -- the
8805
8996
  sim survives with nothing pointing at it. \`stim gc\` (no flag, writes
@@ -9289,6 +9480,13 @@ KEYS STIM READS
9289
9480
  with STIM_BAD_ARG a path that escapes the app or
9290
9481
  holds no .xcworkspace or .xcodeproj, and any value
9291
9482
  on an Expo app, whose prebuild writes ios/.
9483
+ ios.simslim "on" or "off"; default "off", machine or project
9484
+ layers. "on" slims every Stim-owned iOS simulator
9485
+ with SimSlim's default categories when no
9486
+ ios.simslimProfile is set; a profile always wins. A
9487
+ workspace, repo or committed "off" opts that app out
9488
+ of a machine "on" and restores stock services. See
9489
+ \`stim guide lifecycle simslim\`.
9292
9490
  ios.simslimProfile a SimSlim JSON profile under the app directory,
9293
9491
  at most 64 KiB. Install the
9294
9492
  external tool once with
@@ -9509,6 +9707,17 @@ ${ANDROID_AVD_CONFIG_HELP.map((line) => ` ${line}`).joi
9509
9707
  project scope; a committed value opts in everyone who
9510
9708
  runs the app. Only the user enables it. See lifecycle
9511
9709
  hosted-ios.
9710
+ remote.easMaxDurationMinutes
9711
+ Minutes after which EAS stops each EAS Simulator session
9712
+ Stim creates (--remote eas or the easFallback), so a
9713
+ session nobody ended stops billing. A positive integer;
9714
+ default 30. Machine scope only. stop and gc --delete
9715
+ still end a session sooner; a run after the cap expires
9716
+ replaces the stopped session. Stim passes it to eas sim
9717
+ as --max-duration-minutes. EAS rejects a value above the
9718
+ account plan's session limit, so raise it only as far
9719
+ as the plan allows. A run reuses a live session without
9720
+ checking its remaining time.
9512
9721
  metro.tunnel selects how a remote device reaches this workspace's
9513
9722
  Metro after remote intent exists. Plain \`start\` stays
9514
9723
  local. For Expo and bare React Native, "auto" (default)
@@ -9568,7 +9777,9 @@ ${ANDROID_AVD_CONFIG_HELP.map((line) => ` ${line}`).joi
9568
9777
  metro.warmupUrl.android
9569
9778
  an HTTP(S) URL or a /path ending in .bundle, with the
9570
9779
  full query the app uses, including a matching platform.
9571
- Unset uses Expo's manifest or bare React Native defaults.
9780
+ Unset uses the app's most recent bundle request from
9781
+ the workspace's metro log, then Expo's manifest or the
9782
+ bare React Native defaults.
9572
9783
  Stim preserves the path and query but always requests
9573
9784
  this workspace's verified local Metro port; a supplied
9574
9785
  host and port are ignored. No defaults are added to an
@@ -10022,10 +10233,14 @@ Stim connects to a named machine only while its name still belongs to the pinned
10022
10233
  node and never sends the token to another node. \`doctor\` reports each
10023
10234
  remote machine's build pairing state and, for an approved one, asks it for one build
10024
10235
  offer and lists every reason it would not take this app's iOS build: no
10025
- answer, another Stim build, CPU, Xcode, simulator SDK or CocoaPods, no
10236
+ answer, an incompatible Stim build, CPU, Xcode, simulator SDK or CocoaPods, no
10026
10237
  Bundler for an app whose Gemfile.lock pins CocoaPods, no iPhone simulator on
10027
10238
  the runtime \`stim ios\` builds for here, low disk, or busy. With Package.swift
10028
10239
  and no platform selection on a Mac, it also checks the macOS Xcode and SDK.
10240
+ Two machines build for each other when their Stim releases share a build
10241
+ compatibility version, which changes only when what a worker builds, how it
10242
+ builds, or the build messages change; their Stim builds can differ. A
10243
+ stim-server too old to report one needs the same Stim build as this machine.
10029
10244
 
10030
10245
  \`remote.build\` (machine scope, default auto) selects placement for
10031
10246
  \`ios\`, \`android\` and \`macos\`. \`--remote-build <auto|local|name>\`
@@ -10050,6 +10265,11 @@ and records buildMachine with builtOn absent. Build failures retain the selected
10050
10265
  value; builtOn is here or the configured machine entry when compilation ran.
10051
10266
  Prebuild and pod install still run on this machine before a named offload. A refusal
10052
10267
  starts no local xcodebuild, Gradle or SwiftPM compile.
10268
+ A React Native offload sends the tracked and untracked files, and the gitignored
10269
+ files the native fingerprint hashes or the Expo config reads, such as .env.local
10270
+ and other Expo .env files, secrets included. Nothing under node_modules and no
10271
+ build output the fingerprint ignores is sent. A fingerprint-mismatch refusal
10272
+ names the sources that differ and the files pod install or prebuild rewrote there.
10053
10273
  Run stim doctor --fix to ask for build access if not paired. A person on the
10054
10274
  worker approves it by running the stim-server setup command doctor printed, with
10055
10275
  its ticket and expiry. Check stim settings get remote.machines,
@@ -10081,10 +10301,20 @@ and install marker remain present.
10081
10301
  Older workers' dependency hints and mere checkout or build-folder presence do
10082
10302
  not influence this ranking. Exact completed-artifact hits still come first.
10083
10303
 
10304
+ The worker installs dependencies with the lockfile nearest the app: the first
10305
+ pnpm-lock.yaml, yarn.lock or package-lock.json in its directory or above it in
10306
+ the checkout, in the directory that holds it. An app with its own lockfile
10307
+ inside a larger repository installs its own dependencies there. In a pnpm
10308
+ workspace the worker installs every workspace package, as \`pnpm install\` does
10309
+ locally, because a native build can run a script of a package the app does not
10310
+ depend on.
10311
+
10084
10312
  The worker runs the dependency install, prebuild, pods and xcodebuild with the
10085
10313
  Node the app pins, in its directory or the nearest one above it in the
10086
- checkout, first on PATH, chosen as for Metro (see \`stim guide metro\`), and
10087
- names that Node as NODE_BINARY in the iOS project's .xcode.env.local. A warm
10314
+ checkout, first on PATH, chosen as for Metro (see \`stim guide metro\`). On
10315
+ every offloaded iOS build, pinned or not, it writes the first node on its PATH
10316
+ (the pinned Node when it put one first) as NODE_BINARY in the iOS project's
10317
+ .xcode.env.local, replacing any export NODE_BINARY= line already there. A warm
10088
10318
  Gradle daemon keeps running React Native's node steps on the Node it started
10089
10319
  with. When no installed Node fits the pin, the steps run on the worker's node
10090
10320
  and a deps-failed or prebuild-failed reason names the pin and that Node's
@@ -10102,7 +10332,8 @@ STIM_REMOTE_BUILD_MODE overrides it for one command. Device, Release and
10102
10332
  and iOS/Android runs with the build cache off, always build here. Hosted iOS
10103
10333
  Debug builds can use a separate --remote-build, targeting the hosting Mac's
10104
10334
  architecture and runtime.
10105
- macOS uses matching Xcode and macOS SDK, with a per-client SwiftPM dependency
10335
+ macOS uses matching Xcode and macOS SDK (not when --remote-build and --remote name the
10336
+ same Mac; see stim guide macos), with a per-client SwiftPM dependency
10106
10337
  cache on the worker. It skips JavaScript dependencies, prebuild and pods; see
10107
10338
  stim guide macos. Completed caching requires macos.artifactInputs and a locally
10108
10339
  verified compile; remote output is not published under an unverified client key.
@@ -10131,9 +10362,10 @@ lookup. Release and physical-device builds keep their existing paths.
10131
10362
  SwiftPM, compiler and dependency caches use their existing paths.
10132
10363
  For iOS the machine's Xcode and simulator SDK must match, and it needs an
10133
10364
  iPhone simulator on the target runtime. Its project-selected CocoaPods must match too, unless
10134
- the app's Gemfile.lock pins CocoaPods: both machines then run that version through
10365
+ the app's Gemfile.lock, in ios/ or the project root, pins CocoaPods: both machines then run that version through
10135
10366
  bundler, so the machine needs only Bundler on its stim-server PATH and
10136
- installs the pinned gems itself on the first build. The comparison selects
10367
+ installs the pinned gems itself on the first build. This Mac's side of the
10368
+ comparison runs \`pod --version\` in the directory pod install runs in. The comparison selects
10137
10369
  the app's .ruby-version when installed, otherwise rvm's or rbenv's default Ruby, and only when neither exists the GEM_HOME, GEM_PATH and Ruby-related PATH entries of the machine's login shell (read once with $SHELL -lic), unless the caller already sets GEM_HOME, with pod install's UTF-8 locale defaults. pod install, including the Bundler run, uses the same environment.
10138
10370
  For Android its CPU may differ, since the APK's ABIs come from the NDK, so an
10139
10371
  x86_64 Linux or Windows machine running stim-server can build for an Apple silicon Mac. Its JDK major
@@ -10886,7 +11118,8 @@ build pool. remote.buildPoolDisabled excludes members from automatic placement,
10886
11118
  including its local fallback. Explicit local or named placement bypasses membership.
10887
11119
  Configure remote.machines
10888
11120
  and approve build access as described in stim guide settings. The worker needs
10889
- matching Stim, CPU architecture, Xcode and macOS SDK, plus network access to
11121
+ matching Stim, CPU architecture, Xcode and macOS SDK (except for an app built and run on
11122
+ the same Mac, below), plus network access to
10890
11123
  fetch package dependencies the first time. It keeps SwiftPM dependencies in a
10891
11124
  per-client cache and incremental outputs per repository. It runs fixed swift
10892
11125
  build commands without JavaScript installs, prebuild or pods. It receives only
@@ -10894,6 +11127,12 @@ the files git lists (tracked and untracked, not ignored). Resource and catalog
10894
11127
  sources must be among those files. The client sends resolved sources relative
10895
11128
  to the repository root; the worker resolves them inside its checkout.
10896
11129
 
11130
+ With --remote <machine> and --remote-build naming the same machine (the same
11131
+ paired node), the app is built and run there, so this Mac's Xcode, macOS SDK and
11132
+ CPU architecture do not have to match: the worker needs the same Stim build
11133
+ compatibility version and its own Xcode and macOS SDK. This Mac's cache is skipped and the worker's cache
11134
+ identity comes from the worker's toolchain. Any other combination keeps the match.
11135
+
10897
11136
  The client validates the development plist and resource entries before asking a machine. It verifies
10898
11137
  the returned archive's sha256, bundle identifier, executable, declared resources
10899
11138
  and ad hoc signature