stim 1.12.0 → 1.13.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.
- package/README.md +3 -1
- package/dist/{activity-CCZJs__P.mjs → activity-DfVKZTEB.mjs} +42 -25
- package/dist/{android-BQiKJYK0.mjs → android-BHfAu2mf.mjs} +1 -1
- package/dist/{android-B7X-8H7h.mjs → android-CD8pr8Q2.mjs} +62 -47
- package/dist/{android-cas-DzLPXiEn.mjs → android-cas-B9Kv9aIy.mjs} +9 -7
- package/dist/{android-75Sk2rIR.mjs → android-qx_31wJo.mjs} +395 -116
- package/dist/{app-install-CsZi0SAT.mjs → app-install-CDFY2nUL.mjs} +1 -1
- package/dist/{budget-DbzW5VTD.mjs → budget-E5o91NR1.mjs} +154 -37
- package/dist/{build-plan-CqntbR7b.mjs → build-plan-BTa93o_r.mjs} +21 -88
- package/dist/{build-progress-h60GPV27.mjs → build-progress-l7d-X-ZP.mjs} +75 -7
- package/dist/cdp-Dq_ypAlJ.mjs +115 -0
- package/dist/chrome-B5hWgQJS.mjs +61 -0
- package/dist/cli.mjs +16 -15
- package/dist/collector-run.mjs +14 -8
- package/dist/{command-output-BWCj5Vh-.mjs → command-output-BIL7rlX7.mjs} +1 -1
- package/dist/created-devices-Cd558h31.mjs +37 -0
- package/dist/{deps-CO-_7UOm.mjs → deps-2Wo81np9.mjs} +1 -1
- package/dist/{device-9r9xRYDa.mjs → device-Cf7vl-so.mjs} +6 -6
- package/dist/{device-lease-B9LAXIUH.mjs → device-lease-CL9dZf73.mjs} +52 -3
- package/dist/{device-pool-BoezJd-c.mjs → device-pool-MuoiyRcu.mjs} +3 -3
- package/dist/{device-remote-C0_o-tJH.mjs → device-remote-DT9ngZiD.mjs} +10 -10
- package/dist/{doctor-LfDlbR-N.mjs → doctor-D2iysNNH.mjs} +47 -18
- package/dist/{error-diagnostics-CCxjn31V.mjs → error-diagnostics-BoiOhck8.mjs} +6 -6
- package/dist/{gc-C4nQFcTX.mjs → gc-eA-PRBX8.mjs} +853 -126
- package/dist/{guide-BPBlh9ML.mjs → guide-BfZ0OmiP.mjs} +736 -110
- package/dist/{guide-status-i9ogHt4v.mjs → guide-status-BaMYu55M.mjs} +1 -1
- package/dist/{idle-S3tFZ53_.mjs → idle-DxLi5OkN.mjs} +42 -9
- package/dist/{in-use-D9XYEgFD.mjs → in-use-wYEaKQM9.mjs} +9 -5
- package/dist/{ios-CDzWL1mj.mjs → ios-CcfCeZ19.mjs} +98 -54
- package/dist/{ios-CZWOHTTc.mjs → ios-CmEzZiOj.mjs} +10 -5
- package/dist/{ios-device-D9cLxVr5.mjs → ios-device-BW-t_Lkv.mjs} +1 -1
- package/dist/{launch-verify-B2oR_kFN.mjs → launch-verify-CuJaBpEa.mjs} +33 -20
- package/dist/{logs-SzuYudOj.mjs → logs-DcSRbC2t.mjs} +11 -10
- package/dist/{metro-Dzo30hvJ.mjs → metro-BPeY1YMh.mjs} +4 -4
- package/dist/{named-ports-Dn1o61D9.mjs → named-ports-n7tnJsI8.mjs} +78 -6
- package/dist/native-runtime-CiiFHt0e.mjs +74 -0
- package/dist/{ownership-Dqnrjrio.mjs → ownership-Bz2kETAS.mjs} +1 -1
- package/dist/{ownership-B8d4kXBx.mjs → ownership-PUP4Dwai.mjs} +134 -209
- package/dist/page-BTu7I60K.mjs +29 -0
- package/dist/{ports-Dp_QTwTC.mjs → ports-C5UutqpJ.mjs} +4 -4
- package/dist/{project-B8rbutVC.mjs → project-DGeclhvO.mjs} +53 -17
- package/dist/{reload-nocmx8KB.mjs → reload-C-cV5yy_.mjs} +79 -20
- package/dist/{remote-cache-BRsRZru5.mjs → remote-cache--aehr4Pr.mjs} +3 -3
- package/dist/{server-bare-Gn3ssSdK.mjs → server-bare-Bq8BpSIo.mjs} +1 -1
- package/dist/server-expo-BeYwP_Xy.mjs +2 -0
- package/dist/{server-expo-CeT1nIIk.mjs → server-expo-DUCg52-K.mjs} +2 -2
- package/dist/{settings-bE-Gu3Ti.mjs → settings-ssVBToDR.mjs} +10 -10
- package/dist/{settings-BlyDn2Oz.mjs → settings-xB0Frkg6.mjs} +11 -2
- package/dist/settings.schema.json +53 -1
- package/dist/{simslim-COtEEP7x.mjs → simslim-Bbg9UWrt.mjs} +12 -6
- package/dist/{slot-launch-DIACGEfH.mjs → slot-launch-BIWEW-wI.mjs} +3 -3
- package/dist/{start-BboE1HIS.mjs → start-BZhItkiL.mjs} +11 -10
- package/dist/{start-BFstVBlx.mjs → start-Rw2GD3nV.mjs} +1 -1
- package/dist/{state-DcDgzfu3.mjs → state-DwAU2_-D.mjs} +1 -1
- package/dist/state-l1pYwOre.mjs +148 -0
- package/dist/{stats-DiCtmluY.mjs → stats-CaSwmsSZ.mjs} +2 -2
- package/dist/{status-DI9Tjo7T.mjs → status-TJlL0HWo.mjs} +624 -103
- package/dist/{status-BUASYyy_.mjs → status-sszP4XKU.mjs} +59 -2
- package/dist/{stim-desktop-D0xhpZt8.mjs → stim-desktop-CXt8-Z3J.mjs} +13 -2
- package/dist/{stop-Bn6v-GvS.mjs → stop-BZ2qMiBP.mjs} +37 -12
- package/dist/{stop-BI7QY76M.mjs → stop-DskDKNTU.mjs} +2 -2
- package/dist/supervisor-run.mjs +10 -10
- package/dist/web-run.d.mts +22 -0
- package/dist/web-run.mjs +481 -0
- package/dist/web-sWXd5iek.mjs +394 -0
- package/dist/{worktree-B5sTRskL.mjs → worktree-3cBa-bQt.mjs} +1 -1
- package/dist/{worktree-ChDL5fO1.mjs → worktree-D4Do_XiQ.mjs} +226 -19
- package/dist/{xcode-BzplpQzc.mjs → xcode-LM6A8cNZ.mjs} +5 -5
- package/package.json +5 -5
- package/dist/server-expo-eWi9Coof.mjs +0 -2
- package/dist/workspace-process-lock-BvvJTfo_.mjs +0 -57
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-
|
|
3
|
-
import { t as RECENT_LAUNCH_MS } from "./status-
|
|
4
|
-
import { t as guideStatus } from "./guide-status-
|
|
1
|
+
import { a as findProjectRoot } from "./project-DGeclhvO.mjs";
|
|
2
|
+
import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-xB0Frkg6.mjs";
|
|
3
|
+
import { t as RECENT_LAUNCH_MS } from "./status-sszP4XKU.mjs";
|
|
4
|
+
import { t as guideStatus } from "./guide-status-BaMYu55M.mjs";
|
|
5
5
|
import { SETTINGS_SCHEMA_URL } from "@stim-cli/core/state";
|
|
6
6
|
import chalk from "chalk";
|
|
7
7
|
//#endregion
|
|
@@ -81,7 +81,14 @@ other apps or other workspaces' devices.
|
|
|
81
81
|
stim worktree warm
|
|
82
82
|
|
|
83
83
|
stim start
|
|
84
|
-
stim ios # or: stim android
|
|
84
|
+
stim ios # or: stim android, or: stim web
|
|
85
|
+
|
|
86
|
+
For the web target, stim web opens the page in a Stim-owned headless Chrome
|
|
87
|
+
and captures its console and errors in stim logs. It never starts a web
|
|
88
|
+
server: start the dev server first, then run stim web. For Expo web the dev
|
|
89
|
+
server is stim start, and the app needs the react-dom, react-native-web and
|
|
90
|
+
@expo/metro-runtime dependencies. Any other server runs on stim ports get web
|
|
91
|
+
and needs web.url. Read stim guide web first.
|
|
85
92
|
|
|
86
93
|
For a project using EAS development builds, read stim guide lifecycle eas to
|
|
87
94
|
select a profile from eas.json for the requested target, then run
|
|
@@ -223,7 +230,8 @@ Ask the user before these actions:
|
|
|
223
230
|
- worktree remove --force, because it also discards uncommitted and untracked
|
|
224
231
|
files.
|
|
225
232
|
- gc --delete, because it deletes orphaned resources, removes clean linked
|
|
226
|
-
worktrees whose branch
|
|
233
|
+
worktrees whose branch or pull request is merged (or whose pull request
|
|
234
|
+
was closed), and clears the build outputs of every
|
|
227
235
|
workspace not in use. Run stim gc --json first and show
|
|
228
236
|
the user the entries its sections list (guide facts gc). gc --delete
|
|
229
237
|
--cache all empties the shared build caches and those outputs instead, and
|
|
@@ -272,7 +280,8 @@ Read the matching guide before acting in these situations:
|
|
|
272
280
|
| Refusal with a CODE | stim guide errors <CODE> |
|
|
273
281
|
| Running under a sandbox | stim guide errors sandbox |
|
|
274
282
|
| Release configuration or ...Release variant | stim guide lifecycle release |
|
|
275
|
-
| Web
|
|
283
|
+
| Web app in an owned Chrome (stim web) | stim guide web |
|
|
284
|
+
| Web or API server ports | stim guide ports |
|
|
276
285
|
| Remote device, custom Metro, or tunnel | stim guide metro |
|
|
277
286
|
| Cache miss, bypass, or fingerprint exclusions | stim guide lifecycle builds |
|
|
278
287
|
| Capacity limits | stim guide lifecycle concurrency |
|
|
@@ -316,6 +325,7 @@ FULL TOPIC LIST
|
|
|
316
325
|
stim guide lifecycle release # Release configurations and ...Release variants
|
|
317
326
|
stim guide facts # the --json payloads
|
|
318
327
|
stim guide facts devmenu # the Expo dev menu or Tools button over the app
|
|
328
|
+
stim guide web # stim web: owned Chrome, page logs, launched, teardown
|
|
319
329
|
stim guide ports # named ports for web and API servers
|
|
320
330
|
stim guide metro # supervisor, custom Metro, tunnels, and remote devices
|
|
321
331
|
stim guide logs # filters, record shape, and capture limits
|
|
@@ -324,7 +334,7 @@ FULL TOPIC LIST
|
|
|
324
334
|
stim guide settings # configuration files and supported keys`
|
|
325
335
|
},
|
|
326
336
|
facts: {
|
|
327
|
-
summary: "The --json payloads: `start`, `ios`, `android`, `ios|android --plan`, `reload`, `stop`, `status`, `doctor`, `device lock`/`unlock`, `gc`, and the error contract",
|
|
337
|
+
summary: "The --json payloads: `start`, `ios`, `android`, `web`, `ios|android --plan`, `reload`, `stop`, `status`, `doctor`, `device lock`/`unlock`, `gc`, and the error contract",
|
|
328
338
|
preamble: () => `SLOTS
|
|
329
339
|
Named ios/android runs add slot to their JSON facts. Default-run fields remain
|
|
330
340
|
compatible. status adds a slots array per environment with each named slot's
|
|
@@ -333,7 +343,7 @@ Named collector, lease-holder, and launch keys use platform:slot internally.
|
|
|
333
343
|
|
|
334
344
|
FACTS CONTRACT
|
|
335
345
|
|
|
336
|
-
\`start\`, \`ios\`, \`android\`, \`reload\`, \`stop\`, \`status\`, \`stats\`, \`doctor\`,
|
|
346
|
+
\`start\`, \`ios\`, \`android\`, \`web\`, \`reload\`, \`stop\`, \`status\`, \`stats\`, \`doctor\`,
|
|
337
347
|
\`gc\`, and \`device lock\`/\`device unlock\` each print exactly ONE line of JSON on
|
|
338
348
|
stdout for \`--json\`. Every other line goes to stderr, so it is always safe
|
|
339
349
|
to pipe. \`logs --json\` is the one exception: it is NDJSON, one record per
|
|
@@ -372,8 +382,11 @@ status runs \`git status --porcelain=v2 --branch\` in every worktree in
|
|
|
372
382
|
parallel, and caches the merge verdict by HEAD and default-branch commit
|
|
373
383
|
under $STIM_HOME/git-merge. One call starts no new merge check 250 ms after
|
|
374
384
|
its first; later calls judge the rest, and until then a verdict for the same
|
|
375
|
-
HEAD at an older default-branch commit stands in
|
|
376
|
-
|
|
385
|
+
HEAD at an older default-branch commit stands in; a check that timed out
|
|
386
|
+
is retried after 5 minutes. \`status --watch\` reuses a worktree's git read
|
|
387
|
+
until its index, HEAD, reflog or the branch, upstream or default-branch refs
|
|
388
|
+
change, and for at most 60 s, so a file edit, creation or deletion that is
|
|
389
|
+
not staged can take up to a minute to show. Plain status prints "git: 2 changed, 1 untracked, ahead 3" under
|
|
377
390
|
each environment, and the same after each worktree with no environment.
|
|
378
391
|
|
|
379
392
|
status's remoteDevices lists each environment's recorded EAS Simulator
|
|
@@ -396,7 +409,7 @@ Plain status prints one "remote <platform>: EAS session <id> billable" line
|
|
|
396
409
|
per session, with the preview URL.`,
|
|
397
410
|
sections: {
|
|
398
411
|
payloads: {
|
|
399
|
-
summary: "every field of the start, ios, android and reload payloads, the error contract, the device rules",
|
|
412
|
+
summary: "every field of the start, ios, android, web and reload payloads, the error contract, the device rules",
|
|
400
413
|
body: () => ` stim start --json
|
|
401
414
|
|
|
402
415
|
port the Metro port RESERVED for this workspace
|
|
@@ -437,13 +450,18 @@ per session, with the preview URL.`,
|
|
|
437
450
|
hit 6564e2.. (post-prebuild key)\`), so a cold tree -- a
|
|
438
451
|
fresh worktree or clone of a CNG app -- installs an entry
|
|
439
452
|
another workspace already built instead of compiling
|
|
440
|
-
beside it.
|
|
441
|
-
Gradle plugins can rewrite native inputs
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
453
|
+
beside it. Both platforms fingerprint again after the
|
|
454
|
+
compile because Gradle plugins can rewrite native inputs
|
|
455
|
+
while they build; a change under node_modules/ or the
|
|
456
|
+
native directory stores the artifact only under that
|
|
457
|
+
post-build hash. A stable fingerprint prints no shift line.
|
|
458
|
+
If any other input changed while the build ran (the app
|
|
459
|
+
config or a config plugin since the first lookup, other
|
|
460
|
+
than the bundle id or package prebuild adds, or any
|
|
461
|
+
other source during the compile), or a fingerprint after
|
|
462
|
+
prebuild, pod install or the compile cannot be computed,
|
|
463
|
+
the build is installed but not cached, and fingerprint and
|
|
464
|
+
cacheKey are null
|
|
447
465
|
configuration the Xcode configuration that was built ("Release" from
|
|
448
466
|
--configuration or the ios.configuration setting); null for
|
|
449
467
|
the default Debug
|
|
@@ -524,6 +542,12 @@ per session, with the preview URL.`,
|
|
|
524
542
|
finishing
|
|
525
543
|
"unverified" nothing was observed at all: usually a
|
|
526
544
|
dev-client server picker awaiting a tap
|
|
545
|
+
Neither "bundling" nor "unverified" is reported for an app
|
|
546
|
+
whose process is gone when the bundle timeout closes: the
|
|
547
|
+
run fails as FATAL, "the app process exited", with the
|
|
548
|
+
device log's errors. An iOS crash report can land a minute
|
|
549
|
+
after the crash, so \`logs --errors\` may show the native
|
|
550
|
+
stack only later
|
|
527
551
|
See \`guide facts devmenu\` for the dev menu and its button.
|
|
528
552
|
metroPort the port the app was wired to; NULL on a non-Debug
|
|
529
553
|
configuration, whose JS is embedded and which is launched
|
|
@@ -621,18 +645,20 @@ per session, with the preview URL.`,
|
|
|
621
645
|
reason is "not running" or "stopped (idle)" when the
|
|
622
646
|
supervisor had stopped it after metro.idleStopMinutes
|
|
623
647
|
|
|
624
|
-
stim reload [ios|android] --json
|
|
648
|
+
stim reload [ios|android|web] --json
|
|
625
649
|
|
|
626
650
|
Exit 0 and this payload confirm that the reload request was sent. They do
|
|
627
651
|
not prove that new JavaScript loaded or that the screen recovered. The
|
|
628
652
|
command does not observe completion. Verify the expected UI on deviceId
|
|
629
653
|
and inspect stim logs --errors before claiming recovery.
|
|
630
654
|
|
|
631
|
-
platform "ios" | "android"
|
|
632
|
-
deviceId the exact owned simulator UDID or emulator serial targeted
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
655
|
+
platform "ios" | "android" | "web"
|
|
656
|
+
deviceId the exact owned simulator UDID or emulator serial targeted;
|
|
657
|
+
for web, the owned Chrome's DevTools endpoint
|
|
658
|
+
deviceName the owned simulator or AVD name; for web, the Chrome version
|
|
659
|
+
appId the live bundle id or Android package; for web, the page URL
|
|
660
|
+
metroPort the workspace's verified Metro port; for web, the reserved
|
|
661
|
+
Metro port or null
|
|
636
662
|
strategy how the reload was addressed.
|
|
637
663
|
"metro-websocket" -- Metro named its clients and Stim
|
|
638
664
|
addressed every peer matching this platform. A workspace
|
|
@@ -642,11 +668,35 @@ per session, with the preview URL.`,
|
|
|
642
668
|
the reload went to all of them and Stim cannot confirm appId
|
|
643
669
|
was among them. Verify the UI on deviceId; if it did not
|
|
644
670
|
change, reload from the app's own error screen or dev menu
|
|
671
|
+
"cdp" -- web: Page.reload on the owned Chrome page, sent
|
|
672
|
+
over a DevTools connection verified to reach that Chrome
|
|
645
673
|
targets how many peers the reload was addressed to, or null when
|
|
646
674
|
broadcast. Greater than 1 means several devices are running
|
|
647
675
|
this app on that Metro and the request addressed all of
|
|
648
676
|
them, not only deviceId. Completion is not observed
|
|
649
677
|
|
|
678
|
+
stim web --json
|
|
679
|
+
|
|
680
|
+
platform "web"
|
|
681
|
+
browser "chrome"
|
|
682
|
+
version the Chrome product, such as "Chrome/153.0.8010.49", or null
|
|
683
|
+
running true: the owned Chrome answered and holds the page
|
|
684
|
+
pid the owned Chrome's browser process; null when not running
|
|
685
|
+
supervisorPid the Stim process holding its DevTools session, or null
|
|
686
|
+
url the page opened, web.url with its ports filled in
|
|
687
|
+
headless false only with --headed
|
|
688
|
+
viewport "desktop" | "phone" (web.viewport)
|
|
689
|
+
profile the Stim-owned Chrome user data directory
|
|
690
|
+
cdpEndpoint http://127.0.0.1:<port>, the reserved DevTools endpoint, or
|
|
691
|
+
null when not running
|
|
692
|
+
reused true when the running Chrome navigated again instead of
|
|
693
|
+
starting: same --headed, viewport and certificate options
|
|
694
|
+
launched true | "bundling" | "unverified" (see \`guide web\`)
|
|
695
|
+
metroPort the Metro port the page loads from, or null for a web.url
|
|
696
|
+
that does not use {port:metro}
|
|
697
|
+
logs { dir }: web.ndjson holds the page records
|
|
698
|
+
durationMs wall time of the run
|
|
699
|
+
|
|
650
700
|
stim doctor --json
|
|
651
701
|
|
|
652
702
|
project the resolved app root
|
|
@@ -670,7 +720,7 @@ per session, with the preview URL.`,
|
|
|
670
720
|
costs-time finding with a PATH or installation remedy
|
|
671
721
|
|
|
672
722
|
ON FAILURE
|
|
673
|
-
\`start\`, \`ios\` and \`
|
|
723
|
+
\`start\`, \`ios\`, \`android\` and \`web\` all print the error contract instead,
|
|
674
724
|
still one line on stdout, and exit 1:
|
|
675
725
|
|
|
676
726
|
{ "code": "STIM_METRO_TIMEOUT", "message": "...", "remedy": "..." }
|
|
@@ -695,6 +745,12 @@ ON FAILURE
|
|
|
695
745
|
|
|
696
746
|
{ "root": "...", "ok": false, "code": "STIM_STOP_BLOCKED", "message": "...", "remedy": "..." }
|
|
697
747
|
|
|
748
|
+
device.web is present when the workspace had an owned Chrome:
|
|
749
|
+
{ status, label: "Chrome", kind?, reason?, remedy? }; kind is null when no
|
|
750
|
+
kind applies. status is "shut-down"
|
|
751
|
+
when Chrome closed (its profile is kept), else "skipped" (its identity could
|
|
752
|
+
not be verified) or "failed", and ok is then false.
|
|
753
|
+
|
|
698
754
|
Branch on \`code\`, never on the message text. \`guide errors\` enumerates
|
|
699
755
|
every code.
|
|
700
756
|
|
|
@@ -811,13 +867,13 @@ RULES
|
|
|
811
867
|
full commands.`
|
|
812
868
|
},
|
|
813
869
|
gc: {
|
|
814
|
-
summary: "the gc report payload: mode, sections, reasons, failures, and the gc refusals",
|
|
870
|
+
summary: "the gc report payload: mode, sections, reasons, failures, results, inventory, and the gc refusals",
|
|
815
871
|
body: () => ` stim gc [--delete] [--older-than <days>] [--cache <name|all|workspaces>]
|
|
816
872
|
[--worktrees] [--idle <duration>] --json
|
|
817
873
|
|
|
818
874
|
The report the text prints, as one payload. Show the user its sections
|
|
819
875
|
before you run \`gc --delete\`. Under --delete it is the report that run
|
|
820
|
-
acted on: each entry's outcome
|
|
876
|
+
acted on: \`results\` lists each entry's outcome, \`failures\` counts the
|
|
821
877
|
entries it could not delete, and a nonzero count exits 1. Run
|
|
822
878
|
\`stim gc --json\` again to see what is left.
|
|
823
879
|
|
|
@@ -834,6 +890,46 @@ RULES
|
|
|
834
890
|
actionable true when --delete with the same flags reclaims something
|
|
835
891
|
failures null on a dry run without --idle; otherwise the entries it
|
|
836
892
|
could not delete or shut down
|
|
893
|
+
results what --delete or --idle did, one { kind, status, label,
|
|
894
|
+
id, bytes, detail } per entry it acted on; empty on a dry
|
|
895
|
+
run. status is "done", "kept" (left alone, detail says
|
|
896
|
+
why) or "failed" (detail says why and what to retry).
|
|
897
|
+
kind: device, parkedDevice, idleDevice, deviceRecord,
|
|
898
|
+
workspaceOutputs, workspaceDirectory, project, buildLock,
|
|
899
|
+
buildSlot, deviceLease, easSession, worktree, cache.
|
|
900
|
+
label is a device, path or cache name; id is the UDID,
|
|
901
|
+
AVD name or path behind it, or null
|
|
902
|
+
inventory null except on a dry run without --cache or --idle. Report
|
|
903
|
+
only: gc never acts on it, even under --delete.
|
|
904
|
+
{ devices, runtimes, systemImages, notices }
|
|
905
|
+
devices { kind, id, name, model, runtime, state, lastUsedAt, bytes,
|
|
906
|
+
directory, owner, project, slot } every available iOS
|
|
907
|
+
simulator and registered AVD. runtime is the simctl
|
|
908
|
+
runtime identifier or the AVD's system image package.
|
|
909
|
+
lastUsedAt is simctl's last use, or when the emulator
|
|
910
|
+
last wrote the AVD's hardware-qemu.ini. bytes is the
|
|
911
|
+
simulator's data size from simctl; null for AVDs.
|
|
912
|
+
owner is workspace (project and slot say which),
|
|
913
|
+
parked, orphaned (this Stim home created it and no
|
|
914
|
+
workspace holds it), otherStimHome (a stim-* device this
|
|
915
|
+
home has no record of creating, even when a workspace
|
|
916
|
+
names it) or user. Off macOS no simulator is listed
|
|
917
|
+
runtimes { identifier, runtimeIdentifier, version, build, bytes,
|
|
918
|
+
lastUsedAt, deviceCount, command } iOS simulator
|
|
919
|
+
runtimes from \`xcrun simctl runtime list -j\`, then
|
|
920
|
+
any other \`simctl list runtimes\` shows, with bytes
|
|
921
|
+
and command null. deviceCount is the simulators on
|
|
922
|
+
it; command is the \`xcrun simctl runtime delete\`
|
|
923
|
+
line for a deletable runtime, else null. Stim never
|
|
924
|
+
runs it
|
|
925
|
+
systemImages { package, directory, avdCount, command } installed
|
|
926
|
+
Android system images; avdCount is the AVDs whose
|
|
927
|
+
image.sysdir.1 names it; command is the
|
|
928
|
+
\`sdkmanager --uninstall\` line. Stim never runs it
|
|
929
|
+
notices why a listing is missing or partial, such as simctl
|
|
930
|
+
timing out or an AVD or system image folder Stim
|
|
931
|
+
cannot read. A macOS privacy denial (EPERM) names the
|
|
932
|
+
Privacy & Security setting to grant
|
|
837
933
|
sections one array per report section, in the text order. Every key
|
|
838
934
|
is present, empty when there is nothing to report:
|
|
839
935
|
deadProjects { path }
|
|
@@ -841,12 +937,18 @@ RULES
|
|
|
841
937
|
orphanedPorts { project, label, port }
|
|
842
938
|
orphanedWorkspaces { dir, projectRoot, bytes } --delete removes the
|
|
843
939
|
whole workspace directory
|
|
844
|
-
linkedWorktrees { path, idleDays, mergedInto,
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
940
|
+
linkedWorktrees { path, idleDays, mergedInto, pullRequest,
|
|
941
|
+
pullRequestUnknown, willRemove, reason,
|
|
942
|
+
detail, eligibleAt } mergedInto is the
|
|
943
|
+
default branch HEAD is merged into
|
|
944
|
+
("origin/main"), or null. pullRequest is the
|
|
945
|
+
branch's pull request { number, state:
|
|
946
|
+
"open" | "merged" | "closed", url,
|
|
947
|
+
containsHead }, or null; pullRequestUnknown
|
|
948
|
+
says why gh could not answer, else null.
|
|
949
|
+
detail says why it is removed ("merged into
|
|
950
|
+
origin/main", "PR #12 closed", "idle 9d") or
|
|
951
|
+
kept. eligibleAt is the ISO time a
|
|
850
952
|
recent-activity worktree becomes removable,
|
|
851
953
|
else null. Without --worktrees, the source
|
|
852
954
|
checkout and roots outside git are left out
|
|
@@ -856,13 +958,21 @@ RULES
|
|
|
856
958
|
parkedEmulators { name, systemImage, deviceProfile, parkedAt, bytes, listed }
|
|
857
959
|
likewise
|
|
858
960
|
orphanedDevices { kind, id, name, bytes, directory }
|
|
859
|
-
unverifiedDevices { kind, id, name, command } stim-* devices
|
|
860
|
-
has no record of creating; never
|
|
861
|
-
command yourself
|
|
961
|
+
unverifiedDevices { kind, id, name, command } stim-* devices this
|
|
962
|
+
Stim home has no record of creating; never
|
|
963
|
+
deleted, run command yourself (rm -rf <dir>
|
|
964
|
+
for AVD data with no registration)
|
|
862
965
|
staleDevices { kind, id, name, project, slot, idleDays,
|
|
863
966
|
bytes } only with --older-than
|
|
864
967
|
staleDeviceRecords { kind, id, project, slot } --delete clears
|
|
865
968
|
the record only
|
|
969
|
+
staleLedgerEntries { kind: "ios" | "android" | "web", id }
|
|
970
|
+
simulators this Stim home created that a
|
|
971
|
+
complete simctl listing no longer shows, AVD
|
|
972
|
+
names with no registration or data in any AVD
|
|
973
|
+
root, and browser profile paths whose
|
|
974
|
+
directory is gone; --delete forgets the
|
|
975
|
+
ledger entry only
|
|
866
976
|
idleDevices { kind, id, name, project, slot, lastActivityAt,
|
|
867
977
|
idleForMs, buildInProgress } booted owned
|
|
868
978
|
devices whose status activity is "idle";
|
|
@@ -880,6 +990,12 @@ RULES
|
|
|
880
990
|
deviceSweepNotices { message }
|
|
881
991
|
easSessionSweepNotices { message }
|
|
882
992
|
skipped { path, detail } not classified as dead
|
|
993
|
+
workspaceLogs { dir, projectRoot, bytes, trimBytes, willTrim,
|
|
994
|
+
reason, detail } logs/ of each workspace;
|
|
995
|
+
trimBytes is what --delete would drop from
|
|
996
|
+
Metro, client and device logs over twice the
|
|
997
|
+
8 MiB cap; willTrim marks the ones it would
|
|
998
|
+
trim
|
|
883
999
|
workspaceBuildOutputs { dir, projectRoot, bytes, idleDays, willClear,
|
|
884
1000
|
reason, detail } derived-data, gradle-build,
|
|
885
1001
|
android-cas and cache-provider of each
|
|
@@ -898,6 +1014,7 @@ RULES
|
|
|
898
1014
|
A linked worktree's detail is never null.
|
|
899
1015
|
workspaceBuildOutputs unresolved | in-use | last-use-unknown |
|
|
900
1016
|
recently-used
|
|
1017
|
+
workspaceLogs unresolved | in-use | collector
|
|
901
1018
|
linkedWorktrees not-a-worktree | bare-repository |
|
|
902
1019
|
source-checkout-unknown | source-checkout |
|
|
903
1020
|
locked | in-use | status-unreadable | dirty |
|
|
@@ -915,7 +1032,7 @@ RULES
|
|
|
915
1032
|
- --cache together with --worktrees or --idle`
|
|
916
1033
|
},
|
|
917
1034
|
status: {
|
|
918
|
-
summary: "the status payload's issues and their codes, build and device activity fields: a running build, its estimate, each platform's last build,
|
|
1035
|
+
summary: "the status payload's issues and their codes, build and device activity fields: a running build, its estimate, each platform's last build, who drives each device, whether the app runs on it, and what uses CPU and memory now",
|
|
919
1036
|
body: () => ` stim status --json
|
|
920
1037
|
|
|
921
1038
|
Each environment carries issues, the things in that workspace that need
|
|
@@ -945,6 +1062,12 @@ RULES
|
|
|
945
1062
|
supervisor-unverified a supervisor record whose process status
|
|
946
1063
|
cannot prove gone or ours; stop refuses to
|
|
947
1064
|
signal it
|
|
1065
|
+
browser-unverified the owned Chrome's supervisor or Chrome
|
|
1066
|
+
process cannot be proven gone or ours;
|
|
1067
|
+
stop and stim web refuse to signal it
|
|
1068
|
+
browser-orphaned the owned Chrome runs but its supervisor
|
|
1069
|
+
exited, so page logs are not captured;
|
|
1070
|
+
stim stop closes it
|
|
948
1071
|
severity "error" when stop or start refuses until it is resolved, else
|
|
949
1072
|
"warning"
|
|
950
1073
|
remedy a command to run from workspace, such as "stim android --slot
|
|
@@ -956,6 +1079,19 @@ RULES
|
|
|
956
1079
|
\`stop --slot <name>\` forgets that slot's launch, so a device stopped on
|
|
957
1080
|
purpose is not reported while the shared dev server keeps running.
|
|
958
1081
|
|
|
1082
|
+
An environment where \`stim web\` ran carries web, its Stim-owned Chrome:
|
|
1083
|
+
|
|
1084
|
+
web { browser, version, running, pid, supervisorPid, url, headless,
|
|
1085
|
+
viewport, profile, cdpEndpoint }
|
|
1086
|
+
|
|
1087
|
+
running the browser supervisor and Chrome are both verified live;
|
|
1088
|
+
pid, supervisorPid and cdpEndpoint are null when false
|
|
1089
|
+
cdpEndpoint http://127.0.0.1:<port>, the reserved loopback DevTools
|
|
1090
|
+
endpoint of that Chrome. Attach Playwright MCP
|
|
1091
|
+
(--cdp-endpoint) or agent-browser (--cdp <port>) to it; it
|
|
1092
|
+
reaches only the Stim profile, never your own browser
|
|
1093
|
+
profile the Stim-owned user data directory under STIM_HOME
|
|
1094
|
+
|
|
959
1095
|
Each booted simulator and detected emulator in environments (and in
|
|
960
1096
|
slots) carries activity; a shut-down or physical device has none:
|
|
961
1097
|
|
|
@@ -972,7 +1108,8 @@ RULES
|
|
|
972
1108
|
the claim does not record them
|
|
973
1109
|
lastActivityAt the newest of this device's app log records, this
|
|
974
1110
|
platform's Metro bundle requests and the workspace's last
|
|
975
|
-
Stim run; absent when none is
|
|
1111
|
+
Stim run, rounded down to the minute; absent when none is
|
|
1112
|
+
recorded
|
|
976
1113
|
basis the evidence behind state, strongest first:
|
|
977
1114
|
agent-device-claim, agent-device-lease agent-device state,
|
|
978
1115
|
read only; live only when every recorded process is alive
|
|
@@ -988,6 +1125,29 @@ RULES
|
|
|
988
1125
|
\`gc --idle <duration>\` shuts down owned devices idle that long
|
|
989
1126
|
(\`guide cleanup gc\`).
|
|
990
1127
|
|
|
1128
|
+
An owned booted simulator or detected emulator also carries app, whether
|
|
1129
|
+
the workspace's app process is alive on it now:
|
|
1130
|
+
|
|
1131
|
+
app { id, state }
|
|
1132
|
+
|
|
1133
|
+
id the bundle identifier or package checked: the one launched on this
|
|
1134
|
+
device, else the project's
|
|
1135
|
+
state "running" a process of that app runs on the device
|
|
1136
|
+
"stopped" no such process: it crashed, was killed or never launched
|
|
1137
|
+
"unknown" the process listing or the app's Info.plist could not be
|
|
1138
|
+
read; never "stopped"
|
|
1139
|
+
|
|
1140
|
+
app is absent when the device is not owned or no app id is known: the
|
|
1141
|
+
process was not checked.
|
|
1142
|
+
|
|
1143
|
+
This is current process state, read from one host ps (simulator apps are
|
|
1144
|
+
host processes) and the same adb shell ps as activity, so a status --watch
|
|
1145
|
+
refresh notices an exit within its 30-second fallback. It is not launch
|
|
1146
|
+
evidence: launched in an ios or android result keeps its own meaning. For
|
|
1147
|
+
"stopped", run \`stim ios\` or \`stim android\` to launch it again. Plain
|
|
1148
|
+
status appends "<id> running", "<id> not running" or "<id> process
|
|
1149
|
+
unknown" to the device line.
|
|
1150
|
+
|
|
991
1151
|
An environment's metro carries idleStop { reason: "idle", at, idleMinutes }
|
|
992
1152
|
when its supervisor stopped the dev server for idleness and nothing serves
|
|
993
1153
|
the port since; plain \`status\` prints "stopped (idle)" (\`guide metro\`).
|
|
@@ -1027,7 +1187,7 @@ RULES
|
|
|
1027
1187
|
|
|
1028
1188
|
lastBuilds { ios?, android? }, each { platform, status, cacheHit,
|
|
1029
1189
|
cacheSkipped, durationMs, fingerprint, startedAt, finishedAt,
|
|
1030
|
-
errorCode?, missReason? }
|
|
1190
|
+
errorCode?, missReason?, diagnostics? }
|
|
1031
1191
|
|
|
1032
1192
|
status "ok" or "failed"
|
|
1033
1193
|
cacheHit "local" or "remote" for an app from that cache tier; false
|
|
@@ -1045,12 +1205,79 @@ RULES
|
|
|
1045
1205
|
baseline is { fingerprint, from: "workspace" | "project" }, the
|
|
1046
1206
|
cached build compared with; rekeyedBy lists "prebuild" or
|
|
1047
1207
|
"pod install" when those steps moved the key.
|
|
1208
|
+
diagnostics only on a failed run whose compiler reported errors: up to
|
|
1209
|
+
5 { file, line, column, message }, null where the compiler
|
|
1210
|
+
gave no position.
|
|
1048
1211
|
|
|
1049
1212
|
Plain status prints "last build: ios local cache in 12s, android compiled
|
|
1050
1213
|
in 7m02s". To predict the next run instead, see \`guide facts plan\`.
|
|
1051
1214
|
|
|
1215
|
+
An environment with a recorded run also carries builds, each platform's
|
|
1216
|
+
last 10 runs, newest first. Its newest entry that is not "interrupted" is
|
|
1217
|
+
the run lastBuilds reports, once a run has recorded builds.
|
|
1218
|
+
|
|
1219
|
+
builds { ios?, android? }, each a list of lastBuilds entries
|
|
1220
|
+
with { result, slot, configuration, cacheKey, phases }
|
|
1221
|
+
result "succeeded", "failed", "cancelled" (Stim stopped the run
|
|
1222
|
+
after an interrupt or \`stim stop\`) or "interrupted": its
|
|
1223
|
+
process ended without recording a result, such as a kill or a
|
|
1224
|
+
second interrupt, so the next run recorded it with
|
|
1225
|
+
null durationMs and finishedAt, no cache facts, and 0 for the
|
|
1226
|
+
phase it stopped in
|
|
1227
|
+
slot the device slot, "default" without --slot
|
|
1228
|
+
configuration the iOS configuration or Android variant the run built,
|
|
1229
|
+
"Debug" or "debug" by default; null when the run ended
|
|
1230
|
+
before resolving it
|
|
1231
|
+
cacheKey the cache key the run looked up or stored under
|
|
1232
|
+
phases milliseconds spent in each phase the run entered, among
|
|
1233
|
+
prepare, cache-lookup, wait, prebuild, pods, compile,
|
|
1234
|
+
install and launch
|
|
1235
|
+
|
|
1236
|
+
Only runs that record a last build are listed: a run that stops before
|
|
1237
|
+
looking up a build, such as a bad flag, is not. Estimates (expectedMs) come from run statistics, not builds.
|
|
1238
|
+
|
|
1052
1239
|
There is no completion fraction: a compile's log volume depends on what
|
|
1053
|
-
is already built, so it does not measure progress
|
|
1240
|
+
is already built, so it does not measure progress.
|
|
1241
|
+
|
|
1242
|
+
An environment's memoryMb is an estimate, not a measurement: a fixed amount
|
|
1243
|
+
per booted simulator, detected emulator, running Metro and running Chrome.
|
|
1244
|
+
capacity.committedMb sums it, and the memory budget uses the same estimate.
|
|
1245
|
+
What is using CPU and memory now is the top-level machine section:
|
|
1246
|
+
|
|
1247
|
+
machine null, or { owners: [{ kind, name, workspace, slot?, id, owned,
|
|
1248
|
+
cpuPercent, residentMb, processes }] }
|
|
1249
|
+
|
|
1250
|
+
kind simulator a booted simulator's launchd_sim tree
|
|
1251
|
+
emulator an emulator's launcher and qemu tree, by its -avd
|
|
1252
|
+
metro a workspace's supervisor and Metro trees
|
|
1253
|
+
build a running ios or android run's process tree,
|
|
1254
|
+
xcodebuild, Gradle and compilers included
|
|
1255
|
+
browser the Chrome of \`stim web\` and its supervisor
|
|
1256
|
+
server stim-server
|
|
1257
|
+
shared machine-wide processes no workspace owns:
|
|
1258
|
+
CoreSimulator services, adb server, Gradle and
|
|
1259
|
+
Kotlin daemons, Watchman, the emulator's netsimd
|
|
1260
|
+
workspace the workspace that records the device or runs the process;
|
|
1261
|
+
null for a device no workspace records and for server and
|
|
1262
|
+
shared
|
|
1263
|
+
id the simulator's UDID, the AVD name, Metro's port or the
|
|
1264
|
+
build's platform; null otherwise
|
|
1265
|
+
owned true for what Stim started and stops: a workspace's owned
|
|
1266
|
+
device (\`stim stop --slot <slot>\`), its Metro (\`stim
|
|
1267
|
+
stop\`), build or Chrome. Never act on an owner with false.
|
|
1268
|
+
cpuPercent ps %CPU summed over the owner's processes; 100 is one core
|
|
1269
|
+
residentMb summed resident set size. Pages shared between processes
|
|
1270
|
+
count once per process, so a simulator reports well above
|
|
1271
|
+
its physical footprint.
|
|
1272
|
+
|
|
1273
|
+
Each process counts in exactly one owner, the one whose root process is
|
|
1274
|
+
its nearest ancestor, so the supervisor a build started counts as Metro,
|
|
1275
|
+
not as the build, and a Gradle or Kotlin daemon counts in the build that
|
|
1276
|
+
started it until that build exits, then as shared. Processes with no owner
|
|
1277
|
+
are left out. machine comes from one host ps, the one status reads for
|
|
1278
|
+
device activity, and is null when no simulator is booted, no workspace is
|
|
1279
|
+
live and no build runs: status then reads no process table. \`status --watch --json\` rereads it every 15 seconds while
|
|
1280
|
+
machine is not null, with no other subprocess.`
|
|
1054
1281
|
},
|
|
1055
1282
|
plan: {
|
|
1056
1283
|
summary: "the ios and android --plan payload: fingerprint, cacheHit, prebuild, missReason, expectedMs and basis",
|
|
@@ -1355,7 +1582,16 @@ their owning workspaces.
|
|
|
1355
1582
|
|
|
1356
1583
|
The machine registry, under STIM_HOME, serializes allocation and cleanup.
|
|
1357
1584
|
The workspace is the nearest package.json directory, resolved through
|
|
1358
|
-
symlinks.
|
|
1585
|
+
symlinks. In a monorepo, a package that depends on neither react-native nor
|
|
1586
|
+
expo, such as a Vite web app, uses the one Stim app registered in the same
|
|
1587
|
+
git worktree instead, and says so on stderr. ports, web, settings, logs,
|
|
1588
|
+
reload, stop and status follow this rule (status stars the app instead of
|
|
1589
|
+
printing the note); other commands use the nearest package.json. Register the app first: run stim ports get <label>, stim start,
|
|
1590
|
+
stim ios or stim android from the app directory. Every ports command then
|
|
1591
|
+
acts on the app's ports, so ports stop without a label there also stops the
|
|
1592
|
+
app's other labels. A package that already holds ports keeps them; release
|
|
1593
|
+
them to move to the app. With no registered app, or more than one, the
|
|
1594
|
+
nearest package.json stays the workspace; run ports from the app directory.
|
|
1359
1595
|
The allocation reserves a number, not a listening socket. Another process
|
|
1360
1596
|
can bind it before your server does. Use strict-port behavior when supported
|
|
1361
1597
|
and verify the server bound the number supplied. Stim does not start,
|
|
@@ -1397,7 +1633,10 @@ discovered, not enumerated.
|
|
|
1397
1633
|
metro.ndjson, client.ndjson and device.ndjson are size-capped. At about 8 MiB a file
|
|
1398
1634
|
becomes <name>.1, replacing the previous .1, and a new file starts. Queries read
|
|
1399
1635
|
both generations, so the oldest records drop off first. History and --since
|
|
1400
|
-
reach back only as far as those records.
|
|
1636
|
+
reach back only as far as those records. A file written before the cap
|
|
1637
|
+
existed can be larger; \`gc\` reports each workspace's log size and \`gc
|
|
1638
|
+
--delete\` trims a file over 16 MiB to its newest 8 MiB in a workspace not in use
|
|
1639
|
+
(\`guide cleanup disk\`).
|
|
1401
1640
|
|
|
1402
1641
|
EXIT 0 MEANS THE QUERY SUCCEEDED, whether or not records matched. A clean
|
|
1403
1642
|
\`stim logs --errors\` check requires exit code 0 AND no matching errors in
|
|
@@ -1427,18 +1666,23 @@ FLAGS
|
|
|
1427
1666
|
--tail <n> only the last n MATCHING records (applied after filtering,
|
|
1428
1667
|
so --level error --tail 5 is the last five ERRORS)
|
|
1429
1668
|
--errors errors and fatals since the last marker, from metro, client
|
|
1430
|
-
and build, plus confirmed native app-crash reports
|
|
1669
|
+
and build, plus confirmed native app-crash reports and the
|
|
1670
|
+
owned Chrome's device errors (platform web: failed
|
|
1671
|
+
requests, browser errors).
|
|
1431
1672
|
Capped at 20 printed records.
|
|
1432
1673
|
--follow keep streaming until interrupted (Ctrl+C is exit 0)
|
|
1433
1674
|
--json the raw records, one per line, so stdout is valid NDJSON.
|
|
1434
1675
|
ZERO matches is ZERO bytes on stdout (an empty NDJSON
|
|
1435
1676
|
stream), exit 0 -- parse stdout line by line, never as one
|
|
1436
1677
|
JSON document. The "No matching log records" note is human
|
|
1437
|
-
mode only, on stderr.
|
|
1678
|
+
mode only, on stderr. With --errors, an Expo error record
|
|
1679
|
+
also carries context (see THE RECORD).
|
|
1438
1680
|
|
|
1439
1681
|
--ERRORS, PRECISELY
|
|
1440
1682
|
Level error or fatal, from metro, client and build, plus device records with
|
|
1441
|
-
event native_crash (app/device/time-correlated OS reports or fatal app console output)
|
|
1683
|
+
event native_crash (app/device/time-correlated OS reports or fatal app console output)
|
|
1684
|
+
and device records with platform web (the owned page's failed requests and
|
|
1685
|
+
browser errors, from stim web), timestamped after the
|
|
1442
1686
|
marker that closes their window. Three rules, and a field test
|
|
1443
1687
|
caught all three wrong at once -- it returned 3,004 iOS syslog lines on a
|
|
1444
1688
|
healthy app while hiding a real startup crash.
|
|
@@ -1447,7 +1691,10 @@ FLAGS
|
|
|
1447
1691
|
\`simctl log stream\` is predicated on the app's PROCESS, and inside that
|
|
1448
1692
|
process Apple's frameworks log thousands of Error-typed lines (nw_socket,
|
|
1449
1693
|
SecTrust, WebKit, CoreUI) that have nothing to do with your app. The proven
|
|
1450
|
-
ones are demoted to info by the collector
|
|
1694
|
+
ones are demoted to info by the collector, and iOS main-thread
|
|
1695
|
+
"Synchronous URL loading" performance diagnostics (Expo icons served by
|
|
1696
|
+
Metro raise them) to warn, so a launch does not count them as app errors;
|
|
1697
|
+
the scope rule covers the rest.
|
|
1451
1698
|
The metro stream carries exactly one demotion of its own, and it is Stim's
|
|
1452
1699
|
doing: the dev-client deep link \`ios\`/\`android\` open to wire the app to
|
|
1453
1700
|
your port arrives inside the app as a link, and React Navigation logs at
|
|
@@ -1473,8 +1720,15 @@ FLAGS
|
|
|
1473
1720
|
errors are reported -- and nothing else. A failed attempt's own summary
|
|
1474
1721
|
and details land at or after its marker, so they stay reported.
|
|
1475
1722
|
a LAUNCH marker (src build, written before \`ios\` / \`android\` attempts
|
|
1476
|
-
launch) resets EVERYTHING
|
|
1477
|
-
native crash is not hidden by a marker written
|
|
1723
|
+
launch) resets EVERYTHING except the web page's records. It precedes the
|
|
1724
|
+
tool call so an immediate native crash is not hidden by a marker written
|
|
1725
|
+
after the process died.
|
|
1726
|
+
a PAGE-LOAD marker (the web_navigation record \`stim web\` writes for each
|
|
1727
|
+
load of the page's top-level document) resets only the page's records,
|
|
1728
|
+
those with platform web. It is written when the load starts, so a
|
|
1729
|
+
failure logged in the same millisecond belongs to that load, and so does
|
|
1730
|
+
anything the old page logs before it is replaced. Until the first page
|
|
1731
|
+
load is logged, the page's records follow the launch windows.
|
|
1478
1732
|
A finished bundle is not evidence that the app which loaded it is fine.
|
|
1479
1733
|
In the field case the app threw at 16:03:54 and Metro wrote its marker at
|
|
1480
1734
|
16:03:55, one second later, because the bundler finishes accounting for a
|
|
@@ -1495,11 +1749,18 @@ FLAGS
|
|
|
1495
1749
|
not stack depth. For untouched captured records use:
|
|
1496
1750
|
stim logs --source all --json
|
|
1497
1751
|
Neither form can restore text the runtime truncated before capture.
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1752
|
+
With --errors, an Expo error includes the code frame and stack lines Expo
|
|
1753
|
+
printed after it, in human and --json output, with or without --follow.
|
|
1754
|
+
Stim's own Metro records that land between those lines, such as bundle
|
|
1755
|
+
responses, do not cut the stack short. Human output joins the lines to the
|
|
1756
|
+
message. --json leaves msg as captured and adds them to the error record as
|
|
1757
|
+
a context array of strings; each record is still one line. --follow holds an
|
|
1758
|
+
Expo error until a poll, about every 500 ms, adds no more of its lines, so
|
|
1759
|
+
it can print up to about a second after Expo does. Non-follow human output
|
|
1760
|
+
also shows bare React Native symbolication as separate context, because
|
|
1761
|
+
Metro does not provide an error correlation identifier. Context never
|
|
1762
|
+
changes the error count or adds records to --json. --json is never capped,
|
|
1763
|
+
and neither is an explicit --tail.
|
|
1503
1764
|
|
|
1504
1765
|
In --follow mode the marker window is dropped -- every error arriving from
|
|
1505
1766
|
then on is by definition after the last marker seen.
|
|
@@ -1521,6 +1782,10 @@ THE RECORD
|
|
|
1521
1782
|
A collector_clock warning then says timestamps retain device time.
|
|
1522
1783
|
raw true when the level was inferred from a line of text rather than
|
|
1523
1784
|
reported by the producer (every expo-child record)
|
|
1785
|
+
context --errors --json only: the code frame and stack lines Expo
|
|
1786
|
+
printed after this error, as an array of strings. Absent when
|
|
1787
|
+
there are none. Stim adds it at query time; it is not in the
|
|
1788
|
+
log files.
|
|
1524
1789
|
|
|
1525
1790
|
WHAT WRITES WHAT
|
|
1526
1791
|
metro.ndjson the bundler, in both supervisor modes
|
|
@@ -1536,7 +1801,8 @@ WHAT WRITES WHAT
|
|
|
1536
1801
|
is where a native crash that never reached JS shows up
|
|
1537
1802
|
-- and, on iOS, where every Apple framework running in
|
|
1538
1803
|
the app's process also logs. The proven noise sources
|
|
1539
|
-
are recorded at info rather than error
|
|
1804
|
+
are recorded at info rather than error (Synchronous
|
|
1805
|
+
URL loading diagnostics at warn); the rest is why
|
|
1540
1806
|
--errors leaves this source out unless asked. A VERIFIED
|
|
1541
1807
|
LAUNCH counts these records and prints one line:
|
|
1542
1808
|
|
|
@@ -1798,11 +2064,17 @@ Branch on the code, never on the message.`,
|
|
|
1798
2064
|
the source checkout, then warm again.`
|
|
1799
2065
|
},
|
|
1800
2066
|
STIM_BUILD_FAILED: {
|
|
1801
|
-
summary: "xcodebuild or gradle failed; the
|
|
2067
|
+
summary: "xcodebuild or gradle failed; the Android missing-SDK and APK refusals; a damaged compilation-cache object",
|
|
1802
2068
|
body: () => `STIM_BUILD_FAILED
|
|
1803
2069
|
xcodebuild or gradle failed. The EXTRACTED diagnostics are printed (capped),
|
|
1804
2070
|
not the transcript. Read the log path on the next line for the rest.
|
|
1805
|
-
|
|
2071
|
+
Three Android refusals share this code without gradle itself failing:
|
|
2072
|
+
- NO ANDROID SDK, before gradle starts: nothing exists at the SDK path
|
|
2073
|
+
Stim resolves (ANDROID_HOME, else ANDROID_SDK_ROOT, else the default
|
|
2074
|
+
location), and there is no android/local.properties. Set ANDROID_HOME to the SDK or write sdk.dir
|
|
2075
|
+
into android/local.properties; \`stim doctor --platform android\` reports
|
|
2076
|
+
the same condition. When the SDK is found and neither variable is set,
|
|
2077
|
+
Stim passes its path to gradle as ANDROID_HOME.
|
|
1806
2078
|
- MORE THAN ONE debug APK under android/app/build/outputs/apk and nothing
|
|
1807
2079
|
configured to pick one (a project with product flavors, several flavors
|
|
1808
2080
|
already built). Stim will not guess which flavor to install: the
|
|
@@ -2305,6 +2577,12 @@ so a Debug run on one is wired to a LAN origin instead of localhost.`,
|
|
|
2305
2577
|
\`gc --delete\`) and run \`stim ios\` again to create the requested model.
|
|
2306
2578
|
That loses the old sim's app state.
|
|
2307
2579
|
|
|
2580
|
+
"this project's sim runs iOS X, but --runtime asked for Y"
|
|
2581
|
+
The same refusal for an explicit \`--runtime\` that names another installed
|
|
2582
|
+
iOS version than the project's sim runs. Reap the sim the same way, or pass
|
|
2583
|
+
\`--slot <name>\` to create one on the requested runtime beside it. The
|
|
2584
|
+
ios.runtime setting alone never refuses; it applies at creation.
|
|
2585
|
+
|
|
2308
2586
|
"this project's emulator uses device profile X, but Y was requested"
|
|
2309
2587
|
The Android counterpart, from \`--device-profile\` or android.deviceProfile.
|
|
2310
2588
|
Reap the AVD the same way, or pass \`--slot <name>\` to create the requested
|
|
@@ -2485,10 +2763,11 @@ so a Debug run on one is wired to a LAN origin instead of localhost.`,
|
|
|
2485
2763
|
metro.publicUrl for an existing endpoint.`
|
|
2486
2764
|
},
|
|
2487
2765
|
STIM_RELOAD_AMBIGUOUS: {
|
|
2488
|
-
summary: "
|
|
2489
|
-
separator: "--- RELOAD CODES (`stim reload [ios|android]`) ---",
|
|
2766
|
+
summary: "more than one owned app or the owned Chrome is live; name the platform",
|
|
2767
|
+
separator: "--- RELOAD CODES (`stim reload [ios|android|web]`) ---",
|
|
2490
2768
|
body: () => `STIM_RELOAD_AMBIGUOUS
|
|
2491
|
-
|
|
2769
|
+
More than one of the owned iOS app, Android app and Chrome page is live.
|
|
2770
|
+
Name ios, android or web; Stim never guesses.`
|
|
2492
2771
|
},
|
|
2493
2772
|
STIM_RELOAD_RELEASE: {
|
|
2494
2773
|
summary: "the live app has embedded JS; run a Debug build first",
|
|
@@ -2501,7 +2780,10 @@ so a Debug run on one is wired to a LAN origin instead of localhost.`,
|
|
|
2501
2780
|
aliases: ["STIM_RELOAD_UNOWNED", "STIM_RELOAD_PROBE_FAILED"],
|
|
2502
2781
|
body: () => `STIM_RELOAD_STOPPED / STIM_RELOAD_UNOWNED / STIM_RELOAD_PROBE_FAILED
|
|
2503
2782
|
The recorded app is gone, its exact device is not live and owned by this
|
|
2504
|
-
workspace, or simctl/adb could not prove the process exists.
|
|
2783
|
+
workspace, or simctl/adb could not prove the process exists. For web,
|
|
2784
|
+
STOPPED means no owned Chrome is running (run stim web) and PROBE_FAILED
|
|
2785
|
+
that its identity could not be verified. A bare reload picks the Chrome page
|
|
2786
|
+
only when no native launch is recorded. No launch or
|
|
2505
2787
|
device lifecycle action is taken; follow the printed platform-command or
|
|
2506
2788
|
process-probe remedy.`
|
|
2507
2789
|
},
|
|
@@ -2533,6 +2815,51 @@ so a Debug run on one is wired to a LAN origin instead of localhost.`,
|
|
|
2533
2815
|
MORE THAN ONE MATCHING PEER IS NOT A FAILURE. A workspace Metro serves one
|
|
2534
2816
|
app, so several matching peers are that app on several devices. Stim reloads
|
|
2535
2817
|
every one of them and reports the count in the facts as targets.`
|
|
2818
|
+
},
|
|
2819
|
+
STIM_WEB_NO_CHROME: {
|
|
2820
|
+
summary: "stim web found no installed Chrome or Chromium",
|
|
2821
|
+
separator: "--- WEB CODES (`stim web`) ---",
|
|
2822
|
+
body: () => `STIM_WEB_NO_CHROME
|
|
2823
|
+
stim web drives the installed Google Chrome (or Chromium) with a profile
|
|
2824
|
+
Stim creates. It looks in /Applications and ~/Applications on macOS, in
|
|
2825
|
+
Program Files on Windows, and for google-chrome or chromium on PATH. Stim
|
|
2826
|
+
never installs a browser. Install Chrome, then run stim doctor.`
|
|
2827
|
+
},
|
|
2828
|
+
STIM_WEB_NO_URL: {
|
|
2829
|
+
summary: "not an Expo app and web.url is unset, so Stim does not know which page to open",
|
|
2830
|
+
body: () => `STIM_WEB_NO_URL
|
|
2831
|
+
Only Expo serves web from Metro, so for any other app Stim needs web.url.
|
|
2832
|
+
stim web never starts a web server, for any framework. Start yours on a
|
|
2833
|
+
named port and point web.url at it:
|
|
2834
|
+
pnpm exec vite --port "$(stim ports get web)" --strictPort
|
|
2835
|
+
stim settings set web.url 'http://localhost:{port:web}/' --scope workspace
|
|
2836
|
+
See stim guide web.`
|
|
2837
|
+
},
|
|
2838
|
+
STIM_WEB_DEPS_MISSING: {
|
|
2839
|
+
summary: "an Expo app without react-native-web cannot render on the web",
|
|
2840
|
+
body: () => `STIM_WEB_DEPS_MISSING
|
|
2841
|
+
The Expo app does not resolve react-native-web, so Metro cannot build a web
|
|
2842
|
+
bundle. Install the web dependencies, start Metro, then run stim web again:
|
|
2843
|
+
npx expo install react-dom react-native-web @expo/metro-runtime
|
|
2844
|
+
stim start`
|
|
2845
|
+
},
|
|
2846
|
+
STIM_WEB_BROWSER_HELD: {
|
|
2847
|
+
summary: "the previous owned Chrome could not be stopped or verified; it was left running",
|
|
2848
|
+
body: () => `STIM_WEB_BROWSER_HELD
|
|
2849
|
+
stim web replaces the workspace's owned Chrome when its options change, and
|
|
2850
|
+
the previous one could not be stopped: its supervisor or Chrome did not
|
|
2851
|
+
exit, or their process identities could not be verified. Stim never signals
|
|
2852
|
+
a process it cannot verify. Check stim status for browser-unverified, then
|
|
2853
|
+
follow stim guide errors teardown.`
|
|
2854
|
+
},
|
|
2855
|
+
STIM_WEB_LAUNCH_FAILED: {
|
|
2856
|
+
summary: "the owned Chrome did not start or did not open DevTools on its reserved port",
|
|
2857
|
+
body: () => `STIM_WEB_LAUNCH_FAILED
|
|
2858
|
+
The browser supervisor exited before Chrome answered on its reserved
|
|
2859
|
+
DevTools port. The remedy names the supervisor log; web.ndjson carries the
|
|
2860
|
+
failure as web_browser_failed, and browser.log holds Chrome's own output.
|
|
2861
|
+
A port another process bound first also lands here: run stim web again to
|
|
2862
|
+
reserve a fresh one.`
|
|
2536
2863
|
},
|
|
2537
2864
|
STIM_WORKTREE_REMOVAL_IN_PROGRESS: {
|
|
2538
2865
|
summary: "a managed remote start found worktree remove holding the lock; wait, then rerun",
|
|
@@ -2727,8 +3054,10 @@ captured" (in metro.ndjson, bare RN)
|
|
|
2727
3054
|
"Timed out waiting for the lock at <path>."
|
|
2728
3055
|
Short directory locks serialize writes to config, workspace state, device
|
|
2729
3056
|
leases, ownership records, metadata, and cache manifests. The path identifies
|
|
2730
|
-
the lock. These locks wait up to 12s and never expire based on age.
|
|
2731
|
-
|
|
3057
|
+
the lock. These locks wait up to 12s and never expire based on age. When
|
|
3058
|
+
another Stim command holds the lock, the message says so: wait for it and
|
|
3059
|
+
retry. A failed marker write, such as ENOSPC on a full disk, removes the
|
|
3060
|
+
directory it just created before Stim reports the write error.
|
|
2732
3061
|
Short locks use the same process-identity claims as long operations, stored
|
|
2733
3062
|
beside the visible directory at <path>.claims. An opaque marker in the visible
|
|
2734
3063
|
directory also excludes older Stim versions. Only the exclusive claim holder
|
|
@@ -2738,9 +3067,12 @@ captured" (in metro.ndjson, bare RN)
|
|
|
2738
3067
|
STIM_CLAIM_REFUSED and names the claim to inspect; an unavailable native
|
|
2739
3068
|
identity reports STIM_CLAIM_UNAVAILABLE without running the protected work.
|
|
2740
3069
|
Older lock directories have no process identity. A visible directory left
|
|
2741
|
-
empty before marker publication
|
|
2742
|
-
|
|
2743
|
-
|
|
3070
|
+
empty before marker publication (a process killed between creating it and
|
|
3071
|
+
writing its marker) or during final removal also cannot prove it is free.
|
|
3072
|
+
These paths still time out, and the message says no current Stim holds the
|
|
3073
|
+
lock and ends with \`rm -rf '<path>'\`. An older Stim version may still be
|
|
3074
|
+
using it: if none is running, remove the named directory with that command.
|
|
3075
|
+
Standalone Metro and Expo cache packages use the
|
|
2744
3076
|
same core protocol and do not require the Stim CLI.`
|
|
2745
3077
|
},
|
|
2746
3078
|
teardown: {
|
|
@@ -2777,7 +3109,23 @@ the supervisor could not be verified" (stop)
|
|
|
2777
3109
|
"teardown failed: <reason>"
|
|
2778
3110
|
Stim could not release the owned device and keeps its record for a retry.
|
|
2779
3111
|
\`worktree remove\` exits 1 without removing the worktree while the device is
|
|
2780
|
-
still tracked. Fix the reported cause and re-run
|
|
3112
|
+
still tracked. Fix the reported cause and re-run.
|
|
3113
|
+
|
|
3114
|
+
"teardown failed: Owned AVD <name> did not finish shutting down after <n>s:
|
|
3115
|
+
emulator process <pid> is still running"
|
|
3116
|
+
An owned emulator counts as stopped only when no process launched for its
|
|
3117
|
+
AVD (\`qemu-system-*\` or \`emulator\` with \`-avd <name>\`) is left in the
|
|
3118
|
+
process table. Stim asks it to quit with \`adb emu kill\` and waits 60s.
|
|
3119
|
+
Then it sends SIGTERM and, 5s later, SIGKILL. When adb cannot reach the
|
|
3120
|
+
emulator, Stim sends SIGTERM at once and waits 60s before SIGKILL. It signals
|
|
3121
|
+
only a pid whose command line names the AVD and whose process identity,
|
|
3122
|
+
recorded before shutdown, still matches. "(Stim could not verify the
|
|
3123
|
+
identity of <pid>, so it sent no signal)" means that identity could not be
|
|
3124
|
+
read or no longer matches. Check \`ps -p <pid> -o command=\`, stop the
|
|
3125
|
+
process yourself, then re-run the command or \`gc --delete\`. Windows has
|
|
3126
|
+
no process-table check and Stim signals nothing there: it waits for the pid
|
|
3127
|
+
in the AVD's process lock after \`adb emu kill\`, and refuses at once when
|
|
3128
|
+
adb cannot reach the emulator.`
|
|
2781
3129
|
},
|
|
2782
3130
|
remove: {
|
|
2783
3131
|
summary: "worktree remove refused a dirty tree: what it restores itself and what --force discards",
|
|
@@ -3186,7 +3534,7 @@ ANDROID EMULATOR RESTARTS
|
|
|
3186
3534
|
display until it next boots.
|
|
3187
3535
|
|
|
3188
3536
|
DESTRUCTIVE COMMANDS -- ask the user first
|
|
3189
|
-
gc --delete deletes orphaned devices Stim created, tens of GB
|
|
3537
|
+
gc --delete deletes orphaned devices this Stim home created, tens of GB
|
|
3190
3538
|
gc --delete --cache all empties the shared build caches every project uses
|
|
3191
3539
|
gc --delete --cache <name>
|
|
3192
3540
|
empties only the caches that carry <name>
|
|
@@ -3239,8 +3587,10 @@ WAITING FOR A CHANGE
|
|
|
3239
3587
|
status payload per line: one at once, then one each time the payload
|
|
3240
3588
|
changes, never two identical ones in a row. It reacts to Stim state files,
|
|
3241
3589
|
the EAS session ledger, adb device arrivals and departures, and simulator
|
|
3242
|
-
state, and recomputes every 30 seconds as a fallback.
|
|
3243
|
-
|
|
3590
|
+
state, and recomputes every 30 seconds as a fallback. A log append updates
|
|
3591
|
+
only the log error count and device activity, no sooner than 15 seconds
|
|
3592
|
+
after the previous refresh. Ctrl+C, SIGTERM or closing its stdout ends it
|
|
3593
|
+
with exit 0. Without --json it reprints the human view on change.`,
|
|
3244
3594
|
sections: {
|
|
3245
3595
|
eas: {
|
|
3246
3596
|
summary: "download a matching EAS development build; explicit profile, costs, cache and miss remedies",
|
|
@@ -3968,7 +4318,10 @@ THE BUILD CACHE HAS THREE LEVELS
|
|
|
3968
4318
|
records the reason as lastBuilds.<platform>.missReason in status --json
|
|
3969
4319
|
(see \`guide facts status\`), and writes the changed sources (capped at 20
|
|
3970
4320
|
names) to the build log as a fingerprint_diff record. With no baseline the
|
|
3971
|
-
line says there was nothing to compare with.
|
|
4321
|
+
line says there was nothing to compare with. status --json also lists each
|
|
4322
|
+
platform's last 10 runs in builds.<platform>, with their result, cache
|
|
4323
|
+
outcome, miss reason, phase timings and diagnostics, so a hit that turned
|
|
4324
|
+
into a miss shows which run changed what.
|
|
3972
4325
|
|
|
3973
4326
|
THE KEY CAN MOVE MID-RUN, and the run says so in two facts rather than two
|
|
3974
4327
|
explanations. \`expo prebuild\` and \`pod install\` rewrite fingerprinted
|
|
@@ -4005,11 +4358,28 @@ THE BUILD CACHE HAS THREE LEVELS
|
|
|
4005
4358
|
\`expo prebuild --clean\` yourself or delete the directory so the next build
|
|
4006
4359
|
regenerates it.
|
|
4007
4360
|
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4361
|
+
Both platforms fingerprint once more after the compile. A change the build
|
|
4362
|
+
itself makes to a fingerprinted file under node_modules/ or the native
|
|
4363
|
+
directory moves the key the same way, printed as \`(after Gradle)\` or
|
|
4364
|
+
\`(after xcodebuild)\`. Any other input that changed while the build ran
|
|
4365
|
+
-- the app config or a config plugin at any point after the first lookup,
|
|
4366
|
+
or any other source during the compile -- means the artifact may not match
|
|
4367
|
+
the key, so Stim installs what it built and stores nothing. The one config
|
|
4368
|
+
change exempted is the ios.bundleIdentifier or android.package that
|
|
4369
|
+
\`expo prebuild\` adds to a static app.json that lacks one:
|
|
4370
|
+
|
|
4371
|
+
fingerprint expoConfig changed while the build ran, so the artifact may not match its key; the build will be installed but not cached
|
|
4372
|
+
|
|
4373
|
+
The prebuild record never takes a hash that includes the edit, so the next
|
|
4374
|
+
run regenerates a CNG directory from the edited config and compiles it
|
|
4375
|
+
instead of reusing the stale one. An edit under node_modules/ or the native
|
|
4376
|
+
directory during the compile cannot be told apart from the build's own
|
|
4377
|
+
writes and moves the key. Stim also skips storing when the fingerprint
|
|
4378
|
+
after prebuild, pod install or the compile cannot be computed. In every
|
|
4379
|
+
skipped case nothing goes to the local cache, the cache provider or a
|
|
4380
|
+
remote upload, fingerprint and cacheKey are null in the result and
|
|
4381
|
+
lastBuild, and the old key is not reused. These null fields mean
|
|
4382
|
+
unavailable cache information, not an install failure.
|
|
4013
4383
|
|
|
4014
4384
|
WHAT MAKES THE CACHE ACTUALLY HIT: .FINGERPRINTIGNORE
|
|
4015
4385
|
Every entry is keyed on what the tree hashes, so two workspaces share an
|
|
@@ -4430,14 +4800,14 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
|
|
|
4430
4800
|
(\`iOS 26.5\`), exactly; no prefix or suffix matches.
|
|
4431
4801
|
|
|
4432
4802
|
These flags describe a device that does not exist yet. When this workspace
|
|
4433
|
-
ALREADY owns a simulator and \`--device-type\` names a different model,
|
|
4434
|
-
Stim refuses rather than silently
|
|
4435
|
-
sim with \`stim worktree remove\`
|
|
4436
|
-
\`stim ios\` again to create the
|
|
4437
|
-
the same for an AVD of another
|
|
4438
|
-
one its own \`--slot\`.
|
|
4439
|
-
android.systemImage settings apply at creation only, so an
|
|
4440
|
-
keeps the version it was made with. An explicit \`--system-image\` that
|
|
4803
|
+
ALREADY owns a simulator and \`--device-type\` names a different model, or
|
|
4804
|
+
\`--runtime\` a different iOS version, Stim refuses rather than silently
|
|
4805
|
+
booting the wrong one: reap the current sim with \`stim worktree remove\`
|
|
4806
|
+
(or \`stim gc --delete\`), then run \`stim ios\` again to create the
|
|
4807
|
+
requested one. \`--device-profile\` does the same for an AVD of another
|
|
4808
|
+
profile. To keep both devices, give the new one its own \`--slot\`. The
|
|
4809
|
+
ios.runtime and android.systemImage settings apply at creation only, so an
|
|
4810
|
+
existing device keeps the version it was made with. An explicit \`--system-image\` that
|
|
4441
4811
|
names another image than this workspace's AVD refuses the same way, unless
|
|
4442
4812
|
that AVD never finished a boot (for example one made from an image its
|
|
4443
4813
|
profile cannot boot): Stim then deletes it through owned-device teardown and
|
|
@@ -4817,6 +5187,8 @@ HOST MEMORY PRESSURE AND STALLED SIMULATORS
|
|
|
4817
5187
|
and takes at most 10 seconds. A timeout is not proof of an app crash or OOM.
|
|
4818
5188
|
During boot, Stim reports elapsed time, the simulator name, last boot output,
|
|
4819
5189
|
current pressure and the highest observed pressure roughly every 15 seconds.
|
|
5190
|
+
Warning or critical pressure adds recovery advice to the first report at
|
|
5191
|
+
that level; later reports repeat it only after the level changes.
|
|
4820
5192
|
Failure diagnostics retain the highest pressure and unavailable sample count;
|
|
4821
5193
|
they do not infer the cause of a timeout. Monitoring stops when boot ends.
|
|
4822
5194
|
Monitoring and timeout handling are best-effort: synchronous CLI work can
|
|
@@ -4855,12 +5227,13 @@ WHAT RECLAIMS AN OWNED DEVICE
|
|
|
4855
5227
|
stim worktree remove parks eligible owned simulators and emulators
|
|
4856
5228
|
(\`guide lifecycle pool\`); deletes them when
|
|
4857
5229
|
parking is disabled or their setup cannot be verified
|
|
4858
|
-
stim gc --delete sweeps devices Stim created that no project
|
|
5230
|
+
stim gc --delete sweeps devices this Stim home created that no project
|
|
4859
5231
|
references (\`guide cleanup gc\`), clears
|
|
4860
5232
|
verified parked simulators and emulators, and
|
|
4861
5233
|
runs \`stim worktree remove\` on every clean,
|
|
4862
|
-
Stim-managed linked worktree whose branch is merged
|
|
4863
|
-
|
|
5234
|
+
Stim-managed linked worktree whose branch is merged,
|
|
5235
|
+
or whose pull request was merged or closed, and
|
|
5236
|
+
that shows no activity within
|
|
4864
5237
|
gc.worktreeGraceMinutes
|
|
4865
5238
|
stim gc --delete --older-than <days>
|
|
4866
5239
|
also reaps the device of a workspace no Stim
|
|
@@ -4877,8 +5250,9 @@ WHAT RECLAIMS AN OWNED DEVICE
|
|
|
4877
5250
|
|
|
4878
5251
|
\`worktree remove\` and \`gc --delete\` are the only two commands that delete;
|
|
4879
5252
|
\`gc --delete\` deletes worktrees only through \`worktree remove\`. \`gc
|
|
4880
|
-
--delete\` also clears workspace build outputs
|
|
4881
|
-
orphaned workspace directories, never a
|
|
5253
|
+
--delete\` also clears workspace build outputs, trims oversized workspace logs
|
|
5254
|
+
(\`guide cleanup disk\`) and removes orphaned workspace directories, never a
|
|
5255
|
+
checkout. \`stim stop\` shuts a device
|
|
4882
5256
|
DOWN and leaves it assigned, which is what makes returning to a branch cost a
|
|
4883
5257
|
boot rather than a create, a provision and a reinstall.
|
|
4884
5258
|
|
|
@@ -4936,7 +5310,8 @@ SWEEPING FINISHED WORKTREES
|
|
|
4936
5310
|
Every \`gc\` without --cache looks at every registered project root and
|
|
4937
5311
|
every workspace.json root, grouped by git worktree, and reports each linked
|
|
4938
5312
|
worktree with the reason it is removed or kept. A worktree is finished when
|
|
4939
|
-
its branch is merged into the default branch
|
|
5313
|
+
its branch is merged into the default branch, or its pull request was
|
|
5314
|
+
merged or closed (PULL REQUESTS below). \`--worktrees\` also removes
|
|
4940
5315
|
one that is idle: no recorded use for --older-than days, 7 without it; a
|
|
4941
5316
|
worktree whose last use is unknown is kept. Both need the same clean state;
|
|
4942
5317
|
a worktree is kept when it is the source checkout, bare, locked, in use,
|
|
@@ -4958,7 +5333,8 @@ SWEEPING FINISHED WORKTREES
|
|
|
4958
5333
|
gc.worktreeGraceMinutes (120 by default, \`guide settings\`) have passed
|
|
4959
5334
|
since the latest of: a write to its git index, HEAD or HEAD reflog, a write
|
|
4960
5335
|
to its Stim workspace state or log files, and, for a merged branch, the
|
|
4961
|
-
committer date of the commit that brought it into the default branch
|
|
5336
|
+
committer date of the commit that brought it into the default branch, or
|
|
5337
|
+
the time its pull request was merged or closed. That
|
|
4962
5338
|
window is when an agent that just merged runs \`stim stop\` and \`stim
|
|
4963
5339
|
worktree remove\` itself. The reason is recent-activity, and the report
|
|
4964
5340
|
and the JSON eligibleAt field say when it becomes removable. When that
|
|
@@ -4977,16 +5353,33 @@ SWEEPING FINISHED WORKTREES
|
|
|
4977
5353
|
commit on the default branch (a rebase merge), or its whole diff since the
|
|
4978
5354
|
merge base has the same verbatim patch id as a commit there, compared on
|
|
4979
5355
|
the files the branch changes (a squash merge).
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
5356
|
+
From git alone, a squash merge whose content changed during the merge (a
|
|
5357
|
+
conflict resolution, a suggested edit, even whitespace) does not match, and
|
|
5358
|
+
neither does a fast-forwarded branch or a stacked pull request merged after
|
|
5359
|
+
the one below it; the pull request check covers those. When origin/HEAD is not set, the fetch fails, or git
|
|
4984
5360
|
cannot answer, the state is unknown and never counts as merged (reason
|
|
4985
5361
|
merge-unknown, with the remedy); with --worktrees an idle worktree is still
|
|
4986
5362
|
removed. A squash- or rebase-merged branch whose upstream is gone (deleted
|
|
4987
5363
|
after the merge and pruned locally) has commits only it reaches; they do
|
|
4988
5364
|
not block removal, because their change is on the default branch, and the
|
|
4989
5365
|
branch is kept.
|
|
5366
|
+
|
|
5367
|
+
PULL REQUESTS: gc runs one \`gh api graphql\` query per repository that
|
|
5368
|
+
asks for the 20 newest pull requests of each linked worktree's branch, as
|
|
5369
|
+
\`gh pr list --head <branch> --state all\` would, and for each worktree
|
|
5370
|
+
takes the pull request whose head is HEAD, else one whose head contains
|
|
5371
|
+
HEAD. A pull request whose head HEAD is past ("PR #12 merged, and HEAD has
|
|
5372
|
+
commits it does not"), one unrelated to HEAD (an older use of the branch
|
|
5373
|
+
name), and one from a fork do not count. A merged or closed one makes the worktree finished
|
|
5374
|
+
under the same clean state. Merged, its commits are kept on GitHub, so local
|
|
5375
|
+
commits whose remote branch was deleted do not block removal. Closed, they
|
|
5376
|
+
do: a closed pull request whose remote branch is gone keeps the worktree as
|
|
5377
|
+
unpushed. An open pull request never makes a worktree finished. When gh is
|
|
5378
|
+
not installed, not signed in, or fails, the JSON pullRequestUnknown field
|
|
5379
|
+
and the report say why, and gc judges from git alone. A detached HEAD is
|
|
5380
|
+
not looked up. \`stim worktree remove\` makes the same check when
|
|
5381
|
+
local-only commits alone would refuse the removal, and accepts a merged
|
|
5382
|
+
pull request whose head is or contains HEAD.
|
|
4990
5383
|
stim gc # report merged worktrees
|
|
4991
5384
|
stim gc --delete # remove them
|
|
4992
5385
|
stim gc --delete --worktrees --older-than 3 # also the clean idle ones
|
|
@@ -5055,15 +5448,16 @@ it. A record is what makes the device findable again, so it outlives a failed
|
|
|
5055
5448
|
teardown rather than turning it into an orphan.
|
|
5056
5449
|
|
|
5057
5450
|
WHICH stim-* DEVICES gc DELETES
|
|
5058
|
-
A \`stim-\`
|
|
5059
|
-
|
|
5451
|
+
A \`stim-\` name is not proof that this Stim home made a device: every
|
|
5452
|
+
STIM_HOME names its devices the same way. gc deletes an unreferenced device
|
|
5453
|
+
only when this home created it: the device is listed in
|
|
5060
5454
|
$STIM_HOME/created-devices.json, where Stim records every simulator and AVD
|
|
5061
|
-
it creates, or it predates that ledger and
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
disk.dataPartition.size Stim writes. gc lists any other stim-* device under
|
|
5455
|
+
it creates, or it predates that ledger and this home's config records it in
|
|
5456
|
+
the device pool or in a project as owned. gc lists any other stim-* device,
|
|
5457
|
+
including those another STIM_HOME created, under
|
|
5065
5458
|
"Unrecognized stim-* devices" with the command that deletes it
|
|
5066
|
-
(\`xcrun simctl delete <udid
|
|
5459
|
+
(\`xcrun simctl delete <udid>\`, \`avdmanager delete avd -n <name>\`, or
|
|
5460
|
+
\`rm -rf <dir>\` for AVD data with no registration), and
|
|
5067
5461
|
never runs it. Boot, shutdown and teardown re-check ownership by the same
|
|
5068
5462
|
rule, so a device that stops matching is left alone.
|
|
5069
5463
|
|
|
@@ -5132,6 +5526,26 @@ THE MIRROR IMAGE: A STALE DEVICE RECORD
|
|
|
5132
5526
|
at simctl or avdmanager, and the project keeps its entry, its label and its
|
|
5133
5527
|
Metro port. The next \`ios\` / \`android\` creates a fresh owned device.
|
|
5134
5528
|
|
|
5529
|
+
The ledger of devices Stim created (created-devices.json) keeps a
|
|
5530
|
+
simulator's UDID after the simulator is deleted outside Stim. \`gc\`
|
|
5531
|
+
reports such UDIDs under "Stale device ledger entries" when a complete
|
|
5532
|
+
simctl listing, unavailable simulators included, does not show them, and
|
|
5533
|
+
\`gc --delete\` forgets them under the ledger lock. If the listing fails,
|
|
5534
|
+
nothing is reported or forgotten, and like the device sweep it is skipped
|
|
5535
|
+
without a config or under a scoped STIM_HOME. UDIDs are never reused, so a
|
|
5536
|
+
forgotten entry cannot belong to a later simulator.
|
|
5537
|
+
|
|
5538
|
+
Android ledger entries are AVD names, and names are reused: another
|
|
5539
|
+
STIM_HOME can later create an AVD with the same name. \`gc\` reports an
|
|
5540
|
+
AVD name as stale only when \`emulator -list-avds\` answered, the first AVD
|
|
5541
|
+
root exists (a missing one may be an unmounted volume), no AVD root holds
|
|
5542
|
+
<name>.ini or <name>.avd, and no unfinished setup reserves the name.
|
|
5543
|
+
\`gc --delete\` takes that AVD's claim, then re-checks and forgets the name
|
|
5544
|
+
under the config and ledger locks, so a setup in progress or an AVD
|
|
5545
|
+
recreated since the report keeps its entry. A name reused before \`gc\`
|
|
5546
|
+
runs still counts as this home's; run \`gc\` after deleting a Stim AVD by
|
|
5547
|
+
hand.
|
|
5548
|
+
|
|
5135
5549
|
THE ONE CASE GC WILL NOT REAP
|
|
5136
5550
|
If the config is gone entirely (deleted ~/.stim, or a throwaway
|
|
5137
5551
|
STIM_HOME), gc cannot tell your stale devices from another config's LIVE
|
|
@@ -5198,7 +5612,7 @@ THE ONE CASE GC WILL NOT REAP
|
|
|
5198
5612
|
Wall-clock timestamps and command names are not ownership proof.`
|
|
5199
5613
|
},
|
|
5200
5614
|
disk: {
|
|
5201
|
-
summary: "disk usage, workspace build outputs, AVD and build-log sizes, the data partition, trimming the shared caches",
|
|
5615
|
+
summary: "disk usage, workspace build outputs and logs, AVD and build-log sizes, the data partition, trimming the shared caches",
|
|
5202
5616
|
body: () => `DISK
|
|
5203
5617
|
Logs, state, pidfiles and Xcode DerivedData are under the global workspace
|
|
5204
5618
|
directory, and \`worktree remove\` reclaims them. \`gc --delete\` clears the
|
|
@@ -5214,12 +5628,16 @@ THE ONE CASE GC WILL NOT REAP
|
|
|
5214
5628
|
disabled. The first boot and a boot after the emulator, system image, or AVD
|
|
5215
5629
|
settings change are cold, while later supported boots load the one automatic
|
|
5216
5630
|
snapshot saved on exit. \`stop\` waits for the emulator process and, when
|
|
5217
|
-
enabled, the snapshot save to finish.
|
|
5631
|
+
enabled, the snapshot save to finish. An emulator that ignores \`adb emu
|
|
5632
|
+
kill\` or is unreachable over adb is signalled once its identity is verified;
|
|
5633
|
+
one that still runs fails the teardown and keeps its record (see \`stim guide
|
|
5634
|
+
errors teardown\`).
|
|
5218
5635
|
New owned AVDs default to an 8 GiB data partition, though project settings can
|
|
5219
5636
|
change it. When enabled, Quick Boot keeps one automatic snapshot until the AVD is
|
|
5220
5637
|
parked or deleted.
|
|
5221
5638
|
\`gc\` prints the on-disk size beside an orphaned or stale owned Android AVD
|
|
5222
|
-
when its content directory can be read
|
|
5639
|
+
when its content directory can be read, and beside an orphaned or stale
|
|
5640
|
+
owned simulator the data size simctl reports for it.
|
|
5223
5641
|
|
|
5224
5642
|
So are the logs, and one of them is not small: build-ios.ndjson /
|
|
5225
5643
|
build-android.ndjson hold the whole xcodebuild or gradle transcript at debug
|
|
@@ -5268,6 +5686,19 @@ WORKSPACE BUILD OUTPUTS
|
|
|
5268
5686
|
React Native 0.86 Swift does not use it (explicit modules are off), so that
|
|
5269
5687
|
build recompiles Swift.
|
|
5270
5688
|
|
|
5689
|
+
WORKSPACE LOGS
|
|
5690
|
+
\`gc\` reports the size of each workspace's logs/ (the workspaceLogs
|
|
5691
|
+
section of \`gc --json\`). metro.ndjson, client.ndjson and device.ndjson and
|
|
5692
|
+
their .1 generations rotate at 8 MiB (\`guide logs\`), but a file written by
|
|
5693
|
+
a Stim version before the cap can be hundreds of MB. \`gc --delete\` trims
|
|
5694
|
+
each of those six files that is over 16 MiB to its newest 8 MiB, cut at a
|
|
5695
|
+
record boundary; a file just past 8 MiB is normal rotation and stays.
|
|
5696
|
+
\`--older-than\` does not limit it. It skips a workspace that is in use (a
|
|
5697
|
+
dev server, a native run, a build or a held tunnel) or that has a device
|
|
5698
|
+
log collector recorded; \`stim stop\`
|
|
5699
|
+
stops the collector. Build transcripts keep the whole run and are never
|
|
5700
|
+
trimmed, and nothing else under logs/ is touched.
|
|
5701
|
+
|
|
5271
5702
|
SHARED BUILD CACHES
|
|
5272
5703
|
The caches that make a second workspace fast are alive by design and never
|
|
5273
5704
|
included in a plain \`gc --delete\`. Every \`gc\` run reports them anyway,
|
|
@@ -5316,7 +5747,9 @@ shape, before anything is written. Writes to the machine file take its lock
|
|
|
5316
5747
|
and replace it atomically; a committed write keeps the file's other keys and
|
|
5317
5748
|
indentation. Run \`stim settings\` from the app directory: workspace and
|
|
5318
5749
|
committed resolve from the nearest package.json, repo from its Git
|
|
5319
|
-
repository.
|
|
5750
|
+
repository. From a monorepo web package that resolves to its worktree's app
|
|
5751
|
+
(see stim guide ports), workspace and committed are that app's entry and
|
|
5752
|
+
.stim.json. worktree.exclude and worktree.defaultBranch are read only from
|
|
5320
5753
|
the repo layer and the repository root's .stim.json.
|
|
5321
5754
|
|
|
5322
5755
|
android.keystorePassword is sensitive: its value prints as ******** in every
|
|
@@ -5566,6 +5999,21 @@ ${ANDROID_AVD_CONFIG_HELP.map((line) => ` ${line}`).joi
|
|
|
5566
5999
|
driven. Read
|
|
5567
6000
|
when \`start\` spawns the supervisor; see
|
|
5568
6001
|
\`guide metro\`.
|
|
6002
|
+
web.url the page \`stim web\` opens in the owned Chrome, an
|
|
6003
|
+
http:// or https:// URL. {port:<label>} becomes the
|
|
6004
|
+
workspace's named port (allocated like \`stim ports
|
|
6005
|
+
get <label>\`), and {port:metro} its Metro port.
|
|
6006
|
+
Unset, Expo apps open http://localhost:<metroPort>/
|
|
6007
|
+
and other apps refuse until it is set. Example:
|
|
6008
|
+
http://localhost:{port:web}/apps/groups/.
|
|
6009
|
+
See \`guide web\`.
|
|
6010
|
+
web.ignoreCertificateErrors
|
|
6011
|
+
true starts the owned Chrome with
|
|
6012
|
+
--ignore-certificate-errors, for dev servers with
|
|
6013
|
+
self-signed certificates (default false). It applies
|
|
6014
|
+
only to Stim's own profile, never to your browser.
|
|
6015
|
+
web.viewport desktop (default, 1280x800) or phone (390x844 at 3x
|
|
6016
|
+
with touch events) for the owned Chrome page.
|
|
5569
6017
|
worktree.exclude ignored-path skip list for worktree warm. Settings
|
|
5570
6018
|
come from the source checkout's repository-root
|
|
5571
6019
|
.stim.json. A nonempty .worktreeexclude in the source
|
|
@@ -5608,7 +6056,7 @@ ${ANDROID_AVD_CONFIG_HELP.map((line) => ` ${line}`).joi
|
|
|
5608
6056
|
them from the environment or the machine layers.
|
|
5609
6057
|
|
|
5610
6058
|
Each setting takes its documented type: string, array of strings, number,
|
|
5611
|
-
boolean, or object. ios.remote, android.remote, metro.tunnel,
|
|
6059
|
+
boolean, or object. ios.remote, android.remote, metro.tunnel, web.viewport,
|
|
5612
6060
|
optimizations.android.compilerCache and optimizations.android.pch take only
|
|
5613
6061
|
their listed choices. A value of the wrong
|
|
5614
6062
|
type or outside those choices is refused by name on every command that resolves
|
|
@@ -5683,6 +6131,10 @@ To show the booted simulator in Stim Desktop and open no simulator window:
|
|
|
5683
6131
|
|
|
5684
6132
|
Stim Desktop selects the workspace that owns the simulator and focuses that
|
|
5685
6133
|
device. It only displays the simulator; it never boots or shuts it down.
|
|
6134
|
+
When Stim Desktop is not running, Stim starts it without the command's
|
|
6135
|
+
\`STIM_HOME\`, so it reads the same Stim home as when you open it yourself.
|
|
6136
|
+
It shows only devices from that home: under another \`STIM_HOME\`, pick
|
|
6137
|
+
\`--simulator-app xcode\` to see the simulator.
|
|
5686
6138
|
|
|
5687
6139
|
Override the preference for one local launch with
|
|
5688
6140
|
\`stim ios --simulator-app siniulator\`, \`stim ios --simulator-app stim-desktop\`,
|
|
@@ -5711,10 +6163,13 @@ Stim then starts the emulator with \`-no-window -gpu host\` and opens
|
|
|
5711
6163
|
frames and sends input over the emulator's gRPC endpoint. The setting applies
|
|
5712
6164
|
only when Stim boots the emulator: one that is already running keeps its
|
|
5713
6165
|
current display until it next boots, and physical devices are unaffected.
|
|
5714
|
-
|
|
5715
|
-
|
|
6166
|
+
Like the iOS viewer, it starts Stim Desktop without the command's
|
|
6167
|
+
\`STIM_HOME\`. An invalid value refuses before boot. On Linux and Windows the
|
|
6168
|
+
setting has no effect.
|
|
5716
6169
|
|
|
5717
6170
|
Stim finds Stim Desktop by its bundle id, dev.stim.desktop, in Launch Services.
|
|
6171
|
+
A command Stim Desktop runs skips that lookup: Desktop sets \`STIM_DESKTOP_APP\`
|
|
6172
|
+
to its app path for every command it starts.
|
|
5718
6173
|
\`stim settings\` shows that default as \`(default: Stim Desktop installed)\`,
|
|
5719
6174
|
\`settings get\` prints it on stderr, and \`--json\` adds
|
|
5720
6175
|
\`"defaultReason": "Stim Desktop installed"\`. A set value always wins; set
|
|
@@ -5754,7 +6209,8 @@ THE GC WORKTREE GRACE PERIOD IS MACHINE-LEVEL
|
|
|
5754
6209
|
\`gc.worktreeGraceMinutes\` is how long \`gc --delete\` waits before it removes
|
|
5755
6210
|
a merged or idle linked worktree. The clock starts at the worktree's latest
|
|
5756
6211
|
activity: a write to its git index, HEAD or HEAD reflog, its Stim workspace
|
|
5757
|
-
state or logs,
|
|
6212
|
+
state or logs, the merge of its branch into the default branch, or when its
|
|
6213
|
+
pull request was merged or closed.
|
|
5758
6214
|
|
|
5759
6215
|
{
|
|
5760
6216
|
"gc": { "worktreeGraceMinutes": 120 }
|
|
@@ -5992,6 +6448,176 @@ platform instead of one entry. Pass prune: 'atomic' for a cache whose index
|
|
|
5992
6448
|
references its own data (an LLVM CAS): it is then left alone by --older-than
|
|
5993
6449
|
and emptied whole only by 'gc --delete --cache all'.
|
|
5994
6450
|
Registration is idempotent and keyed on the directory.`
|
|
6451
|
+
},
|
|
6452
|
+
web: {
|
|
6453
|
+
summary: "stim web: an owned headless Chrome per workspace, its logs, launched, and teardown",
|
|
6454
|
+
body: () => `WEB: AN OWNED CHROME PER WORKSPACE
|
|
6455
|
+
|
|
6456
|
+
If Stim is not installed globally, replace stim with npx stim.
|
|
6457
|
+
|
|
6458
|
+
stim web opens this workspace's page in a Chrome that Stim owns, captures the
|
|
6459
|
+
page's console, uncaught errors and failed requests in stim logs, and reports
|
|
6460
|
+
whether the page loaded. It uses the installed Google Chrome (or Chromium)
|
|
6461
|
+
with a profile Stim creates under STIM_HOME. Stim never installs a browser;
|
|
6462
|
+
stim doctor reports a missing Chrome.
|
|
6463
|
+
|
|
6464
|
+
stim web never starts a web server, for any framework. It opens, reuses or
|
|
6465
|
+
reloads the owned Chrome at the page URL. Every web project follows the same
|
|
6466
|
+
two steps: start your dev server, then run stim web.
|
|
6467
|
+
|
|
6468
|
+
stim web # headless, the default
|
|
6469
|
+
stim web --headed # show the Chrome window
|
|
6470
|
+
stim web --json # one payload on stdout; progress on stderr
|
|
6471
|
+
stim logs --errors # page errors land here with platform "web"
|
|
6472
|
+
stim reload web # Page.reload on the owned page
|
|
6473
|
+
stim stop # closes Chrome with the rest; the profile stays
|
|
6474
|
+
|
|
6475
|
+
WHICH PAGE AND WHICH DEV SERVER
|
|
6476
|
+
|
|
6477
|
+
Expo web runs on the workspace's Metro. With web.url unset, an Expo app
|
|
6478
|
+
opens http://localhost:<metroPort>/. Its dev server is stim start:
|
|
6479
|
+
|
|
6480
|
+
npx expo install react-dom react-native-web @expo/metro-runtime # once
|
|
6481
|
+
stim start
|
|
6482
|
+
stim web
|
|
6483
|
+
|
|
6484
|
+
Any other web server (Vite, Next, webpack) starts with its own command.
|
|
6485
|
+
Reserve its port with stim ports get, start it with strict-port behavior, and
|
|
6486
|
+
point web.url at it. {port:<label>} in web.url becomes that named port,
|
|
6487
|
+
{port:metro} the Metro port:
|
|
6488
|
+
|
|
6489
|
+
pnpm exec vite --port "$(stim ports get web)" --strictPort
|
|
6490
|
+
stim settings set web.url 'http://localhost:{port:web}/' --scope workspace
|
|
6491
|
+
stim web
|
|
6492
|
+
|
|
6493
|
+
When nothing serves the page, stim web still opens Chrome, reports launched
|
|
6494
|
+
"unverified", and prints the remedy for this workspace: stim start for an
|
|
6495
|
+
Expo web app, the stim ports get web recipe for any other server. A Metro
|
|
6496
|
+
port held by another process is also "unverified", and the page it serves
|
|
6497
|
+
still reaches stim logs; stim start then reserves a free port for this
|
|
6498
|
+
workspace. When this workspace's supervisor is still recorded, run stim stop
|
|
6499
|
+
first.
|
|
6500
|
+
|
|
6501
|
+
In a monorepo whose web app is its own package (apps/web beside apps/mobile),
|
|
6502
|
+
stim ports, web, settings, logs, reload, stop and status run from the web
|
|
6503
|
+
package resolve to the one Stim app registered in the same Git worktree; each
|
|
6504
|
+
names the app on stderr, and status stars it. The port, the browser, web.url
|
|
6505
|
+
and the logs all belong to that app's workspace, so every command can run from
|
|
6506
|
+
the web package. Register the app first, from its directory. See stim guide
|
|
6507
|
+
ports for the exact rule.
|
|
6508
|
+
|
|
6509
|
+
HTTPS dev servers with a self-signed certificate, such as Vite with
|
|
6510
|
+
@vitejs/plugin-basic-ssl, fail with net::ERR_CERT_AUTHORITY_INVALID until
|
|
6511
|
+
web.ignoreCertificateErrors is true, which accepts the certificate in the
|
|
6512
|
+
owned profile only:
|
|
6513
|
+
stim settings set web.url 'https://localhost:{port:web}/' --scope workspace
|
|
6514
|
+
stim settings set web.ignoreCertificateErrors true --scope workspace
|
|
6515
|
+
An https:// URL on a plain HTTP server fails with ERR_SSL_PROTOCOL_ERROR, and
|
|
6516
|
+
an http:// URL on an HTTPS server with ERR_EMPTY_RESPONSE; the remedy line
|
|
6517
|
+
prints the settings command that switches the scheme. web.viewport phone
|
|
6518
|
+
gives the page a 390x844 touch screen at 3x instead of the 1280x800 desktop
|
|
6519
|
+
window. See stim guide settings.
|
|
6520
|
+
|
|
6521
|
+
MONOREPO RECIPE: A VITE PACKAGE WITH A BASE PATH AND HTTPS
|
|
6522
|
+
|
|
6523
|
+
apps/web runs Vite through its dev script, serves the app under /apps/groups/,
|
|
6524
|
+
and uses @vitejs/plugin-basic-ssl; apps/mobile is the Stim app. The flow is
|
|
6525
|
+
the same as for any web project: start the dev server, then run stim web.
|
|
6526
|
+
|
|
6527
|
+
cd apps/mobile && stim ports get web # registers the app; no Metro
|
|
6528
|
+
cd ../web
|
|
6529
|
+
stim settings set web.url 'https://localhost:{port:web}/apps/groups/' --scope repo
|
|
6530
|
+
stim settings set web.ignoreCertificateErrors true --scope repo
|
|
6531
|
+
pnpm dev --port "$(stim ports get web)" --strictPort # keep it running
|
|
6532
|
+
stim web
|
|
6533
|
+
stim logs --errors
|
|
6534
|
+
stim reload web
|
|
6535
|
+
stim stop # closes Chrome; stim ports stop web stops Vite
|
|
6536
|
+
stim worktree remove # in a linked worktree: Chrome, Vite and profile
|
|
6537
|
+
|
|
6538
|
+
The repo layer is shared by every worktree of the repository, so a new
|
|
6539
|
+
worktree skips the two settings lines; the certificate and scheme remedies
|
|
6540
|
+
print --scope workspace, which overrides it for one worktree only. Run ports
|
|
6541
|
+
get from the app directory before any ports or web command in the web
|
|
6542
|
+
package: a reservation made there first keeps the web package as its own
|
|
6543
|
+
workspace until you release it and stop. Pass --port and --strictPort
|
|
6544
|
+
through the dev script: Vite otherwise binds its config default and moves to
|
|
6545
|
+
the next free port when that one is taken. Put the base path in web.url: a
|
|
6546
|
+
path outside it can reach the dev server's proxy instead of the app. API
|
|
6547
|
+
calls the dev server proxies to a backend that is not running fail as device
|
|
6548
|
+
errors in stim logs --errors; the page still loads.
|
|
6549
|
+
|
|
6550
|
+
LAUNCHED
|
|
6551
|
+
|
|
6552
|
+
The web payload's launched keeps its native meaning, from evidence in the
|
|
6553
|
+
owned page rather than a shared port:
|
|
6554
|
+
true the page's document answered and its load event fired; on
|
|
6555
|
+
Metro, the page also fetched a web bundle
|
|
6556
|
+
"bundling" Metro was still building the web bundle when the check ended
|
|
6557
|
+
"unverified" the document failed (for example ERR_CONNECTION_REFUSED:
|
|
6558
|
+
the dev server is not running, or ERR_CERT_AUTHORITY_INVALID: a
|
|
6559
|
+
self-signed certificate), loaded without a Metro bundle, or
|
|
6560
|
+
did not finish: 20 seconds with no answer, 60 once a server
|
|
6561
|
+
other than Metro answered. The remedy line names the fix
|
|
6562
|
+
false is never produced. A page that loads and then throws is still launched
|
|
6563
|
+
true; read stim logs --errors.
|
|
6564
|
+
|
|
6565
|
+
A second stim web with the same options reuses the running Chrome and
|
|
6566
|
+
navigates it again. Changing --headed, web.viewport or the certificate
|
|
6567
|
+
setting restarts it.
|
|
6568
|
+
|
|
6569
|
+
LOGS
|
|
6570
|
+
|
|
6571
|
+
Records go to web.ndjson in the workspace log directory, all with
|
|
6572
|
+
platform "web":
|
|
6573
|
+
src client console calls at their level (console.error is error) and
|
|
6574
|
+
uncaught errors and rejections, with stack frames
|
|
6575
|
+
src device failed requests, which stim logs --errors includes: a failed
|
|
6576
|
+
page document is error whatever its
|
|
6577
|
+
status; another request's network failure or HTTP 5xx is
|
|
6578
|
+
error, a 4xx warn, a canceled request debug; browser messages such
|
|
6579
|
+
as CSP violations; the browser's own lifecycle
|
|
6580
|
+
Expo also prints web console calls on Metro ("Web LOG"), so they can appear
|
|
6581
|
+
twice: once from the page (client), once from Metro (metro, level info).
|
|
6582
|
+
Each load of the page's top-level document is a page-load marker: stim web,
|
|
6583
|
+
stim reload, and a reload or navigation the page makes itself. logs --errors
|
|
6584
|
+
and the status error count report the page's records (platform web) from the
|
|
6585
|
+
latest load only, the way Chrome DevTools clears its console when the page
|
|
6586
|
+
navigates. A page load does not hide the native app's errors, and an ios or
|
|
6587
|
+
android launch does not hide the page's.
|
|
6588
|
+
|
|
6589
|
+
AGENTS AND OTHER TOOLS ON THE SAME BROWSER
|
|
6590
|
+
|
|
6591
|
+
stim status --json shows environments[].web.cdpEndpoint, a reserved loopback
|
|
6592
|
+
DevTools endpoint on 127.0.0.1. Point browser tools at it instead of letting
|
|
6593
|
+
them start their own browser:
|
|
6594
|
+
Playwright MCP --cdp-endpoint http://127.0.0.1:<port>
|
|
6595
|
+
agent-browser --cdp <port>
|
|
6596
|
+
The port reaches only the Stim profile: Chrome refuses remote debugging on
|
|
6597
|
+
your default profile, and Stim never attaches to a browser it did not start.
|
|
6598
|
+
The port is managed like metro: stim ports lists it as web-cdp (managed),
|
|
6599
|
+
and ports get, stop and release refuse it.
|
|
6600
|
+
|
|
6601
|
+
OWNERSHIP AND CLEANUP
|
|
6602
|
+
|
|
6603
|
+
A browser supervisor process holds the DevTools session and an ownership
|
|
6604
|
+
claim for its lifetime; Chrome is the claim's child. Stim signals the
|
|
6605
|
+
supervisor or Chrome only after verifying the process identity it recorded.
|
|
6606
|
+
stim stop closes Chrome and keeps the profile, so cookies and
|
|
6607
|
+
storage survive the next stim web
|
|
6608
|
+
stim worktree remove closes Chrome and deletes the profile
|
|
6609
|
+
stim gc --delete does the same for a workspace whose path is gone,
|
|
6610
|
+
and forgets ledger entries of deleted profiles
|
|
6611
|
+
The profile is deleted only when the created-devices ledger lists it. After
|
|
6612
|
+
Chrome is gone, Stim removes the SingletonLock files a killed Chrome leaves,
|
|
6613
|
+
which would otherwise block the next launch. status reports
|
|
6614
|
+
browser-unverified when an identity cannot be proven; follow stim guide
|
|
6615
|
+
errors teardown.
|
|
6616
|
+
|
|
6617
|
+
LIMITS
|
|
6618
|
+
|
|
6619
|
+
Chrome and Chromium only. No Stim Desktop or phone viewer yet. The owned page
|
|
6620
|
+
is one tab: a page the app opens in a new window is not captured.`
|
|
5995
6621
|
}
|
|
5996
6622
|
};
|
|
5997
6623
|
//#endregion
|