Parallels macOS VM lab: GUI automation, Peekaboo, TCC, Ghostty.
66
78%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./skills/vm-lab/SKILL.mdUse this when the task needs a clean macOS VM to test GUI automation, TCC prompts, screenshot capture, clicking, typing, performance, or "two-way validation" of Peekaboo-like tools.
Core idea: run the tool under test inside the guest, but verify it from outside the guest with Parallels screenshots and host-side observations. Do not close apps you do not own.
op is needed, follow the 1Password skill and run it only inside tmux./tmp.List VMs:
prlctl list --allGet VM status/IP:
prlctl list --info "macOS Tahoe"Run guest commands as Peter:
prlctl exec "macOS Tahoe" \
'sudo -u steipete -H /bin/zsh -lc '\''source ~/.zprofile 2>/dev/null || true; uname -a'\'''Capture an independent host-side screenshot:
prlctl capture "macOS Tahoe" --file /tmp/vm-reference.png
sips -g pixelWidth -g pixelHeight /tmp/vm-reference.pngFor macOS Screen Recording and Accessibility, the responsible process matters.
prlctl exec is headless and can fail to produce useful Screen Recording attribution.System Settings > Privacy & Security > Screen & System Audio Recording.permissions status run through prlctl exec may still report Screen Recording false after Ghostty is allowed; validate Screen Recording by rerunning the capture from Ghostty.Open the Screen Recording pane:
prlctl exec "macOS Tahoe" \
'sudo -u steipete -H open "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture"'Open Ghostty:
prlctl exec "macOS Tahoe" 'sudo -u steipete -H open -a Ghostty'Best path: create a guest script with prlctl exec, open/focus Ghostty, then type only a short launcher path into the visible terminal.
Guest script pattern:
prlctl exec "macOS Tahoe" 'sudo -u steipete -H /bin/zsh -lc '\''cat > /tmp/run-vm-lab.zsh <<EOF
#!/bin/zsh
source ~/.zprofile 2>/dev/null || true
cd ~/Projects/Peekaboo || exit 1
Apps/CLI/.build/debug/peekaboo image --path /tmp/peekaboo-vm.png --json
rc=$?
echo "EXIT:$rc"
[ -f /tmp/peekaboo-vm.png ] && sips -g pixelWidth -g pixelHeight /tmp/peekaboo-vm.png
echo "Press return to close..."
read _
exit $rc
EOF
chmod +x /tmp/run-vm-lab.zsh
ln -sf /tmp/run-vm-lab.zsh /tmp/r
open -a Ghostty'\'''Then link the launcher into Ghostty's home directory and type ./r with scripts/parallels_type.py. This avoids unreliable path characters in Parallels key injection.
prlctl exec "macOS Tahoe" \
"sudo -u steipete -H /bin/zsh -lc 'ln -sf /tmp/run-vm-lab.zsh ~/r'"
python3 skills/vm-lab/scripts/parallels_type.py "macOS Tahoe" $'./r\n'Avoid long command typing. Parallels key injection uses its own key-code table and can be layout-sensitive.
prlctl exec; pbcopy, AppleScript clipboard, and Peekaboo paste can all fail in headless guest context.open -na Ghostty.app --args -e ... may only focus an existing Ghostty window on macOS; do not assume it runs the command.prlctl exec may re-join argv through a guest shell; for complex payloads, pass one fully shell-quoted command string or create the file with a tiny Python writer.send-key-event --key uses Parallels key values, not macOS virtual key codes.prlctl send-key-event <vm> --key <key> with no --event; explicit press/release can repeat or stick. Return is an exception: use press then release.prlctl send-key-event --json batch over many separate send-key-event processes; separate calls can drift under focus/latency.PRL_KEY_ENTER = 36, PRL_KEY_SLASH = 61, PRL_KEY_R = 27, PRL_KEY_T = 28, PRL_KEY_M = 58, PRL_KEY_P = 33.SWIFT TASK CONTINUATION MISUSE, record it as a product bug; do not confuse it with the VM harness.For each GUI action, verify through two independent signals:
prlctl capture, host-side image inspection, file content in guest, or process/window state.Examples:
prlctl capture./usr/bin/time -p; repeat cold/warm runs; keep outputs in /tmp.Inside guest:
cd ~/Projects/Peekaboo
git pull --recurse-submodules
swift build --package-path Apps/CLI
Apps/CLI/.build/debug/peekaboo --version
Apps/CLI/.build/debug/peekaboo permissions status --jsonHost-side reference capture:
prlctl capture "macOS Tahoe" --file /tmp/vm-prlctl-reference.pngGuest-side Peekaboo capture through Ghostty:
/tmp/rCompare:
prlctl exec "macOS Tahoe" \
'sudo -u steipete -H /bin/zsh -lc '\''sips -g pixelWidth -g pixelHeight /tmp/peekaboo-vm.png'\'''
sips -g pixelWidth -g pixelHeight /tmp/vm-prlctl-reference.pngWhen handing off, include only:
bb36883
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.