Supervisor

Apple's container runtime supervises nothing. There is no --restart flag, no policy that brings a crashed service back, and nothing that keeps the engine itself alive. If a container dies, it stays dead until you notice.

The Supervisor is Runbay's app-side answer. It has three parts — and one honest limitation you should understand up front.

Daemon watchdog

The watchdog polls the engine every 30 seconds with a real round-trip (a container ls --format json call, not just a process check). On failure it attempts one automatic container system start, then backs off on a 5s → 15s → 60s schedule so it never hammers the daemon.

Keep-alive and launch-at-login

  • Start at App Launch — mark a container (context menu, or the Supervisor settings tab) and it comes up automatically when the app starts. The list self-prunes if the container is removed.
  • Launch at login — the app itself can start at login via SMAppService, so your supervised containers are there when you sit down.

Keep Running (per-container restart policy)

Opt in per container. When enabled:

  • Crash detection on the 30-second poll.
  • Per-container backoff of 5s → 15s → 60s, with park-after-3: after three failed restarts it stops trying and offers a Try Again button, so a hard-broken container never starves the loop.
  • Health-driven restart for containers that declare a health check — three consecutive unhealthy checks trigger a stop→start. Each container's restart work runs as its own task, so one container's backoff never delays daemon monitoring or another container's recovery.

This is the --restart policy Apple's CLI doesn't have, implemented in the app.

The honest limitation (decision D017)

The app cannot restart a fully-dead engine by itself.

Runbay runs under the macOS App Sandbox. Starting the engine (container system start) submits a launchd job via launchctl bootstrap, and launchd refuses domain-management submissions from sandboxed processes. The daemon-reachability entitlements the app carries let it talk to an already-running daemon; they do not let it register one. The exact same command from a non-sandboxed shell works instantly.

So when the engine is fully down, the watchdog:

  1. Attempts system start once (auto-recovery still works in non-sandboxed dev builds).
  2. Recognizes the sandbox failure signature (failed to get a response from apiserver) and parks immediately in recoveryUnavailable instead of burning retries.
  3. Posts a notification and shows a "Restart in Terminal" button in Settings ▸ Supervisor (which launches the command in your terminal — a path proven safe under the sandbox).
  4. Keeps polling, so the moment you restart the daemon manually, the state self-heals to running.

This was verified end-to-end: engine down → one attempt → parked with "user action required" → manual system start → next poll → "daemon healthy."

The real fix — a bundled non-sandboxed SMAppService launch-agent helper that performs the start over XPC (launch agents don't inherit the app sandbox) — is planned. Until then, in-app engine restart is a guided one-click Terminal action, not silent magic. We'd rather tell you that than fake it.

See also

  • Getting started — install the engine and run the first-run doctor.
  • Stacks — health checks come from stack definitions; health-driven restart uses them.