ozc is a small command that hosts plugins. Install one by its name and it is there: a k3s cluster over SSH, apps as tables in a TOML file, certificates, secrets, storage. The host keeps them on one version and brings them up to date together.
They are published with ozc, at its version, and installed by name: ozc install kube. A plugin loads only in the host it was built for, so an upgrade is one line and never a mismatch.
Everything ozc does is written down first, in a directory of TOML files beside the project. The commands read it; nothing is typed twice, and a second machine runs the same lines.
[app.web]
namespace = "ozaco"
image = "ozaco/web"
tag = "2026-10-12"
port = 80
domain = ["ozaco.com", "www.ozaco.com"]
tls = "web-tls"
issuer = "letsencrypt"
What that table becomes
A Deployment and a Service for the image, an Ingress for both names with one certificate issued into the secret, and a namespace made when it is missing. Add a volume, a dependency such as Postgres, or a one-shot job, and the table grows by a few lines; the objects follow.
Homebrew keeps ozc on macOS; a script keeps it on Linux and Windows. Everything else is installed by ozc itself, by the name it is released under.
once, before the first install: make the tap known to Homebrew
brew tap ozaco/apps https://github.com/ozaco/apps
ozc, as a formula — Homebrew brings it up to date
brew install ozc
then a plugin, by name
ozc install kube
or ozaOS, the same way — the daemon and the command, and off macOS the window too
ozc install ozaos