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,4 +1,4 @@
1
- // user-facing `rnx agent` command tree.
1
+ // user-facing `peach agent` command tree.
2
2
  //
3
3
  // session-lifecycle commands (start, prompt, end, watch) route through
4
4
  // the bridge daemon — the daemon owns the single FIFO reader per
@@ -8,7 +8,7 @@
8
8
  //
9
9
  // disk-only inspection commands (projects, sessions, paths, transcript,
10
10
  // attach, project show/remove) read the attached-projects JSON directly —
11
- // no daemon needed, so `rnx agent projects` stays fast when no
11
+ // no daemon needed, so `peach agent projects` stays fast when no
12
12
  // wrapper is live.
13
13
 
14
14
  import fs from 'node:fs'
@@ -109,7 +109,7 @@ async function withDaemon<T>(fn: (client: AgentDaemonClient) => Promise<T>): Pro
109
109
  }
110
110
 
111
111
  function printHelp(): void {
112
- // delegate to the meta-driven renderer so bare `rnx agent`, `--help`,
112
+ // delegate to the meta-driven renderer so bare `peach agent`, `--help`,
113
113
  // and `unknown subcommand` paths all show the same rich help (header,
114
114
  // options, examples) instead of a sparse hand-coded summary.
115
115
  printCommandHelp('agent')
@@ -153,7 +153,7 @@ async function cmdAttach(argv: string[]): Promise<number> {
153
153
  const dir = positional[0]
154
154
  if (!dir) {
155
155
  process.stderr.write(
156
- 'usage: rnx agent attach <dir> [--name X] [--provider codex|claude]\n',
156
+ 'usage: peach agent attach <dir> [--name X] [--provider codex|claude]\n',
157
157
  )
158
158
  return 2
159
159
  }
@@ -180,7 +180,7 @@ async function cmdAttach(argv: string[]): Promise<number> {
180
180
  async function cmdProjects(): Promise<number> {
181
181
  const projects = [...listProjects()].sort((a, b) => b.updatedAt - a.updatedAt)
182
182
  if (projects.length === 0) {
183
- process.stdout.write('no attached projects yet. try `rnx agent attach <dir>`.\n')
183
+ process.stdout.write('no attached projects yet. try `peach agent attach <dir>`.\n')
184
184
  return 0
185
185
  }
186
186
  const header = `${'ID'.padEnd(18)} ${'NAME'.padEnd(20)} ${'FRAMEWORK'.padEnd(10)} ${'PROVIDER'.padEnd(8)} ${'7D COST'.padEnd(10)} CWD\n`
@@ -199,7 +199,7 @@ async function cmdProject(argv: string[]): Promise<number> {
199
199
  const [action, id] = argv
200
200
  if (action === 'show') {
201
201
  if (!id) {
202
- process.stderr.write('usage: rnx agent project show <id>\n')
202
+ process.stderr.write('usage: peach agent project show <id>\n')
203
203
  return 2
204
204
  }
205
205
  const project = findProjectById(id)
@@ -212,14 +212,14 @@ async function cmdProject(argv: string[]): Promise<number> {
212
212
  }
213
213
  if (action === 'remove') {
214
214
  if (!id) {
215
- process.stderr.write('usage: rnx agent project remove <id>\n')
215
+ process.stderr.write('usage: peach agent project remove <id>\n')
216
216
  return 2
217
217
  }
218
218
  deleteProject(id)
219
219
  process.stdout.write(`✓ removed project ${id}\n`)
220
220
  return 0
221
221
  }
222
- process.stderr.write('usage: rnx agent project [show|remove] <id>\n')
222
+ process.stderr.write('usage: peach agent project [show|remove] <id>\n')
223
223
  return 2
224
224
  }
225
225
 
@@ -260,7 +260,7 @@ async function cmdStart(argv: string[]): Promise<number> {
260
260
  const projectId = positional[0]
261
261
  if (!projectId) {
262
262
  process.stderr.write(
263
- 'usage: rnx agent start <projectId> [--provider codex|claude] [--fresh-thread]\n',
263
+ 'usage: peach agent start <projectId> [--provider codex|claude] [--fresh-thread]\n',
264
264
  )
265
265
  return 2
266
266
  }
@@ -281,8 +281,8 @@ async function cmdStart(argv: string[]): Promise<number> {
281
281
  ` project: ${project.name} (${project.id})\n` +
282
282
  ` provider: ${result.session.provider}\n` +
283
283
  ` pid: ${result.wrapperPid}\n` +
284
- ` prompt with: rnx agent prompt ${result.session.id} "<text>"\n` +
285
- ` watch events: rnx agent watch ${result.session.id}\n`,
284
+ ` prompt with: peach agent prompt ${result.session.id} "<text>"\n` +
285
+ ` watch events: peach agent watch ${result.session.id}\n`,
286
286
  )
287
287
  return 0
288
288
  }
@@ -291,7 +291,7 @@ async function cmdPrompt(argv: string[]): Promise<number> {
291
291
  const [sessionId, ...rest] = argv
292
292
  const text = rest.join(' ')
293
293
  if (!sessionId || !text) {
294
- process.stderr.write('usage: rnx agent prompt <sessionId> "<text>"\n')
294
+ process.stderr.write('usage: peach agent prompt <sessionId> "<text>"\n')
295
295
  return 2
296
296
  }
297
297
  await withDaemon((client) => client.sendPrompt(sessionId, { text }))
@@ -302,7 +302,7 @@ async function cmdPrompt(argv: string[]): Promise<number> {
302
302
  async function cmdWatch(argv: string[]): Promise<number> {
303
303
  const sessionId = argv[0]
304
304
  if (!sessionId) {
305
- process.stderr.write('usage: rnx agent watch <sessionId>\n')
305
+ process.stderr.write('usage: peach agent watch <sessionId>\n')
306
306
  return 2
307
307
  }
308
308
  process.stdout.write(`watching ${sessionId}\n---\n`)
@@ -321,7 +321,7 @@ async function cmdWatch(argv: string[]): Promise<number> {
321
321
  process.stdout.write(formatEvent(event) + '\n')
322
322
  })
323
323
  const offDisconnect = client.onDisconnect(() => {
324
- process.stderr.write('\n[rnx] daemon disconnected; exiting watch.\n')
324
+ process.stderr.write('\n[peach] daemon disconnected; exiting watch.\n')
325
325
  resolveExit(1)
326
326
  })
327
327
  try {
@@ -379,7 +379,7 @@ function formatEvent(ev: AgentEvent): string {
379
379
  async function cmdTranscript(argv: string[]): Promise<number> {
380
380
  const sessionId = argv[0]
381
381
  if (!sessionId) {
382
- process.stderr.write('usage: rnx agent transcript <sessionId>\n')
382
+ process.stderr.write('usage: peach agent transcript <sessionId>\n')
383
383
  return 2
384
384
  }
385
385
  const p = transcriptPath(sessionId)
@@ -394,7 +394,7 @@ async function cmdTranscript(argv: string[]): Promise<number> {
394
394
  async function cmdEnd(argv: string[]): Promise<number> {
395
395
  const sessionId = argv[0]
396
396
  if (!sessionId) {
397
- process.stderr.write('usage: rnx agent end <sessionId>\n')
397
+ process.stderr.write('usage: peach agent end <sessionId>\n')
398
398
  return 2
399
399
  }
400
400
  await withDaemon((client) => client.endSession(sessionId))
@@ -1,4 +1,4 @@
1
- // rnx app-fonts stage — fetch the config-plugin fonts declared on an
1
+ // peach app-fonts stage — fetch the config-plugin fonts declared on an
2
2
  // engine `?appFonts=` wire, gzip them, and merge asset descriptors into a
3
3
  // build's asset manifest.
4
4
  //
@@ -9,7 +9,7 @@
9
9
  // after the asset capture; the descriptors land in the same manifest the
10
10
  // upload step already PUTs, keyed by sha256(url) so the rendered build resolves
11
11
  // each font through /api/preview/share/fetch?url=<fontUrl> identically to the
12
- // preview path (`rnx record upload`). both pipelines share fetchAppFontFiles.
12
+ // preview path (`peach record upload`). both pipelines share fetchAppFontFiles.
13
13
 
14
14
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
15
15
  import { join } from 'node:path'
@@ -39,7 +39,7 @@ async function stage(args: string[]): Promise<void> {
39
39
  const manifestPath = flag(args, 'manifest')
40
40
  if (!outDir || !manifestPath) {
41
41
  console.error(
42
- ' usage: rnx app-fonts stage --wire <wire> --out-dir <dir> --manifest <path>',
42
+ ' usage: peach app-fonts stage --wire <wire> --out-dir <dir> --manifest <path>',
43
43
  )
44
44
  rnxExit(1)
45
45
  }
@@ -1,4 +1,4 @@
1
- // `rnx assert <verb> <verb-args...> <assertion-flags...>`
1
+ // `peach assert <verb> <verb-args...> <assertion-flags...>`
2
2
  //
3
3
  // thin wrapper that runs any read verb with --json forced on, captures the
4
4
  // JSON payload, and converts predicate flags into a bisect-friendly exit
@@ -18,7 +18,7 @@ import { rnxExit } from '../run-rnx'
18
18
  import { rnxSelfInvocation } from '../self-invocation'
19
19
 
20
20
  // READ_VERBS lists every command whose stdout we know is valid JSON under
21
- // --json. keeping this explicit means `rnx assert tap 100 200` fails
21
+ // --json. keeping this explicit means `peach assert tap 100 200` fails
22
22
  // fast with a clear message instead of silently running a write verb and
23
23
  // trying to parse " tapped 100,200" as JSON.
24
24
  const READ_VERBS = new Set([
@@ -47,7 +47,7 @@ const READ_VERBS = new Set([
47
47
 
48
48
  // assertion flags that assert recognizes. everything else is passed through
49
49
  // to the inner verb untouched. keeping this as a set (rather than positional
50
- // parsing) means `rnx assert find --testid X --count 4` reads naturally.
50
+ // parsing) means `peach assert find --testid X --count 4` reads naturally.
51
51
  const BOOL_ASSERT_FLAGS = new Set([
52
52
  '--exists',
53
53
  '--empty',
@@ -502,10 +502,10 @@ function sleep(ms: number): Promise<void> {
502
502
 
503
503
  function printHelp(): void {
504
504
  process.stdout.write(`
505
- rnx assert — run any read verb and convert its output into a bisect-friendly exit code.
505
+ peach assert — run any read verb and convert its output into a bisect-friendly exit code.
506
506
 
507
507
  usage:
508
- rnx assert <verb> <verb-args...> <assertion-flags...>
508
+ peach assert <verb> <verb-args...> <assertion-flags...>
509
509
 
510
510
  exit codes:
511
511
  0 assertion passed (git bisect: good)
@@ -533,10 +533,10 @@ assertion flags (AND'd when multiple are given):
533
533
  --quiet suppress the one-line pass/fail summary
534
534
 
535
535
  examples:
536
- rnx assert find --testid set-max-input --count 4
537
- rnx assert describe --contains "swap-form-header"
538
- rnx assert get errors --count 0
539
- rnx assert find --testid submit --exists --within 3000
540
- rnx assert describe --jq '.tree | contains("swap-form-header")'
536
+ peach assert find --testid set-max-input --count 4
537
+ peach assert describe --contains "swap-form-header"
538
+ peach assert get errors --count 0
539
+ peach assert find --testid submit --exists --within 3000
540
+ peach assert describe --jq '.tree | contains("swap-form-header")'
541
541
  `)
542
542
  }
@@ -7,13 +7,13 @@ import { rnxExit } from '../run-rnx'
7
7
 
8
8
  function printHelp(): void {
9
9
  console.log(`
10
- rnx auth — inspect CLI auth
10
+ peach auth — inspect CLI auth
11
11
 
12
12
  usage:
13
- rnx auth
13
+ peach auth
14
14
 
15
- API keys are read from RNX_API_KEY.
16
- Use \`rnx login\` to sign in and \`rnx logout\` to clear the desktop session.
15
+ API keys are read from PEACH_API_KEY.
16
+ Use \`peach login\` to sign in and \`peach logout\` to clear the desktop session.
17
17
  `)
18
18
  }
19
19
 
@@ -21,7 +21,7 @@ async function printStatus(): Promise<number> {
21
21
  const auth = resolveCliAuth()
22
22
  if (!auth) {
23
23
  console.log(' not signed in')
24
- console.log(' set RNX_API_KEY=sk_rnx_... or run `rnx login`')
24
+ console.log(' set PEACH_API_KEY=sk_rnx_... or run `peach login`')
25
25
  return 1
26
26
  }
27
27
 
@@ -62,7 +62,7 @@ const LIST_FILES_TIMEOUT_MS = 10_000
62
62
  // `touch created.txt` working and the box telling the user it has no file set
63
63
  // to serve: measured here as exit 1 in 103ms, which is what took the box
64
64
  // conformance suite red under a load average of 47. the conditions the two
65
- // tests in test/rnxBoxCheckoutPlane.test.ts hold (a git that never answers, a
65
+ // tests in test/peachBoxCheckoutPlane.test.ts hold (a git that never answers, a
66
66
  // git that always answers with nothing) are permanent, so they still fail, and
67
67
  // they fail naming the same thing.
68
68
  const LIST_FILES_ATTEMPTS = 3
@@ -17,7 +17,7 @@
17
17
  // resolveBridgeWorld reports source 'default' and hands back
18
18
  // DEFAULT_SOOTSIM_BRIDGE_PORT, which on a machine running a real daemon is
19
19
  // that daemon. registering there would attach a test's or a benchmark's box to
20
- // another session's daemon, which is exactly what a private RNX_HOME
20
+ // another session's daemon, which is exactly what a private PEACH_HOME
21
21
  // exists to prevent. so a guessed port is refused by name.
22
22
 
23
23
  import { WebSocket } from 'ws'
@@ -99,7 +99,7 @@ export function sharePlane(root: string, opts: { port?: number } = {}): PlaneSha
99
99
  socket.on('open', () => {
100
100
  // node sends no Origin, so this socket is already cli-role. a browser
101
101
  // client has to send bridge:hello to be corrected off the provisional
102
- // sim role; see plans/rnx-cloud/transport-decision.md.
102
+ // sim role; see plans/peach-cloud/transport-decision.md.
103
103
  socket?.send(JSON.stringify({ type: 'plane:register', id: 'register', root }))
104
104
  })
105
105
  socket.on('message', (data) => {
@@ -1,6 +1,6 @@
1
1
  // step 4: RNX operations registered as just-bash commands.
2
2
  //
3
- // `rnx` inside a box shell is the same CLI, re-invoked as a child process with
3
+ // `peach` inside a box shell is the same CLI, re-invoked as a child process with
4
4
  // the shell's own cwd. that is deliberate — spelling the verbs a second time
5
5
  // in shell-command form would be a second implementation of every command, and
6
6
  // the spec is explicit that the CLI and the in-shell commands are clients of
@@ -12,10 +12,10 @@ import { defineCommand, type CustomCommand } from '@peach/box/shell'
12
12
  import { PROJECT_MOUNT } from '@peach/box/shell'
13
13
  import { rnxPublicBrand } from '../../../src/public-brand'
14
14
  import { rnxSelfInvocation } from '../../self-invocation'
15
- import { RNX_PLACEMENT_ENV } from '../../ws-bridge'
15
+ import { PEACH_PLACEMENT_ENV } from '../../ws-bridge'
16
16
 
17
17
  // map a shell path under /project back onto the real checkout, so a child
18
- // process started from `cd src && rnx describe` sees the directory the user
18
+ // process started from `cd src && peach describe` sees the directory the user
19
19
  // is actually standing in.
20
20
  function hostCwd(root: string, shellCwd: string): string {
21
21
  if (shellCwd === PROJECT_MOUNT) return root
@@ -33,8 +33,8 @@ export function createRnxCommand(options: {
33
33
  cwd: hostCwd(options.root, options.shellCwd()),
34
34
  // mark the child as running inside a local box. this is the only thing
35
35
  // that sets a placement — nothing infers one from cwd — and it is what
36
- // lets `rnx box` refuse to nest inside itself.
37
- env: { ...process.env, [RNX_PLACEMENT_ENV]: 'local-box' },
36
+ // lets `peach box` refuse to nest inside itself.
37
+ env: { ...process.env, [PEACH_PLACEMENT_ENV]: 'local-box' },
38
38
  stdio: ['ignore', 'pipe', 'pipe'],
39
39
  })
40
40
 
@@ -1,13 +1,13 @@
1
- // `rnx box` — the box environment.
1
+ // `peach box` — the box environment.
2
2
  //
3
- // bare `rnx box` is LOCAL and mounts the current checkout at /project. cloud
3
+ // bare `peach box` is LOCAL and mounts the current checkout at /project. cloud
4
4
  // create provisions through the shared client and enters the same shell unless
5
5
  // --json asks for a noninteractive result. connect asks the account service to
6
6
  // turn a Box name into an authorized reference and enters that same shell, so
7
7
  // this process never stores a Box token.
8
8
  //
9
9
  // every verb that acts on an existing Box takes it the same way: the id or
10
- // name on the command line, else the one `rnx box use` remembered. see
10
+ // name on the command line, else the one `peach box use` remembered. see
11
11
  // boxTarget below.
12
12
 
13
13
  import { spawn } from 'node:child_process'
@@ -52,8 +52,8 @@ interface BoxCommandOptions {
52
52
  // no default. a cloud box service has to be deployed before one can exist, and
53
53
  // defaulting to an origin that answers nothing would advertise a capability
54
54
  // that always fails.
55
- const ENDPOINT_ENV = 'RNX_BOX_ENDPOINT'
56
- const API_ORIGIN_ENV = 'RNX_API_ORIGIN'
55
+ const ENDPOINT_ENV = 'PEACH_BOX_ENDPOINT'
56
+ const API_ORIGIN_ENV = 'PEACH_API_ORIGIN'
57
57
  const BOX_TEMPLATES = new BoxTemplateRegistry([
58
58
  terminalBoxTemplate,
59
59
  sourceControlBoxTemplate,
@@ -135,7 +135,7 @@ function namedBox(args: string[]): string | undefined {
135
135
  * which Box a verb acts on.
136
136
  *
137
137
  * one order for every verb that acts on a Box that already exists: the id or
138
- * name on the command line, else the one `rnx box use` remembered, else
138
+ * name on the command line, else the one `peach box use` remembered, else
139
139
  * nothing and the reason printed here.
140
140
  */
141
141
  function boxTarget(args: string[], label: string): string | null {
@@ -143,16 +143,16 @@ function boxTarget(args: string[], label: string): string | null {
143
143
  if (named) return named
144
144
  const stored = readDefaultBox()
145
145
  if (stored) return stored.boxId
146
- const rnx = rnxPublicBrand.commandName
146
+ const peach = rnxPublicBrand.commandName
147
147
  console.error(
148
- ` ${rnx} box ${label}: which box? pass its ID or name, as \`${rnx} box ls\` prints it,\n` +
149
- ` or set one for every box command with \`${rnx} box use <id-or-name>\`.`,
148
+ ` ${peach} box ${label}: which box? pass its ID or name, as \`${peach} box ls\` prints it,\n` +
149
+ ` or set one for every box command with \`${peach} box use <id-or-name>\`.`,
150
150
  )
151
151
  return null
152
152
  }
153
153
 
154
154
  /**
155
- * `rnx box use` — the Box every other verb acts on when none is named.
155
+ * `peach box use` — the Box every other verb acts on when none is named.
156
156
  *
157
157
  * it resolves through the account service exactly as connect does, because
158
158
  * that is the only thing that knows which account owns a Box, and a default
@@ -161,13 +161,13 @@ function boxTarget(args: string[], label: string): string | null {
161
161
  * token is resolved again per command and never reaches disk.
162
162
  */
163
163
  async function runCloudBoxUse(args: string[]): Promise<number> {
164
- const rnx = rnxPublicBrand.commandName
164
+ const peach = rnxPublicBrand.commandName
165
165
  const named = namedBox(args)
166
166
  if (!named) {
167
167
  const stored = readDefaultBox()
168
168
  if (!stored) {
169
169
  console.log(
170
- ` no default box. \`${rnx} box use <id-or-name>\` targets one, and every\n` +
170
+ ` no default box. \`${peach} box use <id-or-name>\` targets one, and every\n` +
171
171
  ` other box command then acts on it when you name none.`,
172
172
  )
173
173
  return 0
@@ -201,7 +201,7 @@ async function runCloudBoxUse(args: string[]): Promise<number> {
201
201
  return 0
202
202
  } catch (error) {
203
203
  if (error instanceof BoxClientError) {
204
- console.error(` ${rnx} box use: ${error.message}`)
204
+ console.error(` ${peach} box use: ${error.message}`)
205
205
  return 1
206
206
  }
207
207
  throw error
@@ -214,7 +214,7 @@ function requireEndpoint(args: string[], label: string): string | null {
214
214
 
215
215
  /**
216
216
  * the cloud box service this command talks to, or null with the reason
217
- * printed. exported because `rnx box send` creates a box too, and a second
217
+ * printed. exported because `peach box send` creates a box too, and a second
218
218
  * spelling of where boxes live is a second place to configure.
219
219
  */
220
220
  export function cloudBoxEndpoint(args: string[], command: string): string | null {
@@ -232,11 +232,11 @@ export function cloudBoxApiOrigin(args: string[], auth: CliAuth): string {
232
232
  return apiOrigin(args, auth)
233
233
  }
234
234
 
235
- // `rnx box send` — the CLI half of "send to box". the shell's rail button runs
235
+ // `peach box send` — the CLI half of "send to box". the shell's rail button runs
236
236
  // the same function inside the daemon; this is the same send for an agent or a
237
237
  // terminal, and it prints the id and URL either way.
238
238
  async function runBoxSend(args: string[], opts: BoxCommandOptions): Promise<number> {
239
- const rnx = rnxPublicBrand.commandName
239
+ const peach = rnxPublicBrand.commandName
240
240
  const { auth, header } = authHeaderOrExit('box send')
241
241
  const accountId = cloudAccountIdOrExit(auth)
242
242
  const { createBridgeFromParsed, parseBridgeCliArgs } = await import('../ws-bridge')
@@ -263,7 +263,7 @@ async function runBoxSend(args: string[], opts: BoxCommandOptions): Promise<numb
263
263
  return 0
264
264
  } catch (error) {
265
265
  console.error(
266
- ` ${rnx} box send: ${error instanceof Error ? error.message : String(error)}`,
266
+ ` ${peach} box send: ${error instanceof Error ? error.message : String(error)}`,
267
267
  )
268
268
  return 1
269
269
  } finally {
@@ -272,7 +272,7 @@ async function runBoxSend(args: string[], opts: BoxCommandOptions): Promise<numb
272
272
  }
273
273
 
274
274
  async function runCloudBoxStop(args: string[], purge: boolean): Promise<number> {
275
- const rnx = rnxPublicBrand.commandName
275
+ const peach = rnxPublicBrand.commandName
276
276
  const label = purge ? 'delete' : 'stop'
277
277
  const endpoint = requireEndpoint(args, label)
278
278
  if (!endpoint) return 1
@@ -303,7 +303,7 @@ async function runCloudBoxStop(args: string[], purge: boolean): Promise<number>
303
303
  return 0
304
304
  } catch (error) {
305
305
  if (error instanceof BoxClientError) {
306
- console.error(` ${rnx} box ${label}: ${error.message}`)
306
+ console.error(` ${peach} box ${label}: ${error.message}`)
307
307
  return 1
308
308
  }
309
309
  throw error
@@ -311,7 +311,7 @@ async function runCloudBoxStop(args: string[], purge: boolean): Promise<number>
311
311
  }
312
312
 
313
313
  async function runCloudBoxList(args: string[]): Promise<number> {
314
- const rnx = rnxPublicBrand.commandName
314
+ const peach = rnxPublicBrand.commandName
315
315
  const { auth, header } = authHeaderOrExit('box ls')
316
316
  const apiKey = header.replace(/^Bearer /, '')
317
317
  const accountId = cloudAccountIdOrExit(auth)
@@ -336,7 +336,7 @@ async function runCloudBoxList(args: string[]): Promise<number> {
336
336
  return 0
337
337
  } catch (error) {
338
338
  if (error instanceof BoxClientError) {
339
- console.error(` ${rnx} box ls: ${error.message}`)
339
+ console.error(` ${peach} box ls: ${error.message}`)
340
340
  return 1
341
341
  }
342
342
  throw error
@@ -344,7 +344,7 @@ async function runCloudBoxList(args: string[]): Promise<number> {
344
344
  }
345
345
 
346
346
  async function runCloudBoxConnect(args: string[]): Promise<number> {
347
- const rnx = rnxPublicBrand.commandName
347
+ const peach = rnxPublicBrand.commandName
348
348
  const json = args.includes('--json')
349
349
  const boxId = boxTarget(args, 'connect')
350
350
  if (!boxId) return 1
@@ -392,7 +392,7 @@ async function runCloudBoxConnect(args: string[]): Promise<number> {
392
392
  return await repl(session, '')
393
393
  } catch (error) {
394
394
  if (error instanceof BoxClientError) {
395
- console.error(` ${rnx} box connect: ${error.message}`)
395
+ console.error(` ${peach} box connect: ${error.message}`)
396
396
  return 1
397
397
  }
398
398
  throw error
@@ -415,7 +415,7 @@ async function runCloudBoxConnect(args: string[]): Promise<number> {
415
415
  * makes it a link somebody can keep, paste, or reload.
416
416
  */
417
417
  async function runCloudBoxOpen(args: string[]): Promise<number> {
418
- const rnx = rnxPublicBrand.commandName
418
+ const peach = rnxPublicBrand.commandName
419
419
  const json = args.includes('--json')
420
420
  const print = args.includes('--print')
421
421
  const boxId = boxTarget(args, 'open')
@@ -458,7 +458,7 @@ async function runCloudBoxOpen(args: string[]): Promise<number> {
458
458
  const url = box.description.pageUrl
459
459
  if (!url) {
460
460
  console.error(
461
- ` ${rnx} box open: this box service has no page origin configured, so it has no page to open.`,
461
+ ` ${peach} box open: this box service has no page origin configured, so it has no page to open.`,
462
462
  )
463
463
  return 1
464
464
  }
@@ -473,7 +473,7 @@ async function runCloudBoxOpen(args: string[]): Promise<number> {
473
473
  return await openInBrowser(url)
474
474
  } catch (error) {
475
475
  if (error instanceof BoxClientError) {
476
- console.error(` ${rnx} box open: ${error.message}`)
476
+ console.error(` ${peach} box open: ${error.message}`)
477
477
  return 1
478
478
  }
479
479
  throw error
@@ -520,7 +520,7 @@ function cloudBoxClient(options: {
520
520
  /**
521
521
  * create a Box that runs an app somebody already built.
522
522
  *
523
- * `box create --bundle` reaches this with a file from disk and `rnx box send`
523
+ * `box create --bundle` reaches this with a file from disk and `peach box send`
524
524
  * with the artifact it just produced. both are the same box: the bundle is
525
525
  * the whole project, the provenance says so, and the page that opens it boots
526
526
  * that bundle instead of building anything.
@@ -545,13 +545,13 @@ async function runCloudBoxCreate(
545
545
  args: string[],
546
546
  opts: BoxCommandOptions,
547
547
  ): Promise<number> {
548
- const rnx = rnxPublicBrand.commandName
548
+ const peach = rnxPublicBrand.commandName
549
549
  const json = args.includes('--json')
550
550
  const endpoint = flag(args, 'endpoint') ?? process.env[ENDPOINT_ENV]?.trim()
551
551
  if (!endpoint) {
552
552
  console.error(
553
- ` ${rnx} box create: no cloud box service to create a box in.\n` +
554
- ` set ${ENDPOINT_ENV} or pass --endpoint=<url>. \`${rnx} box\` runs the\n` +
553
+ ` ${peach} box create: no cloud box service to create a box in.\n` +
554
+ ` set ${ENDPOINT_ENV} or pass --endpoint=<url>. \`${peach} box\` runs the\n` +
555
555
  ` same shell locally over this checkout.`,
556
556
  )
557
557
  return 1
@@ -563,7 +563,7 @@ async function runCloudBoxCreate(
563
563
  const namedTemplate = flag(args, 'template')
564
564
  if (bundlePath && namedTemplate) {
565
565
  console.error(
566
- ` ${rnx} box create: --bundle creates a ${prebuiltBundleBoxTemplate.name} box,\n` +
566
+ ` ${peach} box create: --bundle creates a ${prebuiltBundleBoxTemplate.name} box,\n` +
567
567
  ` so it cannot be combined with --template ${namedTemplate}.`,
568
568
  )
569
569
  return 1
@@ -576,7 +576,7 @@ async function runCloudBoxCreate(
576
576
  template = BOX_TEMPLATES.resolve({ name: templateName })
577
577
  } catch (error) {
578
578
  console.error(
579
- ` ${rnx} box create: ${error instanceof Error ? error.message : String(error)}.`,
579
+ ` ${peach} box create: ${error instanceof Error ? error.message : String(error)}.`,
580
580
  )
581
581
  return 1
582
582
  }
@@ -597,14 +597,14 @@ async function runCloudBoxCreate(
597
597
  artifact = await produceCloudBoxArtifact(resolved)
598
598
  } catch (error) {
599
599
  console.error(
600
- ` ${rnx} box create: could not prepare the bundle at ${resolved}: ${
600
+ ` ${peach} box create: could not prepare the bundle at ${resolved}: ${
601
601
  error instanceof Error ? error.message : String(error)
602
602
  }`,
603
603
  )
604
604
  return 1
605
605
  }
606
606
  if (artifact.bytes.byteLength === 0) {
607
- console.error(` ${rnx} box create: the bundle at ${resolved} is empty.`)
607
+ console.error(` ${peach} box create: the bundle at ${resolved} is empty.`)
608
608
  return 1
609
609
  }
610
610
  for (const warning of artifact.warnings) console.error(` ${warning}`)
@@ -614,7 +614,7 @@ async function runCloudBoxCreate(
614
614
  const root = findRepositoryPackageRoot(process.cwd())
615
615
  if (!root) {
616
616
  console.error(
617
- ` ${rnx} box create: no project here. a box is created from a checkout,\n` +
617
+ ` ${peach} box create: no project here. a box is created from a checkout,\n` +
618
618
  ` so run this inside a git repository that has a package.json.`,
619
619
  )
620
620
  return 1
@@ -624,7 +624,7 @@ async function runCloudBoxCreate(
624
624
  await checkout.refresh()
625
625
  } catch (error) {
626
626
  if (error instanceof CheckoutRequiresGitError) {
627
- console.error(` ${rnx} box create: ${error.message}`)
627
+ console.error(` ${peach} box create: ${error.message}`)
628
628
  return 1
629
629
  }
630
630
  throw error
@@ -703,7 +703,7 @@ async function runCloudBoxCreate(
703
703
  return await repl(session, '')
704
704
  } catch (error) {
705
705
  if (error instanceof BoxClientError) {
706
- console.error(` ${rnx} box create: ${error.message}`)
706
+ console.error(` ${peach} box create: ${error.message}`)
707
707
  return 1
708
708
  }
709
709
  throw error
@@ -830,7 +830,7 @@ async function repl(
830
830
  ): Promise<number> {
831
831
  const rl = createInterface({ input: process.stdin, output: process.stdout })
832
832
 
833
- // enter where the user was standing, so `rnx box` from a subdirectory does
833
+ // enter where the user was standing, so `peach box` from a subdirectory does
834
834
  // not silently teleport them to the project root.
835
835
  if (startRelative && !startRelative.startsWith('..')) {
836
836
  await session.exec(`cd ${JSON.stringify(startRelative)}`)
@@ -1,4 +1,4 @@
1
- // rnx camera drives the host-owned camera source. fixture video uses the
1
+ // peach camera drives the host-owned camera source. fixture video uses the
2
2
  // same hidden video, canvas frame pump, ImageBitmap transfer, and
3
3
  // BarcodeDetector loop as a real device camera. `do scan` remains the narrow
4
4
  // synthetic special case for callers that have a payload string but no media.
@@ -22,13 +22,13 @@ const VIDEO_EXTENSIONS = new Set(['.m4v', '.mov', '.mp4', '.webm'])
22
22
 
23
23
  function printHelp() {
24
24
  console.log(`
25
- rnx camera — control the simulator camera source
25
+ peach camera — control the simulator camera source
26
26
 
27
27
  usage:
28
- rnx camera play <file> [--loop] [--rate <number>]
29
- rnx camera stop
30
- rnx camera status [--json]
31
- rnx do scan <text> [--format <web-format>]
28
+ peach camera play <file> [--loop] [--rate <number>]
29
+ peach camera stop
30
+ peach camera status [--json]
31
+ peach do scan <text> [--format <web-format>]
32
32
 
33
33
  subcommands:
34
34
  play <file> replace the active camera source with a local video fixture
@@ -45,11 +45,11 @@ options:
45
45
  --port <p> WS bridge port (default: 7668)
46
46
 
47
47
  examples:
48
- rnx camera play ./fixtures/qr.mp4 --loop
49
- rnx camera play ./fixtures/document.webm --rate 2
50
- rnx camera status
51
- rnx camera stop
52
- rnx do scan "https://example.com" --format qr_code
48
+ peach camera play ./fixtures/qr.mp4 --loop
49
+ peach camera play ./fixtures/document.webm --rate 2
50
+ peach camera status
51
+ peach camera stop
52
+ peach do scan "https://example.com" --format qr_code
53
53
  `)
54
54
  }
55
55
 
@@ -126,7 +126,7 @@ export async function runCamera(
126
126
  if (subcommand === 'scan') {
127
127
  const text = positional[1]
128
128
  if (!text) {
129
- console.error(' usage: rnx do scan <text>')
129
+ console.error(' usage: peach do scan <text>')
130
130
  return 1
131
131
  }
132
132
  const formatFlag = args.indexOf('--format')
@@ -164,7 +164,7 @@ export async function runCamera(
164
164
  if (subcommand === 'play') {
165
165
  const input = positional[1]
166
166
  if (!input) {
167
- console.error(' usage: rnx camera play <file> [--loop] [--rate <number>]')
167
+ console.error(' usage: peach camera play <file> [--loop] [--rate <number>]')
168
168
  return 1
169
169
  }
170
170
  const sourcePath = path.resolve(input)