Parallels Desktop
Use this skill for Parallels VM work on Peter's Mac.
Guest OS split:
-
macOS guest: use prl-macos-*
-
Linux guest: use prl-linux-*
-
Windows guest: use prl-windows-*
-
unknown guest: probe with prlctl exec "<vm>" --current-user sh -lc 'uname -a; cat /etc/os-release 2>/dev/null || true' before choosing wrappers
Primary tools:
-
prlctl for power, snapshots, guest exec, guest screenshots, VM info
-
peekaboo for host-side GUI automation of the Parallels app/window
-
ssh / Screen Sharing / RDP inside the guest for robust control
-
helper wrappers live in ~/Projects/agent-scripts/skills/parallels-vm/scripts/ ; they are not copied into each target repo's scripts/
Fast Path
-
Verify prlctl exists: which prlctl
-
List VMs: prlctl list -a
-
Inspect target VM: prlctl list -i "<vm>"
-
Prefer guest-native control first:
-
prlctl exec "<vm>" --current-user ...
-
ssh user@<guest-ip>
-
Use peekaboo only when GUI interaction is required.
Guest exec pitfalls:
-
prlctl exec "<vm>" ... without --current-user often runs as root ; this is wrong for per-user launchd checks on macOS guests
-
prlctl exec can have a minimal PATH even with --current-user ; Homebrew CLIs may fail with command not found or env: node: No such file or directory
-
prlctl exec also mangles shell-heavy commands more often than it should on macOS guests; for pipes, redirects, heredocs, or interactive flows, prefer prlctl enter "<vm>" --current-user --use-advanced-terminal
-
prefer absolute guest paths for Homebrew tools on macOS guests, for example /opt/homebrew/bin/openclaw , /opt/homebrew/bin/node , /usr/bin/grep , /usr/bin/plutil
-
if you need shell features or user PATH, wrap with a real shell explicitly: prlctl exec "$VM" --current-user zsh -lc '<cmd>'
-
if a guest-installed npm CLI fails under prlctl exec but works interactively, bypass the shebang and run the entrypoint with absolute Node, for example /opt/homebrew/bin/node /opt/homebrew/lib/node_modules/openclaw/openclaw.mjs ...
-
when validating a same-version npm reinstall inside the guest, use a cache-busted tarball filename and inspect the installed compiled file, not just --version ; npm may leave the old hashed bundle in place if you keep reinstalling the same filename/version pair
Reusable helpers:
-
scripts/prl-linux-openclaw.sh <vm> [--env KEY=VALUE ...] <openclaw-args...> : run guest OpenClaw on Linux via resolved CLI path
-
scripts/prl-linux-install-openclaw.sh <vm> [--version latest] : run the website installer on a Linux guest
-
scripts/prl-linux-gateway-status-version.sh <vm> [--profile <name>] [--state-dir <dir>] [--json] : fetch Linux guest gateway status and extract runtimeVersion , rpc.ok , pid, and port data
-
scripts/prl-linux-openclaw-update-verify.sh <vm> : end-to-end published Linux release smoke using manual gateway verification
-
scripts/prl-macos-enter.sh <vm> : open a real guest shell via prlctl enter
-
scripts/prl-macos-pnpm.sh <vm> <guest-repo-dir> <pnpm args...> : run guest pnpm through absolute Homebrew Node + PATH
-
scripts/prl-macos-vitest.sh <vm> <guest-repo-dir> [--env KEY=VALUE ...] [--] <vitest-args...> : run guest Vitest via pnpm exec vitest --root <repo> ; use this instead of hand-rolled guest Vitest commands
-
scripts/prl-macos-repo-openclaw.sh <vm> <guest-repo-dir|guest-entry.js> [--env KEY=VALUE ...] <openclaw-args...> : run a guest checkout's openclaw.mjs /dist entry directly; use this for secret-bearing onboard/live commands instead of pnpm openclaw ...
-
scripts/prl-macos-live-auth-seed.sh <vm> [--agent <agent-id>] [--guest-path <path>] [--provider <provider:ENV_VAR> ...] : build a minimal guest auth-profiles.json from host env vars and seed it; default providers are openai:OPENAI_API_KEY
- anthropic:ANTHROPIC_API_KEY
-
scripts/prl-macos-download.sh <vm> <url> <guest-path> : download a URL to a guest file first; safer than curl | bash through prlctl exec
-
scripts/prl-macos-openclaw.sh <vm> [--env KEY=VALUE ...] <openclaw-args...> : run guest OpenClaw via absolute Node + resolved entrypoint
-
scripts/prl-macos-install-openclaw.sh <vm> [--version latest] : run the website installer reliably inside the guest
-
scripts/prl-macos-gateway-status-version.sh <vm> [--profile <name>] [--state-dir <dir>] [--json] : fetch gateway status and extract runtimeVersion , rpc.ok , pid, and port data
-
scripts/prl-macos-openclaw-update-verify.sh <vm> : end-to-end published release smoke; install old version from openclaw.ai , verify gateway, update to latest, re-verify, and auto-fallback to manual gateway launch when Tahoe launchd bootstrap is broken
-
scripts/prl-macos-auth-seed.sh <vm> <local-auth-profiles.json|-> : seed auth-profiles.json into the guest with base64 transport
-
scripts/prl-windows-install-openclaw.sh <vm> [--version latest] [--spec <npm-spec-or-url>] : run the Windows website installer with -NoOnboard , or install a host-served/current-checkout npm spec directly; native installer now bootstraps user-local portable Git under %LOCALAPPDATA%\OpenClaw\deps\portable-git
-
scripts/prl-windows-overlay-openclaw.sh <vm> --spec <npm-spec-or-url> : overlay a host-served/current-checkout tgz onto the existing native Windows global install while keeping its node_modules ; use this when you need upcoming-build code fast and a raw unpacked tgz is missing runtime deps
-
scripts/prl-windows-openclaw.sh <vm> [--env KEY=VALUE ...] <openclaw-args...> : run guest OpenClaw on native Windows through a PowerShell wrapper that avoids npm.ps1 / shell quoting nonsense
-
scripts/prl-windows-gateway-status-version.sh <vm> [--json] : fetch native Windows gateway status --json ; strips CLIXML and trailing guidance text before parsing
-
scripts/prl-windows-openclaw-update-verify.sh <vm> : end-to-end native Windows release smoke; can start from a published version or a host-served/local npm spec, attempts update --json , tolerates trailing post-JSON guidance text, reports known release blockers, waits for the user session first, and skips the reinstall automatically when the VM is already on the requested --from-version unless you pass --force-reinstall
-
scripts/prl-windows-onboard-verify.sh <vm> : native Windows onboarding smoke; separates "embedded/provider setup works" from "managed gateway install works", captures expected no-daemon health failures, surfaces Scheduled Task access-denied errors cleanly, and can optionally run an embedded OpenAI hatch in the same wrapper via --hatch
Purpose-Built Wrappers
When the task is about OpenClaw install/update verification, prefer the OS-matched wrappers over ad-hoc prlctl exec :
Linux guest:
-
prl-linux-install-openclaw.sh
-
prl-linux-openclaw.sh
-
prl-linux-gateway-status-version.sh
-
prl-linux-openclaw-update-verify.sh
macOS guest:
-
prl-macos-install-openclaw.sh
-
prl-macos-openclaw.sh
-
prl-macos-gateway-status-version.sh
-
prl-macos-openclaw-update-verify.sh
Windows guest:
-
prl-windows-install-openclaw.sh
-
prl-windows-overlay-openclaw.sh
-
prl-windows-openclaw.sh
-
prl-windows-gateway-status-version.sh
-
prl-windows-openclaw-update-verify.sh
prl-macos-install-openclaw.sh : downloads install.sh to the guest first, then runs it with explicit PATH/env
prl-macos-openclaw.sh : bypasses shebang/PATH issues by calling guest OpenClaw with absolute Node + dist/entry.js
prl-macos-gateway-status-version.sh : normalizes noisy gateway status --json output into a compact version/probe summary
prl-macos-openclaw-update-verify.sh : does the Tahoe-style "install old -> verify gateway -> update -> verify gateway" flow and falls back to a detached manual gateway run probe after forcing gateway.mode=local if LaunchAgent bootstrap fails
prl-linux-install-openclaw.sh : runs the website installer on Ubuntu/Debian-style guests and then resolves the installed openclaw CLI path
prl-linux-openclaw.sh : runs guest OpenClaw on Linux via resolved openclaw binary path and normal PATH
prl-linux-gateway-status-version.sh : normalizes Linux guest gateway status --json output into the same compact summary
prl-linux-openclaw-update-verify.sh : verifies Linux releases with a detached manual gateway run path instead of assuming launchd/systemd service setup
prl-windows-install-openclaw.sh : runs the public PowerShell installer with -NoOnboard , or installs a local/hosted npm spec directly, relying on the installer's user-local MinGit bootstrap instead of admin winget Git
prl-windows-overlay-openclaw.sh : overlays a packed build onto the guest's existing global OpenClaw install so the current code can reuse the installed dependency tree; use this when --spec reinstall is too slow or when unpacking a tgz directly would miss runtime deps like chalk
prl-windows-openclaw.sh : runs native Windows openclaw via encoded PowerShell, which avoids PATH and execution-policy footguns
prl-windows-gateway-status-version.sh : returns parsed status JSON even when gateway status --json appends human guidance after the JSON block
prl-windows-openclaw-update-verify.sh : captures native Windows version/install/update behavior even when the published release is partially broken; use --from-spec and --update-spec to keep the whole smoke on host-served artifacts before npm publish, and lean on the built-in skip-reinstall fast path for repeat runs against the same --from-version
prl-windows-onboard-verify.sh : use this when the question is specifically "does native Windows onboarding succeed?" because it distinguishes expected local-health failures from real daemon install failures and can optionally prove embedded-provider hatching in one pass
prl-macos-auth-seed.sh : avoids fragile inline JSON writes when a live test needs stored auth profiles
Core Commands
VM="macOS Tahoe"
prlctl start "$VM" prlctl status "$VM" prlctl list -i "$VM" prlctl exec "$VM" --current-user whoami prlctl capture "$VM" --file /tmp/parallels-shot.png
prlctl snapshot "$VM" --name pre-change prlctl snapshot-list "$VM" --tree prlctl snapshot-switch "$VM" --id <snapshot-id> prlctl snapshot-delete "$VM" --id <snapshot-id>
Helper examples:
VM="macOS Tahoe" REPO="/Users/steipete/Projects/openclaw-parallels-gpt54"
scripts/prl-macos-pnpm.sh "$VM" "$REPO" install scripts/prl-macos-pnpm.sh "$VM" "$REPO" build scripts/prl-macos-pnpm.sh "$VM" "$REPO" check scripts/prl-macos-pnpm.sh "$VM" "$REPO" test scripts/prl-macos-vitest.sh "$VM" "$REPO" run src/plugins/discovery.test.ts scripts/prl-macos-repo-openclaw.sh "$VM" "$REPO" --version source ~/.profile >/dev/null 2>&1 scripts/prl-macos-live-auth-seed.sh "$VM" scripts/prl-macos-vitest.sh "$VM" "$REPO" --env "OPENCLAW_LIVE_MODELS=openai/gpt-5.4,anthropic/claude-opus-4-6" --env "OPENCLAW_LIVE_TEST=1" --env "CLAWDBOT_LIVE_TEST=1" --env "OPENAI_API_KEY=$OPENAI_API_KEY" --env "ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY" -- run --config vitest.live.config.ts src/agents/models.profiles.live.test.ts scripts/prl-macos-vitest.sh "$VM" "$REPO" --env "OPENCLAW_LIVE_GATEWAY_MODELS=openai/gpt-5.4,anthropic/claude-opus-4-6" --env "OPENCLAW_LIVE_TEST=1" --env "CLAWDBOT_LIVE_TEST=1" --env "OPENAI_API_KEY=$OPENAI_API_KEY" --env "ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY" -- run --config vitest.live.config.ts src/gateway/gateway-models.profiles.live.test.ts scripts/prl-macos-install-openclaw.sh "$VM" --version 2026.3.7 scripts/prl-macos-gateway-status-version.sh "$VM" --json scripts/prl-macos-openclaw-update-verify.sh "$VM" --from-version 2026.3.7 --to-tag latest
VM="Ubuntu 24.04.3 ARM64" scripts/prl-linux-install-openclaw.sh "$VM" --version 2026.3.7 scripts/prl-linux-gateway-status-version.sh "$VM" --json scripts/prl-linux-openclaw-update-verify.sh "$VM" --from-version 2026.3.7 --to-tag latest
VM="Windows 11" scripts/prl-windows-install-openclaw.sh "$VM" --version latest scripts/prl-windows-install-openclaw.sh "$VM" --spec "http://10.211.55.2:8138/openclaw-next.tgz" scripts/prl-windows-overlay-openclaw.sh "$VM" --spec "http://10.211.55.2:8138/openclaw-next.tgz" scripts/prl-windows-openclaw.sh "$VM" --version scripts/prl-windows-gateway-status-version.sh "$VM" --json scripts/prl-windows-onboard-verify.sh "$VM" --json source ~/.profile >/dev/null 2>&1 scripts/prl-windows-onboard-verify.sh "$VM" --openai-api-key-env OPENAI_API_KEY --hatch --json scripts/prl-windows-openclaw-update-verify.sh "$VM" --from-version 2026.3.7 --to-tag latest scripts/prl-windows-openclaw-update-verify.sh "$VM" --from-version 2026.3.7 --skip-install scripts/prl-windows-openclaw-update-verify.sh "$VM" --from-spec "http://10.211.55.2:8138/openclaw-a.tgz" --update-spec "http://10.211.55.2:8138/openclaw-b.tgz" scripts/prl-windows-openclaw-update-verify.sh "$VM" --from-version 2026.3.7 --update-spec "http://10.211.55.2:8138/openclaw-next.tgz" source ~/.profile >/dev/null 2>&1 scripts/prl-windows-openclaw.sh "$VM" --env "OPENAI_API_KEY=$OPENAI_API_KEY" agent --local --agent main --json --thinking low -m "Reply with exactly WINDOWS-HATCH-OK."
Useful IP extractor:
vmip() { prlctl list -i "$1" | awk -F': ' '/IP Addresses/{print $2}'; }
SSH Bootstrap
Shared networking is usually enough for host-to-guest SSH. Check guest IP from prlctl list -i .
Probe SSH:
nc -G 2 -vz "$(vmip "$VM")" 22
If closed on a macOS guest, enable Remote Login in the guest:
-
UI: System Settings > General > Sharing > Remote Login
-
CLI in guest when creds allow: sudo systemsetup -setremotelogin on
Then:
ssh "$USER@$(vmip "$VM")"
If the user wants stable local forwarding like localhost:2222 , configure a Parallels NAT port-forward rule instead of relying on changing guest IPs.
macOS Guest Debugging
For launchd-managed services on a macOS guest, use the guest console user, not root:
VM="macOS Tahoe" prlctl exec "$VM" --current-user 'whoami && echo HOME=$HOME && id -u'
Gateway / launchd checks that worked well:
VM="macOS Tahoe" prlctl exec "$VM" --current-user 'label=ai.openclaw.gateway; domain=gui/$(id -u); plist=$HOME/Library/LaunchAgents/$label.plist; ls -l "$plist"; launchctl print "$domain/$label"' prlctl exec "$VM" --current-user 'launchctl print-disabled gui/$(id -u) | /usr/bin/grep -E "ai\.openclaw|openclaw" || true' prlctl exec "$VM" --current-user 'lsof -nP -iTCP:18789 -sTCP:LISTEN || true' prlctl exec "$VM" --current-user 'curl -i --max-time 5 http://127.0.0.1:18789/health || true'
Notes:
-
launchctl print gui/$(id -u)/<label> is the fastest way to prove “plist exists but launchd lost the service”
-
curl http://127.0.0.1:<port>/health and lsof -iTCP:<port> are more reliable than app-specific CLIs when PATH/env inside prlctl exec is broken
-
if a service CLI fails under prlctl exec , first verify whether the binary or its shebang target is missing from PATH before assuming the service is down
OpenClaw/Tahoe notes:
-
For OpenAI + Anthropic live model coverage, default to OPENCLAW_LIVE_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6" and OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6" unless Peter asks for different models
-
When proving "what version is on main?" from a guest checkout, use scripts/prl-macos-repo-openclaw.sh "$VM" "$REPO" --version . scripts/prl-macos-openclaw.sh "$VM" --version only checks the guest-global install and may lag or be missing after snapshot restore.
-
After snapshot-switch / snapshot restore, assume guest repo checkouts and auth-profiles.json may be stale or gone. Recreate the checkout, pin it to the host commit under test, and reseed live auth before running gateway live tests.
-
Fresh macOS guests may have Homebrew node but no pnpm ; install once with /opt/homebrew/bin/node /opt/homebrew/lib/node_modules/npm/bin/npm-cli.js install -g pnpm
-
scripts/prl-macos-pnpm.sh now auto-installs missing guest pnpm with the guest Homebrew node
-
Some Tahoe guests inherit permissive umask values (000 ); temp dirs/files can land as 0777 /0666 and trip OpenClaw's world-writable plugin safety gates. If discovery/loader tests suddenly return no candidates, check permissions first before blaming cache/env logic.
-
Prefer argv-style guest commands (git -C <repo> ... , wrappers, absolute paths) over prlctl exec ... sh -lc 'cd ... && ...' ; Tahoe shell-wrapped git commands were flaky here.
-
For guest Vitest, prefer scripts/prl-macos-vitest.sh ; if you do it manually, use pnpm exec vitest and pass repo-root-relative test paths under --root <repo> .
-
For env-scoped guest pnpm /Vitest runs, reuse the shared wrapper/lib path (prl_run_pnpm_env via scripts/prl-macos-vitest.sh ) instead of hand-writing prlctl exec ... env ... node ... pnpm ... each time.
-
prlctl exec is fine for argv-style commands; for pipes, heredocs, JSON blobs, or multiline shell work, switch to scripts/prl-macos-enter.sh
-
Website installer verification should use scripts/prl-macos-install-openclaw.sh , not raw curl | bash through prlctl exec
-
Gateway version verification should use scripts/prl-macos-gateway-status-version.sh ; it strips pre-JSON warnings and reports runtimeVersion when present
-
Real release smoke should prefer scripts/prl-macos-openclaw-update-verify.sh ; it now tolerates Tahoe launchctl bootstrap ... Input/output error by falling back to a detached manual gateway probe
-
Released builds may still print /dev/tty: Device not configured during noninteractive installer tail work (doctor / plugin updates); treat that as a follow-up bug unless the requested version failed to land
-
If manual gateway probing is needed, first force gateway.mode=local ; released builds can otherwise block startup with set gateway.mode=local (current: unset) or pass --allow-unconfigured
-
For listener checks, use lsof -nP -iTCP:<port> -sTCP:LISTEN ; plain lsof -i :<port> is too noisy on Tahoe
-
Avoid pnpm openclaw ... --openai-api-key ... / --anthropic-api-key ... in guest live setup; pnpm echoes the full argv. Use scripts/prl-macos-repo-openclaw.sh or direct node <repo>/openclaw.mjs ... instead so secrets stay out of logs.
-
Noninteractive onboarding seeds one provider choice per run. For OpenAI + Anthropic live coverage, run onboard twice or seed auth-profiles.json directly.
-
src/agents/models.profiles.live.test.ts can false-green with "[live-models] no API keys found; skipping" after a snapshot restore. Treat that as "not actually tested"; pass guest env keys explicitly and verify the log shows real model runs, not a skip.
-
src/gateway/gateway-models.profiles.live.test.ts currently filters on stored auth profiles; env-only OPENAI_API_KEY / ANTHROPIC_API_KEY is not enough there. Use scripts/prl-macos-live-auth-seed.sh "$VM" (or prl-macos-auth-seed.sh with a prepared file) before rerunning.
OpenClaw/Linux notes:
-
Linux guests do not use the macOS Homebrew/dist/entry.js assumptions; use the prl-linux-* wrappers
-
Linux release verification uses manual gateway run probes, not launchd
-
Before assuming Linux support is broken, check whether openclaw was installed into ~/.local/bin , /usr/local/bin , or /usr/bin
-
Ubuntu guest labels in Parallels may lag the actual distro patch level; verify with /etc/os-release
OpenClaw/Windows notes:
-
Prefer the prl-windows-* wrappers; raw prlctl exec ... powershell -Command is fragile because quoting and PowerShell execution policy love breaking npm.ps1 / pnpm.ps1
-
If you need multiline/native PowerShell work on Windows guests, use the wrapper/lib encoded path, not raw host-shell powershell -Command "$..." ; host-shell interpolation will happily strip guest $env: variables before the command even reaches the VM
-
After a hard reboot or snapshot switch, wait until prlctl exec "$VM" --current-user whoami works again before trusting wrapper failures; Parallels Tools/user session readiness lags boot
-
Right after reboot, plain prlctl exec "$VM" whoami may already work as NT AUTHORITY\SYSTEM while --current-user still fails; that means the guest booted but the desktop user session is not ready yet
-
A black prlctl capture right after reboot usually means "guest/session still waking up", not "Windows is dead"
-
prl-windows-onboard-verify.sh is the right probe for native onboarding. Without --install-daemon , a final gateway health failure is expected unless a local gateway is already running.
-
Native Windows managed gateway install currently goes through Scheduled Tasks. schtasks create failed: ERROR: Access is denied. means admin PowerShell is the blocker, not provider auth.
-
Keep embedded hatch/provider checks separate from gateway-service checks. prl-windows-openclaw.sh "$VM" --env "OPENAI_API_KEY=..." agent --local --agent main ... can be green while gateway install is still red.
-
Repeat Windows update tests should prefer --skip-install or rely on the default version-match skip path when you only need to re-check the update leg.
-
The public Windows installer now bootstraps user-local portable Git under %LOCALAPPDATA%\OpenClaw\deps\portable-git ; this avoids UAC/admin prompts for Git
-
The portable Git bootstrap is process-local; a fresh guest shell may still say git is missing unless the installer or wrapper added the portable paths for that command
-
For upcoming-build verification, host cache-busted tgz files on the Mac (for example python3 -m http.server 8138 ) and pass them with prl-windows-install-openclaw.sh --spec ... or prl-windows-openclaw-update-verify.sh --from-spec ... --update-spec ...
-
Do not unpack a Windows tgz in the guest and run openclaw.mjs directly as proof; the tarball expects an installed dependency tree. Use prl-windows-install-openclaw.sh --spec ... or prl-windows-overlay-openclaw.sh --spec ... instead
-
After a reboot, openclaw.cmd may not resolve from PATH in a raw guest PowerShell session even though the install is fine; the wrappers already probe %APPDATA%\npm / %LOCALAPPDATA%\pnpm fallback paths, so prefer them over ad-hoc commands
-
For a real OpenAI smoke on native Windows, source ~/.profile on the host and use the embedded path:
-
scripts/prl-windows-openclaw.sh "$VM" --env "OPENAI_API_KEY=$OPENAI_API_KEY" agent --local --agent main --json --thinking low -m "Reply with exactly WINDOWS-HATCH-OK."
-
Embedded agent --local still needs a target; use --agent main for the default session. --model is not a valid flag here.
-
Treat native embedded hatch and native gateway service as separate checks:
-
embedded hatch can pass with only OPENAI_API_KEY
-
onboard --non-interactive --accept-risk ... still fails at the final loopback gateway probe if the Windows gateway service is not installed/running
-
Current published native Windows release (openclaw@2026.3.11 ) can install and report openclaw --version , but deeper CLI paths may still fail on Windows ARM with the released @snazzah/davey binding load problem
-
When you need full native Windows verification today, prefer:
-
website installer for release smoke
-
local tarball/current-checkout install for deeper gateway/plugin/runtime checks
-
prl-windows-openclaw-update-verify.sh reports these published-release blockers instead of pretending the path is green
-
prl-windows-openclaw-update-verify.sh and prl-windows-gateway-status-version.sh support --help ; use that instead of bare execution when checking flags
GUI Automation
Use prlctl capture for the guest screenshot itself.
Use Peekaboo for host-side automation of the Parallels window:
peekaboo see --app Parallels --json peekaboo click --app Parallels --coords 500,400 peekaboo type --app Parallels "hello"
Important:
-
prlctl capture pixels are guest-native
-
peekaboo click/type target the visible host window
-
coordinate mapping gets fragile if the Parallels window is scaled, moved, fullscreened, or retina-scaled differently
Best practice:
-
keep the VM window visible and stable if using Peekaboo
-
prefer SSH / Screen Sharing / RDP for serious automation
-
use prlctl send-key-event only for limited key injection
Snapshot Safety
-
Take a snapshot before risky changes.
-
Do not delete or switch snapshots unless asked or clearly part of the requested workflow.
-
Call out that snapshot revert discards later guest state.
Decision Rule
-
Need lifecycle / state / metadata / screenshots: use prlctl
-
Need commands inside guest: use prlctl exec or ssh
-
Need desktop UI control: use guest-native remote control first, Peekaboo second
-
Need reproducible visual automation from the host: combine prlctl capture for read + Peekaboo for action, but warn about coordinate drift
Peter Notes
-
peekaboo is on PATH on this Mac.
-
~/.codex/skills points to ~/Projects/agent-scripts/skills , so edits there are live for Codex.