Real IPs. No port-forwarding.
klimax adds a single macOS route into the kind bridge CIDR, so every MetalLB LoadBalancer VIP is reachable directly from your Mac — curl http://172.30.1.200/ just works.
klimax spins up kind clusters on your Mac in under a minute, and makes their Services type LoadBalancer directly accessible from your laptop.
$ klimax up ✓ Lima VZ instance ready (38s) ✓ Docker provisioned (4s) ✓ macOS route 172.30.0.0/16 added ✓ Registry mirrors docker · quay · gcr $ klimax cluster create dev ✓ kind cluster dev api :7001 ✓ MetalLB pool 172.30.1.16-254 ✓ kubeconfig merged ~/.kube/config $ kubectl apply -f nginx.yaml deployment.apps/nginx created service/nginx exposed $ kubectl get svc nginx NAME TYPE EXTERNAL-IP PORT(S) nginx LoadBalancer 172.30.1.200 80:31408/TCP $ curl http://172.30.1.200/ <h1>Welcome to nginx!</h1> ← from your Mac, no port-forward ▌
Why
Years of running kind clusters on a MacBook, distilled into one CLI. klimax inherits the engine that the cool kids run on (Lima + Apple VZ) and adds the missing layer: real-IP routing, multiple clusters side by side, and pull-through registry caches.
klimax adds a single macOS route into the kind bridge CIDR, so every MetalLB LoadBalancer VIP is reachable directly from your Mac — curl http://172.30.1.200/ just works.
Each cluster gets its own API port, service subnet, pod subnet, and MetalLB pool slice. Run dev, staging, and prod side by side on the same VM. Switch with kubectx — or declare a whole fleet in one manifest and klimax cluster apply -f.
Built on Lima's VZ driver — Apple Virtualization framework, vzNAT networking, virtiofs mounts. Cold start under a minute. No Hypervisor.framework overhead, no qemu emulation.
Pull-through mirrors for docker.io, quay.io, gcr.io ship pre-configured. Cluster image pulls hit local disk after the first run. Goodbye Docker Hub rate limits.
One Go binary. Downloads the Lima guest agent on first run and caches it. No limactl, no kind, no docker CLI required on the host.
Coexists with OrbStack, Docker Desktop, Colima, and Rancher Desktop out of the box — Lima port mirroring is off by default (disablePortMirroring), so klimax never races other Lima VMs for the same loopback ports.
Demo
One command brings up the VM, installs Docker, wires the routing, and starts the registry mirrors. A second command creates a cluster and merges its kubeconfig. That's the whole workflow.
Upgrading klimax? After brew upgrade --cask
klimax, re-create the VM so the new release re-provisions it:
klimax destroy && klimax up. The host-backed image cache
survives, so it rebuilds fast. See the
docs.
Under the hood
Your Mac, a Lima VZ guest, and a Docker bridge — that's the entire topology. klimax adds a host route into the kind bridge CIDR, an iptables nat-exemption inside the VM, and DOCKER-USER forward rules so kind→host traffic exits without SNAT. Source IPs are preserved end to end.
curl 172.30.1.200/ on your Mac → vzNAT → guest lima0 → Docker bridge → MetalLB VIP. No SNAT, no port-forwarding, no VPN.
Get it
$ brew tap bcollard/klimax
$ brew trust --tap bcollard/klimax
$ brew install --cask klimax
$ klimax up
# Bring up the VM + Docker + routing + registries (idempotent)
$ klimax up
# Create clusters
$ klimax cluster create dev
$ klimax cluster create staging
# List, switch, delete
$ klimax cluster list
$ kubectx dev
$ klimax cluster delete # interactive multi-select picker
# End-to-end smoke test
$ klimax cluster e2e-test-nginx
# Stop the VM (preserves clusters and registry cache)
$ klimax down
The macOS app
klimax-ui is a SwiftUI companion app: a dashboard for every cluster, registry, and VM resource klimax manages — with live charts, kubeconfig copy buttons, and a cluster creator that streams the build log as it runs.
Cluster overview. Every kind cluster, its API port, kubeconfig path, age, and quick actions in one place.
Live VM charts. CPU and memory for the Lima guest, sampled every 5 s over the SSH ControlMaster klimax already maintains — read straight from /proc.
Registry mirror inspector. Cache size and image count for every pull-through mirror in ~/.klimax/registry-cache/.
LoadBalancer probes. Every Service with an external IP gets a TCP reachability check — when it's up, the row turns into a clickable link.
$ brew tap bcollard/klimax
$ brew trust --tap bcollard/klimax
$ brew install --cask klimax-ui
$ open -a Klimax
FAQ
Those each solve one piece of the puzzle. klimax is opinionated about the whole stack: a single CLI that owns the VM, the kind clusters, the routing, the registry mirrors, and the kubeconfig wiring. The killer feature is real-IP routing: you reach pod IPs and LoadBalancer VIPs directly from your Mac without port-forwarding. See the detailed comparisons in the repo.
Yes, out of the box. klimax runs its own Lima VZ instance with a distinct vzNAT IP, so there is no IP-level conflict with other VMs. The one potential friction point — Lima port mirroring — is disabled by default (network.disablePortMirroring: true), so kubeconfigs use the VM's direct lima0 IP and never race other Lima-based tools for 127.0.0.1. Set it to false only if you run a single klimax VM and prefer stable loopback kubeconfigs.
macOS 13 Ventura or later — Apple Virtualization framework (vmType: vz) is required. Built and tested on Apple Silicon.
sudo?Only twice: klimax up adds a macOS host route (route add 172.30.0.0/16 …), and klimax destroy removes it. Everything else — VM lifecycle, cluster create/delete, registries — runs unprivileged.
Yes. klimax down stops the VM but preserves every cluster, its data, and the registry cache. klimax up brings them all back. klimax destroy is the explicit wipe.
No — that's exactly what the pull-through mirrors fix. After the first pull, blobs are served from ~/.klimax/registry-cache/ on your laptop. The mirrors survive klimax destroy.
Yes. Add username / password under any mirror in ~/.klimax/config.yaml. For locally built images there's no push registry — build against the VM's Docker (eval "$(klimax docker-env)") and load them into a cluster with kind load docker-image.