Mac Runtime Reference
12 minute read
Running macOS guests requires an Apple Silicon Mac on macOS 27 or later, invoked as the logged-in desktop user. Commands that talk to the native runner reject root with mac_root and unsupported hosts with mac_host_unsupported. Top-level --help hides mac on Linux and Intel Macs, while local-state queries such as barn mac image ls work without invoking the runner. Running barn mac with no subcommand executes barn mac ls.
This reference covers the Barn 1.2.0 command interface and Barn.app, the native macOS app bundle that runs the VMs (runner protocol 2). The Apple Silicon release and Homebrew installation include the app; see macOS Guests.
For complete per-command syntax, options, and examples, see the macOS Command Reference. This page collects machine rules, networking, result formats, and state files.
Commands
| Command | Purpose |
|---|---|
ls |
List every VM with state, IP, SSH status, macOS build, resources, and shares (aliases: list, status, st) |
up [name] |
Create the VM if needed, start it, and wait for SSH and passwordless sudo |
start [name...] |
Start existing VMs |
stop [name...] |
Request a clean macOS shutdown, powering off after two minutes if still running |
restart [name] |
Stop and start a VM, applying any pending hardware, share, or subnet changes |
open [name] |
Open the desktop window, starting the VM first if needed |
ssh [name] [-- command...] |
Open an interactive shell, or pass a command string after -- to the guest shell |
exec [name] -- command... |
Execute a remote program while preserving argument boundaries |
configure name |
Update CPUs, memory, shares, or subnet while stopped; clipboard can change while running |
recreate name |
Replace a VM with a fresh macOS clone while keeping its hardware and network settings |
destroy name... |
Delete one or more VMs |
password [name] |
Print or copy the guest login password |
ssh-config |
Print, install, or remove ~/.ssh/barn-mac_config entries |
logs [name] |
Read recent lines from the VM’s runner.log |
setup |
Download and prepare the default macOS base image without creating a VM |
image ls |
List cached .ipsw restore files and prepared base images alongside the VMs using them (alias: list) |
image update |
Download and prepare Apple’s latest macOS 27 build as the default base image |
image prune |
List unused images, or delete them when --yes is passed |
doctor |
Check host eligibility, Barn.app, base images, and every VM slot |
SSH and exec
Remote commands require --, for example barn mac exec dev -- sw_vers. Interactive barn mac ssh dev needs no separator.
Before --, pass Barn flags and at most one existing VM name (omitting the name selects the sole VM or mac1). ssh without a command opens an interactive shell; exec requires a non-empty command after --. Unknown VM names or invalid arguments fail with exit code 2 (usage) before attempting a connection and point to barn mac ls.
ssh joins arguments after -- into a command string for the guest shell, whereas exec passes the program and arguments separately (preserving spaces, quotes, and subsequent empty arguments). Use sh -c '...' for pipelines, redirection, or compound commands. Put Barn flags (--json, -v, --help) before --; everything after -- belongs to the guest command.
For compatibility, exec also accepts a single command string as shell shorthand. In new scripts, pass separate arguments or use an explicit sh -c so the intended shell interpretation is clear.
Flags by command
| Command | Flags |
|---|---|
up |
--cpu, --memory, --disk, --user, --share, --clipboard, --subnet, --ipsw, -y/--yes, -n/--no-wait, --open |
start |
--all, -n/--no-wait, --open, --recovery |
stop |
--all, --force |
restart |
-n/--no-wait, --open |
configure |
--cpu, --memory, --share, --unshare, --clipboard, --subnet |
recreate |
--update, --yes/--force, -n/--no-wait |
destroy |
--yes/--force |
password |
-c/--copy |
ssh-config |
-i/--install, --remove |
logs |
-n/--lines positive integer (default 100); returns the requested line count |
setup |
--ipsw, --disk, -y/--yes |
image update |
--ipsw, -y/--yes |
image prune |
--installers, -y/--yes |
When a VM name is optional, omitting it selects the only existing VM or mac1; if multiple VMs exist and none is named mac1, Barn asks you to specify a name. start and stop accept multiple names or --all. On a terminal, destroy and recreate print what will be deleted and ask you to type the command name; --yes (or --force) skips the question and is required without a terminal. Neither command has a -y shorthand, and mac stop --force means immediate power-off.
--no-wait returns as soon as the VM process is running; for a newly created VM, run barn mac up NAME without --no-wait to finish SSH key installation and sudo setup. Ordinary start requires a VM that has completed its first boot—if an uninitialized VM is already running, use barn mac open NAME to view its first boot, or barn mac up NAME --open if it is stopped. Passing --recovery boots directly into the macOS Recovery desktop without waiting for normal SSH readiness.
Flag values
| Flag | Value |
|---|---|
--cpu |
vCPU count: at least 2 and at most the Mac’s logical CPU count (default 4) |
--memory |
Memory size in binary units (16G, 16GiB, 16GB) or exact bytes; must be a whole MiB between 4 GiB and host RAM (default 8 GiB) |
--disk |
Base image disk capacity, minimum 32 GiB (defaults to the prepared base image’s capacity, or 100 GiB for the first base image; requesting another size installs a matching base image if needed) |
--user |
Guest administrator username (defaults to your host macOS username, or barn if the host name is not a valid account identifier) |
--share |
[name=]path[:ro|:rw], repeatable; name defaults to the last path component and ~/ expands to your home directory |
--clipboard |
on or off (also accepts true/false, yes/no; default on) |
--subnet |
Canonical private /24 such as 10.10.30.0/24, or auto for the first free subnet |
If you run up on an existing VM with creation flags that differ from its recorded settings, up exits with mac_configuration_conflict and prints the exact configure or recreate command in next::
- Use
barn mac configurewhile the VM is stopped to change--cpu,--memory,--share/--unshare,--subnet, or--clipboard(clipboard changes can also be saved while the VM is running and take effect on the next start; use the menu bar item to toggle clipboard sync for the active session). Share names may contain spaces and Unicode, must be valid UTF-8 of 1–255 bytes, and cannot be.,.., or contain/or ASCII control characters; reusing a share name inconfigure --shareupdates its path and mode, while--unshareremoves that share. - The guest administrator account (
--user) and disk capacity (--disk) are fixed for the lifetime of a VM and preserved acrossrecreate. Create a new VM if you need a different account or disk size. - To upgrade a VM to a newer macOS build, run
barn mac image updatefollowed bybarn mac recreate NAME --update. Becauserecreate --updatepreserves the VM’s disk capacity, if the new macOS build does not yet have a base image at a custom disk size (for example,200G), prepare it first withbarn mac setup --disk 200G.
Machines
- Names: 1–32 characters starting with a lowercase letter and containing lowercase letters, digits, or internal hyphens (for example
mac1,dev,build-2). - Two-VM host limit: Apple’s Virtualization framework allows at most two macOS VMs to run simultaneously on a single Mac across all apps (including an active
.ipswbase-image installation). Barn never stops a running VM to make room for another.ls.runningcounts VMs in the currentBARN_HOME, while Apple’s framework enforces the host-wide limit. - Administrator account: Configured with passwordless sudo, Ed25519 SSH key authentication, automatic desktop login, and Remote Login enabled. SSH password authentication is disabled, and the random local password is saved in the VM slot’s
passwordfile (0600). - Hostnames: The guest ComputerName matches
<name>and LocalHostName isbarn-<name>(barn-<name>.local). - Shared folders: Mounted inside the guest via a single VirtioFS device at
/Volumes/My Shared Files/<name>. Each host source must resolve to an existing directory; symlinks are supported. Names accept spaces and Unicode. - Clipboard sync: Syncs plain text up to 1 MiB over the VM’s SSH connection whenever the desktop window gains or loses focus, skipping pasteboard items marked concealed.
- Shutdown:
barn mac stoprequests a clean guest shutdown and waits up to two minutes before powering the VM off ("forced": true);--forcepowers off immediately.
Networks
Each VM’s runner process creates an isolated user-space network at startup and tears it down on exit—without root privileges or a background daemon—using Apple’s shared-mode vmnet API:
| Item | Value |
|---|---|
| Subnet | First free /24 from 10.10.20.0/24 through 10.10.59.0/24 that avoids host routes and other VMs (or an explicit --subnet) |
| Gateway | .1 on the Mac host |
| Guest IP | .10, assigned via a vmnet DHCP reservation for the VM’s MAC address |
| Topology | Host-to-guest routing and outbound NAT per VM subnet, with no LAN bridging or inbound port forwards |
If a newly added host route (such as a VPN) overlaps the VM’s saved subnet, start refuses to boot with mac_subnet_in_use; run barn mac configure NAME --subnet auto to move the VM to a free subnet. Because Barn pins SSH host keys to barn-mac-<instance_id> rather than the IP address, changing subnets keeps SSH trust intact.
If macOS Local Network privacy blocks a third-party terminal or IDE from reaching the guest subnet (often surfacing as No route to host), enable that app under System Settings → Privacy & Security → Local Network. Barn routes its own Go SSH transport through /usr/bin/nc and invokes /usr/bin/ssh for user sessions so Apple system binaries handle the local-network socket directly.
JSON output
All barn mac commands except interactive ssh support --json and --yaml on stdout while writing progress to stderr.
ls
| Field | Values |
|---|---|
state |
prepared (created, never completed first boot), starting, running, stopping, stopped, unknown |
ready |
true when this check verified guest SSH connectivity and passwordless sudo |
ssh |
ready, pending (first boot in progress), unavailable, offline, unchecked |
observed |
Present when the running guest reports a macOS build different from its base image |
window_visible |
Present while the VM’s desktop window is open |
error, warnings |
Last recorded failure on the slot and any SSH issues detected during this check |
Lifecycle results
Single-machine operations (up, restart, open, recreate, configure) return a single machine result object, while batch operations (start, stop, destroy) return {"machines": [...]} even when called with one name. If a multi-VM batch partially fails, the response includes both the succeeded entries and the failures and exits 5.
| Field | Values |
|---|---|
action |
created, started, running (already running), restarted, recreated, opened, configured, stopped, powered_off, already_stopped, destroyed, absent |
forced |
true when stop timed out and powered off the VM |
window |
true when the desktop window was opened |
warnings |
Non-fatal notices, such as a clipboard change that takes effect on next start |
Other structured responses:
exec --json: Returns the same schema as Linuxbarn exec --json(node,exit_code,stdout,stderr).password --json: Returns the password, or{"name": "mac1", "copied": true}when combined with--copy.ssh-config --json: Returnsfragmentwhen printing, or installation status when combined with--install/--remove.logs --json: Returnsnameandlogs.doctor --json: Returnsokandchecks[](name,ok,detail, and optionalnext), exiting3if any check fails.
Failures
Exit codes follow the Barn CLI exit code table, and ssh/exec pass through the remote command’s exit status. Structured error objects include stable reason codes and a next recovery command:
| Reason | Exit | Meaning and next step |
|---|---|---|
mac_host_unsupported |
3 |
Host is not Apple Silicon or is running macOS older than 27 |
mac_runner_missing |
3 |
Barn.app / native runner is not installed alongside the barn CLI |
mac_runner_protocol |
3 |
Installed Barn.app uses a different runner protocol version; reinstall matching CLI and app builds |
mac_root |
2 |
Invoked as root; run as the logged-in desktop user without sudo |
mac_download_consent |
2 |
Non-interactive macOS download requires --yes (or supply a local file with --ipsw) |
mac_machine_absent |
4 |
Named VM does not exist; create it with barn mac up NAME |
mac_not_initialized |
4 |
VM has not finished its first boot; complete initialization with barn mac up NAME |
mac_not_running |
4 |
ssh or exec called on a stopped VM; run barn mac start NAME |
mac_running |
4 |
Requested configuration change requires the VM to be stopped; run barn mac stop NAME |
mac_configuration_conflict |
4 |
up flags differ from the existing VM; run the suggested configure or recreate command |
ssh_config_linked |
4 |
~/.ssh/config is a symlink or hard link; add the printed Include line manually |
mac_vm_limit |
6 |
Two macOS VMs are already running on this Mac; stop the reported VM first |
mac_subnet_in_use |
6 |
A host route overlaps the VM’s subnet; run barn mac configure NAME --subnet auto |
disk_full |
6 |
Insufficient free disk space to download or install the macOS base image |
mac_machine_damaged |
7 |
An initialized VM slot is missing its disk or identity files (the slot directory is preserved for inspection) |
mac_readiness_interrupted |
130 |
barn mac stop interrupted a first-boot SSH readiness wait |
Files
$BARN_HOME/mac
- config.jsonInstallation identity, default base image, and ssh_config_off flag
images/
ipsw/
- <build>.ipswCached Apple restore image (.partial while downloading)
- <build>.ipsw.jsonRestore image metadata and digest
base/
- <id>/Read-only, unbooted macOS base image bundle
slots/
<name>/
- state.jsonMachine record (schema 2)
- disk.asifCopy-on-write APFS disk layer cloned from the base image
- machine-id.binApple Virtualization machine identifier
- auxiliary-storage.binNVRAM / boot auxiliary storage
- id_ed25519Per-VM SSH private key
- id_ed25519.pubPer-VM SSH public key
- known_hostsPinned guest host key under barn-mac-<instance>
- passwordGenerated guest login password (mode 0600)
- runner.logPer-VM runtime log read by barn mac logs
- runtime/Global state lock and per-machine operation locks
Additional host and guest paths:
- Control sockets:
/tmp/barn-mac-<uid>-<hash>/. - OpenSSH fragment:
barn mac ssh-configmanages~/.ssh/barn-mac_configand a# barn-mac:includeblock in~/.ssh/config(independent of the Linux# barn:includeblock). Runningbarn mac ssh-config --removesetsssh_config_offinconfig.jsonso subsequent lifecycle commands do not re-add theIncludeblock until you runbarn mac ssh-config --install. - Desktop preferences: Barn stores window positions in
~/Library/Preferences/com.pgsty.barn.plist(0.9.0used~/Library/Preferences/io.pgsty.barn.mac-runner.plist). - Runner discovery: The
barnCLI locates the runner relative to its resolved binary path across app bundle (Barn.app/Contents/MacOS/barn-mac-runner), pkg installer, and Homebrewlibexeclayouts, or viaBARN_MAC_RUNNERwith an absolute path, relative path, or~/path. Before executing VM operations, the CLI verifies runner protocol2;barn mac doctoralso verifies the runner’s local code signature. - Guest configuration files: Inside the macOS guest, Barn writes
~/.ssh/authorized_keys,/private/etc/sudoers.d/80-barn, and/etc/ssh/sshd_config.d/000-barn.conf, configuresComputerNameandLocalHostName, and disables idle sleep viapmset.
Image pruning keeps base images that interrupted recreates still reference until recovery cleanup finishes. A malformed recovery journal stops barn mac image ls, the space estimate in barn mac doctor, and pruning until it is repaired, and every image stays in place. If one machine’s state cannot be read, barn mac ls fails for all machines, while commands that name the other machines keep working.