sootsim 0.1.169 → 0.1.170
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 +66 -63
- package/detox/index.ts +3 -3
- package/dist-cli/bin.js +3 -3
- package/dist-cli/chunks/agent-3C2BKQKX.js +46 -0
- package/dist-cli/chunks/{agent-wrapper-Y5FQA3RL.js → agent-wrapper-OIKCYOXZ.js} +2 -2
- package/dist-cli/chunks/{app-fonts-FYVA4XV6.js → app-fonts-25O32NAP.js} +2 -2
- package/dist-cli/chunks/{assert-U64QBDM2.js → assert-ONEP4NQU.js} +2 -2
- package/dist-cli/chunks/beta-4E5USTEI.js +2 -0
- package/dist-cli/chunks/{camera-3GXBVIAM.js → camera-RORW4MAA.js} +2 -2
- package/dist-cli/chunks/{chunk-5C6BR24W.js → chunk-25RFZ6WP.js} +6 -6
- package/dist-cli/chunks/chunk-35GMFXVJ.js +2 -0
- package/dist-cli/chunks/{chunk-GLRFKYDV.js → chunk-3TM7DHWE.js} +2 -2
- package/dist-cli/chunks/{chunk-4F3BBP7B.js → chunk-4XVY5TUF.js} +2 -2
- package/dist-cli/chunks/{chunk-LZEL2RU3.js → chunk-5ZHUPPS5.js} +1 -1
- package/dist-cli/chunks/{chunk-GC4THE6K.js → chunk-6FAEORJ2.js} +2 -2
- package/dist-cli/chunks/{chunk-G2ZFDIPK.js → chunk-6TSXXN2W.js} +4 -4
- package/dist-cli/chunks/chunk-AJF3QF4K.js +1 -0
- package/dist-cli/chunks/{chunk-FIDPRJYH.js → chunk-AUCNBB6Q.js} +2 -2
- package/dist-cli/chunks/{chunk-SIB6I72P.js → chunk-BP3EGFER.js} +2 -2
- package/dist-cli/chunks/{chunk-OGLWXPVG.js → chunk-DAXME77O.js} +3 -3
- package/dist-cli/chunks/chunk-DGJTEFE7.js +13 -0
- package/dist-cli/chunks/chunk-DIRDEKRW.js +23 -0
- package/dist-cli/chunks/{chunk-3L4NRJ6C.js → chunk-DKTC53HV.js} +1 -1
- package/dist-cli/chunks/{chunk-KUUFY6FC.js → chunk-DWXC25XG.js} +1 -1
- package/dist-cli/chunks/{chunk-CR6DOLUD.js → chunk-E3FKMY5E.js} +1 -1
- package/dist-cli/chunks/chunk-ER4GBJRY.js +2 -0
- package/dist-cli/chunks/chunk-EX6V4ZV6.js +6 -0
- package/dist-cli/chunks/{chunk-VMYMPL6H.js → chunk-GQH3PD3W.js} +5 -5
- package/dist-cli/chunks/{chunk-MVOHANJG.js → chunk-GST4YSBO.js} +4 -4
- package/dist-cli/chunks/{chunk-BIWJE7CB.js → chunk-I4RV5I6V.js} +1 -1
- package/dist-cli/chunks/{chunk-Y6IDAARY.js → chunk-I5WXVKR6.js} +1 -1
- package/dist-cli/chunks/{chunk-HC72ILJK.js → chunk-IO7KAVFK.js} +2 -2
- package/dist-cli/chunks/{chunk-XEH4QGWB.js → chunk-LMX7UB5T.js} +2 -2
- package/dist-cli/chunks/{chunk-YADWU7OZ.js → chunk-N4YCSOCR.js} +2 -2
- package/dist-cli/chunks/{chunk-IODOTOOP.js → chunk-NI3L4A65.js} +2 -2
- package/dist-cli/chunks/{chunk-IACEJQIO.js → chunk-ODGEH6OW.js} +2 -2
- package/dist-cli/chunks/{chunk-DNA6VS6M.js → chunk-Q4NDYO2U.js} +1 -1
- package/dist-cli/chunks/{chunk-PV6MBKKE.js → chunk-QPRF3UYX.js} +2 -2
- package/dist-cli/chunks/{chunk-M2TMFGZH.js → chunk-QXJMXSQP.js} +1 -1
- package/dist-cli/chunks/chunk-RLKSLUNR.js +2 -0
- package/dist-cli/chunks/{chunk-WZG3YVJR.js → chunk-S244IT4W.js} +1 -1
- package/dist-cli/chunks/chunk-SDHOM6ZG.js +62 -0
- package/dist-cli/chunks/{chunk-B7BMSU7H.js → chunk-TXKOJ3P5.js} +1 -1
- package/dist-cli/chunks/{chunk-IBEMMV5E.js → chunk-UDMJSFSH.js} +8 -8
- package/dist-cli/chunks/{chunk-DQZEN256.js → chunk-ULV4PWN4.js} +1 -1
- package/dist-cli/chunks/{chunk-2TYEWVS4.js → chunk-V4HTQPMA.js} +1 -1
- package/dist-cli/chunks/chunk-VATHADSI.js +2 -0
- package/dist-cli/chunks/{chunk-5Q7IHJ7K.js → chunk-VUOCUCJ2.js} +2 -2
- package/dist-cli/chunks/{chunk-JDGLBW64.js → chunk-WN7R4GL4.js} +1 -1
- package/dist-cli/chunks/chunk-XOTJD6PU.js +118 -0
- package/dist-cli/chunks/chunk-XUNPVF5K.js +1 -0
- package/dist-cli/chunks/{chunk-KZIXAYN5.js → chunk-YMFSRCHL.js} +4 -4
- package/dist-cli/chunks/{chunk-X2HNVXNM.js → chunk-YV74D4MG.js} +2 -2
- package/dist-cli/chunks/{chunk-SNX3M4XD.js → chunk-YVTWSC5Y.js} +3 -3
- package/dist-cli/chunks/cli-version-EKKWCHRX.js +2 -0
- package/dist-cli/chunks/{compat-ORRWNXVT.js → compat-ZVZM5TML.js} +3 -3
- package/dist-cli/chunks/control-TWINYHMY.js +2 -0
- package/dist-cli/chunks/{cpu-profile-6PRSBZ2F.js → cpu-profile-RWGQTWLP.js} +2 -2
- package/dist-cli/chunks/daemon-AOSMNBD4.js +2 -0
- package/dist-cli/chunks/{debug-Q3J2X4WW.js → debug-R7PL3MHF.js} +5 -5
- package/dist-cli/chunks/{detox-DN57GMMJ.js → detox-UIJMKIGQ.js} +2 -2
- package/dist-cli/chunks/{device-IL5TPYGU.js → device-7SRVX2PU.js} +2 -2
- package/dist-cli/chunks/{diagnose-BW6QWP4F.js → diagnose-OXAKLLZT.js} +2 -2
- package/dist-cli/chunks/drivers-BPPG22VP.js +2 -0
- package/dist-cli/chunks/{electron-DGMSXQWG.js → electron-CTCH4VOL.js} +3 -3
- package/dist-cli/chunks/flow-KA2WCWDL.js +2 -0
- package/dist-cli/chunks/help-XBQIK2XY.js +2 -0
- package/dist-cli/chunks/{hints-TK3EHB4U.js → hints-P3ZIAP3Z.js} +2 -2
- package/dist-cli/chunks/home-paths-ZSCTLOYE.js +2 -0
- package/dist-cli/chunks/{inspect-NFWFGU4B.js → inspect-2ABU5WET.js} +24 -24
- package/dist-cli/chunks/{install-desktop-GB3JKSNX.js → install-desktop-4NOQ3YY4.js} +3 -3
- package/dist-cli/chunks/{keys-RAAHRIFH.js → keys-RPVEUNUC.js} +2 -2
- package/dist-cli/chunks/{login-KQ37GHDE.js → login-6D6DXBO3.js} +4 -4
- package/dist-cli/chunks/{logout-63SH2Y25.js → logout-T5OSWDTJ.js} +2 -2
- package/dist-cli/chunks/{maestro-24BT3MML.js → maestro-MKCHEOKA.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-EYD2K3QH.js +2 -0
- package/dist-cli/chunks/{preview-KQAOVN6R.js → preview-S52ZNGN2.js} +2 -2
- package/dist-cli/chunks/{profile-AN2B4NJT.js → profile-IG5F3LTL.js} +2 -2
- package/dist-cli/chunks/{react-ATGV35B4.js → react-275HCOFC.js} +2 -2
- package/dist-cli/chunks/{record-36662T3R.js → record-YT63SUHO.js} +4 -4
- package/dist-cli/chunks/runtime-WYZMDZAK.js +2 -0
- package/dist-cli/chunks/{screenshot-K4N5MPAT.js → screenshot-5AZ4MY3A.js} +4 -4
- package/dist-cli/chunks/{screenshot-mode-4QOJDLSH.js → screenshot-mode-4S4EX2XJ.js} +2 -2
- package/dist-cli/chunks/{screenshots-TB35YMSR.js → screenshots-UUJNZSG7.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-W6X33BZ4.js → screenshots-capture-I66JD3AD.js} +2 -2
- package/dist-cli/chunks/{server-L2PKDJZ2.js → serve-O46Q4WAD.js} +18 -17
- package/dist-cli/chunks/setup-C44N54O7.js +77 -0
- package/dist-cli/chunks/skills-PPVS4XOQ.js +40 -0
- package/dist-cli/chunks/{slides-TORKO36P.js → slides-ZWSZJZUY.js} +2 -2
- package/dist-cli/chunks/store-3SLGP5O3.js +2 -0
- package/dist-cli/chunks/telemetry-2XLLWARK.js +2 -0
- package/dist-cli/chunks/{test-5VCENVW3.js → test-362G4M5A.js} +3 -3
- package/dist-cli/chunks/{three-mode-ZVS2DSX6.js → three-mode-JNVTM2UT.js} +2 -2
- package/dist-cli/chunks/{timeline-TNC5OWLF.js → timeline-VKC6ULRK.js} +2 -2
- package/dist-cli/chunks/{upgrade-E7IO6A7Z.js → upgrade-SJPX4SPA.js} +2 -2
- package/dist-cli/chunks/upload-MXOBV6RT.js +2 -0
- package/dist-cli/chunks/version-4Z7AFNH3.js +4 -0
- package/dist-cli/chunks/web-WB2I2AWL.js +2 -0
- package/dist-cli/chunks/{what-happened-RMHZ7DGX.js → what-happened-KQCWMQJT.js} +3 -3
- package/dist-cli/chunks/{whoami-D53ANHR5.js → whoami-K76PXAD4.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +4 -5
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +3 -6
- package/dist-lib/beta.mjs +3 -5
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +4 -4
- package/dist-lib/dev-bundle-resolution.cjs +2 -9
- package/dist-lib/home-paths.cjs +59 -1
- package/dist-lib/host/bridge-host.cjs +67 -5
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +2 -2
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro.cjs +2 -2
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +5 -4
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +124 -8
- package/dist-lib/vite.cjs +2 -2
- package/package.json +2 -1
- package/scripts/dev-server-scanner.ts +3 -4
- package/scripts/postinstall.cjs +2 -2
- package/scripts/preuninstall.cjs +5 -7
- package/skills/soot.md +178 -0
- package/skills/sootsim-debug.md +384 -0
- package/skills/sootsim-setup.md +96 -0
- package/skills/sootsim-test.md +292 -0
- package/skills/sootsim-visual.md +122 -0
- package/src/agent-daemon-client.ts +4 -14
- package/src/beta.ts +3 -5
- package/src/dev-bundle-resolution.ts +1 -14
- package/src/home-paths.ts +77 -2
- package/src/host/agent-host.ts +1 -1
- package/src/host/bridge-host.ts +65 -6
- package/src/metro-plugin.ts +1 -1
- package/src/runtime-assets.ts +1 -1
- package/src/vite-plugin.ts +1 -0
- package/dist-cli/chunks/agent-V3GVCRPL.js +0 -46
- package/dist-cli/chunks/auto-bootstrap-YXDP3WKH.js +0 -2
- package/dist-cli/chunks/beta-FGSMZWLP.js +0 -2
- package/dist-cli/chunks/chunk-2IFWVIKM.js +0 -2
- package/dist-cli/chunks/chunk-3T36XLP3.js +0 -119
- package/dist-cli/chunks/chunk-5KY7TQ42.js +0 -5
- package/dist-cli/chunks/chunk-BQOMDL4K.js +0 -1
- package/dist-cli/chunks/chunk-FHMPJZKM.js +0 -7
- package/dist-cli/chunks/chunk-GQAWFQNN.js +0 -23
- package/dist-cli/chunks/chunk-HJTKKF7M.js +0 -13
- package/dist-cli/chunks/chunk-K4JAWKOY.js +0 -1
- package/dist-cli/chunks/chunk-NXGQS7IR.js +0 -2
- package/dist-cli/chunks/chunk-R2INPDGW.js +0 -1
- package/dist-cli/chunks/chunk-SLL5SZN4.js +0 -2
- package/dist-cli/chunks/chunk-XM66K64H.js +0 -79
- package/dist-cli/chunks/cli-version-3L6FFDIX.js +0 -2
- package/dist-cli/chunks/config-5IB6ONJ2.js +0 -45
- package/dist-cli/chunks/control-BM4V27OB.js +0 -2
- package/dist-cli/chunks/daemon-62MZT4G4.js +0 -67
- package/dist-cli/chunks/drivers-V6QDFZQD.js +0 -2
- package/dist-cli/chunks/flow-VBM6TU32.js +0 -2
- package/dist-cli/chunks/help-XWKNL743.js +0 -2
- package/dist-cli/chunks/home-paths-G23H3RO6.js +0 -2
- package/dist-cli/chunks/install-5YL7FITA.js +0 -2
- package/dist-cli/chunks/launch-DYFE4CAD.js +0 -16
- package/dist-cli/chunks/optional-demo-registry-JJXPB3UD.js +0 -2
- package/dist-cli/chunks/runtime-NRMC3U3D.js +0 -2
- package/dist-cli/chunks/runtime-delivery-RO6CTYPQ.js +0 -2
- package/dist-cli/chunks/setup-repo-AK6QOUE7.js +0 -2
- package/dist-cli/chunks/skills-KDSOWUOE.js +0 -10
- package/dist-cli/chunks/start-GH2AOUX6.js +0 -23
- package/dist-cli/chunks/store-JHW65VGQ.js +0 -2
- package/dist-cli/chunks/telemetry-SZLRXJXW.js +0 -2
- package/dist-cli/chunks/upload-KKEWETA5.js +0 -2
- package/dist-cli/chunks/version-37OD33SE.js +0 -4
- package/dist-cli/chunks/web-4JVMIBTB.js +0 -2
package/dist-lib/profiles.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.170 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
package/dist-lib/render-mode.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.170 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.170 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -33,6 +33,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
33
33
|
var dev_server_scanner_exports = {};
|
|
34
34
|
__export(dev_server_scanner_exports, {
|
|
35
35
|
__applyManifestForTests: () => __applyManifestForTests,
|
|
36
|
+
__isSootSelfServerForTests: () => __isSootSelfServerForTests,
|
|
36
37
|
__resetScannerCache: () => __resetScannerCache,
|
|
37
38
|
__shouldReuseScannerCacheEntry: () => __shouldReuseScannerCacheEntry,
|
|
38
39
|
discoverListeningPorts: () => discoverListeningPorts,
|
|
@@ -412,12 +413,11 @@ async function probePort(port, buildIconProxyUrl) {
|
|
|
412
413
|
return null;
|
|
413
414
|
}
|
|
414
415
|
function isSootSelfServer(server) {
|
|
415
|
-
const projectName = server.projectName?.trim().toLowerCase();
|
|
416
|
-
if (projectName === "soot" || projectName === "sootsim") return true;
|
|
417
416
|
const bundleId = server.bundleId?.trim().toLowerCase();
|
|
418
|
-
if (bundleId?.startsWith("dev.
|
|
417
|
+
if (bundleId?.startsWith("dev.sootsim.")) return true;
|
|
419
418
|
return false;
|
|
420
419
|
}
|
|
420
|
+
var __isSootSelfServerForTests = isSootSelfServer;
|
|
421
421
|
var portCache = /* @__PURE__ */ new Map();
|
|
422
422
|
var NEGATIVE_CACHE_TTL_MS = 3e4;
|
|
423
423
|
var WEAK_RESULT_CACHE_TTL_MS = 1500;
|
|
@@ -507,6 +507,7 @@ async function scanDevServers(opts = {}) {
|
|
|
507
507
|
// Annotate the CommonJS export names for ESM import in node:
|
|
508
508
|
0 && (module.exports = {
|
|
509
509
|
__applyManifestForTests,
|
|
510
|
+
__isSootSelfServerForTests,
|
|
510
511
|
__resetScannerCache,
|
|
511
512
|
__shouldReuseScannerCacheEntry,
|
|
512
513
|
discoverListeningPorts,
|
package/dist-lib/sdk.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.170 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/sdk.mjs
CHANGED
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.170 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -3249,8 +3249,8 @@ var init_registry = __esm({
|
|
|
3249
3249
|
{
|
|
3250
3250
|
range: ">=3.1.0",
|
|
3251
3251
|
coverage: 0.85,
|
|
3252
|
-
note: "
|
|
3253
|
-
working: "
|
|
3252
|
+
note: "native-seam only \u2014 upstream expo-speech-recognition JS (ExpoWebSpeechRecognition, useSpeechRecognitionEvent, constants, and direct module API) runs unchanged from the bundle; SootSim registers only the ExpoSpeechRecognition native module, backed by the host-service SpeechRecognition bridge when available",
|
|
3253
|
+
working: "ExpoSpeechRecognition native module start/stop/abort/state, native event addListener/remove, granted permission helpers, recognition availability, speech services/default-service helpers, supported-locales shape, iOS audio-session getters/setters; upstream ExpoWebSpeechRecognition class, grammar/list classes, hook, and constants stay authoritative",
|
|
3254
3254
|
missing: "native SFSpeechRecognizer and Android SpeechRecognizer engines, real microphone permission prompts, audioSource transcription, recording persistence, locale installation data, offline model downloads, volume metering"
|
|
3255
3255
|
}
|
|
3256
3256
|
]
|
|
@@ -10350,10 +10350,8 @@ async function probePort(port, buildIconProxyUrl) {
|
|
|
10350
10350
|
return null;
|
|
10351
10351
|
}
|
|
10352
10352
|
function isSootSelfServer(server) {
|
|
10353
|
-
const projectName = server.projectName?.trim().toLowerCase();
|
|
10354
|
-
if (projectName === "soot" || projectName === "sootsim") return true;
|
|
10355
10353
|
const bundleId = server.bundleId?.trim().toLowerCase();
|
|
10356
|
-
if (bundleId?.startsWith("dev.
|
|
10354
|
+
if (bundleId?.startsWith("dev.sootsim.")) return true;
|
|
10357
10355
|
return false;
|
|
10358
10356
|
}
|
|
10359
10357
|
function isWeakCachedResult(result) {
|
|
@@ -10507,6 +10505,27 @@ function sootsimHomeDir() {
|
|
|
10507
10505
|
if (override && override.length > 0) return import_node_path.default.resolve(override);
|
|
10508
10506
|
return import_node_path.default.join((0, import_node_os.homedir)(), ".sootsim");
|
|
10509
10507
|
}
|
|
10508
|
+
function isSootsimDevCheckout() {
|
|
10509
|
+
if (process.env.SOOTSIM_FORCE_DAEMON_INSTALL === "1") return false;
|
|
10510
|
+
const env = process.env.SOOTSIM_DEV;
|
|
10511
|
+
if (env === "1" || env === "true") return true;
|
|
10512
|
+
if (env === "0" || env === "false") return false;
|
|
10513
|
+
const argv1 = process.argv[1];
|
|
10514
|
+
if (!argv1) return false;
|
|
10515
|
+
try {
|
|
10516
|
+
const real = import_node_fs2.default.realpathSync(argv1);
|
|
10517
|
+
return real.includes(`${import_node_path.default.sep}packages${import_node_path.default.sep}sootsim${import_node_path.default.sep}`);
|
|
10518
|
+
} catch {
|
|
10519
|
+
return false;
|
|
10520
|
+
}
|
|
10521
|
+
}
|
|
10522
|
+
function isDevWorkstation() {
|
|
10523
|
+
if (process.env.SOOTSIM_FORCE_DAEMON_INSTALL === "1") return false;
|
|
10524
|
+
return process.env.IS_TAMAGUI_DEV === "1";
|
|
10525
|
+
}
|
|
10526
|
+
function shouldSkipPersistentDaemon() {
|
|
10527
|
+
return isSootsimDevCheckout() || isDevWorkstation();
|
|
10528
|
+
}
|
|
10510
10529
|
function runtimesDir() {
|
|
10511
10530
|
return import_node_path.default.join(sootsimHomeDir(), "runtimes");
|
|
10512
10531
|
}
|
|
@@ -10531,6 +10550,9 @@ function cacheDir() {
|
|
|
10531
10550
|
function daemonLockfilePath() {
|
|
10532
10551
|
return import_node_path.default.join(sootsimHomeDir(), DAEMON_LOCKFILE);
|
|
10533
10552
|
}
|
|
10553
|
+
function devBridgeLockfilePath() {
|
|
10554
|
+
return import_node_path.default.join(sootsimHomeDir(), DEV_BRIDGE_LOCKFILE);
|
|
10555
|
+
}
|
|
10534
10556
|
function configFilePath() {
|
|
10535
10557
|
return import_node_path.default.join(sootsimHomeDir(), CONFIG_FILE);
|
|
10536
10558
|
}
|
|
@@ -10636,6 +10658,25 @@ function readDaemonLockfile() {
|
|
|
10636
10658
|
return null;
|
|
10637
10659
|
}
|
|
10638
10660
|
}
|
|
10661
|
+
function readDevBridgeLockfile() {
|
|
10662
|
+
try {
|
|
10663
|
+
const fd = import_node_fs2.default.openSync(devBridgeLockfilePath(), "r");
|
|
10664
|
+
try {
|
|
10665
|
+
const buf = Buffer.alloc(DAEMON_LOCKFILE_MAX_BYTES);
|
|
10666
|
+
const bytesRead = import_node_fs2.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
|
|
10667
|
+
const raw = buf.subarray(0, bytesRead).toString("utf8");
|
|
10668
|
+
const parsed = JSON.parse(raw);
|
|
10669
|
+
if (parsed && parsed.schema === 1 && parsed.source === "vite-dev" && typeof parsed.pid === "number" && typeof parsed.bridgePort === "number" && typeof parsed.runtimePort === "number" && typeof parsed.cwd === "string" && typeof parsed.startedAt === "number" && typeof parsed.heartbeatAt === "number") {
|
|
10670
|
+
return parsed;
|
|
10671
|
+
}
|
|
10672
|
+
return null;
|
|
10673
|
+
} finally {
|
|
10674
|
+
import_node_fs2.default.closeSync(fd);
|
|
10675
|
+
}
|
|
10676
|
+
} catch {
|
|
10677
|
+
return null;
|
|
10678
|
+
}
|
|
10679
|
+
}
|
|
10639
10680
|
function isDaemonLockfileFresh(lock, now = Date.now()) {
|
|
10640
10681
|
if (!lock) return false;
|
|
10641
10682
|
if (now - lock.heartbeatAt > DAEMON_HEARTBEAT_STALE_MS) return false;
|
|
@@ -10646,6 +10687,16 @@ function isDaemonLockfileFresh(lock, now = Date.now()) {
|
|
|
10646
10687
|
return false;
|
|
10647
10688
|
}
|
|
10648
10689
|
}
|
|
10690
|
+
function isDevBridgeLockfileFresh(lock, now = Date.now()) {
|
|
10691
|
+
if (!lock) return false;
|
|
10692
|
+
if (now - lock.heartbeatAt > DAEMON_HEARTBEAT_STALE_MS) return false;
|
|
10693
|
+
try {
|
|
10694
|
+
process.kill(lock.pid, 0);
|
|
10695
|
+
return true;
|
|
10696
|
+
} catch {
|
|
10697
|
+
return false;
|
|
10698
|
+
}
|
|
10699
|
+
}
|
|
10649
10700
|
function writeDaemonLockfile(data) {
|
|
10650
10701
|
ensureSootsimHome();
|
|
10651
10702
|
const tmp = `${daemonLockfilePath()}.tmp`;
|
|
@@ -10653,6 +10704,13 @@ function writeDaemonLockfile(data) {
|
|
|
10653
10704
|
`, "utf8");
|
|
10654
10705
|
import_node_fs2.default.renameSync(tmp, daemonLockfilePath());
|
|
10655
10706
|
}
|
|
10707
|
+
function writeDevBridgeLockfile(data) {
|
|
10708
|
+
ensureSootsimHome();
|
|
10709
|
+
const tmp = `${devBridgeLockfilePath()}.tmp`;
|
|
10710
|
+
import_node_fs2.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
|
|
10711
|
+
`, "utf8");
|
|
10712
|
+
import_node_fs2.default.renameSync(tmp, devBridgeLockfilePath());
|
|
10713
|
+
}
|
|
10656
10714
|
function claimDaemonLockfile(data) {
|
|
10657
10715
|
ensureSootsimHome();
|
|
10658
10716
|
const existing = readDaemonLockfile();
|
|
@@ -10668,7 +10726,13 @@ function removeDaemonLockfile() {
|
|
|
10668
10726
|
} catch {
|
|
10669
10727
|
}
|
|
10670
10728
|
}
|
|
10671
|
-
|
|
10729
|
+
function removeDevBridgeLockfile() {
|
|
10730
|
+
try {
|
|
10731
|
+
import_node_fs2.default.unlinkSync(devBridgeLockfilePath());
|
|
10732
|
+
} catch {
|
|
10733
|
+
}
|
|
10734
|
+
}
|
|
10735
|
+
var import_node_fs2, import_node_os, import_node_path, SOOTSIM_HOME_ENV, ACTIVE_RUNTIME_FILE, DAEMON_LOCKFILE, DEV_BRIDGE_LOCKFILE, CONFIG_FILE, DAEMON_HEARTBEAT_STALE_MS, DAEMON_LOCKFILE_MAX_BYTES;
|
|
10672
10736
|
var init_home_paths = __esm({
|
|
10673
10737
|
"src/home-paths.ts"() {
|
|
10674
10738
|
"use strict";
|
|
@@ -10678,6 +10742,7 @@ var init_home_paths = __esm({
|
|
|
10678
10742
|
SOOTSIM_HOME_ENV = "SOOTSIM_HOME";
|
|
10679
10743
|
ACTIVE_RUNTIME_FILE = "active";
|
|
10680
10744
|
DAEMON_LOCKFILE = "daemon.json";
|
|
10745
|
+
DEV_BRIDGE_LOCKFILE = "dev-bridge.json";
|
|
10681
10746
|
CONFIG_FILE = "config.json";
|
|
10682
10747
|
DAEMON_HEARTBEAT_STALE_MS = 3e4;
|
|
10683
10748
|
DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
|
|
@@ -12860,10 +12925,12 @@ var init_bridge_host = __esm({
|
|
|
12860
12925
|
maxConcurrentAutomationSims;
|
|
12861
12926
|
automationSimActiveGraceMs;
|
|
12862
12927
|
shouldWriteLockfile;
|
|
12928
|
+
shouldWriteDevLockfile;
|
|
12863
12929
|
sootbeanOrigin = null;
|
|
12864
12930
|
effectivePort = 0;
|
|
12865
12931
|
startedAt = 0;
|
|
12866
12932
|
heartbeatTimer = null;
|
|
12933
|
+
devHeartbeatTimer = null;
|
|
12867
12934
|
// ws-level heartbeat: sims that hang up uncleanly (page navigated, network
|
|
12868
12935
|
// dropped, sim crashed) leave their server-side WebSocket sitting "open"
|
|
12869
12936
|
// forever. ping every WS_HEARTBEAT_INTERVAL_MS; if the previous round's
|
|
@@ -12890,6 +12957,7 @@ var init_bridge_host = __esm({
|
|
|
12890
12957
|
this.preferredPort = opts.port || DEFAULT_SOOTSIM_BRIDGE_PORT;
|
|
12891
12958
|
this.port = this.preferredPort;
|
|
12892
12959
|
this.shouldWriteLockfile = opts.writeLockfile === true;
|
|
12960
|
+
this.shouldWriteDevLockfile = opts.writeDevLockfile === true;
|
|
12893
12961
|
this.portFallbackCount = Math.max(1, opts.portFallbackCount ?? 10);
|
|
12894
12962
|
this.openUrlHandler = opts.openUrl;
|
|
12895
12963
|
this.agentHost = new AgentHost({ getExcludePorts: opts.agentScanExcludes });
|
|
@@ -13407,7 +13475,7 @@ var init_bridge_host = __esm({
|
|
|
13407
13475
|
});
|
|
13408
13476
|
});
|
|
13409
13477
|
}
|
|
13410
|
-
/** after a successful bind: start the cli idle sweep, write the daemon
|
|
13478
|
+
/** after a successful bind: start the cli idle sweep, write the daemon/dev
|
|
13411
13479
|
* lockfile (if this host owns it), seed the agent host, kick off the
|
|
13412
13480
|
* heartbeat loop. idempotent across rebinds because close() tears down
|
|
13413
13481
|
* every timer and the lockfile. */
|
|
@@ -13449,6 +13517,23 @@ var init_bridge_host = __esm({
|
|
|
13449
13517
|
this.heartbeatTimer.unref();
|
|
13450
13518
|
this.startRuntimeUpdater();
|
|
13451
13519
|
}
|
|
13520
|
+
if (this.shouldWriteDevLockfile) {
|
|
13521
|
+
try {
|
|
13522
|
+
this.writeDevLockfileSnapshot();
|
|
13523
|
+
} catch (err) {
|
|
13524
|
+
process.stderr.write(
|
|
13525
|
+
`ws bridge failed to write dev bridge lockfile: ${String(err)}
|
|
13526
|
+
`
|
|
13527
|
+
);
|
|
13528
|
+
}
|
|
13529
|
+
this.devHeartbeatTimer = setInterval(() => {
|
|
13530
|
+
try {
|
|
13531
|
+
this.writeDevLockfileSnapshot();
|
|
13532
|
+
} catch {
|
|
13533
|
+
}
|
|
13534
|
+
}, DAEMON_HEARTBEAT_INTERVAL_MS);
|
|
13535
|
+
this.devHeartbeatTimer.unref();
|
|
13536
|
+
}
|
|
13452
13537
|
void this.agentHost.seedOnBoot();
|
|
13453
13538
|
}
|
|
13454
13539
|
bootstrapping = true;
|
|
@@ -13466,9 +13551,25 @@ var init_bridge_host = __esm({
|
|
|
13466
13551
|
bootstrapping: this.bootstrapping
|
|
13467
13552
|
};
|
|
13468
13553
|
}
|
|
13554
|
+
buildDevLockfileSnapshot() {
|
|
13555
|
+
return {
|
|
13556
|
+
schema: 1,
|
|
13557
|
+
pid: process.pid,
|
|
13558
|
+
platform: process.platform,
|
|
13559
|
+
bridgePort: this.effectivePort,
|
|
13560
|
+
runtimePort: this.effectivePort,
|
|
13561
|
+
cwd: process.cwd(),
|
|
13562
|
+
startedAt: this.startedAt,
|
|
13563
|
+
heartbeatAt: Date.now(),
|
|
13564
|
+
source: "vite-dev"
|
|
13565
|
+
};
|
|
13566
|
+
}
|
|
13469
13567
|
writeLockfileSnapshot() {
|
|
13470
13568
|
writeDaemonLockfile(this.buildLockfileSnapshot());
|
|
13471
13569
|
}
|
|
13570
|
+
writeDevLockfileSnapshot() {
|
|
13571
|
+
writeDevBridgeLockfile(this.buildDevLockfileSnapshot());
|
|
13572
|
+
}
|
|
13472
13573
|
refreshActiveRuntime() {
|
|
13473
13574
|
this.activeRuntimeVersion = readActiveRuntime();
|
|
13474
13575
|
this.activeRuntimeDirPath = activeRuntimeDir();
|
|
@@ -13704,6 +13805,7 @@ var init_bridge_host = __esm({
|
|
|
13704
13805
|
bridgePort: this.effectivePort,
|
|
13705
13806
|
runtimePort: this.effectivePort,
|
|
13706
13807
|
activeRuntime: this.activeRuntimeVersion,
|
|
13808
|
+
bridgeSource: this.shouldWriteDevLockfile ? "vite-dev" : this.shouldWriteLockfile ? "daemon" : "embedded",
|
|
13707
13809
|
startedAt: this.startedAt,
|
|
13708
13810
|
uptimeMs: this.startedAt > 0 ? Date.now() - this.startedAt : 0
|
|
13709
13811
|
})
|
|
@@ -14085,6 +14187,10 @@ var init_bridge_host = __esm({
|
|
|
14085
14187
|
clearInterval(this.heartbeatTimer);
|
|
14086
14188
|
this.heartbeatTimer = null;
|
|
14087
14189
|
}
|
|
14190
|
+
if (this.devHeartbeatTimer) {
|
|
14191
|
+
clearInterval(this.devHeartbeatTimer);
|
|
14192
|
+
this.devHeartbeatTimer = null;
|
|
14193
|
+
}
|
|
14088
14194
|
if (this.wsHeartbeatTimer) {
|
|
14089
14195
|
clearInterval(this.wsHeartbeatTimer);
|
|
14090
14196
|
this.wsHeartbeatTimer = null;
|
|
@@ -14099,6 +14205,12 @@ var init_bridge_host = __esm({
|
|
|
14099
14205
|
} catch {
|
|
14100
14206
|
}
|
|
14101
14207
|
}
|
|
14208
|
+
if (this.shouldWriteDevLockfile) {
|
|
14209
|
+
try {
|
|
14210
|
+
removeDevBridgeLockfile();
|
|
14211
|
+
} catch {
|
|
14212
|
+
}
|
|
14213
|
+
}
|
|
14102
14214
|
this.effectivePort = 0;
|
|
14103
14215
|
this.startedAt = 0;
|
|
14104
14216
|
this.agentHost.close();
|
|
@@ -14708,6 +14820,10 @@ __export(ws_bridge_exports, {
|
|
|
14708
14820
|
resolveDefaultBridgePort: () => resolveDefaultBridgePort
|
|
14709
14821
|
});
|
|
14710
14822
|
function resolveDefaultBridgePort() {
|
|
14823
|
+
if (shouldSkipPersistentDaemon()) {
|
|
14824
|
+
const dev = readDevBridgeLockfile();
|
|
14825
|
+
if (dev && isDevBridgeLockfileFresh(dev)) return dev.bridgePort;
|
|
14826
|
+
}
|
|
14711
14827
|
const lock = readDaemonLockfile();
|
|
14712
14828
|
if (lock && isDaemonLockfileFresh(lock)) return lock.bridgePort;
|
|
14713
14829
|
return DEFAULT_SOOTSIM_BRIDGE_PORT;
|
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.170 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -74,7 +74,7 @@ function readActiveRuntime() {
|
|
|
74
74
|
var DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
|
|
75
75
|
|
|
76
76
|
// src/runtime-assets.ts
|
|
77
|
-
var SOOTSIM_RUNTIME_MISSING_MESSAGE = "[sootsim] no engine runtime installed \u2014 run `sootsim setup
|
|
77
|
+
var SOOTSIM_RUNTIME_MISSING_MESSAGE = "[sootsim] no engine runtime installed \u2014 run `sootsim setup`, or `sootsim runtime install`";
|
|
78
78
|
var MIME_TYPES = {
|
|
79
79
|
".js": "application/javascript",
|
|
80
80
|
".mjs": "application/javascript",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sootsim",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.170",
|
|
4
4
|
"description": "sootsim CLI + vite/metro plugins + skills registry. bridge client for driving the proprietary sootsim-engine over WebSocket.",
|
|
5
5
|
"author": "Tamagui LLC",
|
|
6
6
|
"license": "MIT",
|
|
@@ -132,6 +132,7 @@
|
|
|
132
132
|
"dist-cli/",
|
|
133
133
|
"dist-lib/",
|
|
134
134
|
"src/",
|
|
135
|
+
"skills/",
|
|
135
136
|
"scripts/dev-server-scanner.ts",
|
|
136
137
|
"scripts/optional-demo-registry.ts",
|
|
137
138
|
"detox/",
|
|
@@ -556,15 +556,14 @@ export interface ScanOptions {
|
|
|
556
556
|
}
|
|
557
557
|
|
|
558
558
|
function isSootSelfServer(server: DiscoveredServer): boolean {
|
|
559
|
-
const projectName = server.projectName?.trim().toLowerCase()
|
|
560
|
-
if (projectName === 'soot' || projectName === 'sootsim') return true
|
|
561
|
-
|
|
562
559
|
const bundleId = server.bundleId?.trim().toLowerCase()
|
|
563
|
-
if (bundleId?.startsWith('dev.
|
|
560
|
+
if (bundleId?.startsWith('dev.sootsim.')) return true
|
|
564
561
|
|
|
565
562
|
return false
|
|
566
563
|
}
|
|
567
564
|
|
|
565
|
+
export const __isSootSelfServerForTests = isSootSelfServer
|
|
566
|
+
|
|
568
567
|
// per-(port, pid) probe cache. as long as the same process still owns the
|
|
569
568
|
// port, its signature endpoints can't have changed, so we return the cached
|
|
570
569
|
// result without issuing any HTTP. negative results (null) are cached too,
|
package/scripts/postinstall.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// postinstall — best-effort runtime install after `npm i -g sootsim`.
|
|
3
3
|
//
|
|
4
|
-
// runs as a child of npm. failures here are non-fatal
|
|
5
|
-
//
|
|
4
|
+
// runs as a child of npm. failures here are non-fatal; setup/open/runtime
|
|
5
|
+
// commands can install the runtime later.
|
|
6
6
|
//
|
|
7
7
|
// skipped when running as root via sudo: $HOME would be /root, but the user
|
|
8
8
|
// who actually wants the runtime probably isn't root. their first sootsim
|
package/scripts/preuninstall.cjs
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
// reliability: npm preuninstall hooks are best-effort — they don't fire when
|
|
12
12
|
// the package wasn't installed by npm (yarn/bun/pnpm have their own lifecycle
|
|
13
13
|
// rules), and they don't run as part of `npm cache verify` cleanup or manual
|
|
14
|
-
// dir removal. that's why
|
|
15
|
-
// manual
|
|
14
|
+
// dir removal. that's why `sootsim daemon uninstall` is also documented as
|
|
15
|
+
// the manual teardown path.
|
|
16
16
|
//
|
|
17
17
|
// strategy: spawn the bundled bin to run `daemon uninstall` (single source of
|
|
18
18
|
// truth — the same logic the user invokes manually). if that fails for any
|
|
@@ -73,17 +73,15 @@ function rawCleanup() {
|
|
|
73
73
|
const home = sootsimHomeDir()
|
|
74
74
|
if (process.platform === 'darwin') {
|
|
75
75
|
safeSpawn('launchctl', ['bootout', `gui/${getuid()}/dev.sootsim.daemon`])
|
|
76
|
-
safeSpawn('launchctl', ['bootout', `gui/${getuid()}/dev.sootsim.server`])
|
|
77
76
|
safeRemove(path.join(os.homedir(), 'Library/LaunchAgents/dev.sootsim.daemon.plist'))
|
|
78
|
-
safeRemove(path.join(os.homedir(), 'Library/LaunchAgents/dev.sootsim.server.plist'))
|
|
79
77
|
safeRemove(path.join(os.homedir(), 'Library/Logs/sootsim'), {
|
|
80
78
|
recursive: true,
|
|
81
79
|
})
|
|
82
80
|
} else if (process.platform === 'linux') {
|
|
83
|
-
safeSpawn('systemctl', ['--user', 'disable', '--now', 'sootsim-
|
|
81
|
+
safeSpawn('systemctl', ['--user', 'disable', '--now', 'sootsim-daemon'])
|
|
84
82
|
safeSpawn('systemctl', ['--user', 'daemon-reload'])
|
|
85
|
-
safeSpawn('systemctl', ['--user', 'reset-failed', 'sootsim-
|
|
86
|
-
safeRemove(path.join(os.homedir(), '.config/systemd/user/sootsim-
|
|
83
|
+
safeSpawn('systemctl', ['--user', 'reset-failed', 'sootsim-daemon'])
|
|
84
|
+
safeRemove(path.join(os.homedir(), '.config/systemd/user/sootsim-daemon.service'))
|
|
87
85
|
safeRemove(path.join(os.homedir(), '.local/state/sootsim'), { recursive: true })
|
|
88
86
|
}
|
|
89
87
|
// ~/.sootsim is the same on every platform; honor $SOOTSIM_HOME.
|
package/skills/soot.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: soot
|
|
3
|
+
description: >-
|
|
4
|
+
index of all Soot and SootSim agent skills and CLI commands.
|
|
5
|
+
auto-generated from the CLI info registry — do not edit by hand.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# soot
|
|
9
|
+
|
|
10
|
+
overview of all available skills and CLI commands in this repo.
|
|
11
|
+
|
|
12
|
+
> this file is auto-generated by `bun scripts/generate-soot-skill.ts`.
|
|
13
|
+
> to update, edit the source registries and re-run the generator.
|
|
14
|
+
|
|
15
|
+
## sootsim CLI commands
|
|
16
|
+
|
|
17
|
+
the `sootsim` CLI is the operational surface for booting shells, driving
|
|
18
|
+
automation, inspecting the render tree, and managing sims.
|
|
19
|
+
|
|
20
|
+
| command | description |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| `sootsim preview` | production-like preview build |
|
|
23
|
+
| `sootsim test` | run tests against sootsim |
|
|
24
|
+
| `sootsim flow` | run flows through the current sim or manage a draft from live inspect actions |
|
|
25
|
+
| `sootsim maestro` | run existing Maestro YAML flows against sootsim |
|
|
26
|
+
| `sootsim detox` | run existing Detox suites against sootsim on headless Chromium |
|
|
27
|
+
| `sootsim record` | capture the live sim as webm/mp4/gif, or sample N png frames (--frames) |
|
|
28
|
+
| `sootsim profile` | manage isolated storage profiles |
|
|
29
|
+
| `sootsim storage-clear` | clear the current guest app storage and reload it |
|
|
30
|
+
| `sootsim cpu-profile` | capture a JS CPU profile of the sim workers over the Chrome DevTools Protocol |
|
|
31
|
+
| `sootsim react` | inspect React component render cost in the tenant worker |
|
|
32
|
+
| `sootsim assert` | run any read verb and convert its output into an exit code |
|
|
33
|
+
| `sootsim screenshot` | capture the canvas (full or cropped) as PNG |
|
|
34
|
+
| `sootsim get` | read runtime state (tree, a11y, url, count, errors, …) |
|
|
35
|
+
| `sootsim screenshots` | capture + compose app-store screenshot sets from a single plan |
|
|
36
|
+
| `sootsim do` | drive the app (tap, type, scroll, swipe, key, reload, …) |
|
|
37
|
+
| `sootsim screenshots-capture` | headlessly (re)capture editable App Store slides and upload them to your org |
|
|
38
|
+
| `sootsim screenshot-mode` | toggle the screenshot-mode chrome overlay |
|
|
39
|
+
| `sootsim wait` | block until the runtime reaches a known state |
|
|
40
|
+
| `sootsim shell` | drive shell state and simulator chrome |
|
|
41
|
+
| `sootsim slides` | compose App Store screenshot slides in the live sim |
|
|
42
|
+
| `sootsim three-mode` | toggle the live browser 3d device stage |
|
|
43
|
+
| `sootsim upload` | publish the current recorded bundle as a shareable /preview/<id> link |
|
|
44
|
+
| `sootsim device` | inspect or change the live device preset for a sim |
|
|
45
|
+
| `sootsim inspect` | query, describe, and drive the running sootsim instance |
|
|
46
|
+
| `sootsim network` | inspect live network traffic from the running sootsim worker |
|
|
47
|
+
| `sootsim logs` | inspect live console output from the running sootsim worker |
|
|
48
|
+
| `sootsim debug` | drive __sootsimDebug: channels, snapshots, and inspectors |
|
|
49
|
+
| `sootsim camera` | drive the sim camera — inject synthetic barcode scans |
|
|
50
|
+
| `sootsim what-happened` | show recent semantic events: toasts, keyboards, screens, alerts, fetches, errors |
|
|
51
|
+
| `sootsim diagnose` | composed read commands for "what just went wrong?" |
|
|
52
|
+
| `sootsim timeline` | control the semantic event timeline (enable opt-in kinds, clear, dump) |
|
|
53
|
+
| `sootsim open` | load a target into the current sim or open a new one |
|
|
54
|
+
| `sootsim list` | list connected sims or available launch drivers |
|
|
55
|
+
| `sootsim use` | select a connected sim |
|
|
56
|
+
| `sootsim skill` | install and inspect bundled SootSim agent skills |
|
|
57
|
+
| `sootsim claim` | take an exclusive lease on a sim |
|
|
58
|
+
| `sootsim agent` | attached projects + local agent sessions (codex/claude) |
|
|
59
|
+
| `sootsim close` | close a connected sim |
|
|
60
|
+
| `sootsim setup` | set up this machine and, optionally, this repo |
|
|
61
|
+
| `sootsim compat` | check package compatibility (alias: scan) |
|
|
62
|
+
| `sootsim electron` | launch the desktop companion |
|
|
63
|
+
| `sootsim daemon` | manage the sootsim bridge as a login agent |
|
|
64
|
+
| `sootsim version` | show the CLI + engine runtime versions you are running |
|
|
65
|
+
| `sootsim upgrade` | update the sootsim CLI and engine runtime to the latest |
|
|
66
|
+
| `sootsim serve` | run the sootsim bridge in the foreground |
|
|
67
|
+
| `sootsim runtime` | manage engine runtimes under ~/.sootsim/runtimes/ |
|
|
68
|
+
| `sootsim install-desktop` | download and install the optional desktop GUI |
|
|
69
|
+
| `sootsim login` | sign in so preview uploads are associated with your account |
|
|
70
|
+
| `sootsim logout` | clear the local desktop auth state |
|
|
71
|
+
| `sootsim whoami` | print the currently signed-in account |
|
|
72
|
+
| `sootsim keys` | manage the api keys that authorize CI preview uploads |
|
|
73
|
+
| `sootsim hints` | inspect and manage the CLI hint registry |
|
|
74
|
+
|
|
75
|
+
### runtime verb groups
|
|
76
|
+
|
|
77
|
+
every runtime verb is organized under one of these grouping prefixes.
|
|
78
|
+
run `sootsim --help` to see the full list under each group.
|
|
79
|
+
|
|
80
|
+
- `sootsim describe` — summarize the current UI
|
|
81
|
+
- `sootsim find <...>` — unified finder (bare text, --testid, --role, --type, --pressable, --visible)
|
|
82
|
+
- `sootsim get <noun>` — read runtime state (tree, a11y, url, count, errors, warnings, requests, globals, layout, node)
|
|
83
|
+
- `sootsim do <action>` — drive the app (tap, tap-text, tap-id, type, type-into, key, dismiss, scroll, drag, swipe, pinch, reload, shell, sleep, settle, wait)
|
|
84
|
+
- `sootsim debug <tool>` — instrumentation (state, js, eval, perf, sample-color, enable/disable channels, snapshots, diff, record, recent)
|
|
85
|
+
|
|
86
|
+
### global flags
|
|
87
|
+
|
|
88
|
+
- `-h, --help` — show help
|
|
89
|
+
- `-V, --version` — show version
|
|
90
|
+
- `-v, --verbose` — verbose output
|
|
91
|
+
- `-p, --port <number>` — bridge or preview port, depending on command
|
|
92
|
+
- `-d, --device <model>` — override the simulated device model
|
|
93
|
+
- `-t, --theme <scheme>` — override light, dark, or auto color scheme
|
|
94
|
+
- `--headless` — run browser automation without a visible window where supported
|
|
95
|
+
|
|
96
|
+
## bundled SootSim agent skills
|
|
97
|
+
|
|
98
|
+
skills for working with the SootSim native preview engine:
|
|
99
|
+
|
|
100
|
+
| skill | description |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| `/sootsim-debug` | Debug rendering, performance, and accessibility issues in your React Native app under sootsim |
|
|
103
|
+
| `/sootsim-setup` | Get sootsim connected to your React Native app — from `npm install sootsim` to a driveable sim |
|
|
104
|
+
| `/sootsim-test` | Run automated tests against your React Native app under sootsim — native YAML flows, Maestro drop-in, or Detox drop-in |
|
|
105
|
+
| `/sootsim-visual` | Pixel-level rendering comparison between sootsim and native iOS — fonts, gradients, shadows, image fidelity |
|
|
106
|
+
|
|
107
|
+
## automatic settling
|
|
108
|
+
|
|
109
|
+
every CLI command already waits at the right moment — **do not wrap
|
|
110
|
+
commands in your own `sleep` or chain `do settle` "just to be safe"**.
|
|
111
|
+
|
|
112
|
+
- **before read commands** (`describe`, `find`, `get`, `tree`, `node`,
|
|
113
|
+
`layout`, `screenshot`, `capture`, `a11y`, `sample-color`, `count`,
|
|
114
|
+
and every gesture — `tap`, `tap-id`, `tap-text`, `type-into`,
|
|
115
|
+
`touch`, `swipe`, `drag`, `scroll`, `pinch`, `long-press`,
|
|
116
|
+
`double-tap`, `gesture`) the CLI waits up to **1800 ms** for any
|
|
117
|
+
in-flight screen transition to actually start, so the tree you read is
|
|
118
|
+
never mid-flip.
|
|
119
|
+
- **after write commands** (`tap`, `tap-text`, `tap-id`, `type`,
|
|
120
|
+
`type-into`, `key`, `key-sequence`, `keycode`, `drag`, `swipe`,
|
|
121
|
+
`long-press`, `touch`, `gesture`, `pinch`, `scroll`, `shell`)
|
|
122
|
+
the CLI polls the layout hash until it is stable for two consecutive
|
|
123
|
+
frames. budget: **1200 ms for agents** (`SOOTSIM_AGENT=1`, set by the
|
|
124
|
+
harness), 350 ms for humans.
|
|
125
|
+
|
|
126
|
+
what this means:
|
|
127
|
+
|
|
128
|
+
- `sootsim do tap-id login` then `sootsim find "Welcome"` Just Works™.
|
|
129
|
+
- you only need `sootsim do settle <seconds>` or `sootsim wait idle
|
|
130
|
+
--max-ms <N>` when the CLI explicitly prints
|
|
131
|
+
`⚠ auto-wait timed out after Nms — next command may see mid-animation
|
|
132
|
+
state`, or when the transition you care about lasts longer than ~1.2 s
|
|
133
|
+
(full stack navigation, crossfades, video load).
|
|
134
|
+
- opt-out: `--no-wait` on a single command, `SOOTSIM_NO_AUTO_WAIT=1`
|
|
135
|
+
for a whole lane.
|
|
136
|
+
- if a read keeps racing its write, the fix is **never** a blind `sleep` —
|
|
137
|
+
prefer `wait selector`, `wait ready`, `wait idle`, or a longer
|
|
138
|
+
explicit `do settle`, and investigate whether the app's animation
|
|
139
|
+
completion signal is actually firing.
|
|
140
|
+
|
|
141
|
+
## quick reference
|
|
142
|
+
|
|
143
|
+
### dev workflow
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
bun dev # start everything
|
|
147
|
+
sootsim dev -- pnpm dev # wrap a bundler
|
|
148
|
+
sootsim open 8081 # load an app
|
|
149
|
+
sootsim describe # inspect the UI tree
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### debugging
|
|
153
|
+
|
|
154
|
+
```sh
|
|
155
|
+
sootsim get errors 5 # recent console errors
|
|
156
|
+
sootsim get requests 5 # recent failed requests
|
|
157
|
+
sootsim debug snapshot before # capture state
|
|
158
|
+
sootsim debug diff before after # compare snapshots
|
|
159
|
+
sootsim debug state shell # runtime state dump
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### testing
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
sootsim test # run tests
|
|
166
|
+
sootsim flow flows/login.yaml # run a YAML flow
|
|
167
|
+
sootsim flow start # start recording a flow
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### inspection
|
|
171
|
+
|
|
172
|
+
```sh
|
|
173
|
+
sootsim describe # visible elements
|
|
174
|
+
sootsim find "Sign in" # find by text
|
|
175
|
+
sootsim find --testid loginButton # find by testID
|
|
176
|
+
sootsim do tap-text "Submit" # tap by text
|
|
177
|
+
sootsim do type "hello" # type text
|
|
178
|
+
```
|