stim 1.3.1 → 1.4.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 +13 -0
- package/dist/{android-CT-PkXUh.mjs → android-BTR1KTMP.mjs} +197 -114
- package/dist/{android-hMj83VpN.mjs → android-BkM4qTaN.mjs} +65 -72
- package/dist/{android-cas-DXorPCi_.mjs → android-cas-BjLRZyks.mjs} +15 -12
- package/dist/{app-install-DIp9riNx.mjs → app-install--PAocWvq.mjs} +2 -2
- package/dist/{build-slots-C4AouyNz.mjs → build-slots-D6sDzOe-.mjs} +7 -8
- package/dist/{cache-manifest-CXR-Y8pH.mjs → cache-manifest-D02TpYjA.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-6vdGngKa.mjs} +51 -51
- package/dist/dependency-state-BMirHEPD.mjs +76 -0
- package/dist/{deps-0Yt0Inly.mjs → deps-Ck4wuTwa.mjs} +1 -1
- package/dist/{dev-client-VfSZNLT4.mjs → dev-client-Cd0v7iZk.mjs} +12 -12
- package/dist/{device-Bbv45Z9Z.mjs → device-CKXLnRRb.mjs} +7 -7
- package/dist/{xcode-xnxyvJkD.mjs → device-CMDFzx7C.mjs} +208 -967
- package/dist/{device-lease-CJwK7OZr.mjs → device-lease-DDJr85OK.mjs} +3 -3
- package/dist/{device-pool-CcBNTvM7.mjs → device-pool-DJvbIBGW.mjs} +4 -4
- package/dist/{device-remote-DAA0Zm6Z.mjs → device-remote-CMfHhoc8.mjs} +7 -6
- package/dist/{doctor-B4EITgQB.mjs → doctor-B_mfURdt.mjs} +536 -114
- package/dist/{error-diagnostics-DwhNBFDU.mjs → error-diagnostics-_VmkqRZo.mjs} +7 -6
- package/dist/{gc-BRu62v4o.mjs → gc-0AyxmECv.mjs} +61 -27
- package/dist/{guide-D95E0u3i.mjs → guide-CGxdmQ0K.mjs} +126 -7
- package/dist/{ios-DAju3TVy.mjs → ios-CtmGLx3X.mjs} +2667 -2607
- package/dist/{ios-device-CWOM_S44.mjs → ios-device-DJOi9FR5.mjs} +1 -1
- package/dist/{logs-CAdwW6c2.mjs → logs-BF3qPA7w.mjs} +5 -5
- package/dist/metro-DFLmaVz8.mjs +99 -0
- package/dist/named-ports-BO7Zpjp0.mjs +137 -0
- package/dist/{ownership-8O073GIC.mjs → ownership-BvSpZVBk.mjs} +5 -5
- package/dist/{ownership-DXcol4oU.mjs → ownership-C08Yzrp7.mjs} +6 -6
- package/dist/ports-BiKqP92J.mjs +39 -0
- package/dist/ports-ClqG8GPt.mjs +90 -0
- package/dist/{project-fKmuIaMI.mjs → project-CBFCwnN5.mjs} +2 -2
- package/dist/{reclaim-CUmwucWG.mjs → reclaim-DpDVo-AP.mjs} +20 -13
- package/dist/{reload-CWpXoOgN.mjs → reload-ByTqg6ZI.mjs} +8 -8
- package/dist/rolldown-runtime-BsOwBuO_.mjs +30 -0
- package/dist/{server-bare-DEzPZLvf.mjs → server-bare-Buk-k8tI.mjs} +3 -6
- package/dist/{server-expo-DizT4OMk.mjs → server-expo-D4P7iTvf.mjs} +3 -3
- package/dist/server-expo-Dho5Raiw.mjs +2 -0
- package/dist/{settings-DEJf6_kJ.mjs → settings-DwfltIXQ.mjs} +2 -2
- package/dist/{slot-launch-CZklomj6.mjs → slot-launch-DeKen9e5.mjs} +4 -4
- package/dist/{start-B5G4NjiA.mjs → start-BpKUHcU_.mjs} +15 -13
- package/dist/state-CDbvmZdt.mjs +131 -0
- package/dist/{stats-BR-kwj0B.mjs → stats-C59QLKm2.mjs} +1 -1
- package/dist/{stats-CaaQr4yN.mjs → stats-k5qMjyxo.mjs} +4 -4
- package/dist/{status-CI9clRSb.mjs → status-Y2ij3dm6.mjs} +12 -11
- package/dist/{stop-CjlgDk0a.mjs → stop-_P2OQwmZ.mjs} +15 -14
- package/dist/{stop-CQhffpmX.mjs → stop-vKmmxhea.mjs} +2 -2
- package/dist/supervisor-run.d.mts +3 -27
- package/dist/supervisor-run.mjs +7 -6
- package/dist/{teardown--gESs9ck.mjs → teardown-KsPpvldq.mjs} +148 -109
- package/dist/{workspace-process-lock-IBj1Towr.mjs → workspace-process-lock-UEIrvZMJ.mjs} +4 -4
- package/dist/workspace-state-Do1e2mOH.mjs +146 -0
- package/dist/{worktree-DtQGO9-s.mjs → worktree-BvcAIMdJ.mjs} +24 -25
- package/dist/{worktree-Eq6TLH8N.mjs → worktree-DWNx4tUg.mjs} +32 -2
- package/dist/xcode-D9tVItl-.mjs +860 -0
- package/package.json +7 -7
- 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
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { D as withDirLock, F as deviceSlotPlatforms, P as deviceSlotKey, f as getProject } from "./config-6vdGngKa.mjs";
|
|
3
|
+
import { r as readWorkspaceState } from "./workspace-state-Do1e2mOH.mjs";
|
|
4
|
+
import { d as readWorkspaceLaunches } from "./state-CDbvmZdt.mjs";
|
|
4
5
|
import { n as deviceConsoleLevel } from "./ios-device-D3pzTKQE.mjs";
|
|
5
|
-
import { i as resolveProjectMetro } from "./metro-
|
|
6
|
+
import { i as resolveProjectMetro } from "./metro-DFLmaVz8.mjs";
|
|
6
7
|
import { n as parseLogcatLine, t as androidClockOffset } from "./android-BW8i_YxU.mjs";
|
|
7
|
-
import { _ as launchErrorPreview } from "./command-output-
|
|
8
|
-
import { n as androidHome } from "./android-
|
|
9
|
-
import { a as parseLease, n as fileLeaseIo, t as deviceLeasePath } from "./device-lease-
|
|
8
|
+
import { _ as launchErrorPreview } from "./command-output-BuIb_ZOI.mjs";
|
|
9
|
+
import { n as androidHome } from "./android-BkM4qTaN.mjs";
|
|
10
|
+
import { a as parseLease, n as fileLeaseIo, t as deviceLeasePath } from "./device-lease-DDJr85OK.mjs";
|
|
10
11
|
import { l as readLogRecords, t as attachExpoErrorContext } from "./logs-query-Cdp5aaCH.mjs";
|
|
11
12
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
12
13
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -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 {
|
|
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-6vdGngKa.mjs";
|
|
3
|
+
import { i as registeredCaches } from "./cache-manifest-D02TpYjA.mjs";
|
|
4
|
+
import { h as workspaceDir, y as workspaceStateFile } from "./workspace-state-Do1e2mOH.mjs";
|
|
5
|
+
import { _ as repoRoot, s as gitCommonDir } from "./worktree-DWNx4tUg.mjs";
|
|
6
|
+
import { a as findProjectRoot, i as detectIsExpo } from "./project-CBFCwnN5.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-BkM4qTaN.mjs";
|
|
9
|
+
import { A as resolveSettings, N as settingShapeErrors, a as SETTING_SHAPE_REMEDY } from "./settings-DwfltIXQ.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-KsPpvldq.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-DDJr85OK.mjs";
|
|
13
|
+
import { n as listBuildSlots } from "./build-slots-D6sDzOe-.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-CMfHhoc8.mjs";
|
|
15
|
+
import { n as reclaimProject, t as describeDereferenced } from "./reclaim-DpDVo-AP.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,4 @@
|
|
|
1
|
-
import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-
|
|
1
|
+
import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-DwfltIXQ.mjs";
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
//#endregion
|
|
4
4
|
//#region src/guide/index.ts
|
|
@@ -226,8 +226,10 @@ shut down the phone or uninstall the app.
|
|
|
226
226
|
|
|
227
227
|
Treat a refusal as an ownership or state mismatch: read its code and remedy.
|
|
228
228
|
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.
|
|
229
|
+
Stim leaves externally started Metro servers alone. Stop them with their original
|
|
230
|
+
tool; neither a matching Metro port nor --force grants process ownership.
|
|
231
|
+
Named ports are separate: ports stop kills TCP listeners on the workspace's
|
|
232
|
+
reserved named ports, even outside the workspace. Read guide ports before use.
|
|
231
233
|
|
|
232
234
|
Ask the user before these actions:
|
|
233
235
|
|
|
@@ -266,6 +268,7 @@ Read the matching guide before acting in these situations:
|
|
|
266
268
|
| Refusal with a CODE | stim guide errors <CODE> |
|
|
267
269
|
| Running under a sandbox | stim guide errors sandbox |
|
|
268
270
|
| Release configuration or ...Release variant | stim guide lifecycle release |
|
|
271
|
+
| Web or API server ports | stim guide ports |
|
|
269
272
|
| Remote device, custom Metro, or tunnel | stim guide metro |
|
|
270
273
|
| Cache miss, bypass, or fingerprint exclusions | stim guide lifecycle builds |
|
|
271
274
|
| Capacity limits | stim guide lifecycle concurrency |
|
|
@@ -301,6 +304,7 @@ FULL TOPIC LIST
|
|
|
301
304
|
stim guide lifecycle release # Release configurations and ...Release variants
|
|
302
305
|
stim guide facts # the --json payloads
|
|
303
306
|
stim guide facts devmenu # the Expo dev menu or Tools button over the app
|
|
307
|
+
stim guide ports # named ports for web and API servers
|
|
304
308
|
stim guide metro # supervisor, custom Metro, tunnels, and remote devices
|
|
305
309
|
stim guide logs # filters, record shape, and capture limits
|
|
306
310
|
stim guide cleanup # what reclaims a device, and what deletes
|
|
@@ -896,6 +900,58 @@ STARTING YOUR OWN BUNDLER STILL WORKS
|
|
|
896
900
|
|
|
897
901
|
\`stop\` leaves an externally started server running. Stop it with the tool
|
|
898
902
|
that started it.`
|
|
903
|
+
},
|
|
904
|
+
ports: {
|
|
905
|
+
summary: "Workspace ports for web and API servers that Stim does not manage",
|
|
906
|
+
body: () => `NAMED SERVER PORTS
|
|
907
|
+
|
|
908
|
+
If Stim is not installed globally, replace stim with npx stim.
|
|
909
|
+
|
|
910
|
+
stim ports get web
|
|
911
|
+
pnpm exec vite --port "$(stim ports get web)" --strictPort
|
|
912
|
+
stim ports
|
|
913
|
+
stim ports stop web --dry-run
|
|
914
|
+
stim ports stop web
|
|
915
|
+
stim ports release api
|
|
916
|
+
|
|
917
|
+
get <label> allocates on first use and prints only the number to stdout.
|
|
918
|
+
Repeated calls reuse it, even while a server is listening. Labels start with
|
|
919
|
+
a letter and contain up to 64 letters, digits, underscores, or hyphens.
|
|
920
|
+
metro is reserved; use stim start and stim stop for managed Metro.
|
|
921
|
+
|
|
922
|
+
New allocations scan TCP ports 8900-8999. They skip registry reservations
|
|
923
|
+
and existing listeners, announcing occupied ports and upward retries on
|
|
924
|
+
stderr. Allocation requires lsof. All 100 ports occupied or reserved is a
|
|
925
|
+
refusal; stop or release unused allocations in their owning workspaces.
|
|
926
|
+
|
|
927
|
+
The machine registry, under STIM_HOME, serializes allocation and cleanup.
|
|
928
|
+
The workspace is the nearest package.json directory, resolved through
|
|
929
|
+
symlinks. Use the same package directory for every command in a monorepo.
|
|
930
|
+
The allocation reserves a number, not a listening socket. Another process
|
|
931
|
+
can bind it before your server does. Use strict-port behavior when supported
|
|
932
|
+
and verify the server bound the number supplied. Stim does not start,
|
|
933
|
+
supervise, or capture logs for these servers.
|
|
934
|
+
|
|
935
|
+
ports lists named labels and ports, plus Metro marked managed.
|
|
936
|
+
ports stop [label] kills TCP listeners on those named ports and releases
|
|
937
|
+
the allocations. It sends SIGTERM, waits two seconds, then SIGKILL if needed.
|
|
938
|
+
It prints the PID and command for each stopped process. The listener's cwd
|
|
939
|
+
can be anywhere: the named reservation is permission to stop that listener.
|
|
940
|
+
Reserve only services this workspace may stop. --dry-run prints what would
|
|
941
|
+
be stopped and released, without doing either. A failed inspection or stop
|
|
942
|
+
keeps that allocation for retry; other labels are still processed.
|
|
943
|
+
ports release [label] releases without signalling a process.
|
|
944
|
+
Omitting the label selects every named port, never Metro. stim stop leaves
|
|
945
|
+
named ports alone.
|
|
946
|
+
|
|
947
|
+
worktree remove stops named listeners and releases their allocations.
|
|
948
|
+
gc reports allocations whose workspace no longer exists; gc --delete stops
|
|
949
|
+
and releases them. Unmounted or unresolved workspace paths are retained.
|
|
950
|
+
Failed stops keep the registry entry. Use the same current Stim version for
|
|
951
|
+
cleanup: versions without ports do not know about named allocations.
|
|
952
|
+
|
|
953
|
+
A shared API does not get a shared reservation. Pass its port by environment
|
|
954
|
+
instead of allocating a separate label in every worktree.`
|
|
899
955
|
},
|
|
900
956
|
logs: {
|
|
901
957
|
summary: "Querying the merged NDJSON timeline, and what --errors means",
|
|
@@ -1401,7 +1457,7 @@ code, never on the message.`,
|
|
|
1401
1457
|
run the command again.`
|
|
1402
1458
|
},
|
|
1403
1459
|
STIM_CLAIM_REFUSED: {
|
|
1404
|
-
summary: "
|
|
1460
|
+
summary: "an ownership claim blocks the operation; inspect its holder before removing an unresolved claim",
|
|
1405
1461
|
body: () => `STIM_CLAIM_REFUSED
|
|
1406
1462
|
A build lock records the holder's process IDENTITY, not just its pid, so a
|
|
1407
1463
|
recycled pid reads as a gone builder rather than a live one, and a builder
|
|
@@ -1420,7 +1476,26 @@ code, never on the message.`,
|
|
|
1420
1476
|
and nothing was copied. A STIM_HOME or warm-locks ancestor that is a file
|
|
1421
1477
|
also refuses. The message names that blocking path and prints a shell-quoted
|
|
1422
1478
|
move-aside command. Inspect it first: the file may contain unrelated data.
|
|
1423
|
-
An existing backup prompts before overwriting; preserve both files
|
|
1479
|
+
An existing backup prompts before overwriting; preserve both files.
|
|
1480
|
+
Android creation, recovery and teardown use per-AVD claims under
|
|
1481
|
+
~/.stim/avd-locks. Creation records the avdmanager process group, so a claim
|
|
1482
|
+
left by a killed creator becomes recoverable after that group exits. Retry
|
|
1483
|
+
after a live creator or cleanup finishes. An interruption before the child
|
|
1484
|
+
is recorded, or during synchronous teardown, can leave no verifiable
|
|
1485
|
+
identity: inspect the named claim and confirm that neither Stim nor its
|
|
1486
|
+
avdmanager or adb child is still using the AVD before removing only that
|
|
1487
|
+
claim. Keep the AVD and its incomplete workspace record. Once the claim is
|
|
1488
|
+
safe to clear, retry \`stim android\` to reconcile incomplete setup through
|
|
1489
|
+
owned-device teardown. GC and project removal refuse while the claim is
|
|
1490
|
+
live or unresolved.
|
|
1491
|
+
Parked-device adoption and deletion use claims under $STIM_HOME/pool-locks.
|
|
1492
|
+
If a holder dies during a synchronous native callback, its child cannot be
|
|
1493
|
+
identified and the device stays protected, including from older CLIs through
|
|
1494
|
+
an opaque inline marker. Verify that the old Stim process
|
|
1495
|
+
and its native children have finished before removing the named claim.
|
|
1496
|
+
Legacy inline \`deletionClaim\` fields in config.json have no process
|
|
1497
|
+
identity and require separate manual inspection; \`stim guide lifecycle pool\`
|
|
1498
|
+
describes their field-only recovery.`
|
|
1424
1499
|
},
|
|
1425
1500
|
STIM_CLAIM_UNAVAILABLE: {
|
|
1426
1501
|
summary: "a process identity or warm claim store is unavailable, so the protected operation refuses",
|
|
@@ -2062,8 +2137,21 @@ captured" (in metro.ndjson, bare RN)
|
|
|
2062
2137
|
"Timed out waiting for the lock at <path>."
|
|
2063
2138
|
Short directory locks serialize writes to config, workspace state, device
|
|
2064
2139
|
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
|
|
2140
|
+
the lock. These locks wait up to 12s and never expire based on age. Wait for
|
|
2141
|
+
the command holding it; if none is running, remove the named directory.
|
|
2142
|
+
Short locks use the same process-identity claims as long operations, stored
|
|
2143
|
+
beside the visible directory at <path>.claims. An opaque marker in the visible
|
|
2144
|
+
directory also excludes older Stim versions. Only the exclusive claim holder
|
|
2145
|
+
can recover a recognized marker. A
|
|
2146
|
+
complete claim left by a proven-dead owner is recovered automatically on
|
|
2147
|
+
the next attempt. An unreadable or undecodable record instead reports
|
|
2148
|
+
STIM_CLAIM_REFUSED and names the claim to inspect; an unavailable native
|
|
2149
|
+
identity reports STIM_CLAIM_UNAVAILABLE without running the protected work.
|
|
2150
|
+
Older lock directories have no process identity. A visible directory left
|
|
2151
|
+
empty before marker publication or during final removal also cannot prove it is free.
|
|
2152
|
+
These paths still time out; verify that no holder is running before removing
|
|
2153
|
+
only the named directory. Standalone Metro and Expo cache packages use the
|
|
2154
|
+
same core protocol and do not require the Stim CLI.`
|
|
2067
2155
|
},
|
|
2068
2156
|
teardown: {
|
|
2069
2157
|
summary: "an unmanaged port, an unverified supervisor, and a failed device teardown",
|
|
@@ -2820,6 +2908,22 @@ result as proof instead of requiring an unrelated screenshot.`
|
|
|
2820
2908
|
retry it. The reported pool can temporarily exceed the bound rather than
|
|
2821
2909
|
orphaning a simulator.
|
|
2822
2910
|
|
|
2911
|
+
Adoption and deletion share a process-identity claim for each parked iOS
|
|
2912
|
+
simulator or Android emulator under $STIM_HOME/pool-locks. A live owner
|
|
2913
|
+
excludes both operations. A proven dead or different owner is recovered on
|
|
2914
|
+
the next attempt, unless it may have left native work running. Deletion also
|
|
2915
|
+
puts an opaque marker on the pool record so older Stim versions keep it
|
|
2916
|
+
protected. New versions resolve that marker through the same identity claim.
|
|
2917
|
+
A crash during a synchronous device-tool call leaves that work unverifiable; inspect
|
|
2918
|
+
the old process and its native children before following the claim's removal
|
|
2919
|
+
remedy. See \`stim guide errors STIM_CLAIM_REFUSED\`.
|
|
2920
|
+
|
|
2921
|
+
Older inline \`deletionClaim\` markers contain only a pid and stay protected,
|
|
2922
|
+
even when that pid is absent. After verifying that neither the old Stim
|
|
2923
|
+
process nor its native child is using the device, remove only that parked
|
|
2924
|
+
record's \`deletionClaim\` field from config.json, then retry. Keep the pool
|
|
2925
|
+
record and device; do not remove the whole config.
|
|
2926
|
+
|
|
2823
2927
|
and an adopting run says so where a plain boot would say \`booted\`:
|
|
2824
2928
|
|
|
2825
2929
|
device stim-app-412 (iPhone 17 26.5) (9C1F..) adopted (11s)
|
|
@@ -2863,6 +2967,14 @@ result as proof instead of requiring an unrelated screenshot.`
|
|
|
2863
2967
|
When a fresh AVD's preferred name belongs to another workspace or a parked
|
|
2864
2968
|
entry, Stim adds a short suffix instead of taking over that device. Always
|
|
2865
2969
|
use the actual device name and serial reported by the platform command.
|
|
2970
|
+
Creation reserves the owned AVD before running native tools, so other
|
|
2971
|
+
workspaces can update config while GC and teardown retain that reservation.
|
|
2972
|
+
Interrupted creation keeps an incomplete record and protects its recorded
|
|
2973
|
+
native process group until it exits. Retry \`stim android\` for owned-device
|
|
2974
|
+
cleanup and recreation; a live or unresolved per-AVD claim
|
|
2975
|
+
refuses cleanup. Follow \`stim guide errors STIM_CLAIM_REFUSED\` before
|
|
2976
|
+
manually clearing a claim, and keep the AVD data while its process state
|
|
2977
|
+
cannot be verified.
|
|
2866
2978
|
|
|
2867
2979
|
Android cleanup happens AFTER boot, before install or launch: \`adb shell
|
|
2868
2980
|
pm clear\` clears the adopting app's data while retaining its APK, and
|
|
@@ -3881,6 +3993,13 @@ to stats.json.corrupt-<unix ms> and starts a new one.`,
|
|
|
3881
3993
|
branches stay. A branch with an existing Stim ownership record is deleted
|
|
3882
3994
|
only when it has no unique commits.
|
|
3883
3995
|
|
|
3996
|
+
NAMED SERVER PORTS
|
|
3997
|
+
worktree remove stops TCP listeners on each named allocation and releases
|
|
3998
|
+
the ports. gc reports named allocations for missing workspaces; gc --delete
|
|
3999
|
+
stops their listeners and releases them. Unmounted or unresolved paths stay
|
|
4000
|
+
registered. Failed stops retain their allocations for a later retry.
|
|
4001
|
+
stim stop does not touch named ports. See guide ports.
|
|
4002
|
+
|
|
3884
4003
|
ON THE SOURCE CHECKOUT
|
|
3885
4004
|
git cannot remove a repository's main working tree, and deleting the source
|
|
3886
4005
|
checkout is not what anyone meant -- so there, and only there,
|