Skip to content
AI & Agents
Skill

/vm-lab

Parallels macOS VM lab: GUI automation, Peekaboo, TCC, Ghostty.

BOOST
From plugin
agent-scripts
7.1k54 skills
Install
$ npx -y skills add steipete/agent-scripts --skill vm-lab --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/vm-lab

Context preview

The summary Claude sees to decide when to auto-load this skill.

Parallels macOS VM lab: GUI automation, Peekaboo, TCC, Ghostty.

SKILL.md

vm-lab.SKILL.md
name: vm-lab
description: "Parallels macOS VM lab: GUI automation, Peekaboo, TCC, Ghostty."

VM Lab

Use 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.

Safety Rules

  • Only task-owned clones are disposable. Preserve source/golden snapshots, recovery VMs, and other tasks' VMs; never reset, revert, or delete their snapshots.
  • Never access inherited guest credentials or bypass login/startup security to bootstrap a clone.
  • Never print secrets. If `op` is needed, follow the 1Password skill and run it only inside `tmux`.
  • Prefer fresh app windows you create yourself: TextEdit, a local HTML test page, or a small test app.
  • Limit host writes to task-owned temporary diagnostics and explicitly authorized clone recovery. Never change global Bash/Codex settings for a lab workaround.
  • For git repos inside the VM, use HTTPS remotes and normal branch discipline.

Bootstrap Preflight

Before guest automation, confirm the exact task-owned VM UUID and snapshot provenance; the names below are examples, not permission to operate an existing VM.

  • Apple-VZ clone fails to boot: verify the active raw disk's contents, not just clone success or logical size. A sparse linked child alone does not prove a broken chain; `clone --unlink` creates another clone, not an in-place repair.
  • Packaging hangs before its first output: inspect the task-owned shell process and heredoc redirection before changing product code or build guards. A system-Bash retry must also pin PATH-resolved child shells, for that invocation only.

Use [Bootstrap diagnostics](references/bootstrap-diagnostics.md) for read-only checks, evidence limits, and narrowly scoped recovery boundaries.

VM Discovery

List VMs:

prlctl list --all

Get 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.png

TCC / GUI Attribution

For macOS Screen Recording and Accessibility, the responsible process matters.

  • `prlctl exec` is headless and can fail to produce useful Screen Recording attribution.
  • Launch the test command from a visible terminal app in the guest when Screen Recording is involved.
  • Ghostty works as a GUI terminal if installed.
  • After a first failed capture, check `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'

Running Commands Through 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.

Known Pitfalls

  • macOS clipboard APIs may fail from `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.
  • Parallels `send-key-event --key` uses Parallels key values, not macOS virtual key codes.
  • For normal typing, send `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.
  • Prefer one `prlctl send-key-event --json` batch over many separate `send-key-event` processes; separate calls can drift under focus/latency.
  • Use `PRL_KEY_ENTER = 36`, `PRL_KEY_SLASH = 61`, `PRL_KEY_R = 27`, `PRL_KEY_T = 28`, `PRL_KEY_M = 58`, `PRL_KEY_P = 33`.
  • If keystrokes produce garbage, send Return to clear the line, create a shorter launcher, then retry.
  • If Peekaboo permission probes hang with Screen Recording missing and emit `SWIFT TASK CONTINUATION MISUSE`, record it as a product bug; do not confuse it with the VM harness.

Two-Way Validation

For each GUI action, verify through two independent signals:

  • Tool-under-test output: JSON, screenshot file, AX result, or app state.
  • External verifier: `prlctl c
Read more
Ships withagent-scripts

Shared agent instructions, skills, and small portable helpers for Peter's local workspaces.

Get the whole plugin
Stats
7,208
Stars
617
Forks
Active
Maintenance
Shell
Language
MIT
License
19h ago
Last commit
10mo ago
Created
3h ago
Added

Repo: steipete/agent-scripts

Other skills on agent-scripts.