stim 1.3.1 → 1.5.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 +16 -3
- package/dist/{android-hMj83VpN.mjs → android-DJWiTBkz.mjs} +65 -72
- package/dist/{android-cas-DXorPCi_.mjs → android-cas-CSS8gjR7.mjs} +15 -12
- package/dist/{android-CT-PkXUh.mjs → android-sobvO9ia.mjs} +197 -114
- package/dist/{app-install-DIp9riNx.mjs → app-install--PAocWvq.mjs} +2 -2
- package/dist/{build-slots-C4AouyNz.mjs → build-slots-CuPszJDu.mjs} +7 -8
- package/dist/{cache-manifest-CXR-Y8pH.mjs → cache-manifest-uoOKhgUD.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +14 -13
- package/dist/collector-run.mjs +4 -4
- package/dist/{command-output-8wHMEde0.mjs → command-output-BuIb_ZOI.mjs} +1 -4
- package/dist/{config-CcefMY2Q.mjs → config-DMP7L7H6.mjs} +52 -52
- package/dist/dependency-state-CTL8A9p3.mjs +76 -0
- package/dist/{deps-0Yt0Inly.mjs → deps-BAGOnrc7.mjs} +1 -1
- package/dist/{dev-client-VfSZNLT4.mjs → dev-client-BoifdqkU.mjs} +12 -12
- package/dist/{device-Bbv45Z9Z.mjs → device-BUw4JBuH.mjs} +7 -7
- package/dist/{xcode-xnxyvJkD.mjs → device-DvKJ454A.mjs} +208 -967
- package/dist/{device-lease-CJwK7OZr.mjs → device-lease-r7yEQ1R8.mjs} +3 -3
- package/dist/{device-pool-CcBNTvM7.mjs → device-pool-DU4FQKp5.mjs} +4 -4
- package/dist/{device-remote-DAA0Zm6Z.mjs → device-remote-BTUqbl0i.mjs} +7 -6
- package/dist/{doctor-B4EITgQB.mjs → doctor-Di_B26uh.mjs} +396 -117
- package/dist/{error-diagnostics-DwhNBFDU.mjs → error-diagnostics-CTePWAzW.mjs} +7 -6
- package/dist/{gc-BRu62v4o.mjs → gc-C20dWw_8.mjs} +61 -27
- package/dist/{guide-D95E0u3i.mjs → guide-sAnoty2y.mjs} +151 -20
- package/dist/guide-status-BF6RsJJp.mjs +271 -0
- package/dist/{ios-DAju3TVy.mjs → ios-BdpkncL6.mjs} +2667 -2607
- package/dist/{ios-device-CWOM_S44.mjs → ios-device-DJOi9FR5.mjs} +1 -1
- package/dist/{logs-CAdwW6c2.mjs → logs-BfQdIhiF.mjs} +5 -5
- package/dist/metro-ato6ef3J.mjs +99 -0
- package/dist/named-ports-DH9SXd0f.mjs +137 -0
- package/dist/{ownership-8O073GIC.mjs → ownership-CD_XnpDu.mjs} +5 -5
- package/dist/{ownership-DXcol4oU.mjs → ownership-CVY9cqCr.mjs} +6 -6
- package/dist/ports-A6uTJSPj.mjs +39 -0
- package/dist/ports-BZprTJRa.mjs +90 -0
- package/dist/{project-fKmuIaMI.mjs → project-B_SDt4ip.mjs} +2 -2
- package/dist/{reclaim-CUmwucWG.mjs → reclaim-C_rB25f4.mjs} +20 -13
- package/dist/{reload-CWpXoOgN.mjs → reload-CYBJbJfI.mjs} +8 -8
- package/dist/rolldown-runtime-BsOwBuO_.mjs +30 -0
- package/dist/{server-bare-DEzPZLvf.mjs → server-bare-H3pAhbMs.mjs} +11 -35
- package/dist/server-expo-CSwUVYOa.mjs +2 -0
- package/dist/{server-expo-DizT4OMk.mjs → server-expo-Ds8_mfng.mjs} +6 -14
- package/dist/{settings-DEJf6_kJ.mjs → settings-kO2ZqIKy.mjs} +2 -2
- package/dist/{slot-launch-CZklomj6.mjs → slot-launch-BpHiHH6A.mjs} +4 -4
- package/dist/{start-B5G4NjiA.mjs → start-DiEfqEWk.mjs} +20 -22
- package/dist/state-CnWzvCWP.mjs +131 -0
- package/dist/{stats-CaaQr4yN.mjs → stats-DHrO0frH.mjs} +4 -4
- package/dist/{stats-BR-kwj0B.mjs → stats-Fo9ACIv7.mjs} +1 -1
- package/dist/{status-CI9clRSb.mjs → status-J5LAXpag.mjs} +15 -12
- package/dist/{stop-CjlgDk0a.mjs → stop-0jJNahwN.mjs} +15 -14
- package/dist/{stop-CQhffpmX.mjs → stop-CM1fejKW.mjs} +2 -2
- package/dist/supervisor-run.d.mts +7 -28
- package/dist/supervisor-run.mjs +20 -11
- package/dist/{teardown--gESs9ck.mjs → teardown-CAVcWeRD.mjs} +148 -109
- package/dist/{workspace-process-lock-IBj1Towr.mjs → workspace-process-lock-Bz19_R9R.mjs} +4 -4
- package/dist/workspace-state-WVwWw_hB.mjs +146 -0
- package/dist/{worktree-DtQGO9-s.mjs → worktree-CeUKDAQw.mjs} +38 -34
- package/dist/{worktree-Eq6TLH8N.mjs → worktree-DJnBbQZ9.mjs} +79 -22
- package/dist/xcode-BqDeRkpT.mjs +860 -0
- package/package.json +7 -7
- package/shim/expo-metro-config.cjs +11 -17
- package/dist/doctor-BueDfLYG.mjs +0 -530
- package/dist/metro-CORqXyTL.mjs +0 -184
- package/dist/ownership-claim-BtPtJVmq.mjs +0 -584
- package/dist/server-expo-44em5Pmg.mjs +0 -2
- package/dist/state-B3XA2wp2.mjs +0 -268
- package/shim/metro-cache-generation.cjs +0 -20
- package/shim/metro-cache-generation.d.cts +0 -5
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
-
import { A as
|
|
3
|
-
import { i as registeredCaches } from "./cache-manifest-
|
|
4
|
-
import {
|
|
5
|
-
import { g as repoRoot, s as gitCommonDir } from "./worktree-
|
|
6
|
-
import { a as findProjectRoot, i as detectIsExpo } from "./project-
|
|
7
|
-
import { m as shortUdid, o as formatLongDuration, u as plural } from "./command-output-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { a as POOL_SETTING_REMEDY, c as parkedMaxSetting, i as teardownParkedIosSim, l as readParked, n as teardownOwnedIosSim, r as teardownParkedAvd, s as dropParked, t as teardownOwnedAvd, x as resolveEasCliBin } from "./teardown--gESs9ck.mjs";
|
|
2
|
+
import { A as isOnMountedVolume, C as withConfigLock, E as ownership_claim_exports, F as deviceSlotPlatforms, L as projectDeviceSlots, M as volumeRootFor, O as directorySize, f as getProject, g as loadConfig, i as clearDevice, j as listMountedVolumes, k as formatBytes, u as getConfigDir, v as removeProject } from "./config-DMP7L7H6.mjs";
|
|
3
|
+
import { i as registeredCaches } from "./cache-manifest-uoOKhgUD.mjs";
|
|
4
|
+
import { h as workspaceDir, y as workspaceStateFile } from "./workspace-state-WVwWw_hB.mjs";
|
|
5
|
+
import { g as repoRoot, s as gitCommonDir } from "./worktree-DJnBbQZ9.mjs";
|
|
6
|
+
import { a as findProjectRoot, i as detectIsExpo } from "./project-B_SDt4ip.mjs";
|
|
7
|
+
import { m as shortUdid, o as formatLongDuration, u as plural } from "./command-output-BuIb_ZOI.mjs";
|
|
8
|
+
import { B as listBuildLocks, S as listOrphanedAvdDirectories, T as ownedAvdDirectory, b as listAvds } from "./android-DJWiTBkz.mjs";
|
|
9
|
+
import { A as resolveSettings, N as settingShapeErrors, a as SETTING_SHAPE_REMEDY } from "./settings-kO2ZqIKy.mjs";
|
|
10
|
+
import { S as resolveEasCliBin, a as POOL_SETTING_REMEDY, i as teardownParkedIosSim, l as parkedMaxSetting, n as teardownOwnedIosSim, r as teardownParkedAvd, s as dropParked, t as teardownOwnedAvd, u as readParked } from "./teardown-CAVcWeRD.mjs";
|
|
12
11
|
import { d as listIosDeviceTypes, g as parseRuntimeVersion, u as listAllIosSims } from "./ios-Deh5js5V.mjs";
|
|
13
|
-
import { i as listLeaseFiles, r as leaseIsExpired, u as removeExpiredLease } from "./device-lease-
|
|
14
|
-
import { n as listBuildSlots } from "./build-slots-
|
|
15
|
-
import { C as verifyStoppedSession, S as stopSessionArgs, _ as inspectSessionForTeardown, d as withEasProjectLock, f as easMachineStateRoot, g as getSessionArgs, h as findOrphanedOwnedSessions, m as removeEasSessionClaim, p as readEasSessionLedger, u as withRemoteSessionLock, v as isDefinitiveMissingSessionError, x as parseSessionListPage, y as listOwnedSessionsArgs } from "./device-remote-
|
|
16
|
-
import { n as reclaimProject, t as describeDereferenced } from "./reclaim-
|
|
12
|
+
import { i as listLeaseFiles, r as leaseIsExpired, u as removeExpiredLease } from "./device-lease-r7yEQ1R8.mjs";
|
|
13
|
+
import { n as listBuildSlots } from "./build-slots-CuPszJDu.mjs";
|
|
14
|
+
import { C as verifyStoppedSession, S as stopSessionArgs, _ as inspectSessionForTeardown, d as withEasProjectLock, f as easMachineStateRoot, g as getSessionArgs, h as findOrphanedOwnedSessions, m as removeEasSessionClaim, p as readEasSessionLedger, u as withRemoteSessionLock, v as isDefinitiveMissingSessionError, x as parseSessionListPage, y as listOwnedSessionsArgs } from "./device-remote-BTUqbl0i.mjs";
|
|
15
|
+
import { n as reclaimProject, t as describeDereferenced } from "./reclaim-C_rB25f4.mjs";
|
|
17
16
|
import { InvalidArgumentError } from "commander";
|
|
18
17
|
import { existsSync, readFileSync, readdirSync, realpathSync, rmSync, statSync } from "fs";
|
|
19
18
|
import { homedir, tmpdir } from "os";
|
|
@@ -690,13 +689,20 @@ function collectDeviceLeases(now) {
|
|
|
690
689
|
}
|
|
691
690
|
function deleteProjectDevices(orphanedDevices, staleDevices, staleDeviceRecords) {
|
|
692
691
|
let deleteFailures = 0;
|
|
693
|
-
function reap(d) {
|
|
692
|
+
function reap(d, onlyIfMissing = false) {
|
|
694
693
|
const r = d.kind === "ios" ? teardownOwnedIosSim(d.id, {
|
|
695
694
|
del: true,
|
|
696
695
|
label: d.name
|
|
697
696
|
}) : teardownOwnedAvd(d.name, {
|
|
698
697
|
del: true,
|
|
699
|
-
|
|
698
|
+
onlyIfMissing,
|
|
699
|
+
..."project" in d ? { owner: {
|
|
700
|
+
projectPath: d.project,
|
|
701
|
+
slot: d.slot
|
|
702
|
+
} } : {},
|
|
703
|
+
..."project" in d ? { onRemoved: () => {
|
|
704
|
+
if (clearDevice(d.project, d.kind, d.slot, d.id)) console.log(chalk.dim(` cleared the ${d.kind} record for ${d.project}`));
|
|
705
|
+
} } : {},
|
|
700
706
|
..."orphanedDirectory" in d ? { orphanedDirectory: d.orphanedDirectory } : {}
|
|
701
707
|
});
|
|
702
708
|
const what = d.kind === "ios" ? `ios sim ${d.name} (${d.id})` : `android avd ${d.name}`;
|
|
@@ -712,15 +718,20 @@ function deleteProjectDevices(orphanedDevices, staleDevices, staleDeviceRecords)
|
|
|
712
718
|
for (const d of orphanedDevices) reap(d);
|
|
713
719
|
for (const d of staleDevices) {
|
|
714
720
|
const status = reap(d);
|
|
715
|
-
if (status === "torn-down" || status === "missing") {
|
|
716
|
-
clearDevice(d.project, d.kind, d.slot);
|
|
721
|
+
if (d.kind === "ios" && (status === "torn-down" || status === "missing")) {
|
|
722
|
+
clearDevice(d.project, d.kind, d.slot, d.id);
|
|
717
723
|
console.log(chalk.dim(` cleared the ${d.kind} record for ${d.project}`));
|
|
718
724
|
}
|
|
719
725
|
}
|
|
720
|
-
for (const r of staleDeviceRecords) {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
726
|
+
for (const r of staleDeviceRecords) if (r.kind === "android" && r.owned) reap({
|
|
727
|
+
...r,
|
|
728
|
+
name: r.id,
|
|
729
|
+
idleDays: 0
|
|
730
|
+
}, true);
|
|
731
|
+
else if (withConfigLock(() => {
|
|
732
|
+
if (r.kind === "android" && deviceSlotPlatforms(getProject(r.project), r.slot)?.android?.owned) return false;
|
|
733
|
+
return clearDevice(r.project, r.kind, r.slot, r.id);
|
|
734
|
+
})) console.log(chalk.green(`Cleared the ${r.kind} record for ${r.project} (${r.id} is not on this machine)`));
|
|
724
735
|
return deleteFailures;
|
|
725
736
|
}
|
|
726
737
|
//#endregion
|
|
@@ -932,7 +943,7 @@ function malformedRemoteSessionLockNotice(roots) {
|
|
|
932
943
|
for (const root of roots) {
|
|
933
944
|
const lockPath = join(workspaceDir(root), "remote-session.lock");
|
|
934
945
|
if (!existsSync(lockPath)) continue;
|
|
935
|
-
if (readClaimSet(lockPath).unresolved.length === 0) continue;
|
|
946
|
+
if ((0, ownership_claim_exports.readClaimSet)(lockPath).unresolved.length === 0) continue;
|
|
936
947
|
return `EAS session sweep skipped: the remote-session lock at ${lockPath} has a malformed owner record.`;
|
|
937
948
|
}
|
|
938
949
|
return null;
|
|
@@ -1154,7 +1165,7 @@ function unresolvedLockLines(locks, slots) {
|
|
|
1154
1165
|
" remove one yourself once you know nothing is building with it"
|
|
1155
1166
|
];
|
|
1156
1167
|
}
|
|
1157
|
-
function formatGcReport({ skipped = [], deadProjects = [], invalidProjects = [], parkedSims = [], parkedAvds = [], orphanedDevices = [], staleDevices = [], staleDeviceRecords = [], buildLocks = {
|
|
1168
|
+
function formatGcReport({ skipped = [], deadProjects = [], orphanedPorts, invalidProjects = [], parkedSims = [], parkedAvds = [], orphanedDevices = [], staleDevices = [], staleDeviceRecords = [], buildLocks = {
|
|
1158
1169
|
stale: [],
|
|
1159
1170
|
live: [],
|
|
1160
1171
|
unresolved: []
|
|
@@ -1187,6 +1198,7 @@ function formatGcReport({ skipped = [], deadProjects = [], invalidProjects = [],
|
|
|
1187
1198
|
}
|
|
1188
1199
|
lines.push(...projectEntryLines(`Dead project entries (${deadProjects.length}):`, deadProjects));
|
|
1189
1200
|
lines.push(...projectEntryLines(`Invalid project entries (${invalidProjects.length}) - the key is not an absolute path:`, invalidProjects));
|
|
1201
|
+
lines.push(...namedPortLines(orphanedPorts));
|
|
1190
1202
|
lines.push(...formatParkedSimReport(parkedSims, now));
|
|
1191
1203
|
lines.push(...formatParkedAvdReport(parkedAvds, now));
|
|
1192
1204
|
if (orphanedDevices.length) {
|
|
@@ -1292,6 +1304,14 @@ function leaseGarbageLines({ expired, kept }) {
|
|
|
1292
1304
|
function deviceSizeSuffix(device) {
|
|
1293
1305
|
return device.kind === "android" && device.bytes !== void 0 ? ` - ${formatBytes(device.bytes)} on disk` : "";
|
|
1294
1306
|
}
|
|
1307
|
+
function namedPortLines(ports = []) {
|
|
1308
|
+
if (!ports.length) return [];
|
|
1309
|
+
return [
|
|
1310
|
+
`Orphaned named ports (${ports.length}):`,
|
|
1311
|
+
...ports.map(({ project, label, port }) => ` ${project}: ${label} (${port})`),
|
|
1312
|
+
" --delete stops TCP listeners and releases these allocations."
|
|
1313
|
+
];
|
|
1314
|
+
}
|
|
1295
1315
|
//#endregion
|
|
1296
1316
|
//#region src/commands/gc.ts
|
|
1297
1317
|
function removeInvalidProjectEntries(invalidProjects) {
|
|
@@ -1464,6 +1484,11 @@ async function collectGcReport({ olderThan = null, cache = null, now = Date.now(
|
|
|
1464
1484
|
return {
|
|
1465
1485
|
skipped,
|
|
1466
1486
|
deadProjects,
|
|
1487
|
+
orphanedPorts: deadProjects.flatMap((project) => Object.entries(cfg?.projects[project]?.ports ?? {}).map(([label, port]) => ({
|
|
1488
|
+
project,
|
|
1489
|
+
label,
|
|
1490
|
+
port
|
|
1491
|
+
}))),
|
|
1467
1492
|
invalidProjects,
|
|
1468
1493
|
parkedSims,
|
|
1469
1494
|
parkedAvds,
|
|
@@ -1591,7 +1616,16 @@ async function runGcCore(opts, deps) {
|
|
|
1591
1616
|
let deleteFailures = deleteParkedSims(report.parkedSims, deps) + deleteParkedAvds(report.parkedAvds);
|
|
1592
1617
|
removeInvalidProjectEntries(invalidProjects);
|
|
1593
1618
|
for (const path of deadProjects) {
|
|
1594
|
-
|
|
1619
|
+
if (existsSync(path) || !isOnMountedVolume(path)) {
|
|
1620
|
+
console.log(chalk.yellow(`Kept ${path}: its absence can no longer be confirmed.`));
|
|
1621
|
+
continue;
|
|
1622
|
+
}
|
|
1623
|
+
const result = await reclaimProject(path).catch((error) => {
|
|
1624
|
+
deleteFailures++;
|
|
1625
|
+
console.log(chalk.red(`Could not prune ${path}; its registry entry was kept: ${error.message}`));
|
|
1626
|
+
return null;
|
|
1627
|
+
});
|
|
1628
|
+
if (!result) continue;
|
|
1595
1629
|
if (result.keptEntry) console.log(chalk.yellow(`Could not fully prune ${path}; its registry entry was kept.`));
|
|
1596
1630
|
else console.log(chalk.green(`Pruned ${path}`));
|
|
1597
1631
|
for (const dir of result.removedWorkspaceDirs) console.log(chalk.dim(` removed workspace output ${dir}`));
|
|
@@ -1606,7 +1640,7 @@ async function runGcCore(opts, deps) {
|
|
|
1606
1640
|
}
|
|
1607
1641
|
deleteFailures += deleteProjectDevices(orphanedDevices, staleDevices, staleDeviceRecords);
|
|
1608
1642
|
for (const lock of buildLocks.stale) {
|
|
1609
|
-
const cleared = clearFreeClaimSet({
|
|
1643
|
+
const cleared = (0, ownership_claim_exports.clearFreeClaimSet)({
|
|
1610
1644
|
root: lock.path,
|
|
1611
1645
|
label: `${lock.platform} build`
|
|
1612
1646
|
});
|
|
@@ -1623,7 +1657,7 @@ async function runGcCore(opts, deps) {
|
|
|
1623
1657
|
console.log(chalk.green(`Cleared the ${lock.platform} build lock left by pid ${lock.pid ?? "?"} (${lock.projectRoot || "unrecorded workspace"})`));
|
|
1624
1658
|
}
|
|
1625
1659
|
for (const slot of buildSlots.stale) {
|
|
1626
|
-
const cleared = clearFreeClaimSet({
|
|
1660
|
+
const cleared = (0, ownership_claim_exports.clearFreeClaimSet)({
|
|
1627
1661
|
root: slot.path,
|
|
1628
1662
|
label: "build slot"
|
|
1629
1663
|
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as findProjectRoot } from "./project-B_SDt4ip.mjs";
|
|
2
|
+
import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-kO2ZqIKy.mjs";
|
|
3
|
+
import { t as guideStatus } from "./guide-status-BF6RsJJp.mjs";
|
|
2
4
|
import chalk from "chalk";
|
|
3
5
|
//#endregion
|
|
4
6
|
//#region src/guide/index.ts
|
|
@@ -65,8 +67,12 @@ If warm fails or reports incomplete, resolve the reported failure first.
|
|
|
65
67
|
A warm that cannot record its ownership claim refuses before copying. Follow
|
|
66
68
|
the printed remedy and keep concurrent runs on the same STIM_HOME.
|
|
67
69
|
|
|
68
|
-
Before native worktree work, run doctor for the platform in scope.
|
|
69
|
-
the
|
|
70
|
+
Before native worktree work, run doctor for the platform in scope. The STATUS
|
|
71
|
+
block at the top of this topic says when it is due here: never run in this
|
|
72
|
+
checkout, older than seven days, or run under another Stim version. No block
|
|
73
|
+
means doctor is current and Stim is up to date; the same block names a newer
|
|
74
|
+
Stim release when one exists. Doctor checks the source
|
|
75
|
+
checkout from a linked worktree. Fix relevant findings and inspect the
|
|
70
76
|
upstream gap; in the single-checkout workflow those seed findings do not
|
|
71
77
|
appear. It also prints the running CLI version and the stim installation
|
|
72
78
|
resolved from PATH. If that resolved installation is older than another one,
|
|
@@ -153,7 +159,7 @@ RULES DURING THE LOOP
|
|
|
153
159
|
change does not need one.
|
|
154
160
|
- For stale Metro transforms or file-map state, use stim start --reset-cache.
|
|
155
161
|
It restarts only this app's verified owned Metro, preserving devices and other
|
|
156
|
-
apps' caches. See guide lifecycle for reset scope
|
|
162
|
+
apps' caches. See guide lifecycle for reset scope.
|
|
157
163
|
- Reload is not part of the normal workflow. Use stim reload on an owned local
|
|
158
164
|
simulator or emulator when an error screen remains after the fix, and on
|
|
159
165
|
Android after a failed first bundle load. It reloads JavaScript and never
|
|
@@ -226,8 +232,10 @@ shut down the phone or uninstall the app.
|
|
|
226
232
|
|
|
227
233
|
Treat a refusal as an ownership or state mismatch: read its code and remedy.
|
|
228
234
|
Never reach for --force first.
|
|
229
|
-
Stim leaves externally started servers alone. Stop them with their original
|
|
230
|
-
tool; neither a matching port nor --force grants process ownership.
|
|
235
|
+
Stim leaves externally started Metro servers alone. Stop them with their original
|
|
236
|
+
tool; neither a matching Metro port nor --force grants process ownership.
|
|
237
|
+
Named ports are separate: ports stop kills TCP listeners on the workspace's
|
|
238
|
+
reserved named ports, even outside the workspace. Read guide ports before use.
|
|
231
239
|
|
|
232
240
|
Ask the user before these actions:
|
|
233
241
|
|
|
@@ -266,6 +274,7 @@ Read the matching guide before acting in these situations:
|
|
|
266
274
|
| Refusal with a CODE | stim guide errors <CODE> |
|
|
267
275
|
| Running under a sandbox | stim guide errors sandbox |
|
|
268
276
|
| Release configuration or ...Release variant | stim guide lifecycle release |
|
|
277
|
+
| Web or API server ports | stim guide ports |
|
|
269
278
|
| Remote device, custom Metro, or tunnel | stim guide metro |
|
|
270
279
|
| Cache miss, bypass, or fingerprint exclusions | stim guide lifecycle builds |
|
|
271
280
|
| Capacity limits | stim guide lifecycle concurrency |
|
|
@@ -301,6 +310,7 @@ FULL TOPIC LIST
|
|
|
301
310
|
stim guide lifecycle release # Release configurations and ...Release variants
|
|
302
311
|
stim guide facts # the --json payloads
|
|
303
312
|
stim guide facts devmenu # the Expo dev menu or Tools button over the app
|
|
313
|
+
stim guide ports # named ports for web and API servers
|
|
304
314
|
stim guide metro # supervisor, custom Metro, tunnels, and remote devices
|
|
305
315
|
stim guide logs # filters, record shape, and capture limits
|
|
306
316
|
stim guide cleanup # what reclaims a device, and what deletes
|
|
@@ -896,6 +906,58 @@ STARTING YOUR OWN BUNDLER STILL WORKS
|
|
|
896
906
|
|
|
897
907
|
\`stop\` leaves an externally started server running. Stop it with the tool
|
|
898
908
|
that started it.`
|
|
909
|
+
},
|
|
910
|
+
ports: {
|
|
911
|
+
summary: "Workspace ports for web and API servers that Stim does not manage",
|
|
912
|
+
body: () => `NAMED SERVER PORTS
|
|
913
|
+
|
|
914
|
+
If Stim is not installed globally, replace stim with npx stim.
|
|
915
|
+
|
|
916
|
+
stim ports get web
|
|
917
|
+
pnpm exec vite --port "$(stim ports get web)" --strictPort
|
|
918
|
+
stim ports
|
|
919
|
+
stim ports stop web --dry-run
|
|
920
|
+
stim ports stop web
|
|
921
|
+
stim ports release api
|
|
922
|
+
|
|
923
|
+
get <label> allocates on first use and prints only the number to stdout.
|
|
924
|
+
Repeated calls reuse it, even while a server is listening. Labels start with
|
|
925
|
+
a letter and contain up to 64 letters, digits, underscores, or hyphens.
|
|
926
|
+
metro is reserved; use stim start and stim stop for managed Metro.
|
|
927
|
+
|
|
928
|
+
New allocations scan TCP ports 8900-8999. They skip registry reservations
|
|
929
|
+
and existing listeners, announcing occupied ports and upward retries on
|
|
930
|
+
stderr. Allocation requires lsof. All 100 ports occupied or reserved is a
|
|
931
|
+
refusal; stop or release unused allocations in their owning workspaces.
|
|
932
|
+
|
|
933
|
+
The machine registry, under STIM_HOME, serializes allocation and cleanup.
|
|
934
|
+
The workspace is the nearest package.json directory, resolved through
|
|
935
|
+
symlinks. Use the same package directory for every command in a monorepo.
|
|
936
|
+
The allocation reserves a number, not a listening socket. Another process
|
|
937
|
+
can bind it before your server does. Use strict-port behavior when supported
|
|
938
|
+
and verify the server bound the number supplied. Stim does not start,
|
|
939
|
+
supervise, or capture logs for these servers.
|
|
940
|
+
|
|
941
|
+
ports lists named labels and ports, plus Metro marked managed.
|
|
942
|
+
ports stop [label] kills TCP listeners on those named ports and releases
|
|
943
|
+
the allocations. It sends SIGTERM, waits two seconds, then SIGKILL if needed.
|
|
944
|
+
It prints the PID and command for each stopped process. The listener's cwd
|
|
945
|
+
can be anywhere: the named reservation is permission to stop that listener.
|
|
946
|
+
Reserve only services this workspace may stop. --dry-run prints what would
|
|
947
|
+
be stopped and released, without doing either. A failed inspection or stop
|
|
948
|
+
keeps that allocation for retry; other labels are still processed.
|
|
949
|
+
ports release [label] releases without signalling a process.
|
|
950
|
+
Omitting the label selects every named port, never Metro. stim stop leaves
|
|
951
|
+
named ports alone.
|
|
952
|
+
|
|
953
|
+
worktree remove stops named listeners and releases their allocations.
|
|
954
|
+
gc reports allocations whose workspace no longer exists; gc --delete stops
|
|
955
|
+
and releases them. Unmounted or unresolved workspace paths are retained.
|
|
956
|
+
Failed stops keep the registry entry. Use the same current Stim version for
|
|
957
|
+
cleanup: versions without ports do not know about named allocations.
|
|
958
|
+
|
|
959
|
+
A shared API does not get a shared reservation. Pass its port by environment
|
|
960
|
+
instead of allocating a separate label in every worktree.`
|
|
899
961
|
},
|
|
900
962
|
logs: {
|
|
901
963
|
summary: "Querying the merged NDJSON timeline, and what --errors means",
|
|
@@ -1401,7 +1463,7 @@ code, never on the message.`,
|
|
|
1401
1463
|
run the command again.`
|
|
1402
1464
|
},
|
|
1403
1465
|
STIM_CLAIM_REFUSED: {
|
|
1404
|
-
summary: "
|
|
1466
|
+
summary: "an ownership claim blocks the operation; inspect its holder before removing an unresolved claim",
|
|
1405
1467
|
body: () => `STIM_CLAIM_REFUSED
|
|
1406
1468
|
A build lock records the holder's process IDENTITY, not just its pid, so a
|
|
1407
1469
|
recycled pid reads as a gone builder rather than a live one, and a builder
|
|
@@ -1420,7 +1482,26 @@ code, never on the message.`,
|
|
|
1420
1482
|
and nothing was copied. A STIM_HOME or warm-locks ancestor that is a file
|
|
1421
1483
|
also refuses. The message names that blocking path and prints a shell-quoted
|
|
1422
1484
|
move-aside command. Inspect it first: the file may contain unrelated data.
|
|
1423
|
-
An existing backup prompts before overwriting; preserve both files
|
|
1485
|
+
An existing backup prompts before overwriting; preserve both files.
|
|
1486
|
+
Android creation, recovery and teardown use per-AVD claims under
|
|
1487
|
+
~/.stim/avd-locks. Creation records the avdmanager process group, so a claim
|
|
1488
|
+
left by a killed creator becomes recoverable after that group exits. Retry
|
|
1489
|
+
after a live creator or cleanup finishes. An interruption before the child
|
|
1490
|
+
is recorded, or during synchronous teardown, can leave no verifiable
|
|
1491
|
+
identity: inspect the named claim and confirm that neither Stim nor its
|
|
1492
|
+
avdmanager or adb child is still using the AVD before removing only that
|
|
1493
|
+
claim. Keep the AVD and its incomplete workspace record. Once the claim is
|
|
1494
|
+
safe to clear, retry \`stim android\` to reconcile incomplete setup through
|
|
1495
|
+
owned-device teardown. GC and project removal refuse while the claim is
|
|
1496
|
+
live or unresolved.
|
|
1497
|
+
Parked-device adoption and deletion use claims under $STIM_HOME/pool-locks.
|
|
1498
|
+
If a holder dies during a synchronous native callback, its child cannot be
|
|
1499
|
+
identified and the device stays protected, including from older CLIs through
|
|
1500
|
+
an opaque inline marker. Verify that the old Stim process
|
|
1501
|
+
and its native children have finished before removing the named claim.
|
|
1502
|
+
Legacy inline \`deletionClaim\` fields in config.json have no process
|
|
1503
|
+
identity and require separate manual inspection; \`stim guide lifecycle pool\`
|
|
1504
|
+
describes their field-only recovery.`
|
|
1424
1505
|
},
|
|
1425
1506
|
STIM_CLAIM_UNAVAILABLE: {
|
|
1426
1507
|
summary: "a process identity or warm claim store is unavailable, so the protected operation refuses",
|
|
@@ -2062,8 +2143,21 @@ captured" (in metro.ndjson, bare RN)
|
|
|
2062
2143
|
"Timed out waiting for the lock at <path>."
|
|
2063
2144
|
Short directory locks serialize writes to config, workspace state, device
|
|
2064
2145
|
leases, ownership records, metadata, and cache manifests. The path identifies
|
|
2065
|
-
the lock.
|
|
2066
|
-
command holding it; if none is running, remove the named directory
|
|
2146
|
+
the lock. These locks wait up to 12s and never expire based on age. Wait for
|
|
2147
|
+
the command holding it; if none is running, remove the named directory.
|
|
2148
|
+
Short locks use the same process-identity claims as long operations, stored
|
|
2149
|
+
beside the visible directory at <path>.claims. An opaque marker in the visible
|
|
2150
|
+
directory also excludes older Stim versions. Only the exclusive claim holder
|
|
2151
|
+
can recover a recognized marker. A
|
|
2152
|
+
complete claim left by a proven-dead owner is recovered automatically on
|
|
2153
|
+
the next attempt. An unreadable or undecodable record instead reports
|
|
2154
|
+
STIM_CLAIM_REFUSED and names the claim to inspect; an unavailable native
|
|
2155
|
+
identity reports STIM_CLAIM_UNAVAILABLE without running the protected work.
|
|
2156
|
+
Older lock directories have no process identity. A visible directory left
|
|
2157
|
+
empty before marker publication or during final removal also cannot prove it is free.
|
|
2158
|
+
These paths still time out; verify that no holder is running before removing
|
|
2159
|
+
only the named directory. Standalone Metro and Expo cache packages use the
|
|
2160
|
+
same core protocol and do not require the Stim CLI.`
|
|
2067
2161
|
},
|
|
2068
2162
|
teardown: {
|
|
2069
2163
|
summary: "an unmanaged port, an unverified supervisor, and a failed device teardown",
|
|
@@ -2337,12 +2431,11 @@ a seed belongs to this workflow.
|
|
|
2337
2431
|
|
|
2338
2432
|
# If stale Metro transforms or file-map state require recovery:
|
|
2339
2433
|
stim start --reset-cache
|
|
2340
|
-
# Restarts only this app's verified owned Metro, retaining its port/devices
|
|
2341
|
-
#
|
|
2342
|
-
#
|
|
2343
|
-
#
|
|
2344
|
-
#
|
|
2345
|
-
# managers must honor Metro's fileMapCacheDirectory for file-map invalidation.
|
|
2434
|
+
# Restarts only this app's verified owned Metro, retaining its port/devices,
|
|
2435
|
+
# with Metro's own reset (resetCache on a bare server, expo start --clear).
|
|
2436
|
+
# That clears every store in the app's Metro config, including this app's
|
|
2437
|
+
# shared transform store, so other worktrees of the SAME app rebuild their
|
|
2438
|
+
# transforms too. Other apps and native build caches are unchanged.
|
|
2346
2439
|
|
|
2347
2440
|
# 3. Owned device booted, native inputs fingerprinted, cached build
|
|
2348
2441
|
# installed (or built), app launched wired to port 8082, device-log
|
|
@@ -2820,6 +2913,22 @@ result as proof instead of requiring an unrelated screenshot.`
|
|
|
2820
2913
|
retry it. The reported pool can temporarily exceed the bound rather than
|
|
2821
2914
|
orphaning a simulator.
|
|
2822
2915
|
|
|
2916
|
+
Adoption and deletion share a process-identity claim for each parked iOS
|
|
2917
|
+
simulator or Android emulator under $STIM_HOME/pool-locks. A live owner
|
|
2918
|
+
excludes both operations. A proven dead or different owner is recovered on
|
|
2919
|
+
the next attempt, unless it may have left native work running. Deletion also
|
|
2920
|
+
puts an opaque marker on the pool record so older Stim versions keep it
|
|
2921
|
+
protected. New versions resolve that marker through the same identity claim.
|
|
2922
|
+
A crash during a synchronous device-tool call leaves that work unverifiable; inspect
|
|
2923
|
+
the old process and its native children before following the claim's removal
|
|
2924
|
+
remedy. See \`stim guide errors STIM_CLAIM_REFUSED\`.
|
|
2925
|
+
|
|
2926
|
+
Older inline \`deletionClaim\` markers contain only a pid and stay protected,
|
|
2927
|
+
even when that pid is absent. After verifying that neither the old Stim
|
|
2928
|
+
process nor its native child is using the device, remove only that parked
|
|
2929
|
+
record's \`deletionClaim\` field from config.json, then retry. Keep the pool
|
|
2930
|
+
record and device; do not remove the whole config.
|
|
2931
|
+
|
|
2823
2932
|
and an adopting run says so where a plain boot would say \`booted\`:
|
|
2824
2933
|
|
|
2825
2934
|
device stim-app-412 (iPhone 17 26.5) (9C1F..) adopted (11s)
|
|
@@ -2863,6 +2972,14 @@ result as proof instead of requiring an unrelated screenshot.`
|
|
|
2863
2972
|
When a fresh AVD's preferred name belongs to another workspace or a parked
|
|
2864
2973
|
entry, Stim adds a short suffix instead of taking over that device. Always
|
|
2865
2974
|
use the actual device name and serial reported by the platform command.
|
|
2975
|
+
Creation reserves the owned AVD before running native tools, so other
|
|
2976
|
+
workspaces can update config while GC and teardown retain that reservation.
|
|
2977
|
+
Interrupted creation keeps an incomplete record and protects its recorded
|
|
2978
|
+
native process group until it exits. Retry \`stim android\` for owned-device
|
|
2979
|
+
cleanup and recreation; a live or unresolved per-AVD claim
|
|
2980
|
+
refuses cleanup. Follow \`stim guide errors STIM_CLAIM_REFUSED\` before
|
|
2981
|
+
manually clearing a claim, and keep the AVD data while its process state
|
|
2982
|
+
cannot be verified.
|
|
2866
2983
|
|
|
2867
2984
|
Android cleanup happens AFTER boot, before install or launch: \`adb shell
|
|
2868
2985
|
pm clear\` clears the adopting app's data while retaining its APK, and
|
|
@@ -3881,6 +3998,13 @@ to stats.json.corrupt-<unix ms> and starts a new one.`,
|
|
|
3881
3998
|
branches stay. A branch with an existing Stim ownership record is deleted
|
|
3882
3999
|
only when it has no unique commits.
|
|
3883
4000
|
|
|
4001
|
+
NAMED SERVER PORTS
|
|
4002
|
+
worktree remove stops TCP listeners on each named allocation and releases
|
|
4003
|
+
the ports. gc reports named allocations for missing workspaces; gc --delete
|
|
4004
|
+
stops their listeners and releases them. Unmounted or unresolved paths stay
|
|
4005
|
+
registered. Failed stops retain their allocations for a later retry.
|
|
4006
|
+
stim stop does not touch named ports. See guide ports.
|
|
4007
|
+
|
|
3884
4008
|
ON THE SOURCE CHECKOUT
|
|
3885
4009
|
git cannot remove a repository's main working tree, and deleting the source
|
|
3886
4010
|
checkout is not what anyone meant -- so there, and only there,
|
|
@@ -4700,10 +4824,17 @@ function renderIndex(version) {
|
|
|
4700
4824
|
lines.push("", "Read one with: stim guide <topic> (sectioned topics: stim guide <topic> <section>)");
|
|
4701
4825
|
return lines.join("\n");
|
|
4702
4826
|
}
|
|
4703
|
-
function guideCommand(program, version) {
|
|
4704
|
-
|
|
4827
|
+
function guideCommand(program, version, status = (running) => guideStatus({
|
|
4828
|
+
projectRoot: findProjectRoot(process.cwd()),
|
|
4829
|
+
running
|
|
4830
|
+
})) {
|
|
4831
|
+
program.command("guide [topic] [section]").description("Print reference documentation for THIS version of Stim (topics: " + topicNames().join(", ") + "). A topic with sections prints its section index; name a section to print only it, e.g. `stim guide errors STIM_NO_METRO` or `stim guide lifecycle builds`. Generated by the binary, so it cannot drift from the installed CLI.").action(async (topic, section) => {
|
|
4832
|
+
const withStatus = async (body) => {
|
|
4833
|
+
const block = await status(version);
|
|
4834
|
+
return block ? `${block}\n\n${body}` : body;
|
|
4835
|
+
};
|
|
4705
4836
|
if (!topic) {
|
|
4706
|
-
console.log(renderIndex(version));
|
|
4837
|
+
console.log(await withStatus(renderIndex(version)));
|
|
4707
4838
|
return;
|
|
4708
4839
|
}
|
|
4709
4840
|
const body = renderTopic(topic);
|
|
@@ -4715,7 +4846,7 @@ function guideCommand(program, version) {
|
|
|
4715
4846
|
process.exit(1);
|
|
4716
4847
|
}
|
|
4717
4848
|
if (!section) {
|
|
4718
|
-
console.log(body);
|
|
4849
|
+
console.log(topic === "agent" ? await withStatus(body) : body);
|
|
4719
4850
|
return;
|
|
4720
4851
|
}
|
|
4721
4852
|
const index = renderSectionIndex(topic);
|