stim 0.0.0 → 1.0.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/LICENSE +21 -0
- package/README.md +150 -0
- package/dist/android-cas-compiler.d.mts +1 -0
- package/dist/android-cas-compiler.mjs +71 -0
- package/dist/android-jc8MnUyL.mjs +514 -0
- package/dist/cache-manifest-4tH64LQ9.mjs +66 -0
- package/dist/cache-manifest.d.mts +27 -0
- package/dist/cache-manifest.mjs +2 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +27182 -0
- package/dist/collector-run.d.mts +119 -0
- package/dist/collector-run.mjs +539 -0
- package/dist/config-7kmtuhO2.mjs +350 -0
- package/dist/errors-B6W7FkxQ.mjs +15 -0
- package/dist/exec-bsN9MJXb.mjs +63 -0
- package/dist/metro-store-COLl1pOk.mjs +1249 -0
- package/dist/ndjson-DcAtEx_K.mjs +131 -0
- package/dist/ndjson-DvHSsNU9.d.mts +16 -0
- package/dist/process-output-C7IlIzd7.mjs +40 -0
- package/dist/project-Dit1CckW.mjs +234 -0
- package/dist/server-bare-BmTVVmBB.mjs +351 -0
- package/dist/server-expo-BZJm--wA.mjs +2 -0
- package/dist/server-expo-CHJe1r6j.mjs +311 -0
- package/dist/state-2nush3MK.mjs +269 -0
- package/dist/supervisor-run.d.mts +85 -0
- package/dist/supervisor-run.mjs +210 -0
- package/package.json +61 -8
- package/shim/android-cas-pch.cmake +35 -0
- package/shim/android-cas.gradle +29 -0
- package/shim/android-cas.toolchain.cmake +12 -0
- package/shim/android-optimizations.gradle +30 -0
- package/shim/bundle-response.cjs +46 -0
- package/shim/bundle-response.d.cts +5 -0
- package/shim/expo-metro-config.cjs +188 -0
- package/shim/metro-cache-generation.cjs +20 -0
- package/shim/metro-cache-generation.d.cts +5 -0
- package/skill/SKILL.md +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Janic Duplessis
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Stim
|
|
2
|
+
|
|
3
|
+
The `stim` npm package installs the `stim` command.
|
|
4
|
+
|
|
5
|
+
Stim gives coding agents fast, isolated React Native and Expo environments. Each
|
|
6
|
+
project or git worktree gets its own Metro port and owned device. Shared caches
|
|
7
|
+
keep native and JavaScript builds warm across worktrees.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
If you previously installed `stim-cli` globally, follow the
|
|
12
|
+
[migration instructions](#migrating-from-stim-cli) first.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install --global stim
|
|
16
|
+
npx skills add appandflow/stim
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Run without a global install when needed:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx stim <command>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Node 20.19.4 or later on Node 20, or Node 22.12.0 or later, is required.
|
|
26
|
+
|
|
27
|
+
Machine defaults in `~/.stim/config.json` can enable or disable native artifact
|
|
28
|
+
caching, remote caches, Metro sharing, iOS compiler caching and prefix mapping,
|
|
29
|
+
and Android ccache/CAS, PCH, Gradle caching, and target ABI narrowing. Optional
|
|
30
|
+
`.stim.json` runtime overrides apply per app, beside its `package.json`; monorepo
|
|
31
|
+
apps do not inherit the repository-root file. Worktree-copy rules stay at the
|
|
32
|
+
repository root. Run `stim guide settings` for the
|
|
33
|
+
`optimizations` schema; existing defaults remain unchanged.
|
|
34
|
+
|
|
35
|
+
## Normal workflow
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
stim doctor
|
|
39
|
+
stim start
|
|
40
|
+
stim ios # or: stim android
|
|
41
|
+
stim logs --errors
|
|
42
|
+
stim stop
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
For `stim logs --errors`, a clean check requires exit code 0 and no matching
|
|
46
|
+
errors in the captured logs. Exit code 0 alone means the query succeeded, even
|
|
47
|
+
when it prints errors; an empty result does not prove launch or log capture
|
|
48
|
+
succeeded.
|
|
49
|
+
|
|
50
|
+
Use `stim start --reset-cache` to recover from stale Metro transforms or file-map
|
|
51
|
+
state. It restarts only this app's verified owned Metro, keeping its port and
|
|
52
|
+
devices. A fresh persistent cache namespace bypasses old entries without deleting
|
|
53
|
+
shared stores or changing other apps or native build caches. Expo requires SDK
|
|
54
|
+
54+ and Stim's config adapter. See `stim guide lifecycle` for scope and limitations.
|
|
55
|
+
|
|
56
|
+
Use `stim doctor --platform ios` or `stim doctor --platform android` when only
|
|
57
|
+
one native platform is in scope; shared project checks still run. Doctor also
|
|
58
|
+
prints the running CLI version and the `stim` installation resolved from PATH,
|
|
59
|
+
and flags a resolved installation that is older than another available one.
|
|
60
|
+
|
|
61
|
+
For stale Android CMake launcher findings, stop native builds and run
|
|
62
|
+
`stim doctor --fix --platform android` in the affected checkout. It clears
|
|
63
|
+
affected ignored, untracked generated `.cxx` configurations in the app and
|
|
64
|
+
installed native modules, then reports remaining findings. The next build
|
|
65
|
+
recreates that output; source files, custom launcher settings, and shared
|
|
66
|
+
ccache entries are preserved. Its cache-lock check cannot detect uncached,
|
|
67
|
+
release-swap fallback, or direct Gradle builds; stop all native builds first.
|
|
68
|
+
|
|
69
|
+
Stim builds or restores the app, installs it, launches it, and checks launch
|
|
70
|
+
readiness. Plain output streams progress and reports the complete result. Use
|
|
71
|
+
`--json` when a script needs structured data.
|
|
72
|
+
|
|
73
|
+
Use `stim ios --scheme "App Staging"` when a project has several shared Xcode
|
|
74
|
+
app schemes. Combine it with `--configuration Release` if needed. Without the
|
|
75
|
+
flag, Stim keeps its automatic scheme selection. Explicit schemes use separate
|
|
76
|
+
artifact caches and Xcode build directories; run `stim guide lifecycle builds`
|
|
77
|
+
for provider behavior. This selects an Xcode scheme, not a URL scheme.
|
|
78
|
+
|
|
79
|
+
Launch evidence does not prove that the UI is interactive. Apps can optionally
|
|
80
|
+
[declare readiness with two debug log messages](https://appandflow.github.io/stim/docs/dev-server-and-logs#optional-app-declared-readiness),
|
|
81
|
+
without a package or SDK. A captured pending message extends the default
|
|
82
|
+
three-second stability window after bundle delivery to a bounded wait for ready.
|
|
83
|
+
Managed Metro response capture distinguishes a finished build from a finished
|
|
84
|
+
response; servers without capture use the build-complete marker. Run
|
|
85
|
+
`stim guide lifecycle readiness` for implementation instructions; verify the
|
|
86
|
+
expected screen separately.
|
|
87
|
+
|
|
88
|
+
`stim reload [ios|android]` requests a JavaScript reload in the live app on this
|
|
89
|
+
workspace's owned local device. Use it after a failed first bundle load, when
|
|
90
|
+
an error screen remains after a fix, or when you explicitly need an app
|
|
91
|
+
restart. It is not part of the normal workflow and does not build, install,
|
|
92
|
+
boot, or launch an app. The platform is optional when only one app is live.
|
|
93
|
+
Success confirms that the request was sent; Stim does not observe completion.
|
|
94
|
+
Verify the expected UI on the reported device and inspect `stim logs --errors`
|
|
95
|
+
before claiming recovery.
|
|
96
|
+
|
|
97
|
+
For an isolated branch, create the worktree with Git, then warm it:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git worktree add -b feature/settings ../feature-settings HEAD
|
|
101
|
+
cd ../feature-settings
|
|
102
|
+
stim worktree warm
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
If a harness already created the linked worktree, run only `stim worktree warm`
|
|
106
|
+
there. Warm copies missing ignored state from main, including eligible `.env`
|
|
107
|
+
and local configuration files. Existing entries are preserved; existing
|
|
108
|
+
ignored directories such as `node_modules` are skipped whole.
|
|
109
|
+
|
|
110
|
+
Wait for warm to finish before editing, installing dependencies, starting
|
|
111
|
+
Metro/builds, or running another warm in that worktree. Concurrent writes are
|
|
112
|
+
unsafe: entries created after the initial check can be overwritten or removed.
|
|
113
|
+
|
|
114
|
+
After the work is preserved, `stim worktree remove` removes any linked
|
|
115
|
+
worktree, warmed or not. Git-created branches stay. See the
|
|
116
|
+
[worktree guide](https://appandflow.github.io/stim/docs/worktrees) for exclusions
|
|
117
|
+
and cleanup rules.
|
|
118
|
+
|
|
119
|
+
## Reference
|
|
120
|
+
|
|
121
|
+
The [documentation website](https://appandflow.github.io/stim/) explains the
|
|
122
|
+
human workflow and all commands.
|
|
123
|
+
|
|
124
|
+
The installed CLI contains version-matched operational guidance:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
stim guide agent
|
|
128
|
+
stim --help
|
|
129
|
+
stim <command> --help
|
|
130
|
+
stim guide
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Runtime state defaults to `~/.stim`. Set `STIM_HOME` to move it. Stim manages
|
|
134
|
+
owned simulators and emulators, leases connected physical devices, and supports
|
|
135
|
+
configured remote devices.
|
|
136
|
+
|
|
137
|
+
## Migrating from stim-cli
|
|
138
|
+
|
|
139
|
+
Remove the old global package before installing `stim`, since both provide the
|
|
140
|
+
same command:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
npm uninstall --global stim-cli
|
|
144
|
+
npm install --global stim
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Update programmatic imports from `stim-cli/cache-manifest` to
|
|
148
|
+
`stim/cache-manifest`. The `@stim-cli/*` packages keep their names.
|
|
149
|
+
|
|
150
|
+
MIT License.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { t as getExecutor } from "./exec-bsN9MJXb.mjs";
|
|
3
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
6
|
+
import { once } from "node:events";
|
|
7
|
+
//#region bin/android-cas-compiler.ts
|
|
8
|
+
const context = process.env.STIM_ANDROID_CAS_CONTEXT;
|
|
9
|
+
if (!context) throw new Error("Missing STIM_ANDROID_CAS_CONTEXT. Run this build through stim android.");
|
|
10
|
+
const config = JSON.parse(readFileSync(context, "utf8"));
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const cxx = process.argv[1].endsWith("++");
|
|
13
|
+
const compiler = cxx ? config.clangxx : config.clang;
|
|
14
|
+
const extra = ["-resource-dir", config.resourceDir];
|
|
15
|
+
if (cxx) extra.push("-nostdinc++", "-isystem", join(config.ndk, "toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1"));
|
|
16
|
+
if (!args.some((arg) => [
|
|
17
|
+
"-c",
|
|
18
|
+
"-E",
|
|
19
|
+
"-S"
|
|
20
|
+
].includes(arg))) extra.push(`--ld-path=${config.lld}`);
|
|
21
|
+
if (args.includes("-c")) {
|
|
22
|
+
const cwd = process.cwd();
|
|
23
|
+
const overlays = join(config.state, "vfs");
|
|
24
|
+
mkdirSync(overlays, { recursive: true });
|
|
25
|
+
const overlay = join(overlays, `${createHash("sha256").update(cwd).digest("hex")}.json`);
|
|
26
|
+
if (!existsSync(overlay)) {
|
|
27
|
+
const temporary = `${overlay}.${randomUUID()}.tmp`;
|
|
28
|
+
writeFileSync(temporary, JSON.stringify({
|
|
29
|
+
version: 0,
|
|
30
|
+
"use-external-names": false,
|
|
31
|
+
roots: [{
|
|
32
|
+
type: "directory-remap",
|
|
33
|
+
name: "/^src",
|
|
34
|
+
"external-contents": config.source
|
|
35
|
+
}, {
|
|
36
|
+
type: "directory-remap",
|
|
37
|
+
name: "/^build",
|
|
38
|
+
"external-contents": cwd
|
|
39
|
+
}]
|
|
40
|
+
}));
|
|
41
|
+
renameSync(temporary, overlay);
|
|
42
|
+
}
|
|
43
|
+
extra.push("-ivfsoverlay", overlay, "-fdepscan=inline", "-fdepscan-include-tree", "-Xclang", "-fcas-path", "-Xclang", config.cache, "-Rcompile-job-cache", `-fdepscan-prefix-map=${config.source}=/^src`, `-fdepscan-prefix-map=${cwd}=/^build`, `-fdepscan-prefix-map=${config.state}=/^state`);
|
|
44
|
+
}
|
|
45
|
+
const started = performance.now();
|
|
46
|
+
const child = getExecutor().spawn(compiler, [...extra, ...args], { stdio: [
|
|
47
|
+
"inherit",
|
|
48
|
+
"pipe",
|
|
49
|
+
"pipe"
|
|
50
|
+
] });
|
|
51
|
+
let stderr = "";
|
|
52
|
+
child.stdout.on("data", (chunk) => process.stdout.write(chunk));
|
|
53
|
+
child.stderr.on("data", (chunk) => {
|
|
54
|
+
stderr += chunk.toString();
|
|
55
|
+
process.stderr.write(chunk);
|
|
56
|
+
});
|
|
57
|
+
const [code] = await once(child, "close");
|
|
58
|
+
appendFileSync(join(config.state, "compiler.jsonl"), `${JSON.stringify({
|
|
59
|
+
argv: [
|
|
60
|
+
compiler,
|
|
61
|
+
...extra,
|
|
62
|
+
...args
|
|
63
|
+
],
|
|
64
|
+
cwd: process.cwd(),
|
|
65
|
+
code,
|
|
66
|
+
seconds: (performance.now() - started) / 1e3,
|
|
67
|
+
stderr
|
|
68
|
+
})}\n`);
|
|
69
|
+
process.exitCode = code ?? 1;
|
|
70
|
+
//#endregion
|
|
71
|
+
export {};
|