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.
- package/LICENSE +1 -1
- package/README.md +106 -106
- package/cli/app-config.ts +1 -1
- package/cli/app-fonts.ts +4 -4
- package/cli/auth.ts +11 -11
- package/cli/bin.ts +4 -4
- package/cli/bridge-flow-runner.ts +13 -13
- package/cli/browser-evals.ts +2 -2
- package/cli/cli-update.ts +6 -6
- package/cli/cloud-client.ts +16 -16
- package/cli/cloud-dispatch.ts +2 -2
- package/cli/cloud-session.ts +12 -12
- package/cli/cloud-test-tunnel.ts +4 -4
- package/cli/command-registry.ts +7 -7
- package/cli/commands/agent-wrapper.ts +7 -7
- package/cli/commands/agent.ts +16 -16
- package/cli/commands/app-fonts.ts +3 -3
- package/cli/commands/assert.ts +10 -10
- package/cli/commands/auth.ts +5 -5
- package/cli/commands/box/checkout-plane.ts +1 -1
- package/cli/commands/box/plane-share.ts +2 -2
- package/cli/commands/box/rnx-command.ts +5 -5
- package/cli/commands/box.ts +38 -38
- package/cli/commands/camera.ts +13 -13
- package/cli/commands/cleanup.ts +13 -13
- package/cli/commands/compat.ts +7 -7
- package/cli/commands/config.ts +5 -5
- package/cli/commands/control.ts +63 -63
- package/cli/commands/cpu-profile.ts +11 -11
- package/cli/commands/daemon-mac-app.ts +10 -10
- package/cli/commands/daemon.ts +29 -27
- package/cli/commands/debug.ts +35 -35
- package/cli/commands/desktop.ts +3 -3
- package/cli/commands/detox.ts +33 -33
- package/cli/commands/device.ts +9 -9
- package/cli/commands/diagnose.ts +17 -17
- package/cli/commands/do-chain.ts +4 -4
- package/cli/commands/electron.ts +9 -9
- package/cli/commands/film.ts +9 -9
- package/cli/commands/flow.ts +49 -49
- package/cli/commands/inspect/core.ts +12 -12
- package/cli/commands/inspect/count.ts +1 -1
- package/cli/commands/inspect/describe.ts +1 -1
- package/cli/commands/inspect/env.ts +2 -2
- package/cli/commands/inspect/find.ts +2 -2
- package/cli/commands/inspect/get-layout.ts +2 -2
- package/cli/commands/inspect/keyboard.ts +1 -1
- package/cli/commands/inspect/list.ts +4 -4
- package/cli/commands/inspect/memory.ts +1 -1
- package/cli/commands/inspect/resolve-target.ts +1 -1
- package/cli/commands/inspect/screens.ts +1 -1
- package/cli/commands/inspect/shared.ts +1 -1
- package/cli/commands/inspect/tree.ts +1 -1
- package/cli/commands/inspect/url.ts +1 -1
- package/cli/commands/inspect/wait-event.ts +5 -5
- package/cli/commands/inspect.ts +82 -82
- package/cli/commands/install-cli.ts +16 -16
- package/cli/commands/install-desktop.ts +26 -26
- package/cli/commands/login.ts +11 -11
- package/cli/commands/maestro-generate.ts +10 -10
- package/cli/commands/maestro.ts +77 -67
- package/cli/commands/mode.ts +4 -4
- package/cli/commands/no-bridge-hint.ts +12 -12
- package/cli/commands/perf.ts +11 -11
- package/cli/commands/permissions.ts +5 -5
- package/cli/commands/platform.ts +21 -21
- package/cli/commands/preview.ts +5 -5
- package/cli/commands/profile.ts +12 -12
- package/cli/commands/react.ts +15 -15
- package/cli/commands/record.ts +31 -31
- package/cli/commands/report-issue.ts +4 -4
- package/cli/commands/reset.ts +2 -2
- package/cli/commands/runtime.ts +23 -23
- package/cli/commands/screenshot-command.ts +2 -2
- package/cli/commands/screenshot-layers.ts +5 -5
- package/cli/commands/screenshot-mode.ts +7 -7
- package/cli/commands/screenshot.ts +24 -24
- package/cli/commands/screenshots-capture.ts +13 -13
- package/cli/commands/screenshots.ts +6 -6
- package/cli/commands/serve.ts +12 -12
- package/cli/commands/setup.ts +25 -25
- package/cli/commands/skills.ts +30 -23
- package/cli/commands/slides.ts +20 -20
- package/cli/commands/state.ts +2 -2
- package/cli/commands/storage.ts +3 -3
- package/cli/commands/telemetry.ts +2 -2
- package/cli/commands/test.ts +15 -15
- package/cli/commands/three-mode.ts +17 -17
- package/cli/commands/timeline.ts +12 -12
- package/cli/commands/upgrade.ts +11 -11
- package/cli/commands/upload.ts +26 -26
- package/cli/commands/version.ts +7 -7
- package/cli/commands/what-happened.ts +20 -20
- package/cli/current-sim.ts +3 -3
- package/cli/desktop-companion.ts +16 -16
- package/cli/drivers/electron.ts +4 -4
- package/cli/drivers/playwright-sim-host.ts +7 -7
- package/cli/drivers/playwright.ts +4 -4
- package/cli/drivers/registry.ts +1 -1
- package/cli/drivers/types.ts +5 -5
- package/cli/flow-export.ts +1 -1
- package/cli/flow-file.ts +5 -5
- package/cli/flow-session.ts +1 -1
- package/cli/help-core.ts +13 -13
- package/cli/hints.ts +14 -14
- package/cli/inspect-notice-state.ts +1 -1
- package/cli/internal-child.ts +2 -2
- package/cli/maestro-js.ts +4 -4
- package/cli/maestro-report.ts +1 -1
- package/cli/main.ts +14 -14
- package/cli/outbound-endpoints.ts +30 -30
- package/cli/parse-args.ts +7 -7
- package/cli/privacy.ts +1 -1
- package/cli/recording-access.ts +10 -10
- package/cli/resolve-assets.ts +2 -2
- package/cli/rnx-in-process.ts +5 -5
- package/cli/run-registry.ts +1 -1
- package/cli/run-rnx-core.ts +3 -3
- package/cli/run-rnx.ts +1 -1
- package/cli/runtime-notes.ts +1 -1
- package/cli/self-invocation.ts +1 -1
- package/cli/send-to-box.ts +1 -1
- package/cli/shell-init.ts +40 -40
- package/cli/ui.ts +1 -1
- package/cli/ws-bridge.ts +22 -22
- package/detox/config-loader.ts +1 -1
- package/detox/index.ts +28 -28
- package/detox/navigation.ts +2 -2
- package/dist-lib/agent-daemon-client.cjs +12 -12
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +2 -2
- package/dist-lib/agent-sessions.cjs +12 -12
- package/dist-lib/attached-projects.cjs +4 -4
- package/dist-lib/auth/shared-session.cjs +4 -4
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +4 -4
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +2 -2
- package/dist-lib/bridge-contract.mjs +2 -2
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +42 -42
- package/dist-lib/cloud.mjs +42 -42
- package/dist-lib/config.cjs +2 -2
- package/dist-lib/detox/index.cjs +29 -29
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +12 -12
- package/dist-lib/host/bridge-host.cjs +72 -71
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +6 -6
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +48 -48
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/menu.cjs +5 -5
- package/dist-lib/menu.mjs +5 -5
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +15 -15
- package/dist-lib/profiles.cjs +4 -4
- package/dist-lib/public-brand.cjs +3 -3
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +2 -1
- package/dist-lib/sdk.cjs +9 -9
- package/dist-lib/sdk.mjs +9 -9
- package/dist-lib/skills.cjs +416 -415
- package/dist-lib/swift-compile.cjs +1 -1
- package/dist-lib/swift-compile.mjs +1 -1
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite.cjs +24 -24
- package/package.json +1 -1
- package/scripts/dev-server-scanner.ts +4 -3
- package/skills/contrast/SKILL.md +75 -75
- package/skills/{rnx-debug → peach-debug}/SKILL.md +90 -90
- package/skills/{rnx-perf → peach-perf}/SKILL.md +13 -13
- package/skills/{rnx-setup → peach-setup}/SKILL.md +60 -60
- package/skills/{rnx-test → peach-test}/SKILL.md +44 -44
- package/skills/{rnx-visual → peach-visual}/SKILL.md +26 -26
- package/src/agent-daemon-client.ts +5 -5
- package/src/agent-events.ts +1 -1
- package/src/agent-identity.ts +1 -1
- package/src/agent-sessions.ts +13 -13
- package/src/attached-projects.ts +1 -1
- package/src/auth/shared-session.ts +1 -1
- package/src/bridge-constants.ts +3 -3
- package/src/bridge-contract-input.ts +1 -1
- package/src/bridge-contract.ts +3 -3
- package/src/cli-version.ts +6 -6
- package/src/cloud.ts +40 -40
- package/src/config.ts +1 -1
- package/src/connect.ts +6 -6
- package/src/dev-server-open.ts +8 -8
- package/src/disk-cleanup.ts +3 -3
- package/src/home-paths.ts +26 -26
- package/src/host/agent-host.ts +3 -3
- package/src/host/bridge-host.ts +33 -33
- package/src/host/fetch-proxy-handler.ts +1 -1
- package/src/host/plane-host.ts +2 -2
- package/src/host/replacement-module-handler.ts +2 -2
- package/src/menu.ts +2 -2
- package/src/metro-plugin.ts +7 -7
- package/src/metro-production-bundle.ts +2 -2
- package/src/native-dev-bundle-url.ts +2 -2
- package/src/playwright-host-log.ts +1 -1
- package/src/public-brand.ts +2 -2
- package/src/react-native-host-modules.ts +1 -1
- package/src/rolldown-plugin-swift.ts +3 -3
- package/src/runtime-assets.ts +11 -11
- package/src/runtime-delivery.ts +6 -6
- package/src/screenshots/orchestrate.ts +1 -1
- package/src/screenshots/org-deck.ts +1 -1
- package/src/screenshots/schema.ts +2 -2
- package/src/sim-client.ts +1 -1
- package/src/skills/builtin/compat-check.ts +2 -2
- package/src/vite-plugin-one.ts +8 -8
- package/src/vite-plugin-swift.ts +3 -3
- package/src/vite-plugin.ts +6 -19
package/cli/commands/preview.ts
CHANGED
|
@@ -21,10 +21,10 @@ function takeValue(args: string[], flag: string): string | null {
|
|
|
21
21
|
export async function runPreview(args: string[]): Promise<number> {
|
|
22
22
|
if (args.includes('--help') || args.includes('-h')) {
|
|
23
23
|
console.log(`
|
|
24
|
-
|
|
24
|
+
peach preview — publish a prebuilt React Native bundle as a standalone share
|
|
25
25
|
|
|
26
26
|
usage:
|
|
27
|
-
|
|
27
|
+
peach preview <bundle.js|https://bundle-url> [--platform ios|android] [--open]
|
|
28
28
|
|
|
29
29
|
The share contains the immutable build and its automatically discovered Metro assets. It is not a recorded replay.
|
|
30
30
|
`)
|
|
@@ -47,10 +47,10 @@ The share contains the immutable build and its automatically discovered Metro as
|
|
|
47
47
|
throw new Error('--platform must be ios or android')
|
|
48
48
|
}
|
|
49
49
|
if (input.length !== 1 || input[0]?.startsWith('-')) {
|
|
50
|
-
throw new Error('usage:
|
|
50
|
+
throw new Error('usage: peach preview <bundle.js|https://bundle-url>')
|
|
51
51
|
}
|
|
52
52
|
const auth = resolveCliAuth()
|
|
53
|
-
if (!auth) throw new Error('
|
|
53
|
+
if (!auth) throw new Error('peach preview needs `peach login` or PEACH_API_KEY')
|
|
54
54
|
const accountId = cloudAccountIdOrExit(auth)
|
|
55
55
|
|
|
56
56
|
const artifact = await producePreviewArtifact(input[0])
|
|
@@ -96,7 +96,7 @@ The share contains the immutable build and its automatically discovered Metro as
|
|
|
96
96
|
return 0
|
|
97
97
|
} catch (error) {
|
|
98
98
|
console.error(
|
|
99
|
-
`
|
|
99
|
+
` peach preview failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
100
100
|
)
|
|
101
101
|
return 1
|
|
102
102
|
}
|
package/cli/commands/profile.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// peach storage profile — manage isolated app storage profiles.
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
clearProfileStorage,
|
|
@@ -15,25 +15,25 @@ interface ProfileOptions {
|
|
|
15
15
|
|
|
16
16
|
function printHelp() {
|
|
17
17
|
console.log(`
|
|
18
|
-
|
|
18
|
+
peach storage profile — manage isolated storage profiles
|
|
19
19
|
|
|
20
20
|
usage:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
peach storage profile list
|
|
22
|
+
peach storage profile create <id>
|
|
23
|
+
peach storage profile clear <id>
|
|
24
|
+
peach storage profile delete <id>
|
|
25
25
|
|
|
26
26
|
profiles isolate cookies, localStorage, IndexedDB, cache, permissions, and
|
|
27
27
|
service workers in Electron and Playwright launches. Plain browser-tab launches
|
|
28
28
|
cannot honor profiles and will fail clearly if a profile is requested.
|
|
29
29
|
|
|
30
30
|
examples:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
peach storage profile list
|
|
32
|
+
peach storage profile create qa
|
|
33
|
+
peach open 8081 --profile qa
|
|
34
|
+
peach open 8081 --profile qa --driver playwright
|
|
35
|
+
peach storage profile clear qa
|
|
36
|
+
peach storage profile delete qa
|
|
37
37
|
`)
|
|
38
38
|
}
|
|
39
39
|
|
package/cli/commands/react.ts
CHANGED
|
@@ -36,16 +36,16 @@ interface TreeRow {
|
|
|
36
36
|
|
|
37
37
|
function printHelp() {
|
|
38
38
|
console.log(`
|
|
39
|
-
|
|
39
|
+
peach perf react — inspect React component render cost in the tenant worker
|
|
40
40
|
|
|
41
41
|
usage:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
peach perf react profile start [--include-props] [--max-commits N]
|
|
43
|
+
peach perf react profile stop
|
|
44
|
+
peach perf react summary [--limit 10] [--json]
|
|
45
|
+
peach perf react slow [--limit 5] [--json]
|
|
46
|
+
peach perf react rerenders [--limit 5] [--json]
|
|
47
|
+
peach perf react tree [--depth 3] [--find <name>] [--json]
|
|
48
|
+
peach perf react why <fiber-id> [--json]
|
|
49
49
|
|
|
50
50
|
\`react summary\` is the demo-friendly shortcut: it runs both slow and
|
|
51
51
|
rerenders in one round-trip, prints them as a single table per side,
|
|
@@ -53,12 +53,12 @@ and surfaces the duration-zero warning prominently when the bundle is
|
|
|
53
53
|
running without React profiler timers.
|
|
54
54
|
|
|
55
55
|
examples:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
peach perf react profile start
|
|
57
|
+
peach do tap-text Inbox
|
|
58
|
+
peach perf react profile stop
|
|
59
|
+
peach perf react summary --limit 10
|
|
60
|
+
peach perf react slow --limit 10
|
|
61
|
+
peach perf react rerenders --json
|
|
62
62
|
`)
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -332,7 +332,7 @@ export async function runReact(args: string[], opts: ReactOptions): Promise<numb
|
|
|
332
332
|
if (first === 'why') {
|
|
333
333
|
const fiberId = Number(second)
|
|
334
334
|
if (!Number.isFinite(fiberId) || fiberId <= 0) {
|
|
335
|
-
console.error(' usage:
|
|
335
|
+
console.error(' usage: peach perf react why <fiber-id>')
|
|
336
336
|
return 1
|
|
337
337
|
}
|
|
338
338
|
const result = (await callInBridge(
|
package/cli/commands/record.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
//
|
|
1
|
+
// peach record — drives the engine's built-in canvas recorder over
|
|
2
2
|
// the WS bridge. no playwright, no ffmpeg. encoding happens in the
|
|
3
|
-
// running
|
|
3
|
+
// running peach page (webm via MediaRecorder, mp4 via WebCodecs, gif
|
|
4
4
|
// via gifenc, raw png frames via a shared bitmap sampler).
|
|
5
5
|
|
|
6
6
|
import {
|
|
@@ -85,7 +85,7 @@ async function evalCaptureStep<T>(
|
|
|
85
85
|
` ${step} stalled — the render host did not finish within ` +
|
|
86
86
|
`${Math.round(timeoutMs / 1000)}s; it is likely contended or wedged.\n` +
|
|
87
87
|
` the capture lock auto-releases, so simply retry the recording.\n` +
|
|
88
|
-
` if it persists, recover the sim with \`
|
|
88
|
+
` if it persists, recover the sim with \`peach close --sim <id>\`.`,
|
|
89
89
|
)
|
|
90
90
|
rnxExit(1)
|
|
91
91
|
}
|
|
@@ -106,7 +106,7 @@ async function evalCaptureStep<T>(
|
|
|
106
106
|
` releasing. the lock self-heals in ~${Math.round(
|
|
107
107
|
(durationMs + 20_000) / 1000,
|
|
108
108
|
)}s — retry then, or recover now with\n` +
|
|
109
|
-
` \`
|
|
109
|
+
` \`peach close --sim <id>\` and reopen the sim.`,
|
|
110
110
|
)
|
|
111
111
|
rnxExit(1)
|
|
112
112
|
}
|
|
@@ -319,7 +319,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
319
319
|
// only the upload-bearing modes touch the cloud, so gate the recording
|
|
320
320
|
// entitlement here, not on local-file video/gif/png capture (F19).
|
|
321
321
|
// allowGitHubAuth mirrors preview flow recording: the github pr-preview
|
|
322
|
-
// runner authenticates with an installation token, not
|
|
322
|
+
// runner authenticates with an installation token, not PEACH_API_KEY
|
|
323
323
|
// (zero-secrets design). the bypass only fires when auth.kind ===
|
|
324
324
|
// 'github' (ci/preview); local paid users have session/
|
|
325
325
|
// api-key auth and still go through the billing entitlement check.
|
|
@@ -375,7 +375,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
375
375
|
|
|
376
376
|
if (format === 'png') {
|
|
377
377
|
const count = framesCount ?? 10
|
|
378
|
-
const outDir = resolveRecordingOutput(outputArg, `
|
|
378
|
+
const outDir = resolveRecordingOutput(outputArg, `peach-frames-${stamp()}`)
|
|
379
379
|
// --frames writes one png PER frame, so --output names a directory, not
|
|
380
380
|
// a file. a caller passing `--output shot.png` gets a directory literally
|
|
381
381
|
// named `shot.png` — flag the likely mistake rather than silently doing it.
|
|
@@ -445,7 +445,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
445
445
|
|
|
446
446
|
if (format === 'gif') {
|
|
447
447
|
const count = framesCount ?? Math.max(10, Math.round((durationSec * fps) / 3))
|
|
448
|
-
const out = resolveRecordingOutput(outputArg, `
|
|
448
|
+
const out = resolveRecordingOutput(outputArg, `peach-${stamp()}.gif`)
|
|
449
449
|
mkdirSync(dirname(out), { recursive: true })
|
|
450
450
|
console.log(` encoding gif: ${count} frames over ${durationSec}s → ${out}`)
|
|
451
451
|
const result: { data: string; size: number } | null = await evalCaptureStep(
|
|
@@ -466,7 +466,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
466
466
|
}
|
|
467
467
|
|
|
468
468
|
// video path: webm or mp4
|
|
469
|
-
const out = resolveRecordingOutput(outputArg, `
|
|
469
|
+
const out = resolveRecordingOutput(outputArg, `peach-${stamp()}.${format}`)
|
|
470
470
|
mkdirSync(dirname(out), { recursive: true })
|
|
471
471
|
|
|
472
472
|
const startOpts: {
|
|
@@ -501,7 +501,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
501
501
|
console.error(
|
|
502
502
|
' a prior recording was abandoned and its capture is still\n' +
|
|
503
503
|
' releasing. retry in ~20s, or recover now with\n' +
|
|
504
|
-
' `
|
|
504
|
+
' `peach close --sim <id>` then reopen the sim.',
|
|
505
505
|
)
|
|
506
506
|
}
|
|
507
507
|
rnxExit(1)
|
|
@@ -562,7 +562,7 @@ async function probeSim(bridge: WsBridge, code: string): Promise<boolean> {
|
|
|
562
562
|
if (/^command timed out after \d+s$/.test(msg)) {
|
|
563
563
|
console.error(
|
|
564
564
|
' sim did not respond — it is connected to the bridge but has not\n' +
|
|
565
|
-
' loaded an app (or its page is unresponsive). run `
|
|
565
|
+
' loaded an app (or its page is unresponsive). run `peach list`\n' +
|
|
566
566
|
' and target a sim with a loaded app via --sim <id>.',
|
|
567
567
|
)
|
|
568
568
|
rnxExit(1)
|
|
@@ -575,7 +575,7 @@ async function assertRecorderAvailable(bridge: WsBridge) {
|
|
|
575
575
|
const ok = await probeSim(bridge, 'typeof window.__sootsimRecorder !== "undefined"')
|
|
576
576
|
if (!ok) {
|
|
577
577
|
console.error(
|
|
578
|
-
' window.__sootsimRecorder missing — is
|
|
578
|
+
' window.__sootsimRecorder missing — is peach engine running in this sim?',
|
|
579
579
|
)
|
|
580
580
|
rnxExit(1)
|
|
581
581
|
}
|
|
@@ -583,7 +583,7 @@ async function assertRecorderAvailable(bridge: WsBridge) {
|
|
|
583
583
|
|
|
584
584
|
// frame-capturing recordings (video / gif / png / combined) drive their
|
|
585
585
|
// encoder off requestAnimationFrame and throttled timers, which browsers
|
|
586
|
-
// clamp to ~1fps when the
|
|
586
|
+
// clamp to ~1fps when the peach tab is hidden (backgrounded, or its chrome
|
|
587
587
|
// window minimized). that silently produced a frozen-looking file and is
|
|
588
588
|
// exactly why agents started pre-checking `document.hidden` by hand. refuse
|
|
589
589
|
// up front with an actionable message instead. checkSimHealth already emits
|
|
@@ -594,7 +594,7 @@ async function assertTabVisibleForCapture(bridge: WsBridge) {
|
|
|
594
594
|
const { hidden } = await checkSimHealth(bridge)
|
|
595
595
|
if (hidden) {
|
|
596
596
|
console.error(
|
|
597
|
-
' refusing to record: the
|
|
597
|
+
' refusing to record: the peach tab is hidden, so frame capture\n' +
|
|
598
598
|
' would be throttled to ~1fps and produce a frozen-looking file.\n' +
|
|
599
599
|
' bring the chrome window to the foreground (un-minimize / switch to\n' +
|
|
600
600
|
' its tab) or run the recording in headless playwright, then retry.',
|
|
@@ -658,10 +658,10 @@ function stamp(): string {
|
|
|
658
658
|
|
|
659
659
|
// default home for recordings when --output is omitted. writing into the
|
|
660
660
|
// process cwd litters whatever directory the CLI was invoked from (the repo
|
|
661
|
-
// root, most often) with
|
|
661
|
+
// root, most often) with peach-*.mp4 / peach-frames-*/ — F11-2. an
|
|
662
662
|
// explicit --output still resolves relative to cwd as the caller expects.
|
|
663
663
|
function recordingsDir(): string {
|
|
664
|
-
const dir = join(homedir(), '.
|
|
664
|
+
const dir = join(homedir(), '.peach', 'recordings')
|
|
665
665
|
mkdirSync(dir, { recursive: true })
|
|
666
666
|
return dir
|
|
667
667
|
}
|
|
@@ -698,7 +698,7 @@ function parseMode(raw: string | undefined): RecordMode {
|
|
|
698
698
|
}
|
|
699
699
|
|
|
700
700
|
function recordingStatePath(): string {
|
|
701
|
-
return join(tmpdir(), `
|
|
701
|
+
return join(tmpdir(), `peach-recording-${getCliIdentityKey()}.json`)
|
|
702
702
|
}
|
|
703
703
|
|
|
704
704
|
function readRecordingState(): RecordingState | null {
|
|
@@ -744,7 +744,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
|
|
|
744
744
|
const existing = readRecordingState()
|
|
745
745
|
if (existing) {
|
|
746
746
|
console.error(
|
|
747
|
-
` recording already in progress (started ${existing.startedAt}, sim ${existing.simId ?? '?'}). run \`
|
|
747
|
+
` recording already in progress (started ${existing.startedAt}, sim ${existing.simId ?? '?'}). run \`peach record stop\` first, or \`peach record cancel\` to discard.`,
|
|
748
748
|
)
|
|
749
749
|
rnxExit(1)
|
|
750
750
|
}
|
|
@@ -772,7 +772,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
|
|
|
772
772
|
const format = formatArg === 'mp4' ? 'mp4' : 'webm'
|
|
773
773
|
if (formatArg && format !== formatArg) {
|
|
774
774
|
console.error(
|
|
775
|
-
` record start only supports webm or mp4 (got: ${formatArg}). for gif/png use atomic mode:
|
|
775
|
+
` record start only supports webm or mp4 (got: ${formatArg}). for gif/png use atomic mode: peach record --format ${formatArg} --duration <s>`,
|
|
776
776
|
)
|
|
777
777
|
rnxExit(1)
|
|
778
778
|
}
|
|
@@ -797,7 +797,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
|
|
|
797
797
|
// entitlement here, not on local-file webm/mp4 capture (F19).
|
|
798
798
|
// allowGitHubAuth: the PR-preview runner (`record start --mode
|
|
799
799
|
// combined`) authenticates with a GitHub installation token, not
|
|
800
|
-
//
|
|
800
|
+
// PEACH_API_KEY — the whole pipeline is zero-secrets by design.
|
|
801
801
|
// mirrors `flow --record`. the bypass only triggers for github-kind
|
|
802
802
|
// auth (CI); local paid users still hit the billing check.
|
|
803
803
|
await ensureCliRecordingEntitlement('record', {
|
|
@@ -855,11 +855,11 @@ async function recordStart(args: string[], opts: RecordOptions) {
|
|
|
855
855
|
})
|
|
856
856
|
if (mode === 'video') {
|
|
857
857
|
console.log(
|
|
858
|
-
` recording ${format} @ ${fps}fps${layers ? ` (${layers})` : ''} — run \`
|
|
858
|
+
` recording ${format} @ ${fps}fps${layers ? ` (${layers})` : ''} — run \`peach record stop --output <path>\` when done`,
|
|
859
859
|
)
|
|
860
860
|
} else {
|
|
861
861
|
console.log(
|
|
862
|
-
` recording ${mode} — run \`
|
|
862
|
+
` recording ${mode} — run \`peach record stop\` when done (add --open to launch the preview URL)`,
|
|
863
863
|
)
|
|
864
864
|
}
|
|
865
865
|
} finally {
|
|
@@ -871,7 +871,7 @@ async function recordPreludeStart(args: string[], opts: RecordOptions) {
|
|
|
871
871
|
const existing = readRecordingState()
|
|
872
872
|
if (existing) {
|
|
873
873
|
console.error(
|
|
874
|
-
` recording already in progress (started ${existing.startedAt}, sim ${existing.simId ?? '?'}). run \`
|
|
874
|
+
` recording already in progress (started ${existing.startedAt}, sim ${existing.simId ?? '?'}). run \`peach record stop\` first, or \`peach record cancel\` to discard.`,
|
|
875
875
|
)
|
|
876
876
|
rnxExit(1)
|
|
877
877
|
}
|
|
@@ -911,7 +911,7 @@ async function recordPreludeStart(args: string[], opts: RecordOptions) {
|
|
|
911
911
|
rnxExit(1)
|
|
912
912
|
}
|
|
913
913
|
console.log(
|
|
914
|
-
' recording preview prelude — run `
|
|
914
|
+
' recording preview prelude — run `peach record start --mode combined` when the visible proof segment is ready',
|
|
915
915
|
)
|
|
916
916
|
} finally {
|
|
917
917
|
bridge.close()
|
|
@@ -1027,8 +1027,8 @@ async function recordStatus(args: string[], opts: RecordOptions) {
|
|
|
1027
1027
|
console.log(
|
|
1028
1028
|
' a recording preview prelude is active. hidden setup is being\n' +
|
|
1029
1029
|
' captured for the next live/combined preview recording. finish\n' +
|
|
1030
|
-
' it with `
|
|
1031
|
-
' with `
|
|
1030
|
+
' it with `peach record start --mode combined`, or discard it\n' +
|
|
1031
|
+
' with `peach record cancel`.',
|
|
1032
1032
|
)
|
|
1033
1033
|
return
|
|
1034
1034
|
}
|
|
@@ -1040,7 +1040,7 @@ async function recordStatus(args: string[], opts: RecordOptions) {
|
|
|
1040
1040
|
' (atomic `--mode video/gif/png` writes a local file from that\n' +
|
|
1041
1041
|
' process; live/combined upload to /preview/<id>). if the run was\n' +
|
|
1042
1042
|
' killed, the recording is abandoned and will NOT finish — reclaim\n' +
|
|
1043
|
-
' it now with `
|
|
1043
|
+
' it now with `peach record cancel`, or it auto-reclaims when the\n' +
|
|
1044
1044
|
" abandoned capture's deadline lapses.",
|
|
1045
1045
|
)
|
|
1046
1046
|
} else {
|
|
@@ -1133,7 +1133,7 @@ async function recordCancel(args: string[], opts: RecordOptions) {
|
|
|
1133
1133
|
async function recordStop(args: string[], opts: RecordOptions) {
|
|
1134
1134
|
const state = readRecordingState()
|
|
1135
1135
|
if (!state) {
|
|
1136
|
-
console.error(' no recording in progress. start one with `
|
|
1136
|
+
console.error(' no recording in progress. start one with `peach record start`.')
|
|
1137
1137
|
rnxExit(1)
|
|
1138
1138
|
}
|
|
1139
1139
|
|
|
@@ -1165,7 +1165,7 @@ async function recordStop(args: string[], opts: RecordOptions) {
|
|
|
1165
1165
|
}
|
|
1166
1166
|
|
|
1167
1167
|
const outputArg = valueOf(args, '--output')
|
|
1168
|
-
const out = resolveRecordingOutput(outputArg, `
|
|
1168
|
+
const out = resolveRecordingOutput(outputArg, `peach-${stamp()}.${state.format}`)
|
|
1169
1169
|
mkdirSync(dirname(out), { recursive: true })
|
|
1170
1170
|
const stopResult: {
|
|
1171
1171
|
ok: boolean
|
|
@@ -1211,7 +1211,7 @@ async function assertStoreBridgesAvailable(bridge: WsBridge) {
|
|
|
1211
1211
|
)
|
|
1212
1212
|
if (!ok) {
|
|
1213
1213
|
console.error(
|
|
1214
|
-
' SootSim.bridges.startRecording missing — is
|
|
1214
|
+
' SootSim.bridges.startRecording missing — is peach engine running in this sim?',
|
|
1215
1215
|
)
|
|
1216
1216
|
rnxExit(1)
|
|
1217
1217
|
}
|
|
@@ -1219,7 +1219,7 @@ async function assertStoreBridgesAvailable(bridge: WsBridge) {
|
|
|
1219
1219
|
|
|
1220
1220
|
// CLI-driven live/combined recording runs in a headless browser that was
|
|
1221
1221
|
// never logged in, so browser-side upload has no bearer. push the CLI's own
|
|
1222
|
-
// auth — the same
|
|
1222
|
+
// auth — the same PEACH_API_KEY / `peach login` / GitHub token
|
|
1223
1223
|
// ensureCliRecordingEntitlement just verified — into the page's shared-session
|
|
1224
1224
|
// store before starting. GitHub PR-preview auth also needs its repo identity
|
|
1225
1225
|
// in the upload init body so the server treats the bearer as a GitHub upload
|
|
@@ -1308,7 +1308,7 @@ async function injectPreviewSessionAuth(
|
|
|
1308
1308
|
console.error(
|
|
1309
1309
|
' SootSim.bridges.setSession missing — this sim is running an engine\n' +
|
|
1310
1310
|
' build without CLI-injected preview auth. reload the sim or open a\n' +
|
|
1311
|
-
' fresh one (`
|
|
1311
|
+
' fresh one (`peach open --new`); if it persists, update peach.',
|
|
1312
1312
|
)
|
|
1313
1313
|
rnxExit(1)
|
|
1314
1314
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// peach report-issue — submit an explicitly approved compatibility report.
|
|
2
2
|
|
|
3
3
|
import { existsSync, readFileSync } from 'node:fs'
|
|
4
4
|
import { resolve } from 'node:path'
|
|
@@ -214,7 +214,7 @@ export async function runReportIssue(
|
|
|
214
214
|
} catch (error) {
|
|
215
215
|
dependencies.stderr(
|
|
216
216
|
` ${error instanceof Error ? error.message : String(error)}\n` +
|
|
217
|
-
` usage:
|
|
217
|
+
` usage: peach report-issue [--app <dir>] [--dry-run] [--yes] "<description>"\n`,
|
|
218
218
|
)
|
|
219
219
|
return 1
|
|
220
220
|
}
|
|
@@ -237,7 +237,7 @@ export async function runReportIssue(
|
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
dependencies.stdout(
|
|
240
|
-
`\n
|
|
240
|
+
`\n peach issue report preview\n\n` +
|
|
241
241
|
` description: ${payload.note}\n` +
|
|
242
242
|
` compatibility: ${compatibilitySummary(payload.bundle.compatibility)}\n` +
|
|
243
243
|
` environment: CLI ${payload.bundle.cliVersion}, runtime ${
|
|
@@ -260,7 +260,7 @@ export async function runReportIssue(
|
|
|
260
260
|
return 2
|
|
261
261
|
}
|
|
262
262
|
const approved = await dependencies.confirmSubmission(
|
|
263
|
-
'send this compatibility report to the
|
|
263
|
+
'send this compatibility report to the peach team??',
|
|
264
264
|
false,
|
|
265
265
|
)
|
|
266
266
|
if (!approved) {
|
package/cli/commands/reset.ts
CHANGED
|
@@ -19,10 +19,10 @@ function isResetResult(value: unknown): value is ResetResult {
|
|
|
19
19
|
|
|
20
20
|
function printHelp(): void {
|
|
21
21
|
console.log(`
|
|
22
|
-
|
|
22
|
+
peach reset - clear the current guest app and relaunch it
|
|
23
23
|
|
|
24
24
|
usage:
|
|
25
|
-
|
|
25
|
+
peach reset [--full] [--json] [--sim <id>]
|
|
26
26
|
|
|
27
27
|
options:
|
|
28
28
|
--full also clear keychain, user defaults, and permissions
|
package/cli/commands/runtime.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
//
|
|
1
|
+
// peach runtime — manage engine runtimes under ~/.peach/runtimes/.
|
|
2
2
|
//
|
|
3
3
|
// runtimes are versioned tarballs hosted behind the configured CDN origin
|
|
4
4
|
// (default https://contrast.dev/runtimes/). each install:
|
|
5
5
|
// 1. fetches manifest.json to resolve a version (or confirm the literal)
|
|
6
6
|
// 2. downloads sootsim-runtime-<version>.tar.gz to an operation temp directory
|
|
7
7
|
// 3. verifies sha256
|
|
8
|
-
// 4. extracts to ~/.
|
|
8
|
+
// 4. extracts to ~/.peach/runtimes/<version>/
|
|
9
9
|
// 5. (optionally) sets it active + tells the daemon to hot-swap
|
|
10
10
|
//
|
|
11
|
-
// the daemon-side state (active runtime) is mirrored in ~/.
|
|
11
|
+
// the daemon-side state (active runtime) is mirrored in ~/.peach/runtimes/active
|
|
12
12
|
// so the CLI can change it even when the daemon isn't running.
|
|
13
13
|
|
|
14
14
|
import fs from 'fs'
|
|
@@ -63,15 +63,15 @@ export async function runRuntime(args: string[], opts: RuntimeOptions = {}) {
|
|
|
63
63
|
|
|
64
64
|
function printHelp() {
|
|
65
65
|
console.log(`
|
|
66
|
-
|
|
66
|
+
peach runtime — manage engine runtimes under ~/.peach/runtimes/
|
|
67
67
|
|
|
68
68
|
usage:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
peach runtime install [version] install a version (default: channel latest)
|
|
70
|
+
peach runtime list show installed + available versions
|
|
71
|
+
peach runtime use <version> switch active runtime
|
|
72
|
+
peach runtime remove <version> delete an installed runtime
|
|
73
|
+
peach runtime which print active runtime version
|
|
74
|
+
peach runtime notes print repo or default engine release notes
|
|
75
75
|
|
|
76
76
|
flags:
|
|
77
77
|
--channel <name> channel to resolve 'latest' from (default: stable)
|
|
@@ -79,14 +79,14 @@ flags:
|
|
|
79
79
|
--set-active=false do not switch active runtime after install
|
|
80
80
|
|
|
81
81
|
environment:
|
|
82
|
-
|
|
82
|
+
PEACH_CDN_ORIGIN override the CDN base URL (default: ${DEFAULT_RUNTIME_CDN_ORIGIN})
|
|
83
83
|
|
|
84
84
|
examples:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
peach runtime install
|
|
86
|
+
peach runtime install 1.2.3
|
|
87
|
+
peach runtime install --channel beta
|
|
88
|
+
peach runtime use 1.2.3
|
|
89
|
+
peach runtime notes
|
|
90
90
|
`)
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -100,7 +100,7 @@ async function runtimeInstall(args: string[], opts: RuntimeOptions) {
|
|
|
100
100
|
|
|
101
101
|
ensureRnxHome()
|
|
102
102
|
|
|
103
|
-
console.log(`
|
|
103
|
+
console.log(`peach runtime install`)
|
|
104
104
|
console.log(` cdn: ${rnxRuntime.resolveCdnOrigin()}`)
|
|
105
105
|
|
|
106
106
|
try {
|
|
@@ -136,7 +136,7 @@ async function activateVersion(version: string) {
|
|
|
136
136
|
const notified = await tellDaemonRuntimeChanged(version)
|
|
137
137
|
if (!notified) {
|
|
138
138
|
console.log(
|
|
139
|
-
` (no daemon running — next
|
|
139
|
+
` (no daemon running — next peach/electron launch will pick up ${version})`,
|
|
140
140
|
)
|
|
141
141
|
}
|
|
142
142
|
}
|
|
@@ -234,14 +234,14 @@ async function runtimeList(_args: string[]) {
|
|
|
234
234
|
async function runtimeUse(args: string[]) {
|
|
235
235
|
const version = args[0]
|
|
236
236
|
if (!version) {
|
|
237
|
-
console.error(` usage:
|
|
237
|
+
console.error(` usage: peach runtime use <version>`)
|
|
238
238
|
rnxExit(1)
|
|
239
239
|
}
|
|
240
240
|
const installed = rnxRuntime.listInstalled()
|
|
241
241
|
if (!installed.includes(version)) {
|
|
242
242
|
console.error(` version ${version} is not installed`)
|
|
243
243
|
console.error(` installed: ${installed.join(', ') || '(none)'}`)
|
|
244
|
-
console.error(` run \`
|
|
244
|
+
console.error(` run \`peach runtime install ${version}\` first`)
|
|
245
245
|
rnxExit(1)
|
|
246
246
|
}
|
|
247
247
|
await activateVersion(version)
|
|
@@ -252,14 +252,14 @@ async function runtimeUse(args: string[]) {
|
|
|
252
252
|
async function runtimeRemove(args: string[]) {
|
|
253
253
|
const version = args[0]
|
|
254
254
|
if (!version) {
|
|
255
|
-
console.error(` usage:
|
|
255
|
+
console.error(` usage: peach runtime remove <version>`)
|
|
256
256
|
rnxExit(1)
|
|
257
257
|
}
|
|
258
258
|
const active = readActiveRuntime()
|
|
259
259
|
if (active === version) {
|
|
260
260
|
console.error(` cannot remove active runtime ${version}`)
|
|
261
261
|
console.error(
|
|
262
|
-
` switch with \`
|
|
262
|
+
` switch with \`peach runtime use <other>\` first, or install another version`,
|
|
263
263
|
)
|
|
264
264
|
rnxExit(1)
|
|
265
265
|
}
|
|
@@ -291,7 +291,7 @@ async function runtimeWhich() {
|
|
|
291
291
|
|
|
292
292
|
async function runtimeNotes(args: string[]) {
|
|
293
293
|
if (args.length > 0) {
|
|
294
|
-
console.error(` usage:
|
|
294
|
+
console.error(` usage: peach runtime notes`)
|
|
295
295
|
rnxExit(1)
|
|
296
296
|
}
|
|
297
297
|
const { config } = await resolveRNXAppConfig()
|
|
@@ -85,7 +85,7 @@ export async function runScreenshotCommand(
|
|
|
85
85
|
// repo-only tooling: screenshots-capture statically imports playwright-core,
|
|
86
86
|
// which the published CLI never ships (it's external in build-cli.ts). a
|
|
87
87
|
// static import here would put that bare import at the top of THIS chunk,
|
|
88
|
-
// so every published `
|
|
88
|
+
// so every published `peach screenshot` printed ERR_MODULE_NOT_FOUND —
|
|
89
89
|
// keep it a runtime dynamic import that only evaluates when capture runs.
|
|
90
90
|
try {
|
|
91
91
|
const { runScreenshotsCapture } = await import('./screenshots-capture')
|
|
@@ -95,7 +95,7 @@ export async function runScreenshotCommand(
|
|
|
95
95
|
} catch (err) {
|
|
96
96
|
if (err instanceof Error && 'code' in err && err.code === 'ERR_MODULE_NOT_FOUND') {
|
|
97
97
|
console.error(
|
|
98
|
-
'screenshot appstore capture is repo-only tooling — it needs the
|
|
98
|
+
'screenshot appstore capture is repo-only tooling — it needs the peach workspace (playwright is not shipped with the published CLI).',
|
|
99
99
|
)
|
|
100
100
|
return 1
|
|
101
101
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// peach screenshot layers — engine-rendered layer isolation export.
|
|
2
2
|
//
|
|
3
3
|
// captures one screen as a stack the 3d stage can pull apart: `full.png` is
|
|
4
4
|
// the normal frame, `base.png` re-renders the frame with the target subtrees
|
|
@@ -26,14 +26,14 @@ export async function runScreenshotLayers(
|
|
|
26
26
|
): Promise<void> {
|
|
27
27
|
if (args.includes('--help') || args.includes('-h')) {
|
|
28
28
|
console.log(`
|
|
29
|
-
|
|
29
|
+
peach screenshot layers — export a screen as engine-isolated layers
|
|
30
30
|
|
|
31
31
|
usage:
|
|
32
|
-
|
|
32
|
+
peach screenshot layers --ids <testID,testID,...> [--out-dir <dir>]
|
|
33
33
|
|
|
34
34
|
options:
|
|
35
35
|
--ids <list> comma-separated testIDs of the subtrees to isolate
|
|
36
|
-
--out-dir <dir> output directory (default: /tmp/
|
|
36
|
+
--out-dir <dir> output directory (default: /tmp/peach-layers)
|
|
37
37
|
|
|
38
38
|
output:
|
|
39
39
|
full.png the normal frame
|
|
@@ -58,7 +58,7 @@ output:
|
|
|
58
58
|
rnxExit(1)
|
|
59
59
|
}
|
|
60
60
|
const outDirArg = args.find((_, i) => args[i - 1] === '--out-dir')
|
|
61
|
-
const outDir = resolve(process.cwd(), outDirArg ?? '/tmp/
|
|
61
|
+
const outDir = resolve(process.cwd(), outDirArg ?? '/tmp/peach-layers')
|
|
62
62
|
|
|
63
63
|
const parsed = parseBridgeCliArgs(args, {
|
|
64
64
|
port: opts.port,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
// in the running
|
|
1
|
+
// peach mode screenshot — toggle the "screenshot mode" chrome overlay
|
|
2
|
+
// in the running peach sim. orthogonal to `--no-shell` on the
|
|
3
3
|
// `screenshot` command: this hides the DOM browser chrome (rail, menubar,
|
|
4
4
|
// window controls) while still rendering the iOS shell inside the canvas.
|
|
5
5
|
//
|
|
@@ -12,10 +12,10 @@ import { runShellBooleanMode, type ShellBooleanModeOptions } from './shell-boole
|
|
|
12
12
|
export async function runScreenshotMode(args: string[], opts: ShellBooleanModeOptions) {
|
|
13
13
|
if (args.includes('--help') || args.includes('-h')) {
|
|
14
14
|
console.log(`
|
|
15
|
-
|
|
15
|
+
peach mode screenshot — toggle the screenshot-mode chrome overlay
|
|
16
16
|
|
|
17
17
|
usage:
|
|
18
|
-
|
|
18
|
+
peach mode screenshot [on|off|toggle]
|
|
19
19
|
|
|
20
20
|
arguments:
|
|
21
21
|
on enable screenshot mode (enables showFrame if needed)
|
|
@@ -23,9 +23,9 @@ arguments:
|
|
|
23
23
|
toggle flip the current state (default)
|
|
24
24
|
|
|
25
25
|
examples:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
peach mode screenshot
|
|
27
|
+
peach mode screenshot on
|
|
28
|
+
peach mode screenshot off
|
|
29
29
|
`)
|
|
30
30
|
rnxExit(0)
|
|
31
31
|
}
|