MacVisor can keep a VM running without you watching it, in three ways. Each is set per VM, and each is off until you turn it on.
| Acts when | Restarts at most | Set in | |
|---|---|---|---|
| High availability | The VM crashes, stops with an error, or fails to start | 10 times an hour | VM Settings → General → Startup, mvz ha |
| VM Watchdog | The guest stopped responding, as MacVisor's guest agent reports it, or the guest's QEMU guest agent where MacVisor's can't run | 3 times a day (Normal), once (Low) | Under High Availability, mvz ha --watchdog |
| Health check | A command of yours keeps failing: your service stopped answering | Once a day | VM Settings → Advanced → Health Check, mvz hooks <vm> check |
VM Watchdog acts only while high availability is on, and needs MacVisor's guest agent or a QEMU guest agent in the VM. A health check's restart works with or without high availability.
When to use what
| You want | Use |
|---|---|
| The VM back after a crash or a failed start | High availability |
| To know when a service in the VM stops answering | A health check without restart, with a When It Fails, Run command that tells you |
| The VM restarted when its service stays down | A health check with Restart the VM when it keeps failing |
| A frozen guest restarted, without writing a check | VM Watchdog, with high availability |
| To be told when a VM stops, for any reason | An After the VM Stops hook, or mvz events --follow |
| An appliance shut down its own way | A shutdown command |
High availability
With high availability on, MacVisor's background service starts the VM again when:
- it crashes: the VM's process ended while it ran;
- it stops with an error from Virtualization;
- it fails to start.
Turn it on in VM Settings → General → Startup → High Availability, for every VM at once in Settings → VMs, or with mvz ha <vm> on. A VM with it on carries an HA badge in the VM list and HIGH AVAILABILITY beside its name on the Overview. It's independent of Start at Login: it watches the VM from the moment it runs. Templates can't have it.
mvz ha web on
mvz ha web # what it's set to, and what VM Watchdog is doing
mvz ha web off
Timing and limits
- The wait before each restart is 5 seconds, then 15, 30, 60, 120 and 300 seconds, and 300 from there on.
- A VM that ran for 10 minutes before it stopped starts the waits afresh, at 5 seconds.
- No more than 10 restarts in an hour. After the tenth, high availability gives up and the VM stays stopped. Tasks says so: High availability gave up on "web",
"web" crashed again after 10 restarts within an hour, so it stays stopped. Start it yourself once it's fixed: high availability watches it again from then.Starting it yourself counts its restarts afresh, so a crash later in that hour is restarted again. - The VM comes back the way it was last started, with its window or without. A suspended session is resumed.
Each restart is listed in Tasks and Task History as Restarted by high availability: "web", with the attempt and the reason: Attempt 2: it crashed. mvz events lists them as ha-restart and ha-gave-up.
When the background service restarts
High availability keeps its promise across restarts of MacVisor's background service: an app update, mvz service restart, or a crash of the service. VMs keep running meanwhile, in their own processes, and the service remembers its restarts and their count for the hour on disk:
- a restart that was waiting its turn when the service stopped is still made, after the same wait;
- a VM that crashed while the service was away is listed as "web" stopped unexpectedly in Tasks, and started again under the same limits.
It doesn't bring VMs back after you log out or restart the Mac, which are stops you meant. Use Start at Login for that.
Stops you ask for
High availability never starts a VM again after a stop someone meant:
- Shut Down, Power Off, Suspend and the stop half of Restart, from the app, the menu bar, the window or
mvz; - a shutdown from inside the guest, and a reboot from inside the guest that ends the VM;
- reverting to a snapshot, and moving the VM to the Trash;
- the Mac logging out or shutting down.
Any of these also calls off a restart that's waiting its turn, as does starting the VM yourself.
High availability only sees the VM's process. A guest that has frozen inside a running VM, or whose service has stopped, looks fine to it. That's what VM Watchdog and health checks are for.
VM Watchdog
VM Watchdog restarts a VM whose guest stops responding, as MacVisor's guest agent reports it, with no check to write. In a guest that can't run MacVisor's agent but has a QEMU guest agent, such as Home Assistant OS, the QEMU guest agent's answers are its heartbeats instead. It needs one of the two in the VM. It's off by default, and acts only while high availability is on.
Turn it on in VM Settings → General → Startup: VM Watchdog shows under High Availability while that's on, with a Sensitivity. Or with mvz ha:
mvz ha web on --watchdog # Normal sensitivity
mvz ha mac on --watchdog low
mvz ha web --no-watchdog
--monitoring and --no-monitoring, its earlier names, still work.
| Normal (default) | Low | |
|---|---|---|
| Not responding for this long before a restart | 10 minutes | 30 minutes |
| Never in the first … after a start or restore | 10 minutes | 20 minutes |
| Restarts at most | 3 in 24 hours | 1 in 24 hours |
There's no faster setting: a restart is a last resort. AI sandboxes and templates can't have VM Watchdog.
What it watches
MacVisor watches for two signs that a guest has stopped responding. It shows them, and mvz events lists guest-not-responding and guest-responding, whether VM Watchdog is on or not.
A macOS guest's screen not responding. The MacVisor Agent checks every 30 seconds that the guest's WindowServer still answers. It reads no window names and needs no Screen Recording permission, so it raises no prompt. When WindowServer doesn't answer while the agent's heartbeats keep arriving, the guest's kernel, network and agent are fine, but its screen and apps have stopped. The Overview's Guest Tools card says Guest screen not responding since 11
AM.A guest gone silent. For any guest with the MacVisor Agent: its heartbeats stopped, and the VM has done almost no disk or CPU work for 2 minutes since. A guest that's rebooting, updating or busy reads and writes the disk and uses CPU, so it doesn't count. The card says Guest not responding since 11
AM.The QEMU guest agent as heartbeats. While MacVisor's agent isn't connected, each answer from a guest's QEMU guest agent counts as a heartbeat, an error too: a guest frozen for a backup refuses most commands but is alive. When it stops answering, the same rule decides. While MacVisor's agent is connected, the QEMU guest agent's answers are ignored. Before a restart, a guest that still answers a ping on its address isn't restarted: one whose QEMU guest agent simply isn't running (Home Assistant OS doesn't start it on MacVisor yet) stays up.
mvz show <vm>has a Guest status row that says the same, and--jsonaguestLivenessobject.- A pause, a suspend, a restore, a snapshot, a gap in the heartbeats or a disconnect starts both counts again. The Mac's sleep isn't counted: a silence that began before it goes on from the wake, and a guest that doesn't answer after the wake is silent from then.
- Before restarting a silent guest, MacVisor checks whether it answers another way: its QEMU guest agent, or a ping to its address, which MacVisor knows also while the app is closed. If either answers, it isn't restarted, and the card says VM Watchdog didn't restart it: its agent is silent, but the guest answers.
- A guest without the MacVisor Agent gives neither sign. Use a health check on this Mac for it.
Its limits
- Restarts per day by sensitivity, counted together with the health check's. Once the limit is reached, MacVisor only reports, until someone starts or restarts the VM from MacVisor or
mvz, which lifts it. The card says VM Watchdog won't restart it again yet: the limit is one restart in 24 hours (a Start or Restart from MacVisor or mvz lifts it). - Not while you're using its window, as for health checks: restart postponed: you're using its window.
- One VM at a time, one per 10 minutes across all VMs.
- After the Mac wakes, a guest's silence is measured from the wake, so one that never answers again is restarted after the usual time, not at once.
The Overview's High Availability card says what it will do: VM Watchdog restarts it at 11
AM if its guest still isn't responding, VM Watchdog is restarting it now, and afterwards Restarted by VM Watchdog at 11 AM; next allowed after 3 PM.mvz ha <vm> says it in words too:
High availability is on for web: it's started again when it crashes, stops with an error or fails to start; a stop you ask for is honoured.
VM Watchdog is on for web (normal sensitivity): MacVisor restarts it when its guest has stopped responding for 10 minutes, at most 3 times a day, and not while you're using its window.
VM Watchdog now: restarts it at 11:45 AM if its guest still isn't responding.
mvz ha <vm> --json has highAvailability, vmMonitoring (enabled, sensitivity) and, while the VM runs, monitoringStatus.
Evidence
Before it restarts a VM, VM Watchdog saves what it can to MacVisor's logs folder, ~/Library/Application Support/MacVisor/logs/, within a minute in all:
- The VM's last frame, if its window is open:
<VM id>-monitoring-<time>-frame.png. - A spindump of the guest, for a macOS guest whose screen stopped responding, over SSH with passwordless
sudo:<VM id>-monitoring-<time>-spindump.txt, at most 64 MB. It's taken withsudo -n spindump -notarget 5 -stdoutand written straight to the Mac, with no file in the guest. Without passwordless sudo it's skipped, and the evidence says why. - What the agent last reported, in the VM's hooks.log, with the names of the files.
<time> is in UTC, such as 20261102-113500. The newest six evidence files of each VM are kept. The restart's task names them: Evidence in MacVisor's logs folder: ….
Health checks
A health check is one command per VM that exits 0 while the VM is healthy. MacVisor runs it every so often while the VM runs. When it has failed for long enough, it can run a command of yours and, with Restart the VM when it keeps failing, restart the VM, with or without high availability.
Where it runs
| Runs | How | Needs |
|---|---|---|
| On This Mac (the default) | Like a hook, with MVZ_EVENT=check and MVZ_HOOK=check | Nothing in the guest. Use it for appliances, and for anything you can test from outside, such as a web page. |
| In the VM | In the guest over SSH, as mvz exec runs a command | SSH into the VM: Remote Login on a macOS guest, an SSH server and your keys elsewhere |
A check on this Mac that reaches the VM's address needs MacVisor's Local Network access, as any app does. Without it every run fails with "No route to host": see No route to host. Name the VM as <vm>.mvz, or by "$MVZ_IP", the address MacVisor last learned for it. MacVisor learns it also while the app is closed: see What a hook gets.
Timing
- Interval: 30 to 3600 seconds, 60 by default.
- Time limit of a run: 30 seconds, or the interval less 5 seconds if that's shorter.
- Only while the VM runs. A run still going when the next is due is skipped.
- After a start or a restore, the first run waits 15 minutes for a check on this Mac and 10 for a check in the VM, so a booting guest isn't judged. A resume from a pause isn't a start.
Passed, failed, or can't run
| Result | When | Counts |
|---|---|---|
| Passed | Exit 0 | Ends a run of failures |
| Failed | Any other exit status, or the time limit | Toward the failure time |
| Can't run | In the VM: SSH couldn't connect or sign in, or Remote Login is off. On this Mac: the command couldn't be started. A command in the VM that exits 255, as ssh does, counts as can't run too. | Neither: it starts the count again |
Failures count from the first one, as long as they come one after another:
- Any change in the VM's state starts the count again, and so does a gap between runs, such as the Mac sleeping.
- In the VM, a failure only counts while the MacVisor Agent's heartbeats keep arriving, so the guest is otherwise up. A reboot, an update, a pause or the agent reconnecting starts the count again, and the status says why the failure wasn't counted. In a VM without the agent, failures count as on this Mac.
After 20 minutes of failures on this Mac, or 10 in the VM, the check has failed: its When It Fails, Run command runs, once, whether or not the check restarts the VM, so it can tell you. mvz events lists check-failed then, and check-recovered at the next pass.
Restarting the VM
With Restart the VM when it keeps failing on (--restart), MacVisor restarts the VM once the check has failed for those 20 or 10 minutes. High availability doesn't need to be on.
- At most once a day per VM: one restart in 24 hours, counted together with VM Watchdog's. After that the check only reports, until someone starts or restarts the VM from MacVisor or
mvz, which lifts the limit. - Not while you're using the VM: while its window is in front, MacVisor is the active app and the Mac has had keyboard or pointer input in the last 10 minutes, the restart is postponed, not dropped, and the status says so: restart postponed: you're using its window.
- One VM at a time: across all VMs, MacVisor restarts one VM per 10 minutes, health checks and VM Watchdog together. A problem on the Mac's side, such as its network or a NAS the checks probe, fails every check on this Mac at once, and restarting every VM wouldn't fix it. The status says MacVisor restarted another VM a moment ago, and restarts one VM at a time.
- Checked again right before: the VM is still running in the same boot, the check is unchanged and still set to restart, and MacVisor isn't busy with the VM.
See What a restart does.
Set it in VM Settings
VM Settings → Advanced → Health Check, above Hooks:
- Command: with the hint "Command that exits 0 while the VM is healthy". Test runs the saved check once now, where it would run, and shows the result. It isn't counted. The status line under it says how the check is doing.
- Runs: On This Mac or In the VM.
- Interval: seconds between runs.
- Restart the VM when it keeps failing: "At most once a day, and not while you're using its window."
- When It Fails, Run: a command run on this Mac once the check has failed, with its own Test. It runs like a hook, with
MVZ_EVENT=check-failed.
The fields under the command show once there's a command, or a When It Fails, Run command set with mvz, so nothing is ever hidden. Changes save by themselves. Emptying the command removes the check.
Set it with mvz hooks
mvz hooks web check set 'curl -fsS -m 10 http://web.mvz/health' --interval 60 --restart
mvz hooks db check set 'systemctl is-active --quiet postgresql' --in-guest
mvz hooks web check set --interval 120 # change only the interval
mvz hooks web check set --on-fail 'curl -fsS -m 10 -d "$MVZ_VM_NAME is unhealthy" https://ntfy.sh/my-vms'
mvz hooks web check set --no-on-fail # run nothing when it fails
mvz hooks web check # the check and how it's doing
mvz hooks web check test # run it once now; not counted
mvz hooks web check remove
- On a VM with no check,
check setneeds the command, and what you leave out is the default: on this Mac, every 60 seconds, no restart. Options alone are refused: "web has no health check to change, so check set needs its command: …". - On a VM that has a check,
check setchanges only what you give, a new command,--in-guestor--on-mac,--interval N,--restartor--no-restart, and keeps the rest.check set --interval 120keeps the command and the restart, andcheck set --no-restartturns the restart off. With nothing to change it's refused. --on-fail "<command>"sets the command run when the check has failed (the When It Fails, Run field, thecheck-failedhook), and--no-on-failremoves it. Given alone, they leave the check as it is.--in-guestwith--on-mac, or--restartwith--no-restart, is refused: "Give --restart or --no-restart, not both." Put--before a command that starts with an option.
mvz hooks <vm> check, the Hooks list and mvz show say how it's doing, for example:
check every 60 s on this Mac, restarts it when it fails: curl -fsS -m 10 http://web.mvz/health
failing since 1:12 PM (exit 7: curl: (7) Failed to connect to web.mvz port 80); restart postponed: you're using its window
Other states read first run at 1:27 PM, after the VM's start, passing (last run 1:30 PM), can't run: …, not counted: the guest agent's heartbeats stopped, and restarted at 1:32 PM; next allowed after Nov 3, 1:32 PM. The Overview's High Availability card, under Guest Tools, shows the same in a line such as Health check failing since 1
Example checks
| Checks that | Command | Runs |
|---|---|---|
| A web service answers | curl -fsS -m 10 http://web.mvz/health | On This Mac |
| A port is open | nc -z -G 5 db.mvz 5432 | On This Mac |
| A Linux service is up | systemctl is-active --quiet postgresql | In the VM |
| A process exists | pgrep -x nginx | In the VM |
| A log is still being written, so the work goes on | find /var/log/jobs/run.log -mmin -15 | grep -q . | In the VM |
A check of a log that must keep changing catches a guest whose work has stopped, whatever hung, on any OS. On macOS, find ~/Library/Logs/job.log -mmin -15 | grep -q . does the same.
What a restart does
A health check's and VM Watchdog's restarts go through MacVisor's own Restart:
- The evidence goes to the VM's hooks.log: the reason, since when, and the check's last output or the agent's last report. Tasks shows Restart "web":
Waiting for the guest to shut down: its health check had failed since 1:12 PM. - The guest is shut down, its own way if it can be:
- with the VM's shutdown command, if it has one;
- else, for a check in the VM of a Linux or FreeBSD guest (or a macOS guest whose agent isn't connected), and for a macOS guest whose screen stopped responding, with
sudo -n shutdown -h nowover SSH (-pon FreeBSD), which needssudowithout a password; - else, or if that's refused, with MacVisor's usual Shut Down.
- After 3 minutes, a guest that's still running is looked at:
- a silent guest is powered off;
- one that does almost no disk or CPU work over the next 30 seconds is taken as hung and powered off;
- one that's still at work, such as installing updates as it shuts down, is never powered off. It gets up to 10 minutes in all, as any Restart does. If it still hasn't stopped, MacVisor leaves it running and Tasks says
"web" didn't shut down within 10 minutes, so it wasn't restarted or powered off: it was still at work. Shut it down or power it off, then start it again.
- The VM starts again, with its window or without, as it was started. If the start fails and high availability is on, high availability tries again, within its limits.
- Tasks says why, and macOS shows a notification:
Restarted "web": its health check had failed since 1:12 PM; it was powered off after its shutdown didn't finish.The reason reads "its screen had stopped responding" or "it had stopped responding" for VM Watchdog.
The restart isn't a stop you asked for, so high availability's own counts stay as they are. A Cancel of its task before the VM starts again leaves the VM shut down.
What it risks
A restart is meant for a VM that has stopped working anyway, but it can still cost you:
- Power Off loses what the guest hadn't saved. Unsaved documents are gone, and files open for writing, such as a database's, may need recovery at the next start, or may be damaged. MacVisor powers off only a guest that's idle or silent after 3 minutes, never one still at work.
- A check that tests the wrong thing restarts a healthy VM, once a day. Run a new check without Restart the VM when it keeps failing for a few days first, with a When It Fails, Run command that tells you, and turn restarting on once it only fails when it should.
- A problem on the Mac's side fails every check on this Mac: its network, Local Network access, or a NAS a check probes. MacVisor restarts one VM per 10 minutes, so this is slow, but not stopped.
- A guest that was about to recover is restarted anyway. VM Watchdog's waits (10 or 30 minutes, after a grace of 10 or 20) are long for that reason; choose Low for a guest that's sometimes slow.
For a VM whose data matters, such as a database server, prefer a check that only tells you, and keep snapshots and backups.
Troubleshooting
A VM restarted by itself
Find out who restarted it:
- Tasks and Task History. Restarted by high availability: "web" with the attempt and the reason ("it crashed", "it stopped with an error", "it didn't start"), or Restarted "web" with the health check's or VM Watchdog's reason.
mvz events webshowsha-restart, orstopped (restart)thenstartedfor a health check's or VM Watchdog's restart, while the service remembers them.- The VM's hooks.log has a
watchdog: restarting the VMentry with the evidence, for a health check's or VM Watchdog's. - The service log (
mvz service logs --tail 200) has lines that startHigh availability:,Watchdog:orVM Watchdog:.
To stop it happening again, turn off the part that acted: mvz ha <vm> off, mvz ha <vm> --no-watchdog, or mvz hooks <vm> check set … --no-restart.
Reading hooks.log
~/Library/Application Support/MacVisor/logs/<VM id>-hooks.log has every hook run, every failed check run and the first pass after failures (passes alone aren't written), checks that couldn't run, and each restart's evidence:
2026-11-02T12:32:10.412Z watchdog: restarting the VM: its health check had failed since 2026-11-02T12:12:04.950Z
evidence:
…
Times are in UTC. mvz show <vm> --json | jq -r .id gives the VM's id.
Guest screen not responding
The guest's WindowServer hasn't answered the MacVisor Agent since that time, while the rest of the guest is fine: SSH, mvz exec and the network still work, but the screen and apps don't move.
- If you want to report it, take a spindump first: in
mvz shell <vm>, runsudo spindump -notarget 5 -file /tmp/spindump.txt, and copy the file out. - Restart the VM. Its Shut Down may not finish, since its apps can't quit: in
mvz shell <vm>, runsudo shutdown -r now, or use Power Off if nothing in it needs saving. - If it happens again, turn on VM Watchdog for the VM, so it's restarted with the evidence saved.
Guest not responding
The agent's heartbeats stopped and the VM is doing almost no work. Look at its window or its console: a guest at a kernel panic or a firmware screen looks like this. If nothing responds, Power Off and start it again.
Health check can't run
The status says why, such as Health check can't run: SSH couldn't connect to the guest or sign in, or can't run: Remote Login is off in web. Fix SSH, then try the check by hand: mvz exec <vm> '<command>', and mvz hooks <vm> check test.
A restart doesn't come
The Overview's High Availability card, mvz ha <vm> or mvz hooks <vm> check says why:
| It says | What to do |
|---|---|
| restart postponed: you're using its window | Nothing: it restarts once you've been away from the window for 10 minutes |
| MacVisor restarted another VM a moment ago, and restarts one VM at a time | Nothing: it waits its turn |
| VM Watchdog restarts the VM only while High Availability is on | mvz ha <vm> on |
| won't restart it again yet: the limit is … | Restart the VM yourself, which lifts the limit |
| MacVisor is busy with the VM (…) | Wait for that task to finish |
| VM Watchdog didn't restart it: its agent is silent, but the guest answers | The guest isn't hung. Look at it, or restart it yourself |
| MacVisor's record of watchdog restarts … can't be read | Fix ~/Library/Application Support/MacVisor/watchdog-restarts.json, or move it to the Trash |
See also VM hooks and Always-on host.
DeltaSync