peachsim 0.1.571 → 0.1.573

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.
Files changed (235) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +106 -106
  3. package/cli/app-config.ts +1 -1
  4. package/cli/app-fonts.ts +4 -4
  5. package/cli/auth.ts +11 -11
  6. package/cli/bin.ts +4 -4
  7. package/cli/bridge-flow-runner.ts +13 -13
  8. package/cli/browser-evals.ts +2 -2
  9. package/cli/cli-update.ts +6 -6
  10. package/cli/cloud-client.ts +16 -16
  11. package/cli/cloud-dispatch.ts +2 -2
  12. package/cli/cloud-session.ts +12 -12
  13. package/cli/cloud-test-tunnel.ts +4 -4
  14. package/cli/command-registry.ts +7 -7
  15. package/cli/commands/agent-wrapper.ts +7 -7
  16. package/cli/commands/agent.ts +16 -16
  17. package/cli/commands/app-fonts.ts +3 -3
  18. package/cli/commands/assert.ts +10 -10
  19. package/cli/commands/auth.ts +5 -5
  20. package/cli/commands/box/checkout-plane.ts +1 -1
  21. package/cli/commands/box/plane-share.ts +2 -2
  22. package/cli/commands/box/rnx-command.ts +5 -5
  23. package/cli/commands/box.ts +38 -38
  24. package/cli/commands/camera.ts +13 -13
  25. package/cli/commands/cleanup.ts +13 -13
  26. package/cli/commands/compat.ts +7 -7
  27. package/cli/commands/config.ts +5 -5
  28. package/cli/commands/control.ts +63 -63
  29. package/cli/commands/cpu-profile.ts +11 -11
  30. package/cli/commands/daemon-mac-app.ts +10 -10
  31. package/cli/commands/daemon.ts +29 -27
  32. package/cli/commands/debug.ts +35 -35
  33. package/cli/commands/desktop.ts +3 -3
  34. package/cli/commands/detox.ts +33 -33
  35. package/cli/commands/device.ts +9 -9
  36. package/cli/commands/diagnose.ts +17 -17
  37. package/cli/commands/do-chain.ts +4 -4
  38. package/cli/commands/electron.ts +9 -9
  39. package/cli/commands/film.ts +9 -9
  40. package/cli/commands/flow.ts +49 -49
  41. package/cli/commands/inspect/core.ts +12 -12
  42. package/cli/commands/inspect/count.ts +1 -1
  43. package/cli/commands/inspect/describe.ts +1 -1
  44. package/cli/commands/inspect/env.ts +2 -2
  45. package/cli/commands/inspect/find.ts +2 -2
  46. package/cli/commands/inspect/get-layout.ts +2 -2
  47. package/cli/commands/inspect/keyboard.ts +1 -1
  48. package/cli/commands/inspect/list.ts +4 -4
  49. package/cli/commands/inspect/memory.ts +1 -1
  50. package/cli/commands/inspect/resolve-target.ts +1 -1
  51. package/cli/commands/inspect/screens.ts +1 -1
  52. package/cli/commands/inspect/shared.ts +1 -1
  53. package/cli/commands/inspect/tree.ts +1 -1
  54. package/cli/commands/inspect/url.ts +1 -1
  55. package/cli/commands/inspect/wait-event.ts +5 -5
  56. package/cli/commands/inspect.ts +82 -82
  57. package/cli/commands/install-cli.ts +16 -16
  58. package/cli/commands/install-desktop.ts +26 -26
  59. package/cli/commands/login.ts +11 -11
  60. package/cli/commands/maestro-generate.ts +10 -10
  61. package/cli/commands/maestro.ts +77 -67
  62. package/cli/commands/mode.ts +4 -4
  63. package/cli/commands/no-bridge-hint.ts +12 -12
  64. package/cli/commands/perf.ts +11 -11
  65. package/cli/commands/permissions.ts +5 -5
  66. package/cli/commands/platform.ts +21 -21
  67. package/cli/commands/preview.ts +5 -5
  68. package/cli/commands/profile.ts +12 -12
  69. package/cli/commands/react.ts +15 -15
  70. package/cli/commands/record.ts +31 -31
  71. package/cli/commands/report-issue.ts +4 -4
  72. package/cli/commands/reset.ts +2 -2
  73. package/cli/commands/runtime.ts +23 -23
  74. package/cli/commands/screenshot-command.ts +2 -2
  75. package/cli/commands/screenshot-layers.ts +5 -5
  76. package/cli/commands/screenshot-mode.ts +7 -7
  77. package/cli/commands/screenshot.ts +24 -24
  78. package/cli/commands/screenshots-capture.ts +13 -13
  79. package/cli/commands/screenshots.ts +6 -6
  80. package/cli/commands/serve.ts +12 -12
  81. package/cli/commands/setup.ts +25 -25
  82. package/cli/commands/skills.ts +30 -23
  83. package/cli/commands/slides.ts +20 -20
  84. package/cli/commands/state.ts +2 -2
  85. package/cli/commands/storage.ts +3 -3
  86. package/cli/commands/telemetry.ts +2 -2
  87. package/cli/commands/test.ts +15 -15
  88. package/cli/commands/three-mode.ts +17 -17
  89. package/cli/commands/timeline.ts +12 -12
  90. package/cli/commands/upgrade.ts +11 -11
  91. package/cli/commands/upload.ts +26 -26
  92. package/cli/commands/version.ts +7 -7
  93. package/cli/commands/what-happened.ts +20 -20
  94. package/cli/current-sim.ts +3 -3
  95. package/cli/desktop-companion.ts +16 -16
  96. package/cli/drivers/electron.ts +4 -4
  97. package/cli/drivers/playwright-sim-host.ts +7 -7
  98. package/cli/drivers/playwright.ts +4 -4
  99. package/cli/drivers/registry.ts +1 -1
  100. package/cli/drivers/types.ts +5 -5
  101. package/cli/flow-export.ts +1 -1
  102. package/cli/flow-file.ts +5 -5
  103. package/cli/flow-session.ts +1 -1
  104. package/cli/help-core.ts +13 -13
  105. package/cli/hints.ts +14 -14
  106. package/cli/inspect-notice-state.ts +1 -1
  107. package/cli/internal-child.ts +2 -2
  108. package/cli/maestro-js.ts +4 -4
  109. package/cli/maestro-report.ts +1 -1
  110. package/cli/main.ts +14 -14
  111. package/cli/outbound-endpoints.ts +30 -30
  112. package/cli/parse-args.ts +7 -7
  113. package/cli/privacy.ts +1 -1
  114. package/cli/recording-access.ts +10 -10
  115. package/cli/resolve-assets.ts +2 -2
  116. package/cli/rnx-in-process.ts +5 -5
  117. package/cli/run-registry.ts +1 -1
  118. package/cli/run-rnx-core.ts +3 -3
  119. package/cli/run-rnx.ts +1 -1
  120. package/cli/runtime-notes.ts +1 -1
  121. package/cli/self-invocation.ts +1 -1
  122. package/cli/send-to-box.ts +1 -1
  123. package/cli/shell-init.ts +40 -40
  124. package/cli/ui.ts +1 -1
  125. package/cli/ws-bridge.ts +22 -22
  126. package/detox/config-loader.ts +1 -1
  127. package/detox/index.ts +28 -28
  128. package/detox/navigation.ts +2 -2
  129. package/dist-lib/agent-daemon-client.cjs +12 -12
  130. package/dist-lib/agent-events.cjs +1 -1
  131. package/dist-lib/agent-identity.cjs +2 -2
  132. package/dist-lib/agent-sessions.cjs +12 -12
  133. package/dist-lib/attached-projects.cjs +4 -4
  134. package/dist-lib/auth/shared-session.cjs +4 -4
  135. package/dist-lib/backend-origin.cjs +1 -1
  136. package/dist-lib/beta.cjs +1 -1
  137. package/dist-lib/beta.mjs +1 -1
  138. package/dist-lib/bridge-constants.cjs +4 -4
  139. package/dist-lib/bridge-contract-input.cjs +1 -1
  140. package/dist-lib/bridge-contract-input.mjs +1 -1
  141. package/dist-lib/bridge-contract.cjs +2 -2
  142. package/dist-lib/bridge-contract.mjs +2 -2
  143. package/dist-lib/capture-contract.cjs +1 -1
  144. package/dist-lib/capture-contract.mjs +1 -1
  145. package/dist-lib/cli-constants.cjs +1 -1
  146. package/dist-lib/cloud-contract.cjs +1 -1
  147. package/dist-lib/cloud-contract.mjs +1 -1
  148. package/dist-lib/cloud-test-args.cjs +1 -1
  149. package/dist-lib/cloud-test-args.mjs +1 -1
  150. package/dist-lib/cloud.cjs +42 -42
  151. package/dist-lib/cloud.mjs +42 -42
  152. package/dist-lib/config.cjs +2 -2
  153. package/dist-lib/detox/index.cjs +29 -29
  154. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  155. package/dist-lib/home-paths.cjs +12 -12
  156. package/dist-lib/host/bridge-host.cjs +72 -71
  157. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  158. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  159. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  160. package/dist-lib/host/replacement-module-handler.cjs +6 -6
  161. package/dist-lib/host/websocket-proxy.cjs +1 -1
  162. package/dist-lib/index.cjs +48 -48
  163. package/dist-lib/jump-to-source-babel.cjs +1 -1
  164. package/dist-lib/jump-to-source-native.cjs +1 -1
  165. package/dist-lib/menu.cjs +5 -5
  166. package/dist-lib/menu.mjs +5 -5
  167. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  168. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  169. package/dist-lib/metro-production-bundle.cjs +1 -1
  170. package/dist-lib/metro-production-bundle.mjs +1 -1
  171. package/dist-lib/metro.cjs +15 -15
  172. package/dist-lib/profiles.cjs +4 -4
  173. package/dist-lib/public-brand.cjs +3 -3
  174. package/dist-lib/react-native-host-modules.cjs +1 -1
  175. package/dist-lib/react-native-host-modules.mjs +1 -1
  176. package/dist-lib/render-mode.cjs +1 -1
  177. package/dist-lib/scripts/dev-server-scanner.cjs +2 -1
  178. package/dist-lib/sdk.cjs +9 -9
  179. package/dist-lib/sdk.mjs +9 -9
  180. package/dist-lib/skills.cjs +416 -415
  181. package/dist-lib/swift-compile.cjs +1 -1
  182. package/dist-lib/swift-compile.mjs +1 -1
  183. package/dist-lib/swift-package.cjs +1 -1
  184. package/dist-lib/swift-package.mjs +1 -1
  185. package/dist-lib/swift-submit.cjs +1 -1
  186. package/dist-lib/swift-submit.mjs +1 -1
  187. package/dist-lib/swift.cjs +1 -1
  188. package/dist-lib/vite.cjs +24 -24
  189. package/package.json +1 -1
  190. package/scripts/dev-server-scanner.ts +4 -3
  191. package/skills/contrast/SKILL.md +75 -75
  192. package/skills/{rnx-debug → peach-debug}/SKILL.md +90 -90
  193. package/skills/{rnx-perf → peach-perf}/SKILL.md +13 -13
  194. package/skills/{rnx-setup → peach-setup}/SKILL.md +60 -60
  195. package/skills/{rnx-test → peach-test}/SKILL.md +44 -44
  196. package/skills/{rnx-visual → peach-visual}/SKILL.md +26 -26
  197. package/src/agent-daemon-client.ts +5 -5
  198. package/src/agent-events.ts +1 -1
  199. package/src/agent-identity.ts +1 -1
  200. package/src/agent-sessions.ts +13 -13
  201. package/src/attached-projects.ts +1 -1
  202. package/src/auth/shared-session.ts +1 -1
  203. package/src/bridge-constants.ts +3 -3
  204. package/src/bridge-contract-input.ts +1 -1
  205. package/src/bridge-contract.ts +3 -3
  206. package/src/cli-version.ts +6 -6
  207. package/src/cloud.ts +40 -40
  208. package/src/config.ts +1 -1
  209. package/src/connect.ts +6 -6
  210. package/src/dev-server-open.ts +8 -8
  211. package/src/disk-cleanup.ts +3 -3
  212. package/src/home-paths.ts +26 -26
  213. package/src/host/agent-host.ts +3 -3
  214. package/src/host/bridge-host.ts +33 -33
  215. package/src/host/fetch-proxy-handler.ts +1 -1
  216. package/src/host/plane-host.ts +2 -2
  217. package/src/host/replacement-module-handler.ts +2 -2
  218. package/src/menu.ts +2 -2
  219. package/src/metro-plugin.ts +7 -7
  220. package/src/metro-production-bundle.ts +2 -2
  221. package/src/native-dev-bundle-url.ts +2 -2
  222. package/src/playwright-host-log.ts +1 -1
  223. package/src/public-brand.ts +2 -2
  224. package/src/react-native-host-modules.ts +1 -1
  225. package/src/rolldown-plugin-swift.ts +3 -3
  226. package/src/runtime-assets.ts +11 -11
  227. package/src/runtime-delivery.ts +6 -6
  228. package/src/screenshots/orchestrate.ts +1 -1
  229. package/src/screenshots/org-deck.ts +1 -1
  230. package/src/screenshots/schema.ts +2 -2
  231. package/src/sim-client.ts +1 -1
  232. package/src/skills/builtin/compat-check.ts +2 -2
  233. package/src/vite-plugin-one.ts +8 -8
  234. package/src/vite-plugin-swift.ts +3 -3
  235. package/src/vite-plugin.ts +6 -19
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: rnx-test
2
+ name: peach-test
3
3
  description: Run automated tests against your React Native app under Peach with Maestro YAML or Detox/Jest
4
4
  ---
5
5
 
@@ -9,10 +9,10 @@ Peach has two test runners. Maestro owns every YAML test, whether it was
9
9
  hand-authored, generated from a goal, or recorded from live CLI actions.
10
10
  Detox runs existing imperative Jest suites through the Peach driver.
11
11
 
12
- > needs a connected, pinned sim. if `rnx describe` errors, load
13
- > `/rnx-setup` first.
12
+ > needs a connected, pinned sim. if `peach describe` errors, load
13
+ > `/peach-setup` first.
14
14
 
15
- Set `RNX_NO_OPEN=1` before starting an app dev server for a Detox,
15
+ Set `PEACH_NO_OPEN=1` before starting an app dev server for a Detox,
16
16
  Maestro, or iOS-only pass. Apps can opt into a named Electron window through
17
17
  the official Vite or Metro plugin, and test-only work must not open that window.
18
18
 
@@ -37,15 +37,15 @@ Do not invent a third runner for how a Maestro flow was authored.
37
37
  implementation and author flows against it.
38
38
  - **pin a sim before running a suite.** parallel CI jobs colliding
39
39
  on the default bridge port is the #1 flake source. pass `--port` in
40
- CI and `rnx use <id>` locally.
40
+ CI and `peach use <id>` locally.
41
41
  - **every flow ends with an assert, not a screenshot.** a screenshot
42
42
  passes as long as the flow didn't throw. `assertVisible` (or
43
43
  `expect(...).toBeVisible()`) actually verifies the happy path.
44
44
  - **don't run a 40-step "smoke everything" flow.** when it fails, you
45
45
  can't tell what regressed. split into `login.yaml`, `compose.yaml`,
46
46
  `settings.yaml`, chain with `runFlow`.
47
- - **inside an `rnx do` chain, use `sleep` only for gesture timing.** after the
48
- chain, use `rnx wait` for app state so automation advances on a real condition.
47
+ - **inside an `peach do` chain, use `sleep` only for gesture timing.** after the
48
+ chain, use `peach wait` for app state so automation advances on a real condition.
49
49
 
50
50
  ## you're done when
51
51
 
@@ -62,8 +62,8 @@ batch. use a chain for a short repro, form fill, or timing-sensitive gesture
62
62
  that does not belong in a saved test:
63
63
 
64
64
  ```sh
65
- rnx do tap email --then type user@example.com --then tap submit
66
- rnx wait selector dashboard
65
+ peach do tap email --then type user@example.com --then tap submit
66
+ peach wait selector dashboard
67
67
  ```
68
68
 
69
69
  the batch stops on the first failure. add `--json` for per-action results.
@@ -79,23 +79,23 @@ Write declarative Maestro YAML. The same command runs existing suites,
79
79
  generates tests, records live drafts, profiles, and uploads replayable results.
80
80
 
81
81
  ```sh
82
- rnx maestro test .maestro/login.yaml # run one flow
83
- rnx maestro test .maestro/login.yaml --record # record video
84
- rnx maestro test .maestro/login.yaml --profile # include perf stats
85
- rnx maestro test .maestro/ # run the suite
82
+ peach maestro test .maestro/login.yaml # run one flow
83
+ peach maestro test .maestro/login.yaml --record # record video
84
+ peach maestro test .maestro/login.yaml --profile # include perf stats
85
+ peach maestro test .maestro/ # run the suite
86
86
  ```
87
87
 
88
88
  Author from a live interaction:
89
89
 
90
90
  ```sh
91
- rnx maestro start # begin a draft
92
- rnx do tap-id loginButton # drive the app via the CLI
93
- rnx maestro keep # save the step
94
- rnx do type "user@example.com"
95
- rnx maestro keep
96
- rnx do tap-id submit
97
- rnx maestro keep
98
- rnx maestro end --output .maestro/login.yaml --validate
91
+ peach maestro start # begin a draft
92
+ peach do tap-id loginButton # drive the app via the CLI
93
+ peach maestro keep # save the step
94
+ peach do type "user@example.com"
95
+ peach maestro keep
96
+ peach do tap-id submit
97
+ peach maestro keep
98
+ peach maestro end --output .maestro/login.yaml --validate
99
99
  ```
100
100
 
101
101
  the recorder emits minimal YAML — no coordinate dumps, no `sleep` noise —
@@ -129,7 +129,7 @@ exemplar flow:
129
129
  run with env interpolation:
130
130
 
131
131
  ```sh
132
- rnx maestro --env USERNAME=alice --env PASSWORD=hunter2 \
132
+ peach maestro --env USERNAME=alice --env PASSWORD=hunter2 \
133
133
  test .maestro/login.yaml \
134
134
  --record --profile
135
135
  ```
@@ -144,7 +144,7 @@ CLI's `wait idle` with a generous budget. use it before any
144
144
  Generate and immediately run a Maestro flow from a plain-language goal:
145
145
 
146
146
  ```sh
147
- rnx maestro generate "log in with the demo account and verify the dashboard"
147
+ peach maestro generate "log in with the demo account and verify the dashboard"
148
148
  ```
149
149
 
150
150
  Generation writes the same deterministic Maestro artifact, uploads its replay,
@@ -161,19 +161,19 @@ command change:
161
161
  maestro test .maestro/login.yaml
162
162
 
163
163
  # after
164
- rnx maestro test .maestro/login.yaml
164
+ peach maestro test .maestro/login.yaml
165
165
  ```
166
166
 
167
167
  no test rewrites, no detox config, no simulator. the runtime auto-launches
168
168
  a Peach shell if one isn't running.
169
169
 
170
170
  ```sh
171
- rnx maestro # auto-discover .maestro/ or maestro/
172
- rnx maestro test .maestro/login.yaml
173
- rnx maestro test .maestro/ # every flow in a directory
174
- rnx maestro init # scaffold a starter flow
175
- rnx maestro --list-compat # supported / partial / unsupported
176
- rnx maestro --env USERNAME=alice test .maestro/login.yaml
171
+ peach maestro # auto-discover .maestro/ or maestro/
172
+ peach maestro test .maestro/login.yaml
173
+ peach maestro test .maestro/ # every flow in a directory
174
+ peach maestro init # scaffold a starter flow
175
+ peach maestro --list-compat # supported / partial / unsupported
176
+ peach maestro --env USERNAME=alice test .maestro/login.yaml
177
177
  ```
178
178
 
179
179
  ### supported verbs
@@ -211,7 +211,7 @@ these throw `unsupported maestro verb: X`:
211
211
  ### troubleshooting
212
212
 
213
213
  - **"no maestro flows found"** — pass an explicit path
214
- (`rnx maestro test path/to/flow.yaml`) or run `rnx maestro
214
+ (`peach maestro test path/to/flow.yaml`) or run `peach maestro
215
215
  init` to scaffold one.
216
216
  - **"missing environment variable for flow placeholder: FOO"** — pass
217
217
  `--env FOO=bar` or export it. pick one mechanism per repo and document
@@ -229,7 +229,7 @@ an existing detox suite runs against Peach with **one line** of jest
229
229
  config and zero test changes.
230
230
 
231
231
  `import { by, device, element, expect, waitFor } from 'detox'` is
232
- rewritten by jest to an rnx-backed driver that drives the real shell
232
+ rewritten by jest to a peach-backed driver that drives the real shell
233
233
  over playwright. matchers, assertions, and the `waitFor` API match the
234
234
  upstream detox surface.
235
235
 
@@ -259,14 +259,14 @@ works until your first hung shell.
259
259
  ### commands
260
260
 
261
261
  ```sh
262
- rnx detox # run e2e/, test/e2e/, or detox/
263
- rnx detox --config my.cjs # use a specific jest config
264
- rnx detox --watch # jest watch mode
265
- rnx detox -t "login" # --testNamePattern
266
- rnx detox --headed # keep the shell window visible
267
- rnx detox --no-launch # don't auto-launch a shell
268
- rnx detox --port 5173 # explicit bridge port for CI
269
- rnx detox init # scaffold config + e2e/example.test.ts
262
+ peach detox # run e2e/, test/e2e/, or detox/
263
+ peach detox --config my.cjs # use a specific jest config
264
+ peach detox --watch # jest watch mode
265
+ peach detox -t "login" # --testNamePattern
266
+ peach detox --headed # keep the shell window visible
267
+ peach detox --no-launch # don't auto-launch a shell
268
+ peach detox --port 5173 # explicit bridge port for CI
269
+ peach detox init # scaffold config + e2e/example.test.ts
270
270
  ```
271
271
 
272
272
  ### compat surface
@@ -292,12 +292,12 @@ rnx detox init # scaffold config + e2e/example.test.ts
292
292
  ### troubleshooting
293
293
 
294
294
  - **"no Peach shell reachable"** — start one yourself
295
- (`rnx open <port>`) or pass `--port <n>`.
295
+ (`peach open <port>`) or pass `--port <n>`.
296
296
  - **"jest cannot find module 'detox'"** — the preset isn't wired. confirm
297
297
  `preset: 'peachsim/detox'` is in the jest config jest
298
298
  actually loaded (`--config` overrides package.json).
299
299
  - **matchers fail on elements that exist** — canvas has no DOM. use
300
- `by.id` (testID); `rnx describe` shows what the shell sees.
300
+ `by.id` (testID); `peach describe` shows what the shell sees.
301
301
  - **passes locally, flakes in CI** — the shell boots asynchronously.
302
302
  bump jest `testTimeout` to 10–15 s and add a `waitFor(element(...))
303
303
  .toBeVisible().withTimeout(10000)` before the first assertion.
@@ -315,7 +315,7 @@ rnx detox init # scaffold config + e2e/example.test.ts
315
315
  the first assertion, pin the bridge port, and run with `--video` so
316
316
  failing Maestro runs land a recording next to the output.
317
317
  - **a flake reproduces but resists fixing** — don't paper over with
318
- `sleep`. open `/rnx-debug` against the same sim, capture
319
- the timeline (`rnx timeline start` → reproduce → `rnx
318
+ `sleep`. open `/peach-debug` against the same sim, capture
319
+ the timeline (`peach timeline start` → reproduce → `peach
320
320
  what-happened`), and look for the missing animation-completion or
321
321
  the unresolved fetch that's racing the assertion.
@@ -1,25 +1,25 @@
1
1
  ---
2
- name: rnx-visual
2
+ name: peach-visual
3
3
  description: Pixel-level rendering comparison between Peach and native iOS — fonts, gradients, shadows, image fidelity
4
4
  ---
5
5
 
6
6
  # Peach visual fidelity
7
7
 
8
8
  pixel-level rendering fidelity: does the Peach canvas match native iOS
9
- for text, gradients, shadows, blur, and image rendering? the `rnx`
10
- CLI gives you two primitives — **canvas capture** (`rnx screenshot`)
11
- and **structural diff** (`rnx debug snapshot`/`diff`). pixel
9
+ for text, gradients, shadows, blur, and image rendering? the `peach`
10
+ CLI gives you two primitives — **canvas capture** (`peach screenshot`)
11
+ and **structural diff** (`peach debug snapshot`/`diff`). pixel
12
12
  comparison itself is "capture both sides, diff the PNGs with a standard
13
13
  image tool" — there is no single oracle-diff command, and that's fine:
14
14
  the capture step is the hard part and it's fully reproducible.
15
15
 
16
- > needs a connected, pinned sim. if `rnx describe` errors,
17
- > load `/rnx-setup` first.
16
+ > needs a connected, pinned sim. if `peach describe` errors,
17
+ > load `/peach-setup` first.
18
18
 
19
19
  ## route in
20
20
 
21
21
  - structural change ("which nodes / which props changed?") → load
22
- `/rnx-debug`, debugging branch — `debug snapshot` + `debug
22
+ `/peach-debug`, debugging branch — `debug snapshot` + `debug
23
23
  diff` is faster, deterministic, and tells you *why*.
24
24
  - visual change (color, gradient, shadow, font metric, blur, image)? →
25
25
  continue here.
@@ -28,36 +28,36 @@ the capture step is the hard part and it's fully reproducible.
28
28
 
29
29
  ## anti-patterns (read first)
30
30
 
31
- - **run structural diff before pixel work.** `rnx debug snapshot` /
32
- `debug diff` (in `/rnx-debug`) is cheaper, deterministic, and
31
+ - **run structural diff before pixel work.** `peach debug snapshot` /
32
+ `debug diff` (in `/peach-debug`) is cheaper, deterministic, and
33
33
  points at the responsible nodes. only when it's empty (or the change is
34
34
  pure rendering) does a pixel comparison add information.
35
35
  - **don't single-screenshot animated surfaces.** a gradient
36
- mid-animation never matches. gate the capture behind `rnx wait
36
+ mid-animation never matches. gate the capture behind `peach wait
37
37
  idle` first.
38
38
  - **a > 5% pixel threshold hides regressions.** ~1% is the right
39
39
  ballpark for catching real font / shadow / gradient drift without
40
40
  flagging anti-alias noise. go higher only with a written reason.
41
41
  - **pin device and theme.** capture both sides on the same simulated
42
42
  device and appearance. capture each appearance separately with
43
- `rnx screenshot` after setting it on both simulators.
43
+ `peach screenshot` after setting it on both simulators.
44
44
  - **commit baselines alongside the code change that produced them.**
45
45
  baseline churn without code churn means someone captured noise.
46
46
 
47
- ## capturing — `rnx screenshot`
47
+ ## capturing — `peach screenshot`
48
48
 
49
49
  fast, no extra setup, works on any loaded app:
50
50
 
51
51
  ```sh
52
- rnx screenshot --output app.png # full canvas
53
- rnx screenshot --area 0,200,393,400 # crop to a logical rect
54
- rnx screenshot --id loginButton -o btn.png # crop to a node by testID
55
- rnx screenshot --text "Sign in" # crop to a node by text
56
- rnx screenshot --no-shell -o tenant.png # tenant surface only, no iOS chrome
57
- rnx screenshot --shell-only # only the simulated iOS chrome
52
+ peach screenshot --output app.png # full canvas
53
+ peach screenshot --area 0,200,393,400 # crop to a logical rect
54
+ peach screenshot --id loginButton -o btn.png # crop to a node by testID
55
+ peach screenshot --text "Sign in" # crop to a node by text
56
+ peach screenshot --no-shell -o tenant.png # tenant surface only, no iOS chrome
57
+ peach screenshot --shell-only # only the simulated iOS chrome
58
58
  ```
59
59
 
60
- `rnx screenshot` captures the current screen as a PNG. navigate to each
60
+ `peach screenshot` captures the current screen as a PNG. navigate to each
61
61
  screen you want to inspect and capture it with a distinct output filename.
62
62
 
63
63
  ## comparing pixels
@@ -67,9 +67,9 @@ capture both sides to PNGs, then diff with any standard image tool.
67
67
  **Peach vs Peach (regression across your own commits):**
68
68
 
69
69
  ```sh
70
- rnx screenshot -o before.png # baseline, before your change
70
+ peach screenshot -o before.png # baseline, before your change
71
71
  # … make the rendering change, let the sim hot-reload …
72
- rnx screenshot -o after.png # after your change
72
+ peach screenshot -o after.png # after your change
73
73
  npx pixelmatch before.png after.png diff.png 0.1 # writes diff.png
74
74
  # or: magick compare before.png after.png diff.png
75
75
  ```
@@ -80,9 +80,9 @@ npx pixelmatch before.png after.png diff.png 0.1 # writes diff.png
80
80
  # native side: lifecycle and UI use xcodebuildmcp with one claimed simulator
81
81
  # lossless capture names that simulator explicitly; never use the booted alias
82
82
  xcrun simctl io <udid> screenshot --type=png native.png
83
- # rnx side: same screen, same appearance
84
- rnx screenshot -o rnx.png
85
- npx pixelmatch native.png rnx.png diff.png 0.1
83
+ # peach side: same screen, same appearance
84
+ peach screenshot -o peach.png
85
+ npx pixelmatch native.png peach.png diff.png 0.1
86
86
  ```
87
87
 
88
88
  `xcodebuildmcp simulator screenshot` may return an optimized JPEG even when the
@@ -97,7 +97,7 @@ under unrelated chrome.
97
97
  ## typical workflow
98
98
 
99
99
  1. structural diff first — confirm the change is genuinely visual.
100
- 2. capture the affected screen with `rnx screenshot` (crop to the
100
+ 2. capture the affected screen with `peach screenshot` (crop to the
101
101
  element if you can).
102
102
  3. diff against the baseline (previous commit, or a native capture).
103
103
  4. iterate the rendering until the diff is under threshold.
@@ -114,7 +114,7 @@ under unrelated chrome.
114
114
  ## recovery — common failure modes
115
115
 
116
116
  - **a single icon/glyph diffs** — font-load race or image not yet
117
- cached. recapture after `rnx wait idle`, or navigate away and back
117
+ cached. recapture after `peach wait idle`, or navigate away and back
118
118
  to seed the cache.
119
119
  - **everything diffs by a constant offset** — you captured the two sides
120
120
  on different devices or appearances. pin both, recapture.
@@ -1,7 +1,7 @@
1
1
  // node-side client for the daemon's agent:* ws protocol.
2
2
  //
3
3
  // used by electron main (translates IPC → daemon) and by the CLI
4
- // `sootsim agent …` subcommands. the browser shell has its own shim that
4
+ // `peach agent …` subcommands. the browser shell has its own shim that
5
5
  // uses window.WebSocket; this file is node-only.
6
6
  //
7
7
  // single long-lived connection per client. if the daemon goes away, the
@@ -105,7 +105,7 @@ export class AgentDaemonClient {
105
105
  this.ws.off('open', onOpen)
106
106
  reject(
107
107
  new AgentDaemonError(
108
- `could not connect to rnx daemon on port ${this.port}: ${err.message}`,
108
+ `could not connect to peach daemon on port ${this.port}: ${err.message}`,
109
109
  'NO_DAEMON',
110
110
  ),
111
111
  )
@@ -361,7 +361,7 @@ export async function ensureDaemonRunning(
361
361
  }
362
362
  if (shouldSkipPersistentDaemon()) {
363
363
  throw new AgentDaemonError(
364
- `no rnx bridge on port ${port}. run \`rnx daemon install\` to enable the faster background service, or \`rnx serve\` in another shell.`,
364
+ `no peach bridge on port ${port}. run \`peach daemon install\` to enable the faster background service, or \`peach serve\` in another shell.`,
365
365
  'DEV_HOST_REFUSED',
366
366
  )
367
367
  }
@@ -385,8 +385,8 @@ export async function ensureDaemonRunning(
385
385
  await new Promise((r) => setTimeout(r, 100))
386
386
  }
387
387
  throw new AgentDaemonError(
388
- `spawned rnx daemon on port ${port} but it did not come up in time. ` +
389
- `run \`rnx serve\` manually to diagnose.`,
388
+ `spawned peach daemon on port ${port} but it did not come up in time. ` +
389
+ `run \`peach serve\` manually to diagnose.`,
390
390
  'SPAWN_TIMEOUT',
391
391
  )
392
392
  }
@@ -1,7 +1,7 @@
1
1
  // wire format emitted by the agent-wrapper CLI subcommand on the events.out
2
2
  // FIFO. every line on the FIFO is exactly one JSON object — parse line-by-line.
3
3
  //
4
- // this file is the source of truth for the sootsim ↔ agent channel. it's
4
+ // this file is the source of truth for the peach ↔ agent channel. it's
5
5
  // imported by electron main (cockpit bridge), the CLI watch/transcript tools,
6
6
  // and the wrapper implementation itself, so it must stay runtime-safe (no
7
7
  // node-specific or electron-specific imports).
@@ -6,7 +6,7 @@ export function agentSessionIdFromCliIdentity(identity: string | null): string |
6
6
  if (colon < 0) return identity.trim() || null
7
7
  const source = identity.slice(0, colon)
8
8
  const value = identity.slice(colon + 1).trim()
9
- return source === 'RNX_CLI_IDENTITY' && value ? value : null
9
+ return source === 'PEACH_CLI_IDENTITY' && value ? value : null
10
10
  }
11
11
 
12
12
  export function teamMachineSessionIdFromCliIdentity(
@@ -1,5 +1,5 @@
1
- // session lifecycle shared between the CLI (`sootsim agent ...`) and electron
2
- // main (IPC handlers). both contexts spawn the same `sootsim agent-wrapper`
1
+ // session lifecycle shared between the CLI (`peach agent ...`) and electron
2
+ // main (IPC handlers). both contexts spawn the same `peach agent-wrapper`
3
3
  // subcommand, mutate the same AttachedProjects store, and subscribe to the
4
4
  // same events.out FIFO.
5
5
  //
@@ -67,10 +67,10 @@ export function pidIsAlive(pid: number | undefined, sessionId?: string): boolean
67
67
 
68
68
  // --- invocation resolution ---
69
69
 
70
- /** locate the rnx CLI so this process can run a subcommand of it. callers
70
+ /** locate the peach CLI so this process can run a subcommand of it. callers
71
71
  * range from the CLI itself to electron main and the vite-plugin daemon.
72
72
  * priority:
73
- * 1. RNX_BIN env var (explicit override)
73
+ * 1. PEACH_BIN env var (explicit override)
74
74
  * 2. this process already IS the CLI — `rnxSelfInvocation` owns that answer
75
75
  * 3. electron prod: bundled binary under process.resourcesPath/bin/
76
76
  * 4. workspace build artifacts (dist-bin/<binary> or dist-cli/bin.js)
@@ -80,8 +80,8 @@ export function pidIsAlive(pid: number | undefined, sessionId?: string): boolean
80
80
  * 5. CLI dev (argv[1] points at the entry script): re-use argv[0] + argv[1]
81
81
  */
82
82
  export function resolveSootsimInvocation(): RnxSelfInvocation {
83
- if (process.env.RNX_BIN) {
84
- return { executable: process.env.RNX_BIN, prefixArgs: [] }
83
+ if (process.env.PEACH_BIN) {
84
+ return { executable: process.env.PEACH_BIN, prefixArgs: [] }
85
85
  }
86
86
  // the compiled standalone binary cannot be found through argv: bun reports
87
87
  // argv[0] as the literal string "bun" and argv[1] as a path inside its
@@ -121,11 +121,11 @@ export function resolveSootsimInvocation(): RnxSelfInvocation {
121
121
  return { executable: process.argv[0], prefixArgs: [argv1] }
122
122
  }
123
123
  // anything else — a bin shim such as `…/node_modules/.bin/vite`, or no
124
- // argv[1] at all — names no rnx entry script, so say so instead of
124
+ // argv[1] at all — names no peach entry script, so say so instead of
125
125
  // spawning the host runtime with no arguments.
126
126
  throw new Error(
127
- 'rnx CLI not found. set RNX_BIN to the path of the rnx binary, ' +
128
- 'or build the workspace CLI via `bun run --cwd packages/sootsim build:cli`.',
127
+ 'peach CLI not found. set PEACH_BIN to the path of the peach binary, ' +
128
+ 'or build the workspace CLI via `bun run --cwd packages/peachsim build:cli`.',
129
129
  )
130
130
  }
131
131
 
@@ -133,7 +133,7 @@ function tryWorkspaceSootsim(): RnxSelfInvocation | null {
133
133
  try {
134
134
  const sootsimDir = resolveSootsimPackageDir()
135
135
  if (!sootsimDir) return null
136
- const binaryName = `rnx-${
136
+ const binaryName = `peach-${
137
137
  process.platform === 'win32' ? 'windows' : process.platform
138
138
  }-${process.arch}${process.platform === 'win32' ? '.exe' : ''}`
139
139
  const distBinary = path.join(sootsimDir, 'dist-bin', binaryName)
@@ -147,8 +147,8 @@ function tryWorkspaceSootsim(): RnxSelfInvocation | null {
147
147
  const buildMtime = fs.statSync(distBin).mtimeMs
148
148
  if (buildMtime < srcMtime) {
149
149
  console.warn(
150
- `[rnx] dist-cli/bin.js is older than agent-wrapper.ts — ` +
151
- `rebuild with \`bun run --cwd packages/sootsim build:cli\`.`,
150
+ `[peach] dist-cli/bin.js is older than agent-wrapper.ts — ` +
151
+ `rebuild with \`bun run --cwd packages/peachsim build:cli\`.`,
152
152
  )
153
153
  }
154
154
  }
@@ -342,7 +342,7 @@ export async function startSession(opts: StartSessionOpts): Promise<StartSession
342
342
  'ALREADY_RUNNING',
343
343
  `session already running for project=${project.id} provider=${provider} ` +
344
344
  `(session ${existingLive.id}, pid ${existingLive.wrapperPid}). ` +
345
- 'end it first with `rnx agent end <sessionId>`.',
345
+ 'end it first with `peach agent end <sessionId>`.',
346
346
  )
347
347
  }
348
348
 
@@ -114,7 +114,7 @@ function userDataDir(): string {
114
114
  return electronUserDataDir()
115
115
  }
116
116
 
117
- /** exposed for CLI status printing so `sootsim agent projects` can show the
117
+ /** exposed for CLI status printing so `peach agent projects` can show the
118
118
  * user which file it's reading from. */
119
119
  export function getUserDataDir(): string {
120
120
  return userDataDir()
@@ -38,7 +38,7 @@ export type SharedDesktopAuthSession = {
38
38
  validatedAt?: string
39
39
  /**
40
40
  * the account this sign-in bills cloud work to. a session token names the
41
- * person, not an account, so the CLI chooses one at `rnx login` and names it
41
+ * person, not an account, so the CLI chooses one at `peach login` and names it
42
42
  * on every request that opens a paid session.
43
43
  */
44
44
  accountId?: string
@@ -127,16 +127,16 @@ export function resolveSootsimWebSocketProxyUrl(input: {
127
127
  }): string {
128
128
  const pageUrl = parseHrefUrl(input.href)
129
129
  if (!pageUrl || (pageUrl.protocol !== 'http:' && pageUrl.protocol !== 'https:')) {
130
- throw new Error(`invalid rnx websocket proxy page URL: ${input.href}`)
130
+ throw new Error(`invalid peach websocket proxy page URL: ${input.href}`)
131
131
  }
132
132
  let targetUrl: URL
133
133
  try {
134
134
  targetUrl = new URL(input.targetUrl)
135
135
  } catch {
136
- throw new Error(`invalid rnx websocket proxy target URL: ${input.targetUrl}`)
136
+ throw new Error(`invalid peach websocket proxy target URL: ${input.targetUrl}`)
137
137
  }
138
138
  if (targetUrl.protocol !== 'ws:' && targetUrl.protocol !== 'wss:') {
139
- throw new Error(`invalid rnx websocket proxy target URL: ${input.targetUrl}`)
139
+ throw new Error(`invalid peach websocket proxy target URL: ${input.targetUrl}`)
140
140
  }
141
141
  const proxyUrl = new URL('/__websocket-proxy', pageUrl)
142
142
  proxyUrl.protocol = pageUrl.protocol === 'https:' ? 'wss:' : 'ws:'
@@ -1,6 +1,6 @@
1
1
  import { SIM_LONG_PRESS_MAX_MS } from './bridge-contract'
2
2
  // untrusted JSON -> bridge-contract argument. one owner for that conversion, so
3
- // every transport in front of a sim (the RNX Cloud sim service's HTTP and
3
+ // every transport in front of a sim (the Peach Cloud sim service's HTTP and
4
4
  // WebSocket routes) validates its request bodies here rather than growing a
5
5
  // second reader for the same shapes.
6
6
  import type {
@@ -1,4 +1,4 @@
1
- // the wire contract for the sootsim ws bridge. the engine implements it in
1
+ // the wire contract for the peach ws bridge. the engine implements it in
2
2
  // sootsim-engine/src/mcp/ws-bridge.ts; the peachsim cli client, the SimClient
3
3
  // sdk, and the flow runner speak it. it is the single owner of these shapes,
4
4
  // and neither side redeclares them.
@@ -367,7 +367,7 @@ export const SEMANTIC_READY_CONTENT_NODE_FLOOR = 100
367
367
  export const SEMANTIC_READY_NODE_STABLE_MS = 750
368
368
  export const SEMANTIC_READY_POLL_MS = 150
369
369
 
370
- export const PUBLIC_NO_NETWORK_MARKER = 'public RNX Cloud simulators have no network'
370
+ export const PUBLIC_NO_NETWORK_MARKER = 'public Peach Cloud simulators have no network'
371
371
  export const HEADLESS_TENANT_FETCH_HUNG_MARKER = 'headless tenant fetch hung'
372
372
 
373
373
  export function readyProbeHasContent(
@@ -424,7 +424,7 @@ export interface SimStateOptions {
424
424
  route?: boolean
425
425
  errors?: boolean
426
426
  // include the bounded guest console tail. omitted by the ordinary state
427
- // command so one-shot state remains compact; `rnx logs` requests it.
427
+ // command so one-shot state remains compact; `peach logs` requests it.
428
428
  logs?: boolean
429
429
  // tree depth, matching the standalone `tree` command. default 5.
430
430
  depth?: number
@@ -1,22 +1,22 @@
1
- // rnx cli version, resolved once and cached. standalone builds embed it so
1
+ // peach cli version, resolved once and cached. standalone builds embed it so
2
2
  // lazy command chunks do not depend on an npm package layout at runtime.
3
3
 
4
4
  import { readFileSync } from 'node:fs'
5
5
  import { fileURLToPath } from 'node:url'
6
6
  import { rnxPublicBrand } from './public-brand.ts'
7
7
 
8
- declare const __RNX_CLI_VERSION__: string
8
+ declare const __PEACH_CLI_VERSION__: string
9
9
 
10
10
  let cached: string | null = null
11
11
 
12
12
  export function getCliVersion(): string {
13
13
  if (cached != null) return cached
14
14
  if (
15
- typeof __RNX_CLI_VERSION__ !== 'undefined' &&
16
- typeof __RNX_CLI_VERSION__ === 'string' &&
17
- __RNX_CLI_VERSION__
15
+ typeof __PEACH_CLI_VERSION__ !== 'undefined' &&
16
+ typeof __PEACH_CLI_VERSION__ === 'string' &&
17
+ __PEACH_CLI_VERSION__
18
18
  ) {
19
- cached = __RNX_CLI_VERSION__
19
+ cached = __PEACH_CLI_VERSION__
20
20
  return cached
21
21
  }
22
22
  // prefer package resolution (works for npm/global installs); fall back to