Honeycrisp

macOS app & CLI · open source

Virtual Macs, Linux and containers, on your Mac.

Honeycrisp runs macOS and Linux virtual machines, and Linux containers, on Apple silicon — from a native app or the crisp command line. Push VMs to any OCI registry, give every CI job a fresh machine, and spread the work over a rack of Macs.

Coming soon Read the docs

Free and open source · macOS 27+ · Apple silicon

crisp cluster · 3 Macs
Waiting at the controller

A simulation of the scheduler, not a screenshot. Each Mac runs at most two macOS VMs; queue more and the extras wait their turn.

VMs and containers, kept apart.

A virtual machine and a container are different things, and Honeycrisp doesn't pretend otherwise. Each gets its own commands and its own images. crisp ps lists them side by side.

VM Container
What it is A whole machine: kernel, disks, display An OCI image running a single workload
Guests macOS and Linux Linux
Images Honeycrisp VM images, stored in any OCI registry Standard OCI and Docker images
Runs on Apple's Virtualization framework Apple's container system
$ crisp ps KIND NAME OS STATE IP PORTS IMAGE vm sonoma macos running 192.168.64.5 - ghcr.io/me/macos:base container web linux running 192.168.65.2 8080->80/tcp docker.io/library/nginx:latest

A Mac inside your Mac. Linux in seconds.

Create a VM from the app's three-step sheet or one command. Honeycrisp fetches what it needs, and the machine that boots is ready to use.

crisp vm create macos

Any macOS Apple publishes

Every version Apple offers for virtual Macs, a local IPSW or a URL. Set up an account, automatic login and SSH on first boot, and Setup Assistant is already done.

crisp vm create linux

Linux, ready on first boot

Debian and Ubuntu cloud images boot straight into a configured system with your SSH keys. Or use the installer for Ubuntu, Debian or Alpine, or any arm64 ISO.

crisp vm snapshot

Snapshots, memory and all

Disks are copy-on-write, so a snapshot is instant. Take one of a running VM and restoring it resumes exactly where it was, open apps included.

# The newest macOS this Mac supports, with an account set up on first boot $ crisp vm create macos sonoma --user admin --password-source env:VM_PASSWORD $ crisp vm run sonoma --show $ crisp vm ssh sonoma -- sw_vers # Debian, configured by cloud-init, then a shell through the guest agent $ crisp vm create linux web --cloud-image debian $ crisp vm run web && crisp vm shell web

Reach inside, even without a network.

A small guest agent runs in macOS and Linux guests and talks to your Mac over vsock. Install it from the Honeycrisp Tools disk, with no network or SSH; Linux cloud images install it on their own.

crisp vm shell · crisp vm exec

A shell, or one command

An interactive terminal sized to your window, or a command with streamed output, exit codes and stdin, as any user.

clipboard

Copy here, paste there

While a VM's window is open, its clipboard is shared with your Mac's.

--dir src:~/code/app

Shared folders

Share a folder for one run or for good, read-only if you like. Linux guests mount it with virtiofs.

-p 8080:80

Ports and networks

Forward ports from your Mac, put VMs on a named network so they can reach each other, or bridge onto a host interface.

USB

USB passthrough

Connect a device plugged into your Mac to a running VM. macOS asks you to approve each one.

console

The serial console

See a VM's console output as it boots. Linux VMs without a display show it in the library instead of a screen.

Images live in any OCI registry.

Push a VM to GitHub's registry, GitLab's or your own, the same way you would push a container image. crisp login keeps credentials in your keychain, and existing docker login credentials work too.

Disks travel in pieces

A disk is split into compressed chunks, empty regions are skipped, and every chunk is verified.

  • An interrupted pull resumes where it stopped
  • Pushing again uploads only the chunks that changed

Clones that cost nothing

Clone an image into an independent copy-on-write VM, or a thin overlay for throwaway CI machines.

  • Export a stopped VM to a single .crispvm file
  • Import one with a command, or drop it on the app's window
$ crisp vm push sonoma ghcr.io/me/macos:base $ crisp vm clone ghcr.io/me/macos:base ci-1 --overlay $ crisp vm export builder # writes builder.crispvm

Run your CI on your own Macs.

Honeycrisp is also a CI runner. Point GitLab, GitHub, Gitea or Forgejo at your Macs and they build and test your code there, macOS and iOS apps included, without a hosted runner.

Every job gets a fresh machine: a VM cloned from an image, or a new container, deleted when the job finishes. Nothing carries over from one job to the next.

crisp-gitlab-executor

GitLab, the job's image decides

A custom executor that works like GitLab's Docker executor. A Honeycrisp VM image runs in a throwaway VM; any other OCI image, such as node:22, runs in an Apple container that starts in a couple of seconds.

fleeting-plugin-honeycrisp · crisp pool

Autoscaling and warm pools

A fleeting plugin for GitLab's autoscaling executors, and pools of VMs booted ahead of time, so a job that matches claims a ready machine in well under a second.

crisp-actions-runner

GitHub, Gitea and Forgejo Actions

Pools of single-use runners. Each VM takes exactly one job and is replaced when it finishes. Registration tokens reach the VM over SSH stdin, never on a command line.

honeycrisp-vm

Build images with Packer

A Packer builder that starts from a restore image, an ISO, a raw disk or an existing image, provisions over SSH and pushes the result.

# .gitlab-ci.yml ios: image: ghcr.io/me/macos-xcode:26 # a macOS VM script: - xcodebuild -version web: image: node:22 # an Apple container script: - npm ci && npm test

A rack of Mac minis, one controller.

Link several Macs and one controller places VMs across all of them. It serves the same API as a single Mac, so the app, crisp and the CI runners point at it and carry on. Jobs wait in line at the controller until a Mac has room.

Mutual TLS, a private CA

Join tokens carry the CA's fingerprint, so a new Mac checks the controller before trusting it. Private keys never leave the Mac that made them.

  • Certificates renew on their own
  • Remove a Mac or revoke leaked CI credentials

Labels and selectors

Label a Mac xcode=26 or pool=ios and send jobs only to Macs that match. A max-jobs label caps Linux work on a node.

Images fetched once

The controller is a pull-through registry cache. Each layer comes from the internet once, then from the LAN, and the least recently used layers make room when it fills.

A standby, ready to take over

A standby keeps a copy of the controller's CA, members, tokens, labels and revocations, updated every ten seconds. If the controller is gone for good, crisp cluster promote makes the standby the new one, and the other Macs follow on their own.

VM ports, from anywhere on the cluster

A VM's address is private to the Mac it runs on, so every node runs an mTLS tunnel, and clients reach a VM's SSH port through it without being told.

$ crisp cluster init # on the controller $ crisp cluster token # prints a join command $ crisp cluster join https://mini-1.local:7443 --token hc1.… # on every other Mac $ crisp cluster nodes NAME ROLE STATE ADDRESS CPU MEMORY VMS MACOS mini-1 controller ready 10.0.0.11:7443 10 32G 2 2/2 mini-2 agent ready 10.0.0.12:7443 10 32G 1 1/2

The limit everything is built around: Apple lets a Mac run two macOS virtual machines at a time. Honeycrisp keeps to that rather than working around it. A cluster is how you get more: more Macs.

The app and the terminal, one and the same.

A background service, crispd, owns your VMs, images and networks. The app, crisp, the CI runners and the Packer plugin all talk to it, so a VM started in the terminal shows up in the app at once. The app installs and starts the service the first time it opens.

A library of live screens

Every VM as a live image of its screen, even the ones running without a window, with a bar for macOS slots, memory and processors in use.

Drop a file to start

Drop an .ipsw or .iso on the window to make a VM from it, or a .crispvm to import one.

From the menu bar

Start and stop VMs without opening the app. Each running VM has its own small host process, so VMs keep running when the service restarts.

The whole cluster at a glance

Once this Mac is part of a cluster, the sidebar gains a Cluster page: how many Macs are online and how many macOS slots are in use across all of them.

  • A card for each Mac with its role, slots, cores, memory and labels
  • A Mac that stops reporting is flagged with when it was last seen

Honeycrisp is on its way.

The app hasn't been released yet. The download will be here when it ships, free. Until then it builds from source: clone the repository and run make app.

Free · open source under MIT · macOS 27+ · Apple silicon only

The things worth asking first.

Why only two macOS VMs per Mac?

That is Apple's limit for virtual Macs, not Honeycrisp's. Linux VMs and containers aren't held to it. When you need more macOS machines at once, add Macs to a cluster: the controller treats every slot on every Mac as one pool.

Do I need Docker for containers?

No. Containers run on Apple's own container system, which you install from Apple's container releases. crisp container passes straight through to it, and plugins such as compose work through Honeycrisp too.

Will it run on an Intel Mac, or an older macOS?

No. Honeycrisp needs a Mac with Apple silicon running macOS 27 or later.

Is it ready to use?

It works, and it is in early development: commands, file formats and the API may still change between versions. Expect rough edges, and please report them.

Is it really free?

Yes. Honeycrisp is open source under the MIT license, and the code is on GitHub. There is no account and nothing to pay for.

Built with AI

I built Honeycrisp with heavy use of AI coding tools.

Saying so seems more useful than leaving you to guess.