Vm Lab logo

Vm Lab

CommunityPopular
steipete
vm-lab

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

Overview

Publishersteipete
Repositoryagent-scripts
Skill namevm-lab
Stars
6.6K
Forks
547
Bundled files
3
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 3 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by steipete on GitHub. Read the source before you install it.

Installation

Install the Vm Lab AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/steipete/agent-scripts.git /tmp/agent-scripts
mkdir -p .claude/skills
cp -r /tmp/agent-scripts/skills/vm-lab .claude/skills/vm-lab
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Vm Lab in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Vm Lab on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Vm Lab is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

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 for read-only checks, evidence limits, and narrowly scoped recovery boundaries.

VM Discovery

List VMs:

bash
prlctl list --all

Get VM status/IP:

bash
prlctl list --info "macOS Tahoe"

Run guest commands as Peter:

bash
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:

bash
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:

bash
prlctl exec "macOS Tahoe" \
  'sudo -u steipete -H open "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture"'

Open Ghostty:

bash
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:

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

bash
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 capture, host-side image inspection, file content in guest, or process/window state.

Examples:

  • Screenshot: compare Peekaboo image dimensions/content against prlctl capture.
  • Click: use Peekaboo to click a test button, then verify both guest app state and host screenshot.
  • Type: use Peekaboo to type into a controlled text field, then verify AX value and host screenshot.
  • Performance: wrap commands with /usr/bin/time -p; repeat cold/warm runs; keep outputs in /tmp.

Peekaboo VM Baseline

Inside guest:

bash
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 --json

Host-side reference capture:

bash
prlctl capture "macOS Tahoe" --file /tmp/vm-prlctl-reference.png

Guest-side Peekaboo capture through Ghostty:

bash
/tmp/r

Compare:

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

Reporting

When handing off, include only:

  • VM name and OS build.
  • repo commit tested.
  • permission state.
  • commands that passed/failed.
  • independent verifier result.
  • product bugs discovered.

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Vm Lab AI skill do?

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

Why use Vm Lab on TypingMind?

Because you install it once and use it with any model. Vm Lab is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Vm Lab in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/steipete/agent-scripts/tree/main/skills/vm-lab. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Vm Lab?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Vm Lab?

As many as you like. As long as a model supports skills, you can use Vm Lab with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Vm Lab AI skill free?

Yes. It is published on GitHub by steipete under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇