On a Mac there is no virtual machine route to many environments: Apple's licence and its virtualisation framework stop at two macOS guests per machine. The unit we found that gives an attempt its own clipboard, preferences, privacy state, home folder and input stream is one macOS user logged in to its own graphical session in the background. This note says what that unit gives, what it does not, and which of the numbers here were measured where.
The short answer
Probably workable for a small number of environments; not shown for a large one. macOS has run several live GUI sessions at once since 10.7 (vendor claim, Apple technical notes). Each session runs its own pasteboard server and its own privacy daemon (measured on the laptop). A third party drove a background session with screenshots, clicks, typing, drags and scrolls on macOS 26.3 (author claim). No public API logs a user in without a person, so each account takes one manual login after every boot. It is not a security boundary: all sessions share one kernel, one WindowServer and one root.
What a session owns and what stays shared
| Item | Scope | Evidence |
|---|---|---|
Pasteboard (com.apple.pboard) | own per session | runs in the session's launchd domain (measured, laptop) |
Preferences daemon (cfprefsd) | own per user | one agent per user id; changing HOME does not move it (measured, laptop) |
Privacy daemon (tccd) | own per session | runs in the session domain (measured, laptop); Screen Recording and Accessibility rows live in the system database (author claim) |
| Home, keychain, per-user temp folders, Launch Services | own per user | follow the user id, not HOME (measured, laptop) |
| Input event stream | own per session | a third party posted input to one session's tap (author claim); leaks across sessions never tested with N at once |
| Dock, Finder, loginwindow, Notification Center | one copy per session | measured, laptop |
| Kernel, WindowServer | shared | one WindowServer serves every session (vendor claim); it is the single point of failure for every environment |
| root, system privacy database | shared | |
| Network, DNS, printers | shared | one resolver and one set of print queues per host (measured, laptop) |
| Modifier-key state | system-wide inside a session (vendor claim); across sessions untested | |
| CPU, GPU, RAM | shared |
Why sessions and not per-process input
Inside one session there is exactly one general pasteboard, one frontmost app, one key window, one menu bar, one Dock, one input source and one hotkey table, and no public API splits any of them per environment (inference). Per-process input exists but is weak: the public per-pid event call reportedly delivers keys only when the app is in front or owns the menu bar (author claims); the working third-party version uses private window-server calls that still exist on macOS 27.0 (measured, laptop) and can change in any release; keys land in an app's key window, so two agents in one app take turns; drags, hover, canvas apps and modified clicks need the app in front; modifier state is system-wide. N environments in one session become turns on one input stream. The experiment uses this setup only as the positive control, the arrangement that must leak so the detectors can be shown to fire.
Why VMs lose on a Mac
Apple's licence allows up to two macOS virtual machines per Mac, and the virtualisation framework refuses a third with VZError code 6, virtualMachineLimitExceeded (vendor claim and first-hand reports). So VM-per-environment stops at two per Mac. Linux guests reportedly do not count toward the cap (third-party claim, not measured; we treat the Linux cap as unknown). The results table will carry a row "macOS VMs: cap 2 per host, not measured".
The licence, in plain words
- Two VMs per Mac. The licence allows "up to two (2) additional copies or instances" in virtual environments on each Apple-branded computer, for software development, testing during development, macOS Server, or personal non-commercial use. The framework enforces the cap regardless.
- One user at a time; no time-sharing even in-house. "Only one user may use the Apple Software at a time", and it may not be made available over a network where it could be used by multiple computers at the same time. Only one device may remotely control the displayed desktop session at a time; no "time-sharing, terminal sharing or other similar types of services, whether such services are being provided within your own organization or to third parties".
- Leasing. A lease must be the software in its entirety, for a minimum of 24 consecutive hours, with the lessee having sole use of the hardware, scoped to permitted developer services (continuous integration, building, automated testing during software development, developer tools); the lessor must notify Apple first. This is why hosted Mac prices are per day.
- Automation. No clause bans scripting, Accessibility or synthetic input (inference); the limits are on who controls sessions and what VMs may do.
Unresolved, and stated as such: whether RL training of computer-use agents is a permitted developer service (closest phrase: "automated testing during software development"); whether many agents driving GUI sessions on a Mac the operator owns is "one user at a time" or in-house "time-sharing" (the text assumes humans and remote desktops); whether the two-guest cap is universal. The experiment's not-claimed list says: "Not a license opinion. Run on a Mac we own; hosting for others is not supported by this result."
CGSession, and which macOS build says what
CGSession is the small helper that parks the console at the login window from a script. The harness used it in make park-console and checks for it at Gate 0.
- Measured on the Studio on 2026-10-22:
CGSessionis missing on macOS 15.7.5 (24G624). Gate 0 returned code 2. Earlier internal documents claimed it was present on macOS 15; that claim was wrong on this build, and the measured finding wins. - Measured on the development laptop: absent on macOS 27.0. Reported absent on 26 as well; we did not check 26.
- Consequence: the console is parked by hand (user-switching menu, then Login Window). The probes do not use it. Whether Screen Sharing survives a manual park is untested.
Related version facts: the per-session daemon layout above was measured on 27.0, not on 15.7.5; the private window-server input symbols still exist on 27.0 (measured, laptop); the older window-capture API is obsoleted at 15.0 in the SDK and reportedly returns gray on 27 betas; the user privacy database moved on macOS 27. One third-party report wrote privacy grants by file on macOS 26.3; an Apple staff forum reply says on 27 grants come only from System Settings or device management, and our 27 machine matched. We plan on manual clicks.
Measured primitives (laptop, not Studio)
| Primitive | Measurement | Where |
|---|---|---|
| APFS clone of a 20,000-file, 78 MB tree | 2.27 s clone, 4.72 s plain copy, 0.8 s delete | M2 8 GB laptop, macOS 27.0 (measured) |
| Cloning out of a snapshot | silently made a full copy | laptop (measured) |
| Chrome, fresh profile, one tab | 580 to 614 MB footprint | laptop (measured) |
| Two fresh Chromes | shared 483 MB of code pages, almost no written memory | laptop (measured) |
| Safari | 57 to 89 MB | laptop (measured) |
| Electron apps | 332 MB (author claim) to 804 MB (measured) | laptop |
| Finder alone | 241 MB footprint | laptop (measured) |
| LibreOffice | no trusted number | |
| Window screenshot | 89 ms p50, 108 ms p95 on one M-series Mac | vendor claim |
Capacity arithmetic from these numbers (about 50 Chrome-class environments per 48 GB machine before idle-session cost, shrinking to about 10 to 30 under real pages and screenshots) is inference from laptop measurements and is not published as a result. The experiment reads vm_stat and memory pressure rather than summing per-process figures, because summed footprints count compressed pages at full size.
Reset estimate: "1 to 3 s for a real Chrome or LibreOffice profile" is an estimate; no real profile was timed. For scale, the published desktop VM reset bar is 37.2 s p50 and 100.1 s p95 including queueing (MAI-Gym, author-reported).
What is open
| Unknown | Known today | What settles it (design) |
|---|---|---|
| Session cap | one administrator ran 3 to 5 and guessed about 10 (author claim) | log in accounts until the first refusal, up to 32 |
| Memory per idle session | unknown | WindowServer footprint and memory pressure per login |
| Login without a human | no public API (inference) | not needed: one manual login per account per boot |
| Painting in a background session | switched-out processes keep drawing (vendor claim); Chromium and Electron stop painting when they think they are hidden (vendor claim) | at least 55 distinct frames of 60 from at least one Chrome configuration |
| Privacy grants per user | tccd per session (measured); device management can deny but not grant Screen Recording (vendor claim); macOS 15 re-asks monthly (author claim) | grant for the first account, see whether the second prompts |
| Leaks between sessions | own pasteboard and event stream per session; never tested with N at once | four sessions type and copy at once; each document and pasteboard holds only its own tag |
| Capture at scale | capture streams once stopped silently until replayd restarted (author claim) | screenshot p95 under 200 ms at N=1; stalls counted at every N |
The decision rule adopted from the internal devil's-advocate note: if macOS cannot clearly beat the same-Mac Linux arm on cost per valid rollout, macOS-first is dropped. Linux has none of the licence limits, which is one reason the Linux arm exists.