peachsim 0.1.570 → 0.1.572

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 (242) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +108 -108
  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 +28 -20
  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 +3 -2
  12. package/cli/cloud-session.ts +12 -12
  13. package/cli/cloud-test-result-files.ts +97 -0
  14. package/cli/cloud-test-tunnel.ts +4 -4
  15. package/cli/command-registry.ts +7 -7
  16. package/cli/commands/agent-wrapper.ts +7 -7
  17. package/cli/commands/agent.ts +16 -16
  18. package/cli/commands/app-fonts.ts +3 -3
  19. package/cli/commands/assert.ts +10 -10
  20. package/cli/commands/auth.ts +5 -5
  21. package/cli/commands/box/checkout-plane.ts +1 -1
  22. package/cli/commands/box/plane-share.ts +2 -2
  23. package/cli/commands/box/rnx-command.ts +5 -5
  24. package/cli/commands/box.ts +38 -38
  25. package/cli/commands/camera.ts +13 -13
  26. package/cli/commands/cleanup.ts +13 -13
  27. package/cli/commands/compat.ts +7 -7
  28. package/cli/commands/config.ts +5 -5
  29. package/cli/commands/control.ts +63 -63
  30. package/cli/commands/cpu-profile.ts +11 -11
  31. package/cli/commands/daemon-mac-app.ts +10 -10
  32. package/cli/commands/daemon.ts +29 -27
  33. package/cli/commands/debug.ts +35 -35
  34. package/cli/commands/desktop.ts +3 -3
  35. package/cli/commands/detox.ts +33 -33
  36. package/cli/commands/device.ts +9 -9
  37. package/cli/commands/diagnose.ts +17 -17
  38. package/cli/commands/do-chain.ts +4 -4
  39. package/cli/commands/electron.ts +9 -9
  40. package/cli/commands/film.ts +9 -9
  41. package/cli/commands/flow.ts +49 -49
  42. package/cli/commands/inspect/core.ts +12 -12
  43. package/cli/commands/inspect/count.ts +1 -1
  44. package/cli/commands/inspect/describe.ts +1 -1
  45. package/cli/commands/inspect/env.ts +2 -2
  46. package/cli/commands/inspect/find.ts +2 -2
  47. package/cli/commands/inspect/get-layout.ts +2 -2
  48. package/cli/commands/inspect/keyboard.ts +1 -1
  49. package/cli/commands/inspect/list.ts +4 -4
  50. package/cli/commands/inspect/memory.ts +1 -1
  51. package/cli/commands/inspect/resolve-target.ts +1 -1
  52. package/cli/commands/inspect/screens.ts +1 -1
  53. package/cli/commands/inspect/shared.ts +1 -1
  54. package/cli/commands/inspect/tree.ts +1 -1
  55. package/cli/commands/inspect/url.ts +1 -1
  56. package/cli/commands/inspect/wait-event.ts +5 -5
  57. package/cli/commands/inspect.ts +82 -82
  58. package/cli/commands/install-cli.ts +16 -16
  59. package/cli/commands/install-desktop.ts +26 -26
  60. package/cli/commands/login.ts +11 -11
  61. package/cli/commands/maestro-generate.ts +10 -10
  62. package/cli/commands/maestro.ts +173 -71
  63. package/cli/commands/mode.ts +4 -4
  64. package/cli/commands/no-bridge-hint.ts +12 -12
  65. package/cli/commands/perf.ts +11 -11
  66. package/cli/commands/permissions.ts +5 -5
  67. package/cli/commands/platform.ts +21 -21
  68. package/cli/commands/preview.ts +5 -5
  69. package/cli/commands/profile.ts +12 -12
  70. package/cli/commands/react.ts +15 -15
  71. package/cli/commands/record.ts +31 -31
  72. package/cli/commands/report-issue.ts +4 -4
  73. package/cli/commands/reset.ts +2 -2
  74. package/cli/commands/runtime.ts +23 -23
  75. package/cli/commands/screenshot-command.ts +2 -2
  76. package/cli/commands/screenshot-layers.ts +5 -5
  77. package/cli/commands/screenshot-mode.ts +7 -7
  78. package/cli/commands/screenshot.ts +24 -24
  79. package/cli/commands/screenshots-capture.ts +13 -13
  80. package/cli/commands/screenshots.ts +6 -6
  81. package/cli/commands/serve.ts +12 -12
  82. package/cli/commands/setup.ts +25 -25
  83. package/cli/commands/skills.ts +30 -23
  84. package/cli/commands/slides.ts +20 -20
  85. package/cli/commands/state.ts +2 -2
  86. package/cli/commands/storage.ts +3 -3
  87. package/cli/commands/telemetry.ts +2 -2
  88. package/cli/commands/test.ts +176 -18
  89. package/cli/commands/three-mode.ts +17 -17
  90. package/cli/commands/timeline.ts +12 -12
  91. package/cli/commands/upgrade.ts +11 -11
  92. package/cli/commands/upload.ts +26 -26
  93. package/cli/commands/version.ts +7 -7
  94. package/cli/commands/what-happened.ts +20 -20
  95. package/cli/current-sim.ts +3 -3
  96. package/cli/desktop-companion.ts +16 -16
  97. package/cli/drivers/electron.ts +4 -4
  98. package/cli/drivers/playwright-sim-host.ts +7 -7
  99. package/cli/drivers/playwright.ts +4 -4
  100. package/cli/drivers/registry.ts +1 -1
  101. package/cli/drivers/types.ts +5 -5
  102. package/cli/flow-export.ts +1 -1
  103. package/cli/flow-file.ts +5 -5
  104. package/cli/flow-session.ts +1 -1
  105. package/cli/help-core.ts +13 -13
  106. package/cli/hints.ts +14 -14
  107. package/cli/inspect-notice-state.ts +1 -1
  108. package/cli/internal-child.ts +2 -2
  109. package/cli/maestro-js.ts +4 -4
  110. package/cli/maestro-report.ts +4 -2
  111. package/cli/main.ts +14 -14
  112. package/cli/outbound-endpoints.ts +32 -30
  113. package/cli/parse-args.ts +7 -7
  114. package/cli/privacy.ts +1 -1
  115. package/cli/recording-access.ts +10 -10
  116. package/cli/resolve-assets.ts +2 -2
  117. package/cli/rnx-in-process.ts +5 -5
  118. package/cli/run-registry.ts +3 -2
  119. package/cli/run-rnx-core.ts +3 -3
  120. package/cli/run-rnx.ts +1 -1
  121. package/cli/runtime-notes.ts +1 -1
  122. package/cli/self-invocation.ts +1 -1
  123. package/cli/send-to-box.ts +1 -1
  124. package/cli/shell-init.ts +40 -40
  125. package/cli/ui.ts +1 -1
  126. package/cli/ws-bridge.ts +22 -22
  127. package/detox/config-loader.ts +1 -1
  128. package/detox/index.ts +28 -28
  129. package/detox/jest-preset.cjs +2 -2
  130. package/detox/navigation.ts +2 -2
  131. package/dist-lib/agent-daemon-client.cjs +12 -12
  132. package/dist-lib/agent-events.cjs +1 -1
  133. package/dist-lib/agent-identity.cjs +2 -2
  134. package/dist-lib/agent-sessions.cjs +12 -12
  135. package/dist-lib/attached-projects.cjs +4 -4
  136. package/dist-lib/auth/shared-session.cjs +4 -4
  137. package/dist-lib/backend-origin.cjs +1 -1
  138. package/dist-lib/beta.cjs +1 -1
  139. package/dist-lib/beta.mjs +1 -1
  140. package/dist-lib/bridge-constants.cjs +4 -4
  141. package/dist-lib/bridge-contract-input.cjs +1 -1
  142. package/dist-lib/bridge-contract-input.mjs +1 -1
  143. package/dist-lib/bridge-contract.cjs +2 -2
  144. package/dist-lib/bridge-contract.mjs +2 -2
  145. package/dist-lib/capture-contract.cjs +1 -1
  146. package/dist-lib/capture-contract.mjs +1 -1
  147. package/dist-lib/cli-constants.cjs +1 -1
  148. package/dist-lib/cloud-contract.cjs +1 -1
  149. package/dist-lib/cloud-contract.mjs +1 -1
  150. package/dist-lib/cloud-test-args.cjs +116 -0
  151. package/dist-lib/cloud-test-args.mjs +86 -0
  152. package/dist-lib/cloud.cjs +42 -42
  153. package/dist-lib/cloud.mjs +42 -42
  154. package/dist-lib/config.cjs +2 -2
  155. package/dist-lib/detox/index.cjs +29 -29
  156. package/dist-lib/detox/jest-preset.cjs +2 -2
  157. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  158. package/dist-lib/home-paths.cjs +12 -12
  159. package/dist-lib/host/bridge-host.cjs +87 -77
  160. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  161. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  162. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  163. package/dist-lib/host/replacement-module-handler.cjs +6 -6
  164. package/dist-lib/host/websocket-proxy.cjs +1 -1
  165. package/dist-lib/index.cjs +63 -73
  166. package/dist-lib/jump-to-source-babel.cjs +1 -1
  167. package/dist-lib/jump-to-source-native.cjs +1 -1
  168. package/dist-lib/menu.cjs +5 -5
  169. package/dist-lib/menu.mjs +5 -5
  170. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  171. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  172. package/dist-lib/metro-production-bundle.cjs +1 -1
  173. package/dist-lib/metro-production-bundle.mjs +1 -1
  174. package/dist-lib/metro.cjs +15 -15
  175. package/dist-lib/profiles.cjs +4 -4
  176. package/dist-lib/public-brand.cjs +3 -3
  177. package/dist-lib/react-native-host-modules.cjs +1 -1
  178. package/dist-lib/react-native-host-modules.mjs +1 -1
  179. package/dist-lib/render-mode.cjs +1 -1
  180. package/dist-lib/scripts/dev-server-scanner.cjs +2 -1
  181. package/dist-lib/sdk.cjs +9 -9
  182. package/dist-lib/sdk.mjs +9 -9
  183. package/dist-lib/skills.cjs +534 -520
  184. package/dist-lib/swift-compile.cjs +372 -0
  185. package/dist-lib/swift-compile.mjs +339 -0
  186. package/dist-lib/swift-package.cjs +78 -0
  187. package/dist-lib/swift-package.mjs +52 -0
  188. package/dist-lib/swift-submit.cjs +1 -1
  189. package/dist-lib/swift-submit.mjs +1 -1
  190. package/dist-lib/swift.cjs +1 -1
  191. package/dist-lib/vite.cjs +479 -161
  192. package/package.json +22 -1
  193. package/scripts/dev-server-scanner.ts +4 -3
  194. package/skills/contrast/SKILL.md +75 -75
  195. package/skills/{rnx-debug → peach-debug}/SKILL.md +90 -90
  196. package/skills/{rnx-perf → peach-perf}/SKILL.md +13 -13
  197. package/skills/{rnx-setup → peach-setup}/SKILL.md +60 -60
  198. package/skills/{rnx-test → peach-test}/SKILL.md +47 -47
  199. package/skills/{rnx-visual → peach-visual}/SKILL.md +26 -26
  200. package/src/agent-daemon-client.ts +5 -5
  201. package/src/agent-events.ts +1 -1
  202. package/src/agent-identity.ts +1 -1
  203. package/src/agent-sessions.ts +13 -13
  204. package/src/attached-projects.ts +1 -1
  205. package/src/auth/shared-session.ts +1 -1
  206. package/src/bridge-constants.ts +3 -3
  207. package/src/bridge-contract-input.ts +1 -1
  208. package/src/bridge-contract.ts +3 -3
  209. package/src/cli-version.ts +6 -6
  210. package/src/cloud-test-args.ts +100 -0
  211. package/src/cloud.ts +40 -40
  212. package/src/config.ts +1 -1
  213. package/src/connect.ts +6 -6
  214. package/src/dev-server-open.ts +8 -8
  215. package/src/disk-cleanup.ts +3 -3
  216. package/src/home-paths.ts +26 -26
  217. package/src/host/agent-host.ts +3 -3
  218. package/src/host/bridge-host.ts +33 -33
  219. package/src/host/fetch-proxy-handler.ts +1 -1
  220. package/src/host/plane-host.ts +2 -2
  221. package/src/host/replacement-module-handler.ts +2 -2
  222. package/src/menu.ts +2 -2
  223. package/src/metro-plugin.ts +7 -7
  224. package/src/metro-production-bundle.ts +2 -2
  225. package/src/native-dev-bundle-url.ts +2 -2
  226. package/src/playwright-host-log.ts +1 -1
  227. package/src/public-brand.ts +2 -2
  228. package/src/react-native-host-modules.ts +1 -1
  229. package/src/rolldown-plugin-swift.ts +11 -10
  230. package/src/runtime-assets.ts +11 -11
  231. package/src/runtime-delivery.ts +6 -6
  232. package/src/screenshots/orchestrate.ts +1 -1
  233. package/src/screenshots/org-deck.ts +1 -1
  234. package/src/screenshots/schema.ts +2 -2
  235. package/src/sim-client.ts +1 -1
  236. package/src/skills/builtin/compat-check.ts +2 -2
  237. package/src/swift-compile.ts +359 -0
  238. package/src/swift-package.ts +69 -0
  239. package/src/swift-submit.ts +3 -2
  240. package/src/vite-plugin-one.ts +8 -8
  241. package/src/vite-plugin-swift.ts +106 -110
  242. package/src/vite-plugin.ts +6 -19
@@ -1,5 +1,5 @@
1
- // rnx inspect — dump node tree, accessibility info, query nodes
2
- // connects to the rnx WS bridge (no Playwright)
1
+ // peach inspect — dump node tree, accessibility info, query nodes
2
+ // connects to the peach WS bridge (no Playwright)
3
3
 
4
4
  import { getCliInspectVerbMeta } from '@peach/skills/cli'
5
5
  import { renderCliCommandHelp, renderCliGroupHelp } from '@peach/skills/cli/renderers'
@@ -155,8 +155,8 @@ function formatNetworkDuration(ms: number | null): string {
155
155
  function printRecoverHint(): void {
156
156
  process.stderr.write(
157
157
  ` the sim is not responding. recover it with:\n` +
158
- ` rnx close --sim <id> # force-close the wedged sim\n` +
159
- ` rnx list # confirm it's gone\n`,
158
+ ` peach close --sim <id> # force-close the wedged sim\n` +
159
+ ` peach list # confirm it's gone\n`,
160
160
  )
161
161
  }
162
162
 
@@ -495,7 +495,7 @@ function printRenderProfile(worker: string, rp: Record<string, any> | undefined)
495
495
  // pretty-print the shell frame profile payload (__sootsimShellPerf.stop()):
496
496
  // per-painted-frame timing from the shell worker merged with the render
497
497
  // profile counters. numbers arrive pre-rounded from the worker. also used by
498
- // `rnx maestro test --profile`, which records the same payload.
498
+ // `peach maestro test --profile`, which records the same payload.
499
499
  export function printShellPerfReport(result: Record<string, any>) {
500
500
  const fps = result.avgMs > 0 ? (1000 / result.avgMs).toFixed(1) : '?'
501
501
  const jank = result.jank && typeof result.jank === 'object' ? result.jank : null
@@ -862,7 +862,7 @@ async function performCloudKeys(
862
862
  if (result.ok) return
863
863
  const failed = result.steps.find((step) => !step.ok)
864
864
  console.error(
865
- ` ${actionLabel} failed: ${failed?.error ?? result.error ?? 'no text input had focus'}. focus an input first with rnx do tap-id or rnx do type-into.`,
865
+ ` ${actionLabel} failed: ${failed?.error ?? result.error ?? 'no text input had focus'}. focus an input first with peach do tap-id or peach do type-into.`,
866
866
  )
867
867
  rnxExit(1)
868
868
  }
@@ -877,7 +877,7 @@ async function requireVisualKeyboard(bridge: WsBridge, actionLabel: string) {
877
877
  rnxExit(1)
878
878
  }
879
879
  console.error(
880
- ` ${actionLabel} requires the iOS keyboard to be visible. focus an input first with rnx do tap-id/tap-text or rnx do type-into.`,
880
+ ` ${actionLabel} requires the iOS keyboard to be visible. focus an input first with peach do tap-id/tap-text or peach do type-into.`,
881
881
  )
882
882
  rnxExit(1)
883
883
  }
@@ -913,7 +913,7 @@ async function runShellVisualCommand(
913
913
  code: `(async () => {
914
914
  const toggleLock = window.SootSim?.bridges?.mainShell?.toggleLock
915
915
  if (typeof toggleLock !== 'function') {
916
- throw new Error('rnx mainShell.toggleLock bridge unavailable')
916
+ throw new Error('peach mainShell.toggleLock bridge unavailable')
917
917
  }
918
918
  await toggleLock()
919
919
  return { ok: true, action: 'lock' }
@@ -949,9 +949,9 @@ function keyCodeToVisualKey(code: string) {
949
949
  }
950
950
 
951
951
  function getInspectCommandName(subcommand: string, directSubcommand: string | null) {
952
- if (directSubcommand === subcommand) return `rnx ${subcommand}`
952
+ if (directSubcommand === subcommand) return `peach ${subcommand}`
953
953
  const group = getCliInspectVerbMeta(subcommand)?.group
954
- return group ? `rnx ${group} ${subcommand}` : `rnx ${subcommand}`
954
+ return group ? `peach ${group} ${subcommand}` : `peach ${subcommand}`
955
955
  }
956
956
 
957
957
  function getInspectUsage(
@@ -993,7 +993,7 @@ async function recordInspectAction(
993
993
  '`maestro keep` commits one action at a time',
994
994
  )
995
995
  } else {
996
- console.error(' draft: action pending — `rnx maestro keep` to commit')
996
+ console.error(' draft: action pending — `peach maestro keep` to commit')
997
997
  }
998
998
  }
999
999
 
@@ -1056,9 +1056,9 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1056
1056
  // strip a leading grouping verb — `get`, `do`, and (when forwarded from
1057
1057
  // runDebug) `debug`. these are organizational prefixes and shouldn't leak
1058
1058
  // into subcommand dispatch. e.g.:
1059
- // rnx get tree → effectiveArgs = ['tree']
1060
- // rnx do tap 100 200 → effectiveArgs = ['tap', '100', '200']
1061
- // rnx debug state shell → effectiveArgs = ['state', 'shell']
1059
+ // peach get tree → effectiveArgs = ['tree']
1060
+ // peach do tap 100 200 → effectiveArgs = ['tap', '100', '200']
1061
+ // peach debug state shell → effectiveArgs = ['state', 'shell']
1062
1062
  const verbPrefix =
1063
1063
  args[0] === 'get' || args[0] === 'do' || args[0] === 'debug' || args[0] === 'wait'
1064
1064
  ? args[0]
@@ -1133,21 +1133,21 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1133
1133
  const topLevelCommand = isTopLevel ? effectiveArgs[0] : null
1134
1134
  // a usage string has to name something the user can actually type. the
1135
1135
  // registry knows which group each verb belongs to, so an unprefixed
1136
- // invocation still renders `rnx get tree` rather than a bare verb.
1136
+ // invocation still renders `peach get tree` rather than a bare verb.
1137
1137
  const inspectCommand = (name: string) => {
1138
1138
  if (opts.internalPerfCommand && name === 'perf') {
1139
- return `rnx perf ${opts.internalPerfCommand}`
1139
+ return `peach perf ${opts.internalPerfCommand}`
1140
1140
  }
1141
- if (isTopLevel && name === effectiveArgs[0]) return `rnx ${name}`
1141
+ if (isTopLevel && name === effectiveArgs[0]) return `peach ${name}`
1142
1142
  const group = invocationPrefix ?? getCliInspectVerbMeta(name)?.group
1143
- return group ? `rnx ${group} ${name}` : `rnx ${name}`
1143
+ return group ? `peach ${group} ${name}` : `peach ${name}`
1144
1144
  }
1145
1145
  const inspectUsage = (name: string, tail: string) =>
1146
1146
  ` usage: ${inspectCommand(name)}${tail ? ` ${tail}` : ''}`
1147
1147
 
1148
1148
  if (!subcommand || args.includes('--help') || args.includes('-h')) {
1149
1149
  // all help output comes from the registry in packages/peach-skills
1150
- // so `rnx do --help`, `rnx get --help`, the website docs, and
1150
+ // so `peach do --help`, `peach get --help`, the website docs, and
1151
1151
  // the Contrast skill markdown stay in lock-step. a drift check in
1152
1152
  // test/sootsimCliRegistry.test.ts fails CI if a verb lands without a
1153
1153
  // matching registry entry.
@@ -1217,8 +1217,8 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1217
1217
  return
1218
1218
  }
1219
1219
 
1220
- // `rnx list --drivers` — pure local registry view, no bridge needed.
1221
- // short-circuit here so users can discover drivers even when no rnx
1220
+ // `peach list --drivers` — pure local registry view, no bridge needed.
1221
+ // short-circuit here so users can discover drivers even when no peach
1222
1222
  // session is running.
1223
1223
  if (
1224
1224
  subcommand === 'list' &&
@@ -1327,7 +1327,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1327
1327
  // like a settled sim to the next read, and that read then hands out
1328
1328
  // coordinates the screen is still animating away from.
1329
1329
  process.stderr.write(
1330
- ` ⚠ auto-settle failed (${error instanceof Error ? error.message : String(error)}) — next command may see mid-animation state. use \`rnx do settle\` to retry.\n`,
1330
+ ` ⚠ auto-settle failed (${error instanceof Error ? error.message : String(error)}) — next command may see mid-animation state. use \`peach do settle\` to retry.\n`,
1331
1331
  )
1332
1332
  }
1333
1333
  return
@@ -1345,7 +1345,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1345
1345
  })
1346
1346
  if (!settled) {
1347
1347
  process.stderr.write(
1348
- ` ⚠ auto-wait timed out after ${elapsed ?? budgetMs}ms — next command may see mid-animation state. use \`rnx do settle\` for a longer wait.\n`,
1348
+ ` ⚠ auto-wait timed out after ${elapsed ?? budgetMs}ms — next command may see mid-animation state. use \`peach do settle\` for a longer wait.\n`,
1349
1349
  )
1350
1350
  }
1351
1351
  } catch {
@@ -1360,7 +1360,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1360
1360
  ` tap failed: ${label} resolved to (${Math.round(x)},${Math.round(y)}), outside the ${screen?.width}x${screen?.height} screen`,
1361
1361
  )
1362
1362
  console.error(
1363
- ' the node exists but is scrolled out of view — scroll it on-screen first (rnx do scroll / swipe), then tap.',
1363
+ ' the node exists but is scrolled out of view — scroll it on-screen first (peach do scroll / swipe), then tap.',
1364
1364
  )
1365
1365
  return
1366
1366
  }
@@ -1594,7 +1594,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1594
1594
  if (!seen.has(kind) && n) parts.push(`${n} ${kind}${n === 1 ? '' : 's'}`)
1595
1595
  }
1596
1596
  if (parts.length === 0) return
1597
- console.error(`\n since last: ${parts.join(' · ')} — rnx what-happened`)
1597
+ console.error(`\n since last: ${parts.join(' · ')} — peach what-happened`)
1598
1598
  // advance cursor so the next CLI call only sees *new* events.
1599
1599
  if (payload.summary.lastAt) {
1600
1600
  try {
@@ -1660,7 +1660,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1660
1660
  const verboseTransitions =
1661
1661
  (args.includes('--verbose') || args.includes('-v')) && !args.includes('--json')
1662
1662
  if (invocationPrefix === 'do' && subcommand === 'shell') {
1663
- console.error(' `rnx do shell` was removed. use `rnx shell ...` instead.')
1663
+ console.error(' `peach do shell` was removed. use `peach shell ...` instead.')
1664
1664
  rnxExit(1)
1665
1665
  }
1666
1666
  if (writeCommands.has(subcommand)) {
@@ -1797,9 +1797,9 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1797
1797
  }
1798
1798
 
1799
1799
  case 'event': {
1800
- // rnx wait event <kind> — timeline-backed wait. delegates
1800
+ // peach wait event <kind> — timeline-backed wait. delegates
1801
1801
  // matcher + polling to runWaitEventSubcommand so the same
1802
- // logic is reachable from `rnx wait event` regardless of
1802
+ // logic is reachable from `peach wait event` regardless of
1803
1803
  // verb-group prefix (and the same shape is testable on its
1804
1804
  // own).
1805
1805
  await runWaitEventSubcommand({ bridge, args, positional, inspectUsage })
@@ -1808,7 +1808,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1808
1808
 
1809
1809
  case 'layout': {
1810
1810
  const id = positional[1]
1811
- // bare `rnx get layout` (no id) measures visible elements on the
1811
+ // bare `peach get layout` (no id) measures visible elements on the
1812
1812
  // screen by bounding box. --styling opts into box-model/style detail via
1813
1813
  // the shared get-layout kernel the agent's app_get_layout also uses.
1814
1814
  // passing an id keeps the single-node {x, y, width, height} lookup.
@@ -1844,7 +1844,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1844
1844
  case 'capture':
1845
1845
  case 'screenshot': {
1846
1846
  const outputArg = args.find((_, i) => args[i - 1] === '--output')
1847
- const outputPath = outputArg || '/tmp/rnx-inspect.png'
1847
+ const outputPath = outputArg || '/tmp/peach-inspect.png'
1848
1848
  const rect = await resolveSampleRect(args, bridge)
1849
1849
 
1850
1850
  const request: { type: 'screenshot'; crop?: SampleRect } = { type: 'screenshot' }
@@ -1870,7 +1870,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1870
1870
  ),
1871
1871
  )
1872
1872
  console.error(
1873
- ' samples an averaged color from the canvas. coords are logical rnx units.',
1873
+ ' samples an averaged color from the canvas. coords are logical peach units.',
1874
1874
  )
1875
1875
  rnxExit(1)
1876
1876
  }
@@ -2255,7 +2255,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
2255
2255
  const payload = outcome.payload
2256
2256
 
2257
2257
  if (payload?.error === 'bridge-not-ready') {
2258
- console.error(' rnx test bridge not ready')
2258
+ console.error(' peach test bridge not ready')
2259
2259
  rnxExit(1)
2260
2260
  }
2261
2261
 
@@ -2366,7 +2366,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
2366
2366
  }
2367
2367
 
2368
2368
  case 'tap-best': {
2369
- // rnx do tap-best <query> — try tap-id, then tap-text. the
2369
+ // peach do tap-best <query> — try tap-id, then tap-text. the
2370
2370
  // common agent ergonomic problem: the agent has a label like
2371
2371
  // "Create expense" and doesn't know whether that's a testID
2372
2372
  // or visible text. with tap-text it fails when the only
@@ -2402,7 +2402,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
2402
2402
  | null
2403
2403
  if (!payload) {
2404
2404
  console.error(
2405
- ` tap-best: no testID or visible text matched "${query}". try \`rnx find --interactive-targets\` to list candidates.`,
2405
+ ` tap-best: no testID or visible text matched "${query}". try \`peach find --interactive-targets\` to list candidates.`,
2406
2406
  )
2407
2407
  rnxExit(1)
2408
2408
  }
@@ -2412,7 +2412,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
2412
2412
  }
2413
2413
  if (payload.strategy === 'none') {
2414
2414
  console.error(
2415
- ` tap-best: no testID or visible text matched "${query}". try \`rnx find --interactive-targets\` to list candidates.`,
2415
+ ` tap-best: no testID or visible text matched "${query}". try \`peach find --interactive-targets\` to list candidates.`,
2416
2416
  )
2417
2417
  rnxExit(1)
2418
2418
  }
@@ -3102,8 +3102,8 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3102
3102
 
3103
3103
  case 'state': {
3104
3104
  const stateCmd = positional[1]
3105
- // `rnx get state` (no sub-arg) → compact runtime dashboard.
3106
- // `rnx debug state <kind>` continues to dispatch the raw dumps.
3105
+ // `peach get state` (no sub-arg) → compact runtime dashboard.
3106
+ // `peach debug state <kind>` continues to dispatch the raw dumps.
3107
3107
  if (verbPrefix === 'get' && !stateCmd) {
3108
3108
  const base = await callTestBridge<Record<string, any>>(
3109
3109
  bridge,
@@ -3512,14 +3512,14 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3512
3512
 
3513
3513
  case 'reload': {
3514
3514
  // a cloud simulator is a headless runtime with no page to reload, and
3515
- // rnx itself runs inside the box's workerd isolate rather than a node
3515
+ // peach itself runs inside the box's workerd isolate rather than a node
3516
3516
  // process, so the full-page branch below cannot work: it reconnects
3517
3517
  // through `waitForBridgeConnected`, whose `createBridge` constructs the
3518
3518
  // `ws` package's WebSocket, and that import has no constructor in
3519
3519
  // workerd.
3520
3520
  if (bridge.plane === 'cloud') {
3521
3521
  const message =
3522
- 'rnx do reload is not available on a cloud simulator; it runs headless with no page to reload. restart the simulator instead.'
3522
+ 'peach do reload is not available on a cloud simulator; it runs headless with no page to reload. restart the simulator instead.'
3523
3523
  if (wantsJson(effectiveArgs)) {
3524
3524
  printJson({ cleared: false, ready: false, error: message })
3525
3525
  } else {
@@ -3744,7 +3744,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3744
3744
  if (!code) {
3745
3745
  console.error(inspectUsage('js', '<javascript>'))
3746
3746
  console.error('')
3747
- console.error(' runs the snippet in the engine realm. rnx is the')
3747
+ console.error(' runs the snippet in the engine realm. peach is the')
3748
3748
  console.error(' canonical state surface — reach into it directly.')
3749
3749
  console.error('')
3750
3750
  console.error(' examples:')
@@ -3794,24 +3794,24 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3794
3794
  const lc = code.toLowerCase()
3795
3795
  const suggestions: string[] = []
3796
3796
  if (lc.includes('sootsim:gohome') || lc.includes('gohome'))
3797
- suggestions.push('rnx shell home')
3797
+ suggestions.push('peach shell home')
3798
3798
  if (lc.includes('sootsim:appswitcher') || lc.includes('appswitcher'))
3799
- suggestions.push('rnx shell switcher')
3799
+ suggestions.push('peach shell switcher')
3800
3800
  if (lc.includes('keyboard.isvisible') || lc.includes('keyboard.getmode'))
3801
- suggestions.push('rnx debug state keyboard')
3802
- if (lc.includes('interact.tap')) suggestions.push('rnx do tap <x> <y>')
3803
- if (lc.includes('keyboard.type')) suggestions.push('rnx do type <text>')
3801
+ suggestions.push('peach debug state keyboard')
3802
+ if (lc.includes('interact.tap')) suggestions.push('peach do tap <x> <y>')
3803
+ if (lc.includes('keyboard.type')) suggestions.push('peach do type <text>')
3804
3804
  if (lc.includes('keyboard.press') || lc.includes('keyboard.dispatchkey'))
3805
- suggestions.push('rnx do key <name>')
3806
- if (lc.includes('keyboard.dismiss')) suggestions.push('rnx do dismiss')
3807
- if (lc.includes('dumptree')) suggestions.push('rnx get tree')
3808
- if (lc.includes('dumpaccessibilitytree')) suggestions.push('rnx get a11y')
3809
- if (lc.includes('getnodecount')) suggestions.push('rnx get count')
3810
- if (lc.includes('findbytext')) suggestions.push('rnx find <text>')
3805
+ suggestions.push('peach do key <name>')
3806
+ if (lc.includes('keyboard.dismiss')) suggestions.push('peach do dismiss')
3807
+ if (lc.includes('dumptree')) suggestions.push('peach get tree')
3808
+ if (lc.includes('dumpaccessibilitytree')) suggestions.push('peach get a11y')
3809
+ if (lc.includes('getnodecount')) suggestions.push('peach get count')
3810
+ if (lc.includes('findbytext')) suggestions.push('peach find <text>')
3811
3811
  if (lc.includes('findbytestid') || lc.includes('findbyid'))
3812
- suggestions.push('rnx find --testid <id>')
3812
+ suggestions.push('peach find --testid <id>')
3813
3813
  if (lc.includes('document.hidden'))
3814
- suggestions.push('rnx debug state keyboard (includes tab health)')
3814
+ suggestions.push('peach debug state keyboard (includes tab health)')
3815
3815
  if (suggestions.length > 0) {
3816
3816
  maybeHint('prefer-cli-over-eval', suggestions)
3817
3817
  }
@@ -3820,7 +3820,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3820
3820
  }
3821
3821
 
3822
3822
  case 'globals': {
3823
- // show all available rnx globals and their methods
3823
+ // show all available peach globals and their methods
3824
3824
  const info = await bridge.send({
3825
3825
  type: 'evaluate',
3826
3826
  code: `(async () => {
@@ -3862,7 +3862,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3862
3862
  return globals
3863
3863
  })()`,
3864
3864
  })
3865
- console.log(' rnx JS API:\n')
3865
+ console.log(' peach JS API:\n')
3866
3866
  for (const [name, methods] of Object.entries(info as Record<string, string[]>)) {
3867
3867
  console.log(` ${name}:`)
3868
3868
  for (const m of methods) {
@@ -3882,7 +3882,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3882
3882
 
3883
3883
  case 'perf': {
3884
3884
  if (invocationPrefix === 'debug' && !opts.internalPerfCommand) {
3885
- console.error(' `rnx debug perf` was removed. use `rnx perf shell ...`.')
3885
+ console.error(' `peach debug perf` was removed. use `peach perf shell ...`.')
3886
3886
  rnxExit(1)
3887
3887
  }
3888
3888
  const perfCmd = positional[1]
@@ -4316,20 +4316,20 @@ export async function runInspect(args: string[], opts: InspectOptions) {
4316
4316
  }
4317
4317
 
4318
4318
  case 'network': {
4319
- // rnx network — live request inspector backed by the shared
4319
+ // peach network — live request inspector backed by the shared
4320
4320
  // observability store (installed at engine boot, fed by worker-side
4321
4321
  // fetch + XHR capture over BroadcastChannel).
4322
4322
  //
4323
4323
  // shapes:
4324
- // rnx network [limit] last N entries (default 20)
4325
- // rnx network --failed only non-2xx / errored
4326
- // rnx network --slow only requests slower than --threshold (default 1000ms)
4327
- // rnx network --threshold <ms> customize slow threshold for --slow
4328
- // rnx network --filter <substring> url substring filter
4329
- // rnx network --json raw json output
4330
- // rnx network tail | -f follow mode (polls)
4331
- // rnx network get <id> detail for one entry
4332
- // rnx network clear drop the buffer
4324
+ // peach network [limit] last N entries (default 20)
4325
+ // peach network --failed only non-2xx / errored
4326
+ // peach network --slow only requests slower than --threshold (default 1000ms)
4327
+ // peach network --threshold <ms> customize slow threshold for --slow
4328
+ // peach network --filter <substring> url substring filter
4329
+ // peach network --json raw json output
4330
+ // peach network tail | -f follow mode (polls)
4331
+ // peach network get <id> detail for one entry
4332
+ // peach network clear drop the buffer
4333
4333
  const sub = positional[1]
4334
4334
 
4335
4335
  // manual flag scan — parseBridgeCliArgs already stripped these
@@ -4373,7 +4373,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
4373
4373
  if (sub === 'get') {
4374
4374
  const id = positional[2]
4375
4375
  if (!id) {
4376
- console.error(' usage: rnx network get <id>')
4376
+ console.error(' usage: peach network get <id>')
4377
4377
  rnxExit(1)
4378
4378
  }
4379
4379
  const entry = (await bridge.send({
@@ -4509,17 +4509,17 @@ export async function runInspect(args: string[], opts: InspectOptions) {
4509
4509
  }
4510
4510
 
4511
4511
  case 'logs': {
4512
- // rnx logs — live console inspector backed by the shared
4512
+ // peach logs — live console inspector backed by the shared
4513
4513
  // observability log store (fed by worker-side console capture over
4514
- // BroadcastChannel). mirrors `rnx network`:
4514
+ // BroadcastChannel). mirrors `peach network`:
4515
4515
  //
4516
- // rnx logs [limit] last N entries (default 50)
4517
- // rnx logs --level error,warn filter by level (csv)
4518
- // rnx logs --filter <str> message substring filter
4519
- // rnx logs --internal include engine-internal [sootsim] logs (hidden by default)
4520
- // rnx logs --json raw json output
4521
- // rnx logs tail | -f follow mode (polls)
4522
- // rnx logs clear drop the buffer
4516
+ // peach logs [limit] last N entries (default 50)
4517
+ // peach logs --level error,warn filter by level (csv)
4518
+ // peach logs --filter <str> message substring filter
4519
+ // peach logs --internal include engine-internal [sootsim] logs (hidden by default)
4520
+ // peach logs --json raw json output
4521
+ // peach logs tail | -f follow mode (polls)
4522
+ // peach logs clear drop the buffer
4523
4523
  const sub = positional[1]
4524
4524
 
4525
4525
  let filter: string | null = null
@@ -4638,11 +4638,11 @@ export async function runInspect(args: string[], opts: InspectOptions) {
4638
4638
  // auto-settle after any write command so the next CLI call doesn't see
4639
4639
  // mid-transition state. short deadline — if the app has a perpetual
4640
4640
  // background animation, we bail to layout-only stability via the same
4641
- // logic `do settle` uses. opt-out: --no-wait or RNX_NO_AUTO_WAIT=1.
4641
+ // logic `do settle` uses. opt-out: --no-wait or PEACH_NO_AUTO_WAIT=1.
4642
4642
  if (
4643
4643
  writeCommands.has(subcommand) &&
4644
4644
  !args.includes('--no-wait') &&
4645
- process.env.RNX_NO_AUTO_WAIT !== '1' &&
4645
+ process.env.PEACH_NO_AUTO_WAIT !== '1' &&
4646
4646
  !(await shouldSkipAutoSettleForInspectPick(bridge, subcommand))
4647
4647
  ) {
4648
4648
  await autoSettleAfterWrite(bridge)
@@ -4677,7 +4677,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
4677
4677
  } catch (err: any) {
4678
4678
  rethrowIfExit(err)
4679
4679
  const message = err instanceof Error ? err.message : String(err)
4680
- console.error(` ${subcommand ?? 'rnx'} failed: ${message}`)
4680
+ console.error(` ${subcommand ?? 'peach'} failed: ${message}`)
4681
4681
  const unknownSim = /^no sim connected with id ([^;]+)(?:; connected sims: .+)?$/.exec(
4682
4682
  message,
4683
4683
  )
@@ -4710,9 +4710,9 @@ export async function runInspect(args: string[], opts: InspectOptions) {
4710
4710
  process.stderr.write(
4711
4711
  ` the sim is still responsive — '${cmd}' just exceeded the ${timedOut[1]}s command budget.\n` +
4712
4712
  ` the screen's node tree is large; narrow the query or raise the budget:\n` +
4713
- ` rnx ${cmd} --testid <id> # scope to one subtree\n` +
4714
- ` rnx find --testid <id> # targeted single-node lookup\n` +
4715
- ` rnx ${cmd} --timeout 60000 # raise per-command budget (ms)\n`,
4713
+ ` peach --testid <id> # scope to one subtree\n` +
4714
+ ` peach find --testid <id> # targeted single-node lookup\n` +
4715
+ ` peach --timeout 60000 # raise per-command budget (ms)\n`,
4716
4716
  )
4717
4717
  } else {
4718
4718
  printRecoverHint()
@@ -1,4 +1,4 @@
1
- // installs the standalone rnx executable into the user's command path.
1
+ // installs the standalone peach executable into the user's command path.
2
2
  //
3
3
  // the public shell installer owns download and checksum verification. this
4
4
  // command mirrors its local mutation after those bytes are trusted, while the
@@ -32,13 +32,13 @@ type CliInstallOptions = {
32
32
  export async function runCliInstall(args: string[]): Promise<void> {
33
33
  const options = parseCliInstallOptions(args)
34
34
  if (!IS_STANDALONE) {
35
- throw new Error('rnx cli install requires the standalone rnx executable')
35
+ throw new Error('peach cli install requires the standalone peach executable')
36
36
  }
37
37
 
38
38
  const target = installedCliPath()
39
39
  if (!options.alreadyInstalled) installCurrentExecutable(target)
40
40
  else if (!existsSync(target)) {
41
- throw new Error(`rnx cli install expected ${target} to exist`)
41
+ throw new Error(`peach cli install expected ${target} to exist`)
42
42
  }
43
43
 
44
44
  const profile = installCommandPath(target)
@@ -57,20 +57,20 @@ export async function runCliInstall(args: string[]): Promise<void> {
57
57
  function parseCliInstallOptions(args: string[]): CliInstallOptions {
58
58
  const [subcommand] = args
59
59
  if (subcommand === '--help' || subcommand === '-h') {
60
- console.log(`\nrnx cli install - install the rnx command in your PATH
60
+ console.log(`\npeach cli install - install the peach command in your PATH
61
61
 
62
62
  usage:
63
- rnx cli install
63
+ peach cli install
64
64
 
65
65
  internal options:
66
- --installed update shell startup after an installer copied rnx
66
+ --installed update shell startup after an installer copied peach
67
67
  --handoff-pid <pid> replace this desktop-owned daemon with the service
68
68
  --port <port> daemon bridge port to preserve during handoff
69
69
  `)
70
70
  process.exit(0)
71
71
  }
72
72
  if (subcommand !== 'install') {
73
- throw new Error('usage: rnx cli install')
73
+ throw new Error('usage: peach cli install')
74
74
  }
75
75
 
76
76
  const handoffPid = readHandoffPid(args)
@@ -109,14 +109,14 @@ function readPort(args: string[]): number | null {
109
109
 
110
110
  function installedCliPath(): string {
111
111
  const home = process.env.HOME || homedir()
112
- const prefix = process.env.RNX_CLI_PREFIX || join(home, '.local')
113
- return join(prefix, 'bin', process.platform === 'win32' ? 'rnx.exe' : 'rnx')
112
+ const prefix = process.env.PEACH_CLI_PREFIX || join(home, '.local')
113
+ return join(prefix, 'bin', process.platform === 'win32' ? 'peach.exe' : 'peach')
114
114
  }
115
115
 
116
116
  function installCurrentExecutable(target: string): void {
117
117
  if (process.execPath === target) return
118
118
  mkdirSync(dirname(target), { recursive: true })
119
- const temporary = join(dirname(target), `.rnx-install-${process.pid}`)
119
+ const temporary = join(dirname(target), `.peach-install-${process.pid}`)
120
120
  try {
121
121
  copyFileSync(process.execPath, temporary)
122
122
  chmodSync(temporary, 0o755)
@@ -152,7 +152,7 @@ function installCommandPath(target: string): string | null {
152
152
  { encoding: 'utf8' },
153
153
  )
154
154
  if (result.status !== 0) {
155
- throw new Error(`could not add rnx to the user PATH: ${result.stderr.trim()}`)
155
+ throw new Error(`could not add peach to the user PATH: ${result.stderr.trim()}`)
156
156
  }
157
157
  }
158
158
  return 'the user PATH'
@@ -167,14 +167,14 @@ function installCommandPath(target: string): string | null {
167
167
  )
168
168
  const bin = dirname(target)
169
169
  const pathLine = `export PATH="${bin}:$PATH"`
170
- const integration = shellName ? `eval "$(command rnx __shell-init ${shellName})"` : ''
170
+ const integration = shellName ? `eval "$(command peach __shell-init ${shellName})"` : ''
171
171
  const current = existsSync(profile) ? readFileSync(profile, 'utf8') : ''
172
172
  if (current.includes(pathLine) && (!integration || current.includes(integration)))
173
173
  return null
174
174
 
175
175
  const additions = [
176
176
  '',
177
- '# added by the rnx installer; delete this block to remove rnx from your shell',
177
+ '# added by the peach installer; delete this block to remove peach from your shell',
178
178
  ...(current.includes(pathLine) ? [] : [pathLine]),
179
179
  ...(integration && !current.includes(integration) ? [integration] : []),
180
180
  ]
@@ -223,7 +223,7 @@ async function handOffDaemon({
223
223
  )
224
224
  if (result.status !== 0) {
225
225
  throw new Error(
226
- `could not register the rnx daemon: ${(result.stderr || result.stdout || 'unknown error').trim()}`,
226
+ `could not register the peach daemon: ${(result.stderr || result.stdout || 'unknown error').trim()}`,
227
227
  )
228
228
  }
229
229
 
@@ -232,10 +232,10 @@ async function handOffDaemon({
232
232
  const lock = readDaemonLockfile()
233
233
  return isDaemonLockfileFresh(lock) && lock.pid !== pid && lock.bridgePort === port
234
234
  },
235
- 'the installed rnx daemon to start',
235
+ 'the installed peach daemon to start',
236
236
  deadline,
237
237
  )
238
- console.log(' desktop daemon: handed off to the installed rnx command')
238
+ console.log(' desktop daemon: handed off to the installed peach command')
239
239
  }
240
240
 
241
241
  async function waitFor(