Orchard

A native Mac app for containers, machines, Kubernetes clusters and local AI models, built on Apple’s container.

Download Orchard

Version 2.9.3.30 released macOS 26 · Apple silicon

Everything container runs, in one window

Containers and images

Run, inspect and clean up containers and images, follow their logs and builds, and see live CPU, memory, network and disk usage on the dashboard.

Local AI and sandboxes

Wire MLX, Ollama or LM Studio models into containers. Inference stays on your Mac’s GPU, and agents run behind a hypervisor boundary with a local endpoint instead of an API key.

Container machines

Create, configure and monitor persistent Linux VMs from any init-capable image, with CPU, memory, home-mount and custom-kernel options.

Kubernetes clusters

Local clusters on container’s k8s plugin: pick the version, workers and CNI, load local images into every node, and get a working kubectl context in one click.

Compose projects

Bring a compose.yaml up in dependency order. Stacks you started in the terminal show up too, and anything the runtime can’t honour is listed before the first run.

Userspace networking

Container traffic leaves your Mac like any app’s, so VPNs, DNS settings and per-app firewalls apply to it. Published ports and host.containers.internal just work.

Signing and scanning

Push, sign and verify images with Sigstore cosign, gate signing on Trivy vulnerability reports, and see each image’s signature at a glance.

Native, not a wrapper

Written in Swift and driven over Apple’s XPC APIs rather than by shelling out, so it starts instantly and stays in step with the runtime.

What’s new

2.9.3

Changed

  • Updates come from verfüg.bar. Orchard checks https://updates.verfüg.bar/orchard/appcast.xml for updates, signed with verfüg.bar's own EdDSA key, instead of upstream's feed: releases built on git.stei.gr are signed with Developer ID and notarized, and only they are offered. Each release is also listed on orchard.verfüg.bar.
2.9.2

Changed

  • The default network is the userspace network. In both userspace modes container's builtin default network is a userspace network, like slirp or pasta on Linux: a container started without a network, from Orchard, the container CLI, docker or Compose, sends its traffic through a process on your Mac, so a VPN handles it like any app's. Userspace and bridge no longer keeps default on vmnet: containers created in Orchard join default and a separate vmnet network for inbound traffic (bridge, host-only by default). No usernet network is created any more; networks named usernet or usernet-… remain userspace networks.
  • diagnose.sh (plugins/container-runtime-usernet) collects the host's VPN, routes, DNS and proxy settings and runs the same tests from the host, a usernet container and a default container.
2.9.1

Fixed

  • Userspace networking reaches every client. It only applied to containers created from Orchard's Run sheet: the container CLI, docker and Compose always start containers with Apple's runtime. Orchard now installs its runtime as container-runtime-linux in container's user plugins, where it shadows Apple's, so every container starts in it and gets userspace networking on a usernet network, with no --runtime flag. With Userspace chosen, container's builtin default network is a userspace one too (a networks file in container's plugin state, written by network setup), so a plain docker run or container run gets it. Containers on other networks run exactly as with Apple's runtime.
  • After a container update to another release series, the runtime hands every start to Apple's runtime, so containers keep working (with vmnet only) until Orchard installs a matching build. Network setup shows again when your choice needs the runtime and it's missing or outdated.
2.9.0

Added

  • Userspace networking for containers. Orchard bundles container-runtime-usernet, a runtime plugin for Apple's container that gives a container a userspace network (gvisor-tap-vsock, the stack behind Podman's gvproxy and Lima): its connections leave your Mac as an app's own sockets, so VPNs, your DNS settings and per-app firewalls apply to them. Published ports work; the network's gateway answers DNS with your Mac's resolver, and host.containers.internal reaches your Mac.
  • Network setup. While container has only its builtin network and networking was never set up, Orchard shows network setup at startup: Userspace (the default), Userspace and bridge (outbound through userspace, inbound over a bridge network that your Mac and other containers reach by IP, with published ports forwarded there), or Bridge only (container's own vmnet networking). The userspace network's name, IPv4 subnet and MTU, and the bridge (container's default network, or a new one with its name, IPv4 subnet, IPv6 prefix and host-only mode) can be set; overlapping subnets are caught before anything changes. Applying installs the plugin into container's plugin directory (as administrator for /usr/local) and restarts container when the choice needs it, then creates the networks. When setup was finished or skipped is remembered; Settings > System shows it and runs setup again.
  • The install wizard has the same choices in a Network section; the plugin installs with container, behind the same password prompt.
  • Containers created in Orchard on the default network join what network setup chose; a usernet network picked by name runs with the usernet runtime.

Changed

  • Building Orchard builds the plugin (Swift, and Go for its helper) for every architecture in the build, signed like the app. A Debug build without Go goes on without it; a Release build needs Go.
2.8.2

Added

  • Image signing with Sigstore cosign. Push, Push and Sign, Sign and Verify in a new Signature menu on the image detail. Orchard pushes with container image push (over plain HTTP to a registry on localhost) and signs repository@digest, the exact digest the image list shows, never a tag that could have moved. Images matching a signing pattern are signed every time Orchard pushes them.
  • Key or keyless signing (Settings > Signing). With a key, Orchard generates a cosign key pair with a random password kept in your Keychain, or imports an existing cosign.key (the password is checked by deriving its public key). The password reaches cosign in its environment, never its arguments. By default key signatures stay out of Sigstore's public transparency log, so a private image's name doesn't become public; recording them there is a setting. Keyless signing logs in through the browser and is recorded publicly.
  • A vulnerability gate: don't sign images whose current Trivy report has Critical (or High, or Medium) vulnerabilities and above. An image without a report for its current digest is scanned first.
  • Signature verification. Images matching a verification pattern are verified when they appear or change, against Orchard's key, imported public keys, and keyless identities (an identity and its OIDC issuer, e.g. a GitHub Actions workflow). When one isn't verified, Orchard shows it (a badge), warns, or blocks launching it from Orchard.
  • Each image's signature shows on its detail (verified and by whom, signed, not signed, failed, outdated when the image changed), in the image list (verified, signed, or an unverified warning), and on its vulnerability report.
  • cosign install and update in Settings > Signing: Orchard downloads cosign's latest release for this Mac from GitHub, checks it against GitHub's checksum and keeps it in Application Support/Orchard/bin; Homebrew's cosign is used when that is what is installed. cosign keeps its default locations: Docker's config and credential helper for registry logins (found in Homebrew, /usr/local/bin or Docker Desktop), ~/.sigstore for its cache.
2.8.1

Added

  • Vulnerability scanning with Trivy. Images whose reference matches one of your patterns (Settings > Scanning; * and ? wildcards, docker.io/library/ optional, a pattern without a tag matches every tag) are scanned every time Orchard builds them, and whenever they appear or change in the image list (a pull, a build from the Docker API or the CLI, a new digest under the same tag). Any image can be scanned by hand with Scan on its detail. Scans run one at a time.
  • Trivy reads the image where it is: Orchard lays out the image's manifest for this Mac's platform as a temporary OCI layout over container's own content store, so nothing is exported or copied. Trivy keeps its vulnerability database in its default cache (~/Library/Caches/trivy), shared with Trivy run from a terminal.
  • A Vulnerabilities section in the sidebar: each scanned image with its counts by severity, marked when the image changed since its scan. A report lists every vulnerability with its package, installed and fixed versions, and expands to its description and link. It filters by severity (All, Low or above … Critical) and by fix (All, Fixed, Unfixed), with a search for CVE, package or title.
  • A default report filter in Settings > Scanning, e.g. High or above and only Fixed, that every report opens with; a report's filter can be changed while viewing and made the new default.
  • Trivy install and update in Settings > Scanning: Orchard downloads Trivy's latest release for this Mac from GitHub, checks it against GitHub's checksum and keeps it in Application Support/Orchard/bin; Homebrew's Trivy is used when that is what is installed.
2.8.0

Added

  • The setup wizard sets up more than container. One page to review, from the current settings: the kernel, the Docker API (and the orchard Docker context), container DNS (and its servers), and build resources (Apple's builder's CPUs and memory, and an optional orchard buildx builder with its own). A numbered summary lists every step Install takes, the privileged one marked: installing container and, with container DNS, the DNS helper, behind one administrator prompt. Once container runs, the choices are saved and applied: socktainer is downloaded and started, the buildx builder created on it, and container DNS turned on; anything that didn't work is said at the end. Nothing changes before Install, and everything can be changed later in Settings.
  • Settings > Kernel: the kernel container boots its VMs with, and where it came from: container's recommended kernel (with its Kata Containers release), a kernel chosen in Orchard (its Kata release and archive URL), or one set outside Orchard. The same choice as the setup wizard installs another: the recommended kernel, or one from a Kata release URL, detected from the archive.
  • A Kata Containers version check, in Settings > Kernel: it compares the active kernel's Kata release with Kata's latest on GitHub, and Install Its Kernel downloads the latest kata-static archive for this Mac, checks it against GitHub's checksum and installs Kata's default kernel from it.

Fixed

  • A custom Kata Containers kernel chosen in the setup wizard didn't show up in Settings: container keeps no record of where a kernel came from, and Settings > System shows container's recommended kernel.url. Orchard now remembers the archive, its Kata release and the kernel in it, and Settings > System labels those properties as the recommended kernel's.
2.7.1

Added

  • Start container when Orchard starts, on by default (Settings > General). When Orchard opens and the container system is installed but stopped, Orchard starts it, as the Start button does; with Start at login, containers are ready after you log in. Not while the setup wizard is showing, nor when the installed container is a version Orchard can't talk to.

Fixed

  • The setup wizard finds the kernels in a Kata Containers release archive (.tar.zst) on a Mac without Homebrew's zstd: it read the archive with macOS's tar, which has no zstd of its own, and reported "the download isn't an archive tar can read" (seen with kata-static-4.3.1-arm64.tar.zst). It now reads it with Containerization's archive reader, as container system kernel set does. A download's last progress update no longer turns a finished detection back to "Downloading", and an unreadable archive is no longer reported as an installer failure.
2.7.0

Added

  • A setup wizard for Apple's container. When Orchard finds no container on the Mac, the main window offers to install it instead of showing that the system isn't running: Orchard downloads Apple's installer for the newest container release Orchard is built for (1.6.x) from GitHub, checks it against the checksum GitHub publishes and with pkgutil (signed with Apple's Containerization Developer ID Installer certificate, and notarized), installs it behind one administrator prompt, and starts it. The wizard also chooses the Linux kernel: container's recommended one, or one from a Kata Containers release whose URL you paste. Orchard downloads that archive, lists the kernels in it, preselects Kata's default (vmlinux.container) and installs the one you choose with container system kernel set, warning when the archive is for the other architecture. Check Again looks for a container installed by hand.
  • Start at login, on by default. Orchard registers itself as a login item the first time it runs from an Applications folder (not from a disk image or Downloads), once: turned off in Settings > General or in System Settings > General > Login Items, it stays off. When macOS wants the login item approved, Settings links to Login Items.
  • A Docker API, through socktainer, so the docker CLI, Compose, Testcontainers and IDEs can use Apple's container runtime. Turn it on in Settings > Docker. Orchard downloads the socktainer release built for your container version into its Application Support folder, checked against the checksum GitHub publishes, or uses one installed with socktainer's pkg or Homebrew. It runs socktainer while the container system is running, stops it when the system stops, never starts the system on its own, and relaunches it if it crashes, giving up after five quick crashes. An orchard Docker context points at socktainer's socket and can be made Docker's current context, and turning that or the Docker API off switches back to the context you used before. If another socktainer, such as Whalebridge's, already serves the socket, Orchard leaves it alone. The integration follows Whalebridge.
  • Container DNS through your Mac's resolver (apple/container#402). Turn it on in Settings > DNS, and install its helper there once, with your administrator password. Orchard then answers DNS on every container network's gateway, including networks you create later, from the first container on each, and keeps answering for as long as the network exists. Lookups go through macOS's own resolver, so VPN, per-domain and /etc/resolver DNS work in containers as they do on your Mac, and nothing needs configuring; you can still enter DNS servers to use instead. This also fixes containers that can't resolve names because another DNS server on your Mac, such as unbound, dnsmasq or Cloudflare WARP, holds port 53. The helper only opens port 53 on gateway addresses and hands it to Orchard, which does the answering, and it serves only your user. Answers run while Orchard is open.
  • CPUs and memory for builds, in Settings > Docker. The builder's size applies to Apple's builder, which runs docker build through the Docker API, Orchard's image builds and container build; Apply restarts it at that size. An orchard buildx builder can be created there too, for multi-platform builds and cache export (docker buildx build --builder orchard --platform linux/arm64,linux/amd64 …), with its own CPUs and memory; its cache is kept when you change its size.
  • scripts/docker-api-test.sh tests the Docker API end to end: linux/arm64 and linux/amd64 images through docker build and through buildx, the buildx builder's CPU and memory limits, and build cache reuse, both within a builder and through an exported cache imported after a prune.
  • The menu bar shows whether the Docker API and the DNS forwarder are running, when they're turned on.
  • Right-clicking Orchard's menu bar icon shows a menu with Open Orchard, Settings… and Quit Orchard. The menu bar panel opens with those three at the top, Open Orchard first, instead of an Open Orchard button at the bottom. Open Orchard and Settings close the panel as they open their window.
2.6.0

Added

  • Clusters can have worker nodes (#87). With Apple container 1.6.0 or later, Create Cluster has a Workers field under Advanced. With no workers the cluster is one node that also runs workloads, as before. With workers, workloads run on the workers only, and each worker gets the same CPUs and memory as the control plane. Workers can only be chosen when a cluster is created, because Apple container can't add a node to a running cluster yet. Recreate keeps the worker count, and deleting a cluster removes its workers. Load Image can load an image into every node, which is the default, or only the nodes you pick. On container 1.5.x neither control appears, and the single-node notice now says that 1.6.0 adds workers.
  • A cluster with more than one node can be expanded in the Clusters list to show its nodes, with their roles and status. Selecting a node shows its container's detail. The left and right arrow keys expand and collapse a cluster and move between it and its nodes, as in a Finder list.
  • Clusters can be created with no CNI, for installing your own (#135). With Apple container 1.6.0 or later, the CNI choice under Advanced in Create Cluster is Default (kindnet), Custom manifest or None (install your own). With None the create finishes without waiting for the nodes, which stay NotReady until you install a CNI with kubectl or Helm, so Cilium, Calico and other CNIs that a single manifest can't express can be used. Until then the cluster reads "Waiting for CNI" in the list, and its detail explains what to do next. Orchard checks the nodes from inside the control plane, so this needs no kubectl on your Mac, and the state clears once every node is Ready. Recreate keeps the choice.
  • Containers can be committed to an image (#133). With Apple container 1.6.0 or later, Commit… in the container's detail header, Commit to Image… in the containers list's context menu and "commit " in the Cmd+K palette open a sheet that asks for the image name, suggesting <container>:latest. A running container is snapshotted first and keeps running. The image holds the container's filesystem as one layer and starts the way the container did, with the same command, user, environment, working directory, labels and stop signal; ports, volumes and the healthcheck aren't carried over. The container's executable becomes the image's entrypoint, so running a different program means overriding the entrypoint, not just the command. If an image with that name already exists, the sheet says so and asks before replacing it. The sheet shows each step while it runs and, when it's done, links to the new image in the Images tab and can run it. Orchard does this through the same client libraries as container commit, without running the CLI.
  • Container machines can be created with an account of your choosing (#136). With Apple container 1.6.0 or later, Create Machine has an Account section with User, UID, GID and Home Directory fields. Each starts empty, with your Mac user's value as its placeholder, and only the fields you fill in are sent, so a machine created without touching them still gets your Mac user. The machine's detail view shows the account and its Linux home next to the home mount. The account can't be changed after creation, because Apple container has no way to change it. The user, UID and home directory must not already exist in the image, such as ubuntu or UID 1000 on Ubuntu images, or the machine can't set up the account when it first boots.

Changed

  • The home mount captions in Create Machine now say that your Mac home folder is mounted at the same path, and that with read/write anything in the machine, including root through passwordless sudo, can change your files. The README and the machines guide say the same, following Apple's updated machine docs (#136).
  • Orchard now builds against Apple container 1.6.0 (containerization 0.52.1), up from 1.5.0 (containerization 0.47.0) (#132). Container machines changed shape: images can no longer supply their own user setup script, and the machine's account is set by the runtime. Orchard still creates machines with your Mac user's name, UID and GID, as before, and still works with container 1.5.x.
2.5.2

Added

  • The Compose tab runs post_start and pre_stop hooks (#126), the same way the compose plugin does. Each post_start hook runs in its container after it starts, and each pre_stop hook runs before the container stops on down and when a service is recreated. While a hook runs, its service's row shows the hook and its latest line of output. A failing post_start hook stops the up and leaves its container in place. A failing pre_stop hook is reported, and the stop goes ahead. Either way the message names the hook and its last few lines of output, along with its exit status or, for a hook that couldn't start, why not. Hooks don't run when you start or stop a compose container from the Containers tab or the menu bar.

Changed

  • Orchard now uses compose 0.5.0, which labels the containers it creates com.compose.* instead of com.container-compose.*. Projects brought up with an earlier version of Orchard or the compose plugin are no longer recognised in the Compose tab. To fix one, take it down with the version that brought it up (or remove its containers), then bring it up again.

Fixed

  • Adding a compose project whose name sorts first no longer leaves its row squashed in the Compose list. The new row kept a height of about a third of the others, with the next project drawn over it, until you switched tabs and back.
  • Containers brought up from a Compose project get the nameservers the file asks for (#124). Orchard dropped a service's dns, dns_search and dns_opt, and sent no resolver configuration at all, so the container had no /etc/resolv.conf and every lookup in it failed with connection refused on [::1]:53. Containers created from the Run form get a resolver configuration the same way, so one with no DNS domain set now gets the network's own nameserver as container run gives it.
2.5.1

Fixed

  • Open Orchard in the menu bar brings the Orchard window to the front instead of opening a second one (#118). A minimised window is restored, and a new window opens only if none is open.
  • Making a DNS domain the default works again on container 1.4.1 and later (#116). Orchard set it with container system property set dns.domain, which those releases no longer have, so Make Default and the DNS Domain picker in Settings failed with "3 unexpected arguments". The default is now an Orchard setting, used for containers you create in Orchard, so changing it needs no administrator password and no restart of the container system. If you haven't chosen one, Orchard uses the [dns] domain from your ~/.config/container/config.toml, and Settings > General shows that value as the container default.
  • Compose projects no longer disappear from the Compose tab when Orchard briefly can't read its saved project list. A failed read was treated as an empty list. Orchard now keeps the projects it already has, and won't save over the list until it has read it.
  • The container list no longer jumps back to an older, sometimes empty, list when several refreshes overlap. A slow refresh that finished after a newer one could overwrite the newer result.
  • Dismissing an error alert no longer logs a SwiftUI warning about publishing changes during a view update.
2.5.0

Added

  • Choose the Kubernetes version when creating a cluster. The Create Cluster sheet's free-text node image field is now a menu headed by the node image Apple container's k8s plugin ships with (marked Recommended, and read from the installed plugin rather than a copy in Orchard), followed by the newest kindest/node release of each Kubernetes version from 1.31, fetched from Docker Hub when the sheet opens and pinned by digest. "Custom Image" takes any other reference. Choosing a version only became meaningful with container 1.5.0: until then the plugin configured the control plane for its default version whatever image you passed, so a different image ran mismatched components. For the same reason 1.5.0 rejects a node image with no tag, and Orchard now says so before creating anything. Offline, the menu offers the recommended image and a custom one.
  • Use your own CNI with a new cluster. The Create Cluster sheet's Advanced section takes a CNI manifest to apply instead of the default kindnet (container 1.5.0's --cni). Orchard can't check that a manifest suits the cluster, so the sheet points out that it must fit the pod subnet and links to Apple container's Custom CNI guide.
  • Redirect a DNS domain to your Mac's localhost. The Add DNS Domain sheet takes an optional IPv4 address; the domain resolves to it and Apple container redirects that address to the host's 127.0.0.1, so containers can reach a service running on the Mac by name. Domains set up this way are marked LOCALHOST in the list and show their address in the detail header. Before container 1.5.0, adding or removing one of these redirects reloaded the Mac's whole packet filter configuration and cut outbound networking for every running container; 1.5.0 reloads only its own rules.

Changed

  • Orchard now builds against Apple container 1.5.0 (containerization 0.47.0), up from 1.4.1 (containerization 0.45.0). Nothing Orchard calls has changed shape. The release also fixes GHSA-44v5-vx46-ghv6 in the k8s plugin (kubeconfig values from the guest are now sanitised before being merged into your kubeconfig), which Orchard picks up through the CLI.
  • Orchard no longer warns that cluster creation will fail on a guest kernel built without nftables. Container 1.5.0 prepares nodes with the node image's own iptables backend instead of hard-coding iptables-nft, so the older kernel that an upgraded install keeps now works (apple/container#2120). A node-preparation failure still gets Orchard's own message rather than the CLI's, which names a step that succeeded, but it no longer blames the kernel.

Removed

  • Starting a stopped cluster, which is replaced by Recreate. Container 1.5.0 removed container k8s start, so a stopped cluster can only be deleted and created again; Recreate does both in one step. It opens the Create Cluster sheet filled in from the cluster (its name, CPUs and memory, the Kubernetes version and, for clusters Orchard created, the CNI manifest) and deletes and creates when you confirm. A node doesn't record its image tag, so Orchard recovers the version from the image digest, and asks when it can't. Stopped cluster nodes in the Containers list, the menu bar and the command palette no longer offer Start either: a plain start skips the boot, readiness wait and kubeconfig write the old command did, so the node's detail offers Recreate Cluster instead.

Fixed

  • Orchard notices a missing Kubernetes plugin again on container 1.5.0, which reports it as an unknown command rather than a missing plugin. Without this, the Clusters tab showed a Create Cluster button that stayed disabled with no explanation.
  • A stopped container's resource charts are hidden, as they are for a container that hasn't run. A container that ran earlier in the session kept its charts after it stopped, and a time window with too few samples then showed a "Collecting" spinner for samples that were never coming. The same applies to machines and clusters.
  • Orchard offers to reinstall the compose plugin after a Homebrew upgrade of container removes it (#113). Orchard decided whether the plugin was installed by looking in /usr/local, but a Homebrew container looks for plugins inside its own versioned install, so after a brew upgrade a copy in /usr/local still counted as installed although the CLI could not see it, and an install from Orchard went where that CLI never looks. Orchard now asks the CLI itself whether container compose works, and installs into the directory the CLI names in its error. That directory belongs to you under Homebrew, so the install no longer asks for an administrator password there.
  • Images that clear their inherited entrypoint with ENTRYPOINT [""] now run. Orchard used the empty string as the program to launch, so the container failed to start; the command now runs on its own, as the CLI does from 1.5.0.
2.4.3

Added

  • The AI Models panel's detected endpoints can now be re-pointed and switched off (#110). The four addresses discovery probes (Ollama on 11434, LM Studio on 1234, an MLX server on 8080 or 8000) were a hardcoded list. A server listening anywhere else was undiscoverable, and there was no way to exclude one you would rather Orchard left alone. Each one is now a configuration you own: the detail pane carries the host and port it probes, with Save and, for an address you have moved, "Restore default". Switching one off stops Orchard contacting it at all rather than merely hiding it, and it moves to a "Not probed" section in the list, so there is a way back on. An endpoint you have moved keeps its row under "Not answering" while nothing responds there, so a mistyped address can be corrected rather than taking the endpoint out of the panel; a built-in sitting on its shipped address stays quiet, since "you aren't running Ollama" is not news. Both choices persist, and a built-in added in a later release joins your list rather than replacing it. An endpoint pointed at another machine is bridged into containers by its own address, since only a server on this Mac needs the network gateway indirection.

Fixed

  • Saving an API key for a locked model server now tells you what happened (#110). The field cleared itself on Save and said nothing further, which looked the same whether the key had been stored and rejected, stored and accepted, or never stored at all. Keychain writes also discarded their status entirely, so a refusal from the keychain was invisible by construction. The panel now reports each outcome in its own words, including the one that previously had no voice: a key saved successfully that the server still rejects, which is a wrong key rather than a broken Save. A stored key is shown as stored, with a Remove button, instead of an empty field that could mean either nothing saved or something hidden.
  • A model server that wants an API key is no longer probed every 5 seconds for as long as Orchard runs (#110). The background tick backed off to 30s only while nothing was detected, and a server answering 401 counts as detected, so an endpoint Orchard could never get into held the fast cadence indefinitely and filled that server's own log with rejected requests. The tick now backs off unless something usable is detected. Saving a key still re-probes immediately, so nothing that depends on a fresh answer waits on the slower cadence, and an endpoint switched off is not contacted at all.
2.4.2

Hi everyone, this release is a huge one personally, and one that's long overdue.

Since Apple launched container, everyone's been looking for Compose support so Docker Compose files can be brought across. The maintainers themselves have turned this down in several issues, pushing it onto the community. I've closed a lot of feature requests because I hoped this would be a core feature, but the maintainers made it very clear they are not going to work on it.

In the early days, many people, including myself, attempted to build something to solve that. However, they were all independent binaries, and still are — requiring their own commands and not portable.

A few releases ago, container added support for plugins, the first of which is an official k8s one — it's the same plugin Orchard itself calls to bring k8s to your box.

So in order to bring these worlds together, I've created a new project, compose, which is a plugin for apple/container that can be installed without Orchard (although it's offered to you with minimal work involved via the UI).

The syntax for compose looks exactly how you would want it:

container compose up --help

I'm opening that up in the hope that other developers can contribute to it and make it the standard way to use Compose with containers. There is no Orchard logic in it — it's a plugin and can be bundled as a Swift library in 3rd party tools such as other UI's or applications, instead of being proprietary.

With this being so new, if you have any feedback or want to contribute, please do!

Check out the project and give this new Orchard release a go — navigate to the Compose view where it will be installed for you, if you wish.


Added

  • The shell a container terminal opens with is now a setting, taken as written and passed through with its flags, so bash -l gets a login shell that reads your rc files (#107). Which shells an image has and which flags they accept is a property of the image, so there is nothing here for Orchard to enumerate and nothing worth validating beyond refusing to send an empty command. sh remains the default because it is the one shell a minimal image is likely to have, which makes it a safe default rather than a good one.

  • A Compose tab, for bringing a set of services up and down from a compose file. Projects are found by the labels on their containers rather than by any file Orchard keeps, so a project brought up from the terminal appears here without Orchard having been told anything, and a project Orchard has been shown a file for can be brought up, taken down and reconciled from the window. Running up a second time compares each service against a hash stamped on the container it produced, then creates, starts, leaves alone, recreates or removes each one accordingly, and every step is listed as it happens.

  • Compose keys that cannot be honoured are never quietly dropped. Adding a project shows what will be ignored, how much ignoring it costs, and the line each key sits on, and the project goes on showing that afterwards: three weeks later nobody remembers what they accepted, and the containers cannot tell them. A file that grows a new unhandled key is put back in front of you before the next up rather than waved through on an older answer. A service that builds is built through the same path as the Images tab, so its BuildKit log shows up under Builds like any other build.

    The planning behind the tab is andrew-waters/compose, a Swift package Orchard links and which also backs the container compose plugin, so the terminal and the window cannot drift apart. Two limitations are worth stating up front: without health reporting in the runtime, up starts dependencies before dependents but does not wait for them to become ready, and hostnames have to be unique across every container on the machine, so a service answers to <project>-<service> rather than to its service name.

  • The Compose tab offers to install the container compose CLI plugin when it is not there. Orchard itself never needs it, because the window links the planner and runs plans over XPC, so this is an offer rather than a fault and the banner is coloured accordingly: every project in the list works with nothing installed. It is worth offering because container's own installer clears the plugin directory on every upgrade (apple/container#1617), so a plugin someone installed by hand goes missing again through no fault of theirs. Installing fetches the latest release, unpacks it, and puts the two files where the CLI looks, with the work shown step by step in a sheet: this downloads 15MB and then asks for an administrator password, and someone about to be asked for their password should be able to see what asked and why. Everything up to the copy happens unprivileged in a temporary directory, so a failure before that point never prompts at all, and a download in flight can be cancelled.

Fixed

  • Ghostty no longer gets a new window, and a second copy of itself, every time you open a container terminal (#107). Orchard launched it with open -na, and -n starts a separate instance: a window in one instance can never join a window in another, so a new window was not a design choice so much as an inevitability, and every container opened left another Ghostty running. Ghostty 1.3 ships a scripting dictionary, so it is now driven the way Terminal.app and iTerm2 already were rather than through open, and all three stop being special cases. Whether the terminal arrives as a tab or a window follows the system-wide "Prefer tabs when opening documents" setting rather than a preference of Orchard's own: you have answered that question once, for every app. macOS defaults that to fullscreen rather than always, so the default is still a window; the difference is that it is now the system's answer rather than Orchard overriding it.
2.4.1

Added

  • The k8s Clusters tab now warns when the guest kernel cannot bootstrap a cluster, and offers to fix it. container k8s create prepares its node with iptables-nft, which needs a kernel built with nftables; the kernel Apple container recommended before 1.3.0 was not, and container system start skips the kernel download whenever a kernel already exists (apple/container#905), so an install carried forward from an earlier release keeps the old kernel and fails every cluster creation however new the CLI is. Orchard reads the default kernel the CLI records, and when it predates nftables the tab says so and offers "Install Recommended Kernel" in place of the empty state. Creation is still available from there, because the check is a version floor rather than a capability probe and a deliberately chosen custom kernel is nobody's business but yours.

Changed

  • Sheets have one Cancel button rather than two. Create Cluster, Create Machine, Edit Machine, Add Network and Add DNS Domain each had one in the header and another in the footer, and several bound the Escape key twice over. The footer keeps its Cancel, beside the action it cancels.
  • The log viewer's target picker now shares a row with the filter field instead of sitting on a row of its own above a divider, which gives every pane back a band of vertical space; a window split four ways spent four of them on it. The picker also sits flush with the pane's leading edge: a menu picker centres itself in a flexible frame, which was insetting it from everything above and below.

Fixed

  • Opening Containers or Images no longer highlights a row from the middle of the list. Both lists sort and filter in the view (by name, running first, the search field, the in-use toggle), while the selection was made from the first element of the service's array, which is the order the daemon returned. On this machine that meant Images opened on a digest-pinned Kubernetes node image nine rows down. Each of those lists now claims the first row it is actually showing.
  • A single-node Kubernetes cluster is no longer treated as though it had no control plane. Container 1.4.1 labels the one node of a default container k8s create cluster control-plane,worker, because it is both, and Orchard compared that label to control-plane exactly. The node therefore classified as a worker, the cluster read as stopped while it was running, and everything gated on a running control plane was hidden: the detail header offered Start instead of Terminal (kubectl), Write Kubeconfig, Copy Kubeconfig Path and Load Image, and every resource panel showed "Not running" over live charts. Roles are now read as the list the label can be, so a node that is both counts as the control plane.
  • A cluster that fails while its node is being prepared now explains why. The plugin runs node preparation as one set -e script whose last two commands are the iptables-nft calls, so an abort there surfaces the accumulated output of the steps that already succeeded: the error names net.ipv4.ip_forward = 1, a sysctl that worked, and never shows the command that failed (apple/container#2120, open with no fix in 1.4.1). Orchard recognises that failure and names the real cause, including the kernel responsible when it can tell.
  • "Install Recommended Kernel" no longer reports success without installing anything. An "already exists" refusal from the CLI was treated as an idempotent success, which is wrong in the one case that matters most: someone on an outdated kernel would be told the recommended one was installed and would still fail every cluster creation. The refusal is now retried with --force, which replaces only a kernel of the same name.
2.4.0

Quick none-changelog related note from me - I hope you're finding Orchard useful to you. The last month has seen stargazers on the project double, so it's great to have you here. Please let me know if you're finding this useful and feel free to add any feature requests / bug reports on Github.

The last release had over 3,100 downloads, so please consider giving it a star on Github if you're using it and spreading the word.

And a special thanks to everyone who's contributed to the project so far!

Added

  • Reclaim disk space on a running container, from the container detail header ("Reclaim Space") or the containers list context menu. Deleting files inside a container doesn't shrink its host-side disk images on its own, so the space stays claimed until the free blocks are trimmed; this hands them back and refreshes the system disk usage tiles once the daemon reports the trim done. Apple container exposes the operation for running containers only, so the action is offered only while a container runs, and a mixed multi-selection reclaims just the running members. Note that container 1.4.1 cannot yet complete the trim on a container's root filesystem: the guest's FITRIM ioctl returns "not supported" even though the block device backing the rootfs advertises discard, and the daemon trims "/" for every container that isn't read-only, so the operation fails there. Orchard reports that as a plain sentence rather than the daemon's three-deep nested error, and the action will start working against a container release that fixes the trim.

Changed

  • Orchard now builds against Apple container 1.4.1 (containerization 0.45.0), up from 1.3.1 (containerization 0.42.0). The client-facing surface is additive between the two releases (a new XPC route and its client method), so nothing Orchard already called has changed shape. The bump also removes the two containerization advisories fixed in 1.4.1 (GHSA-4587-w9mm-xxvh, an OCI layout load that followed symlinks out of the extraction directory, and GHSA-rgqp-277h-gcwj, a socket path length limit longer than the buffer it copied into) from the shipped bundle. Neither was reachable from Orchard: the app has no OCI layout import path and doesn't open unix sockets, but there is no reason to ship the code.
  • The container system version Orchard displays is now the bare release number. Apple container 1.4.1 changed what its health check reports, from container-apiserver 1.4.1 to 1.4.1.
2.3.4

Fixed

  • Scrolling a container's detail pane no longer hangs the app (#103). The six configuration wells sat in a LazyVGrid, and placing a row whose wells hold selectable text re-entered the grid's own placement: the main thread spun in over a thousand nested sizeThatFits frames at 100% CPU with memory climbing about 13 MB a second, and the window never recovered. The same two-column layout is now built eagerly from stacked rows, which six wells cost nothing to lay out up front. The wells also pair up only while the pane is wide enough to carry two and stack below that: at a 1024-point window two columns left a key/value row so little width that its value and Show/Copy controls fell out of the row entirely. Long environment-variable and OCI-label keys additionally cap their column rather than sizing to the longest key without limit, so a namespaced key wraps instead of crowding out its own value.
2.3.3

Fixed

  • Local-model detection no longer probes every 5 seconds when nothing is listening. Each probe of the four conventional ports (11434, 1234, 8080, 8000) with no server behind them produced a connection-refused URLSession task, and CFNetwork logs every one - dozens of NSURLErrorDomain -1004 console lines per minute on an idle machine. The background tick now backs off to 30s while no provider is detected; while one is detected, the 5s cadence stays so a stopped server disappears promptly, and opening the Models tab or the run form's model bridge still probes immediately.
  • Editing a container no longer silently strips its labels. The edit sheet's prefill omitted labels entirely, so the recreation that applies an edit dropped every label on the container, including Orchard's own sandbox markers (a sandbox stopped being recognised as one after any edit). Labels now carry through: internal ones untouched, the rest editable in the new labels editor.
  • Running a locally built image no longer fails with a 401 from Docker Hub. The Run Container sheet canonicalised every image reference before running, so a local tag like mono2 was rewritten to docker.io/library/mono2 and the backend tried to pull a repository that doesn't exist on the registry (Hub answers 401 for unknown repositories). The reference now resolves against the local image store first - a match runs under the exact reference the store knows (including the implied :latest), and only unmatched references canonicalise into pullable registry form. The "Local image available" hint and the actual run decision now agree.

Added

  • Labels can be set when running a container: the Run/Edit form's Advanced tab gains a key/value labels editor (matching the environment-variables editor), and the containers list can group by any of those keys. Internal com.apple.container.* and com.orchard.* labels are managed by the runtime/Orchard and don't appear as editable rows.
  • A Builds sidebar tab (Resources section, orchard://builds) tracks every image build Orchard has started, and the records survive relaunches (stored as versioned JSON in Application Support, with each log's last 1000 lines). The list shows status, start time, and duration per build, searchable by image name; the detail pane shows the build's request (Dockerfile, platform) and its log - complete while the app runs, trimmed to the last 1000 lines for records restored after a relaunch - live while building and reviewable after, with Cancel Build for in-flight builds and a context-menu Remove Record for finished ones. Once a build's image exists, the detail also mirrors the image view's affordances: a "Launch image" button opening the run-container sheet pre-filled with the built reference, a "Containers using this image" list that jumps to each container, and a confirmed Delete that removes both the build record and the built image (disabled while containers use the image; if the image delete fails, the record is kept). Builds and images cross-reference: the build detail's "View Image" jumps to the built image, and an image produced by an Orchard build gains a "View Build" button jumping to the newest successful build of that reference. Builds run concurrently and survive closing the Build Image sheet; a build still running when the app quits is marked "interrupted" on the next launch, since the CLI process was orphaned and its outcome never observed (the image may still have been built). The registry only lists builds Orchard itself started: apple/container's builder shim exposes just info() and a build stream over its gRPC surface, so BuildKit's own history is not reachable from the host.
  • Deep links: Orchard registers the orchard:// URL scheme. orchard://<tab> opens any sidebar tab (e.g. orchard://dashboard), and orchard://container/<id>, orchard://image/<reference>, orchard://mount/<id>, orchard://machine/<id>, orchard://dns/<domain>, and orchard://network/<id> jump straight to a resource, reusing the same navigation path as the command palette and menu bar (so a target in a still-loading list is selected once it appears). A resource noun without an identifier falls back to its tab, and image references keep their interior slashes.
  • Containers can be grouped by label: the containers sort menu gains a "Group by Label" submenu listing every label key present on current containers (internal com.apple.container.* bookkeeping labels excluded). With a key selected, the list renders one collapsible section per label value - click a header to fold it - with a count badge, a "No label" bucket for containers missing the key, and a per-group actions menu to start or stop everything in the group. The choice persists, and search/running filters apply within the groups.
  • Containers can be exported as tar archives (container 1.2+ API). An "Export…" button in the container detail header and an "Export Filesystem…" context-menu item in the containers list prompt for a destination, stream the filesystem through the API client (written to a scratch directory first, so a failed export never leaves a partial file at the chosen path), show an "Exporting…" state while in flight, and reveal the archive in Finder when done.
  • Image pulls now show real progress: a determinate bar with downloaded/total bytes and blob counts (e.g. "256 MB / 512 MB · 3/8 blobs") instead of an indeterminate spinner, updating live from the registry client's progress events (throttled to ~10 Hz so per-chunk byte updates don't churn the UI). The bar stays indeterminate until the total size is known, and the phase label ("Fetching image") replaces the static "Pulling image..." message.
  • Build images from a Dockerfile. The Images tab gains a hammer button (and the command palette a "Build an Image..." action) opening a Build Image sheet: pick the Dockerfile through a file panel so non-default names like Dockerfile.dev are discoverable (the build context auto-fills to the Dockerfile's folder), name the image, choose the target platform (Apple silicon linux/arm64 or Intel linux/amd64, defaulting to the host), and optionally build without cache. The build shells out to container build, which starts the BuildKit builder on demand, and the build log streams live into the sheet through the ANSI console; closing the sheet leaves the build running, and a Cancel Build button terminates it. Successful builds refresh the image list automatically.
  • Log views now render ANSI colours and support selection across lines. Container and machine logs were previously drawn as one SwiftUI Text per line, which printed colour escape codes as literal garbage and scoped text selection to a single line. Both the detail Logs tab and the log viewer window now share a single NSTextView-backed console: SGR styles (16-colour, bright, 256-colour, truecolour, bold/italic/underline) are rendered, other escape sequences are stripped, carriage-return progress lines show their final state, and click-drag or Cmd+A/Cmd+C works across the whole log. Filtering now matches the escape-stripped text, so a filter term can no longer hit or miss because of bytes inside a colour code, and the console follows the tail only while scrolled to the bottom (scrolling up to read no longer fights the 2s refresh, which previously only auto-scrolled on first load).
2.3.2

Fixed

  • The GUI now tracks the container system when it is stopped and started from the CLI (#100). The 5-second status poll was torn down by the main interface's onDisappear, which also fires when the system stops and the "not running" screen swaps in. After that, nothing polled, so a container system start run in a terminal was never noticed and Orchard stayed on "Container is not currently running" until the power button was clicked. The same dead end was reachable by launching Orchard while the system was stopped. The poll's lifetime now matches the window rather than one branch of the state view, so external stops appear within a poll tick (a stop can still lag while container system stop drains running containers, since the API server answers until it deregisters) and an external start restores the full interface automatically.
2.3.1

Fixed

  • Image sizes now match container image ls -v (#98). Orchard was showing the size of each variant's manifest descriptor — a couple of kilobytes of JSON — instead of the image content, so every image listed as "1 KB"–"3 KB". Variant sizes are now computed the same way the CLI computes FULL SIZE: manifest descriptor plus config blob plus the sum of the compressed layers. The container detail's Image section and the multi-select image cards previously showed the raw index descriptor size as "Size"; both now use the same resolved size as the images list, and the image Technical Details row is relabeled "Index Size (bytes)" since that value genuinely is the index descriptor size.
2.3.0

Changed

  • Orchard now links the Apple container 1.3.1 client libraries (previously 1.2.2), restoring compatibility with current container installs. 1.3.1 also patches six security advisories in the containerization package that Orchard's image operations link directly, including path traversal in the local content store and a RegistryClient that followed WWW-Authenticate realms without validating the host.
  • Image pulls now default to https for all registries, matching container 1.3.0's removal of the auto registry scheme. Pulls from localhost or private-IP registries no longer silently downgrade to plain http; a local http registry needs registry.scheme = "http" in the container configuration, same as the container CLI.

Fixed

  • Local-model detection no longer follows HTTP redirects when probing for providers. The probe targets conventional ports (11434, 1234, 8080, 8000), which are often owned by something else entirely; a dev server on 8080 that redirects to its TLS port would take the probe with it, so Orchard opened a connection to an unrelated endpoint every five seconds and abandoned it when the 1.5s probe deadline expired. Against a Rails app running with force_ssl this leaked a socket per probe until the server's accept loop stopped and it served nothing at all. A real provider answers 200 directly, so a redirect is now simply classified as "not a provider" - which also stops a redirecting server from being misreported as a model server.
2.2.2

Added

  • The menu bar popup now exposes a Stop control for the container system alongside the existing Start control, so the system can be shut down without opening the main window or going through the command palette. The button is gated on a running system and disabled while a transition is in flight; calling stopSystem() while a transition is already in flight is a no-op at the service layer.

Fixed

  • Menu-bar System analytics no longer stays stuck on "Collecting…" when container stats fail. The menu-bar hover popover now distinguishes four explicit states: collecting during the initial two-tick baseline, available with real CPU/memory history, "No running containers" when the system has none to sample, and "Stats unavailable" with a short reason when the XPC service is unreachable or every stats call failed. Per-container stats failures are now logged via Log.xpc so diagnostics aren't blind, and the existing dashboard, container, and machine stats paths are unchanged. No new macOS permission is required.
  • Container service-unavailable failures in the menu-bar sampling tick are now logged only once per tick via Log.xpc; subsequent outcomes in the same tick fold in silently while the first error is retained, so a single tick with several unreachable containers no longer produces one log line per outcome.
2.2.1

Added

  • Command palette: press Cmd+K (or View > Command Palette...) to fuzzy-search everything Orchard manages - containers, images, mounts, machines, k8s clusters, AI models, sandboxes, DNS domains and networks - and jump straight to any of them, or run actions from the keyboard: run a container, pull an image, create networks/machines/clusters, start/stop/restart the container system, and per-resource verbs like "stop db", "logs api" or "console web". Results rank with real fuzzy matching (exact prefix beats word-boundary beats scattered match); destructive operations are deliberately not palette-reachable.
  • The Dock icon can now be hidden (Settings > General > "Hide Dock icon"): Orchard switches to a menu-bar accessory, staying reachable from the menu bar, and the preference applies immediately and persists across launches. Note that macOS also removes accessory apps from the Cmd-Tab switcher.

Fixed

  • The AI Models and Sandboxes middle columns no longer render lighter than every other list: they used the sidebar list style, which paints its own source-list background, instead of the plain style the rest of the middle columns use.
  • Searching in the DNS and Networks tabs now actually filters the list; previously the search field rendered, but typing did nothing.
  • The search query is cleared when switching tabs, so a query typed in one tab no longer silently filters the next.
  • The containers list now supports Command+A select-all like the other multi-select lists.

Removed

  • Dead internal code: the never-shipped item navigator popover, its orphaned header component and an unused detail column wrapper.
2.2.0

Added

  • Containers owned by a container plugin (such as k8s cluster nodes) are badged in the containers list and detail header with the owning plugin and their role, e.g. "k8s · control-plane", so kindest/node containers aren't mystery rows.
  • Clusters: a new sidebar section for local Kubernetes clusters created with the container k8s plugin (container 1.2.2+). Node containers are grouped into clusters with per-node role, status, IP, CPUs, memory, and published ports; clusters can be created, started, and deleted from the UI, local images can be loaded into a cluster's containerd, and the kubeconfig can be written or its path copied, with a one-click terminal preconfigured for kubectl. Installs without the plugin get an explanatory state with upgrade guidance.

Fixed

  • With the sidebar hidden, the Dashboard (and other full-width pages) no longer render underneath the macOS window controls (#88).
2.1.7

Changed

  • Orchard now links the Apple container 1.2.2 client libraries (previously 1.1.0), restoring compatibility with current container installs (#54).
  • When the installed container release doesn't match the client Orchard links, the app now shows the version-incompatibility screen with upgrade guidance instead of reporting the system as stopped with a raw health-check decode error (#37, #39).
2.1.6

Added

  • Pull images by reference from non-Docker-Hub registries: the image search gains a pull-by-reference input, and references are canonicalized so by-reference and search-result pulls share progress tracking.
  • Docker Hub search now searches as you type (300ms debounce, Enter bypasses it) and paginates as you scroll.

Changed

  • Image sizes display consistently and pull progress is clearer, with failed pulls dismissible and retryable.
  • Multi-selection across containers, images, mounts, DNS domains, and networks: shift-click range selection, Command+A select-all, batch deletion, and a summary detail view for the selection (#53).

Fixed

  • The Run Container sheet now stays open when the run fails, so the configuration can be adjusted and retried; previously it dismissed regardless, leaving only the error alert.
  • When the container system is stopped or XPC is unreachable, Orchard no longer storms error dialogs from background refresh. Failed XPC connections surface as a clear "container service is unavailable" message, and after starting the system Orchard waits until the service is actually reachable before loading data.
  • Running containers' stop buttons in the menu-bar panel now respond on first click.
2.1.5

Added

  • Containers can now be created with a chosen CPU and memory allocation, and both can be changed later from Edit Configuration (via the usual stop/recreate flow). Previously every container silently got the runtime defaults of 4 CPUs and 1 GB with no way to change them in the GUI (#73).
  • The AI Models section now recognises oMLX servers. oMLX serves the same OpenAI-style API on the same conventional port (8000) as mlx_lm.server, so it previously appeared as a generic "MLX Server"; it's now identified by the owned_by: omlx stamp in its models listing (#72).
  • Local model servers that require an API key (oMLX generates one at setup) are no longer invisible: they appear as a locked provider with a field to paste the key, which is then used for detection, model listing, the chat tester, and the container bridge (OPENAI_API_KEY).

Fixed

  • Edit Configuration no longer drops the executable from the Command Override field: the form now shows the full command (sleep 3600, not just 3600), so saving doesn't corrupt the container's process configuration. Quoted arguments (sh -c "echo hi") now also survive the round-trip (#42).
  • Unchecking "Run in detached mode (background)" now does what it says: after the container starts, Orchard opens your preferred terminal attached to it. The toggle no longer appears in the Edit Configuration sheet, where recreation always happens in the background (#43).
  • Opening a container terminal in Terminal.app or iTerm2 no longer fails with "Not authorized to send Apple events" on notarized builds: the app now carries the com.apple.security.automation.apple-events entitlement and a usage description, so macOS shows the Automation consent prompt. If permission is denied, the error now points to System Settings → Privacy & Security → Automation instead of dumping the raw AppleScript error (#64).
2.1.4

Added

  • Error message displayed when trying to start container now includes a download link if the binary could not be found.
2.1.3

Added

  • Local AI models (MLX): a new AI Models section discovers model servers running on your Mac (Ollama, LM Studio, and MLX servers), and can start and stop your own mlx_lm.server instances - pick a model and port, choose whether to bind 0.0.0.0 so containers can reach it, with child-process supervision, crash surfacing and log access.
  • The container↔model bridge: wire a container to a host model in one step. Orchard computes the container-reachable endpoint from the network gateway and injects OPENAI_BASE_URL at create time - so a containerised app or agent talks to a local model with no hand-configured host networking. Inference runs on the Apple GPU on the host (Virtualization.framework guests have no GPU access).
  • Sandboxes: a first-class view of containers wired to a local model, recognised by a label Orchard stamps or by a model-endpoint environment variable. Each sandbox shows its model endpoint, an isolation badge (host-only/no-egress vs internet-open), and agent-runner controls - chat, terminal, and a stop kill-switch. Create one from the New Sandbox button or from a model's detail.
  • In-app chat tester: hold a short conversation with any model server from the AI Models view - no terminal or container needed - to check it's working.
  • Sandbox containers are flagged with a shield badge (and an explanatory popover) in the Containers list and detail, since a sandbox appears in both places.
  • A new Local AI guide on the site covering MLX, the bridge, isolation, and a runnable quick start.

Changed

  • Reorganised the sidebar so Sandboxes joins Containers and Machines under Compute, and AI Models sits under Resources alongside Images and Mounts.
2.1.2

Added

  • Container machines: create, configure, run and monitor Apple container machines (persistent Linux VMs) directly in Orchard, over the native XPC API rather than shelling out to the CLI. A new Machines section in the sidebar lists your machines with state, IP address and a default badge, and the detail view shows the full configuration plus live CPU, memory, network and disk usage.
  • Create machines from an image with configurable CPUs, memory (defaulting to about half your host RAM), home-directory mount mode (read/write, read-only, or none), nested virtualization, and an optional custom kernel.
  • Machine lifecycle controls - start, stop, set-default, and delete - each with clear in-progress feedback.
  • Edit a machine's configuration with a one-click stop, apply and restart, since Apple's runtime only applies CPU/memory/home-mount/kernel changes on the next boot.
  • Machine output and boot logs stream in the same multi-pane log viewer as containers, and running machines appear in a Machine Utilisation table on the Dashboard.
  • Init-system guardrails for the most common machine pitfall: a warning before creating from an image that has no init system, and a clear "the image has no init system" explanation when a machine boots and immediately stops because it lacks /sbin/init.

Changed

  • Reorganised the sidebar into Compute (Containers, Machines), Resources (Images, Mounts) and Networking (DNS, Networks), with Machines a first-class peer of Containers.

Fixed

  • Container machines' backing containers no longer appear as unexplained entries in the container list - they're now filtered out, matching the container CLI.
2.1.1

Changed

  • Updated for Apple's container 1.1.0. Orchard now builds against the 1.1.0 client libraries (previously 0.12.3), which had many breaking API changes across the 1.0 release; container 1.0.0 or later is now required.

Fixed

  • Stop, force-stop, and remove container actions work again on container 1.0.0 and later. Orchard was still linking the pre-1.0 client, so these commands silently failed against a 1.x daemon and the container never stopped (#54).
  • The System pane in Settings no longer stays stuck on "Loading…". container 1.0 changed system property list --format=json from a flat array to a nested object keyed by category, which the parser didn't recognise, so every daemon property read as missing.
1.12.7

Added

  • App preferences now live in a native Settings window (⌘,), split into a General pane (terminal application, container-binary path, default DNS domain, and software updates) and a System pane showing the read-only container daemon properties (Rosetta, image builder/init, kernel, registry).

Changed

  • Configuration moved out of the sidebar into the Settings window (⌘,); the sidebar no longer has a Configuration tab.

Fixed

  • Daemon system properties no longer stay stuck on "Loading…" and the default DNS domain shows its current value again - container system property list now returns a JSON array, which the parser didn't recognise, so it read no values at all.
  • The sidebar no longer stays greyed-out after you open and dismiss a right-click menu on a container.
1.12.6

Added

  • Live resource charts for every container - CPU, memory, network, and disk over time - on the container Overview, plus a system-wide dashboard in the Dashboard view that sums usage across all containers. Charts have selectable time windows (5m / 15m / 1h / 24h) and hover tooltips, and the container list gains a per-row CPU sparkline.
  • Real CPU usage percentage (previously a placeholder that always read 0%). Stats are sampled continuously in the background and the history is saved between launches, so the longer time windows have data to show. Sampling pauses while the app is hidden to save resources.
  • A redesigned menu-bar panel: CPU and memory usage rings across all running containers, a per-container list with start/stop controls, and hover-to-reveal history panels (per container, and system-wide) showing the last hour of CPU and memory.

Changed

  • Redesigned the container detail view into a single scrolling page (no more Overview/Environment/Mounts/Logs tabs): the resource metrics show as CPU, Memory, Network, and Disk panels pairing current values with their graph (network/disk graphs plot inbound above the axis and outbound below), and the remaining configuration sits in boxed sections below. Environment values are hidden until you click Show, and the image reference now appears under the container name in the header. Logs and Edit Configuration moved into the header, and the Logs button opens on the container you're viewing.
  • Reworked the Stats tab into a Dashboard - now the default view when the app opens - with disk-usage headline tiles, per-metric panels (CPU / Memory / Network / Disk) each pairing current values with a graph, and per-metric sparklines in the container table.
  • Copy controls across the app now read "Copy" and confirm with "Copied" instead of an icon.
  • Ongoing performance and maintainability improvements to the app's internals - views now refresh only when the data they display actually changes.
  • Refactored the internals: the monolithic container service was split into focused per-domain services with each view observing only what it needs, the Run and Edit container forms now share one implementation, and a UI smoke-test harness was added. No user-facing behaviour change.

Fixed

  • Network subnet validation now rejects out-of-range addresses (e.g. 999.999.999.999/24); each octet must be 0–255.
1.12.5

Changed

  • Expanded automated test coverage across the service layer (image, network, builder, container lifecycle/recovery, model mapping, and settings), and hardened the test suite for reliability. No user-facing behaviour change.
1.12.4

Added

  • Sidebar badges showing counts at a glance: running containers, and the number of images, mounts, DNS domains, and networks.
  • Diagnostic logging via Apple's unified logging system - filter by subsystem dev.andon.orchard in Console.app when troubleshooting.
  • Continuous integration: the unit test suite runs on every pull request and must pass before a release can ship.

Fixed

  • Failed actions no longer fail silently. Many operations that failed wrote an error message that most views never displayed, so buttons could appear to do nothing (#54). Errors now appear in a standard alert.
  • Fixed potential crashes when adding or editing a container's port mappings, volume mounts, or environment variables, and when validating a container name.
  • Builder status and container stats failures are no longer silently ignored.
  • CLI commands (builder, DNS, kernel, and system-property operations, including the admin-password prompt for DNS changes) now run off the main thread, so the UI no longer freezes while they execute.
1.12.3

Added

  • Automatic in-app updates via Sparkle. Orchard now checks for updates in the background (after asking on first launch) and can install them in place; "Check for Updates…" is also available from the menu. Updates are delivered through an EdDSA-signed appcast.

Changed

  • The previous manual "check GitHub releases for a newer version" prompt has been replaced by Sparkle.
1.12.2

Fixed

  • System properties no longer get stuck on "Loading…" (wrong JSON format).
  • Tab controls are now clickable across their entire area.

Changed

  • Use relative shell paths instead of absolute paths.
1.12.1

Added

  • Bulk actions for containers.
1.12.0

Added

  • Support for Apple container 0.12.x.
1.11.7

Added

  • Diagnostics view to help troubleshoot setup issues.
1.11.6

Added

  • Automatic detection of common container binary locations, with a setting to override the path.
1.11.5

Changed

  • Larger hit areas for controls for easier clicking.
1.11.4

Added

  • Application icon.
  • Homebrew installation instructions.
1.11.3

Added

  • User-selectable terminal application for attaching a container shell.
1.11.2

Added

  • Additional image information in the image detail view.

Removed

  • System logs and registries views.
1.11.1

Added

  • Release builds are now code-signed with a Developer ID certificate and notarized by Apple.
1.11.0

Added

  • Migrated to the Apple container XPC API for most operations (no longer shells out to the CLI).
  • Multi-pane log viewer with split panes (one container's logs per pane).
  • Force stop action in the container list.
  • Sortable stats table, and sortable container and image lists.
  • MIT license.

Changed

  • Improved log viewer performance.
1.7.3

Fixed

  • Include stopped and pending containers in the container list (container ls -a).
1.7.2

Fixed

  • Running containers not appearing in the container view.
1.7.1

Added

  • Option to keep using the app when a newer version of container is available.

Changed

  • Updated the supported container version.
1.7.0

Added

  • DNS domain management.
  • Container resource stats - CPU, memory, disk, and network - with a sortable stats table.
  • Name-uniqueness check when launching containers.

Changed

  • Renamed "Settings" to "Configuration".
  • Unified content into a single detail view, removed tabs, and made numerous list/table UI improvements.
1.6.0

Added

  • Network management views.
  • System properties and system settings.
  • Published ports and hostname opening.
  • Choose a DNS domain when launching a container.
1.1.8

Added

  • Image Search and Download: New feature to search Docker Hub for container images and download them directly from the UI
    • Search interface with Docker Hub integration
    • Pull progress tracking with visual feedback
    • Quick search suggestions for popular images (nginx, postgres, redis, alpine)
    • Displays official images with badges and star counts
    • Shows which images are already downloaded
    • Automatic image list refresh after successful pulls
  • Run Container from Image: New feature to run containers directly from images with comprehensive configuration options
    • "Run Container" button in image detail view and search results
    • Configuration dialog with tabbed interface for easy navigation
    • Basic settings: container name, detached mode, auto-remove options
    • Port mappings: map container ports to host ports with TCP/UDP protocol selection
    • Volume mounts: bind mount host directories into containers with read-only option
    • Environment variables: set custom environment variables
    • Advanced options: working directory and command override
  • Delete Images: Added ability to delete downloaded images
    • "Delete" button in image detail view (only shown if image is not in use)
    • Context menu delete option in image list
    • Safety check: prevents deletion if image is in use by any container
    • Confirmation dialog before deletion
  • Edit Container Configuration: Added ability to edit stopped containers
    • "Edit Configuration" button appears for stopped containers
    • Pre-filled configuration dialog with all current settings
    • Edit ports, volumes, environment variables, working directory, and commands
    • Container is automatically deleted and recreated with new settings
    • Warning banner explains the recreation process
  • Terminal Attachment: Added ability to attach terminal to running containers
    • "Terminal" button with dropdown menu in toolbar for running containers
    • Choose between sh (default shell) or bash
    • Opens in Terminal.app with interactive session
    • Context menu option to open terminal from container list

Changed

  • Settings page deprecated: You can no longer access them in the main window
    • Loading state now displays to prevent jarring view changes
    • Now requires 0.6.0 and checks the CLI version for compatibility

Fixed

  • Fixed image commands to use correct CLI syntax for container 0.6.0 (container image pull and container image list instead of plural images)
0.1.7

Note: this release was also tagged v1.1.7 by mistake.

Added

  • Split settings into separate views.

Changed

  • Improved DNS domain loading and validity handling.

Removed

  • Registry management.
0.1.6

Changed

  • Removed a conflicting keyboard shortcut.
0.1.5

Added

  • Labels tab in the container view.

Changed

  • Lowered the minimum macOS requirement to 15.0+.
0.1.4

Fixed

  • Release pipeline fixes.
0.1.3

Changed

  • Release process tweaks.
0.1.2

Fixed

  • Corrected permissions in the release workflow.
0.1.1

Changed

  • Updated the release GitHub Action.
0.1.0

Added

  • Initial release - a native macOS GUI for Apple's container tooling, including:
    • Container management (start, stop, view, mounts, logs)
    • Image management and image views, with filtering
    • Multi-container logs viewer
    • Builders / BuildKit and kernel support
    • DNS controls and registry management
    • System status and menu bar integration