A terminal-first, MCP-controllable control plane for self-hosted macOS VMs on Linux.
tmac is an independent Linux x86_64 port of the control model behind terminal-mac. It uses QEMU/KVM instead of Apple's Virtualization.framework, drives the guest through QMP, and exposes a small MCP tool surface for AI agents and test harnesses. No guest helper, Accessibility grant, or virtio-fs mailbox is required.
Status: experimental alpha. It is a laboratory tool for developers who already have a macOS VM, not a supported macOS distribution, a Mac replacement, or a free macOS CI service.
Both lanes use the same QMP/MCP control plane; the display path and maturity differ.
| Lane | Guest | Display / control | Best for | Status |
|---|---|---|---|---|
| Terminal lane | macOS 12.7.6 Monterey | Software framebuffer + host/tmac.py view / MCP |
Headless automation, terminal/SSH work, long-running agent jobs, legacy tooling | Stable; recommended default |
| GPU lane | macOS 26.6.2 Tahoe | Reims vGPU + GUI window; reims-ctl view and tmac attach also work |
Modern macOS, Metal, GUI app experiments | Experimental; 1024×768; host-VRAM limits |
The terminal lane is not obsolete. It is the better choice when stability and terminal-first control matter. The GPU lane is the modern-macOS path, but it is not a drop-in replacement for every workload.
- Monterey terminal lane under QEMU/KVM with a software framebuffer and the native
tmacMCP server. - Tahoe GPU lane under QEMU/KVM and Reims vGPU, reporting Metal 2 and rendering the full desktop.
- Terminal-first viewer for running guests:
reims-ctl viewwith half-block/Kitty/iTerm output. - External-VM MCP through
tmac attach: screenshot, click, move, drag, scroll, type, key, status. - Managed QEMU macOS VMs through
host/tmac.py: lifecycle, snapshots, VNC, audio, WebDAV, and the Monterey terminal lane. - No guest helper on the critical path; QMP provides frames and input even at login/installer screens.
The tested Tahoe configuration is 1024×768 on a 4 GiB NVIDIA GTX 1650 Ti. Higher modes render but can exhaust host Vulkan memory under load. See docs/gpu.md.
Use this for a Reims-created Tahoe GPU VM (or any running QEMU VM with a QMP socket).
Requirements: Linux x86_64, Python 3.10+, and an existing macOS VM that is already running.
git clone https://github.com/RealNarcissus/tmac.git
cd tmac
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[mcp]' # distribution name: tmac-linux
# Register the running VM. This does not start or stop it.
tmac attach tahoe \
--qmp-socket "$HOME/.local/share/reims-ctl/vms/tahoe/qmp.sock" \
--width 1024 --height 768 \
--ssh-port 2224 \
--guest-user "$USER"
tmac status tahoe
tmac action tahoe screenshot --output /tmp/tahoe.png
tmac mcp tahoeTo use the built release wheel instead of an editable checkout:
python -m pip install \
'https://github.com/RealNarcissus/tmac/releases/download/v0.2.0/tmac_linux-0.2.0-py3-none-any.whl'The GitHub release is source/wheel only; it contains no Apple software or VM images.
The external-VM commands refuse start/stop; manage the VM with its owner (reims-ctl, QEMU, or
libvirt). The SSH options are only needed for Unicode paste and are not stored with a password.
After tmac attach, register the stdio server with an MCP client such as Claude Desktop:
{
"mcpServers": {
"macos-vm": {
"command": "tmac",
"args": ["mcp", "tahoe"]
}
}
}The tool surface is:
| Tool | Purpose |
|---|---|
screenshot |
Capture the guest screen; coordinates are pixels in the returned image. |
click |
Click, double-click, triple-click, or right-click. |
move |
Move the pointer. |
drag |
Press, drag, and release. |
scroll |
Scroll at a point. |
type |
Type ASCII through QMP; Unicode uses guest clipboard when SSH is configured. |
key |
Press a key or chord such as cmd+space. |
status |
Report VM state and screen size. |
The verified recipe uses the separately installed reims-ctl, the Reims QEMU build, an offline
macOS installer supplied by the user, and apple-gfx-pci. The complete runbook, including the
required METAL_ERROR_MODE=5 guest preference, SSH setup, cursor patch, and VRAM limits, is in
docs/tahoe.md.
No macOS installer, IPSW, VM disk, OpenCore image, Apple SMC OSK, or Apple binary is included in this repository. You supply the installer and any OSK required by your own managed-QEMU workflow, and you are responsible for Apple's license terms. See LEGAL.md.
The original Linux port and MCP proof used macOS 12.7.6 with a software framebuffer. It remains the
stable terminal-first lane in host/tmac.py and the gui-proof VM home.
The guest shell proof (sw_vers 12.7.6 / Darwin 21.6.0 x86_64) is preserved at
evidence/host/desktop-terminal-proof2.png.
export TMAC_HOME="$PWD/work/main/tmac-home"
python3 host/tmac.py status gui-proof
python3 host/tmac.py start gui-proof
python3 host/tmac.py view gui-proof
python3 host/tmac.py mcp gui-proofSee docs/architecture.md, docs/porting.md, and docs/FINAL-REPORT.md for the original investigation. The terminal lane is independent of the external-VM/MCP path above.
- QMP instead of a guest helper.
screendumpandinput-send-eventwork from firmware through macOS login, without ScreenCaptureKit or Accessibility permissions. - The VM is owned by its hypervisor.
attachrecords the QMP socket and screen metadata but never claims lifecycle ownership. - The terminal is a first-class surface. The viewer is useful over SSH and on headless hosts; Reims' GPU window is available when full color and responsiveness matter.
- Evidence over claims. Research documents distinguish observed, inferred, and unknown results;
screenshots, logs, and reproduced commands live under
evidence/.
- x86_64 only. Apple-silicon VM behavior and arm64-only tooling are out of scope.
- Experimental macOS versions. Tahoe requires Reims; the AppleParavirtGPU path is not stable on the preserved Monterey guest.
- No app build/test CI yet. The MCP server is GUI computer use; it has not been demonstrated compiling or testing a real Xcode project.
- Finite host VRAM. Reims can exhaust a 4 GiB GPU at higher resolutions; 1024×768 is the tested stable mode.
- US-ASCII QMP typing. Unicode depends on guest SSH and the clipboard helper.
- Not a security sandbox. The MCP server can click and type anywhere in the guest. Run a disposable VM and review tool calls.
host/tmac.py QEMU/QMP control plane, viewer, and MCP server
host/qmp_broker.py concurrent QMP client broker for managed VMs
scripts/ OpenCore/AMD helpers and the Reims cursor patch
tests/ unit tests; no QEMU or macOS required
docs/ architecture, porting notes, runbooks, evidence ledger
evidence/ captured screenshots, logs, and validation artifacts
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[mcp,share]'
python -m unittest discover -s tests -v
python -m compileall -q host scriptsCI runs the same unit tests and byte-compilation on Python 3.10, 3.12, and 3.14.
- Read SECURITY.md before exposing a QMP socket or guest SSH port.
- Read LEGAL.md before publishing a fork, hosting a service, or distributing anything built from a macOS guest. Apple's macOS license generally restricts virtualization to Apple-branded hardware; this project does not grant you a macOS license.
- The repository is GPL-2.0-or-later. The Reims cursor patch is a GPL-covered modification. See LICENSE and THIRD_PARTY_NOTICES.md.
Issues and focused pull requests are welcome. Read CONTRIBUTING.md and CODE_OF_CONDUCT.md. Never include credentials, SSH keys, Apple installers, VM disks, or personal screenshots in an issue.
- terminal-mac — MIT; original design and MCP tool model.
- reims-vgpu and metal2vulkan — virtual GPU and runtime.
- OSX-KVM and AMD_Vanilla — boot and kernel-patch foundations.
- QEMU, OpenCore, OVMF, Pillow, WsgiDAV, and Cheroot — see their upstream licenses.
- The preserved Monterey research artifacts are documented in docs/FINAL-REPORT.md.
Not affiliated with Apple Inc.

