Mac Commands
Barn 0.9.0 release candidate; unreleased. This page describes the renamed
barn mac, which uses fresh Barn state and provides no development-state
migration. Earlier native records are retained in Status
and do not establish the same acceptance for the renamed build. Check the
barn mac --help of the binary you run.
barn mac requires Apple Silicon and macOS 27 or later, and runs as the
logged-in user; it refuses to run as root. On other hosts the command is
hidden, and commands that need the Mac component fail with
mac_host_unsupported. Bare barn mac is barn mac ls.
Commands
| Command | Purpose |
|---|---|
ls |
every machine with state, address, SSH, macOS, resources and shares; aliases list, status, st |
up [name] |
create the machine if needed, start it, wait for SSH and sudo |
start [name...] |
start existing machines |
stop [name...] |
shut down normally; power off after two minutes |
restart [name] |
stop, then start, applying configuration changes |
open [name] |
show the desktop, starting the machine first if needed |
ssh [name] |
interactive shell, or, after --, a command line for the guest shell |
exec [name] -- cmd |
run a command, keeping argument boundaries |
configure name |
change a machine’s settings |
recreate name |
replace the machine with a fresh macOS, keeping its settings |
destroy name... |
delete machines |
password [name] |
show or copy the login password |
ssh-config |
print, install or remove the OpenSSH entries |
logs [name] |
recent runtime log |
setup |
prepare the macOS base without creating a machine |
image ls |
restore images and bases with the machines using them; alias list |
image update |
prepare Apple’s newest macOS 27 as the default base |
image prune |
list, and with --yes delete, unused images |
doctor |
check the host, the component, the base and every machine |
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 --force -n/--no-wait |
destroy |
--force |
password |
-c/--copy |
ssh-config |
-i/--install --remove |
logs |
-n/--lines (default 100, at most 10000) |
setup |
--ipsw --disk -y/--yes |
image update |
--ipsw -y/--yes |
image prune |
--installers -y/--yes |
A command without a machine name acts on the only machine, or on mac1; with
several machines and none named mac1, it asks for a name. start and stop
accept several names, or --all. destroy and recreate describe what they
delete and ask for the command name to be typed; --force confirms without a
terminal.
Flag values
| Flag | Value |
|---|---|
--cpu |
virtual CPUs, at least 2 and at most the Mac’s logical CPUs; default 4 |
--memory |
16G, 16GiB, 16GB or bytes; at least 4 GiB and at most installed memory; default 8 GiB |
--disk |
capacity of the base, at least 32 GiB; default the prepared base’s, 100 GiB. Another capacity installs another base |
--user |
administrator account; default your macOS user name, or barn when that is not a valid account name |
--share |
[name=]path[:ro|:rw], repeatable, at most 8; the name defaults to the last path component; ~/ expands to your home |
--clipboard |
on or off; default on |
--subnet |
a canonical private /24 such as 10.10.30.0/24, or auto for the first free one |
up refuses creation options that differ from an existing machine instead of
ignoring them, and its next: line names the fix. CPUs, memory, shares, the
subnet and the clipboard change with configure. The account and disk capacity
are fixed for a machine’s lifetime, and recreate keeps them: other values
need another machine. A different macOS comes from image update, then
recreate --update.
Machines
- Names: 1–32 lowercase letters, digits and inner hyphens, starting with a
letter:
mac1,dev,build-2. - Running limit: two macOS virtual machines per Mac, counting other tools and macOS installation. Barn never stops a machine to make room.
- Account: an administrator with passwordless sudo, SSH key login, desktop
automatic login and Remote Login. SSH password login is disabled. The login
password is random and stored in the machine’s
passwordfile. - Guest names: the computer name is the machine name; the local host name is
barn-<name>, so the guest answers asbarn-<name>.local. - Shares: one VirtioFS device mounted by macOS under
/Volumes/My Shared Files/<name>. Shares must be existing directories, not symlinks, and change only while the machine is stopped. - Clipboard: plain text, synchronized over the machine’s SSH connection when its window gains or loses focus; at most 1 MiB; items marked concealed are never sent.
- Stop: normal shutdown through macOS in the guest; if the machine is still
running after two minutes it is powered off and the result carries
"forced": true.--forcepowers off at once.
Networks
Each machine’s network is created by its own runner process when the machine starts and disappears when it stops. No daemon and no root is involved.
| Item | Value |
|---|---|
| Subnet | first free private /24 from 10.10.20.0/24 to 10.10.59.0/24, avoiding host routes and other machines; --subnet selects one |
| Gateway | .1, the Mac |
| Guest address | .10, by DHCP reservation for the machine’s MAC address |
| Reachability | the Mac and the internet through NAT; not other machines, not the LAN |
start refuses a subnet that a host route now overlaps, such as a VPN, with
reason mac_subnet_in_use. SSH host keys are pinned to the machine instance,
not its address, so configure --subnet keeps trust.
macOS Local Network privacy stops third-party programs from connecting to
these networks unless their app is allowed under Privacy & Security → Local
Network; the error is “No route to host”. Barn itself connects through
Apple’s /usr/bin/nc and /usr/bin/ssh, which are exempt.
JSON output
Every command honors --json and --yaml. Progress goes to stderr.
ls
| Field | Values |
|---|---|
state |
prepared (never booted to readiness), starting, running, stopping, stopped, unknown |
ready |
true only when this check reached the guest over SSH with sudo |
ssh |
ready, pending (first boot in progress), unavailable, offline, unchecked |
observed |
present when the guest reports another macOS build than its base |
window_visible |
present while the desktop window is shown |
error, warnings |
the last recorded failure, and SSH problems found by this check |
Lifecycle results
up, restart, open, recreate and configure return one result;
start, stop and destroy return {"machines": [...]}, one result per
machine, even for a single name.
| Field | Values |
|---|---|
action |
created, started, running (already running), restarted, recreated, opened, configured, stopped, powered_off, already_stopped, destroyed, absent |
forced |
true when a normal stop had to power the machine off |
window |
true when the desktop was shown |
warnings |
non-fatal follow-ups, such as a change that applies at the next start |
exec --json returns the same object as Linux barn exec --json: node is
the machine name, and exit_code, stdout and stderr come from the guest.
An interactive ssh has no JSON form.
Failures
Exit codes are the Barn CLI’s. A remote command’s own
exit status passes through ssh and exec unchanged. JSON failures carry a
stable reason and a next command:
| Reason | Exit | Meaning and next step |
|---|---|---|
mac_host_unsupported |
3 | not Apple Silicon, or older than macOS 27 |
mac_runner_missing |
3 | the Mac component is not installed next to the CLI |
mac_runner_protocol |
3 | CLI and component come from different builds; install them together |
mac_root |
2 | run as your normal login user, not with sudo |
mac_download_consent |
2 | downloading macOS needs --yes without a terminal, or use --ipsw |
mac_machine_absent |
4 | no machine by that name; barn mac up NAME |
mac_not_initialized |
4 | the machine has not finished its first boot; barn mac up NAME |
mac_not_running |
4 | ssh/exec need a running machine; barn mac start NAME |
mac_running |
4 | a change needs the machine stopped; barn mac stop NAME |
mac_configuration_conflict |
4 | up options differ from the existing machine; the named configure or recreate |
ssh_config_linked |
4 | ~/.ssh/config is a link; add the printed Include line yourself |
mac_vm_limit |
6 | two macOS VMs already run; stop the named one |
mac_subnet_in_use |
6 | a host route now overlaps the machine’s network; configure NAME --subnet auto |
disk_full |
6 | not enough free space to download or install macOS |
mac_machine_damaged |
7 | a machine that booted before lost disk or identity files; its directory is kept |
mac_readiness_interrupted |
130 | a stop interrupted a first-boot SSH wait |
Files
Runtime sockets live in /tmp/barn-mac-<uid>-<hash>/. ssh-config writes
~/.ssh/barn-mac_config and one # barn-mac:include block in
~/.ssh/config, independent of the Linux # barn:include block. The desktop
window positions are saved in ~/Library/Preferences/io.pgsty.barn.mac-runner.plist.
Inside the guest, Barn writes ~/.ssh/authorized_keys,
/private/etc/sudoers.d/80-barn, /etc/ssh/sshd_config.d/000-barn.conf,
the computer and local host names, and disables sleep with pmset.