klimax is now marina. Same tool, new name since v0.3. Existing install? Migrate with marina migrate →
Documentation menu

CLI reference

One binary, a handful of verbs. VM lifecycle on top, cluster and registry management below. Every command and flag here is taken straight from the binary's own help text.

Global usage

Persistent flags apply to every command. --config (short -c) points at an alternate config file; it defaults to ~/.marina/config.yaml.

$ marina [-c ~/.marina/config.yaml] [--debug] [--lima-log-level <level>] <command>
FlagDescription
-c, --config <path>Path to the marina config file (default ~/.marina/config.yaml).
--debugEnable marina debug logging — and surface Lima's own logs at info.
--lima-log-level <level>Show the embedded Lima VM logs at this level: trace, debug, info, warn, error, or off. Hidden by default.
📖

This page is a curated summary. For the authoritative, always-current flag list run marina <command> --help — the binary is the source of truth.

Logging

marina's own output uses Go's log/slog; the embedded Lima library logs through logrus. By default marina quiets Lima to error, so you see marina's messages plus any genuine Lima errors — the noisy INFO[…]/WARN[…] Lima lines are hidden. Turn them on when you need to debug the VM itself:

You want…Run
Default — quiet Lima, marina only(nothing — this is the default)
marina debug + Lima at infomarina --debug <command>
Lima at a specific levelmarina --lima-log-level info <command>
Full Lima firehosemarina --lima-log-level trace <command>
Silence Lima entirely (panic-only)marina --lima-log-level off <command>
# See what Lima is doing while the VM comes up
$ marina --lima-log-level info up

# marina debug detail, with Lima surfaced at info
$ marina --debug up
🔎

An explicit --lima-log-level wins over --debug. Levels: trace · debug · info · warn · error · off (none/quiet/silent also work). VM readiness detection is unaffected — the in-VM hostagent keeps its own verbose logs regardless.

VM lifecycle

CommandDescription
marina upCreate/start the VM, provision Docker, create kind clusters, set up routing (idempotent). Alias start.
marina migrateMove a klimax installation (~/.klimax) over: deletes the klimax VM, moves the config and registry cache. --dry-run shows the plan; -y skips the prompt. See Coming from klimax.
marina downStop the VM; every cluster stops with it. Cluster state and registry cache data are preserved (aliases stop, d).
marina down --remove-routeAlso remove the macOS host route (requires sudo).
marina destroyDelete kind clusters, delete the VM, and remove the macOS route.
marina statusShow VM state, host mounts, clusters, route, and iptables rule presence (-o text/json/yaml).
marina doctorDiagnose issues and print actionable fix commands (-o text/json/yaml).
marina doctor --fixApply the repairs marina can perform itself: host route, iptables exemption, guest IP forwarding.
marina shellOpen an interactive SSH session in the marina VM (alias ssh).
marina shell <cmd> [args…]Run a command in the VM and exit with its exit code.
marina copy <src>… <dst>Copy files between the host and the VM over scp (alias cp).
marina disk resize <size>Grow the VM disk — applied on the next VM start.
marina disk resize-image <size>Grow the persistent image-cache disk (vm.imageDisk) in place, keeping the cached images. VM must be stopped.
marina pruneRemove marina's reclaimable cached files.
marina config editOpen the marina config file in $EDITOR.
marina versionPrint the marina version.
# Bring everything up — prompts for sudo once to add the host route
$ marina up

# Stop the VM but keep clusters and cache
$ marina down

# Same pair, under the names Lima and colima use
$ marina start
$ marina stop

# Tear it all down: VM, clusters, and the host route (sudo)
$ marina destroy
⚠

marina down keeps the host route in place. Use --remove-route (or marina destroy) to drop it — either requires sudo. To stop being prompted at all, install the sudoers rules.

⬆

After upgrading marina, re-create the VM. Provisioning is baked into the binary, so marina down/up on an existing VM keeps running the old setup. Run marina destroy && marina up once after each brew upgrade --cask marina — the host-backed image cache survives, so it rebuilds fast.

Running commands in the VM

Bare marina shell opens an interactive session. Give it a command and it runs that in the VM instead, passing stdin/stdout/stderr straight through and exiting with the remote exit code — so it composes in pipelines and if tests without reaching for limactl.

FlagDescription
-t, --ttyForce pseudo-terminal allocation — for commands that need one (htop, an editor).
$ marina shell                                # interactive session
$ marina shell docker ps -a                   # flags after the command are passed through
$ marina shell -- bash -c 'kind get clusters' # -- when a flag could look like marina's
$ cat setup.sh | marina shell bash -s         # stdin is piped in
$ marina shell -t htop                        # force a pseudo-terminal
⛓

Flag parsing stops at the first positional argument, so marina shell docker ps -a works as typed — the -a goes to docker, not to marina. Use -- only when the first word could be mistaken for a marina flag. Because the exit code is the remote command's, if marina shell test -e /run/docker.sock; then … behaves like a local test.

Copying files

Moves files in either direction over scp. Mark the VM side with a vm: prefix (the VM's configured name works too); exactly one side of the copy must carry it.

FlagDescription
-r, --recursiveCopy directories recursively.
$ marina copy ./script.sh vm:/tmp/script.sh   # host → VM
$ marina copy vm:/tmp/out.json ./out.json     # VM → host
$ marina copy -r ./manifests vm:/tmp/          # directories
$ marina copy a.yaml b.yaml vm:/tmp/           # many sources → a directory
📁

Multiple sources are allowed when the destination is a directory. To copy within the VM, use marina shell cp … — two vm: sides are rejected.

Growing the disk

Grows the VM disk without recreating the VM. The new size is written to vm.disk in the marina config and to the Lima instance config; Lima expands the image on the next start and the guest root filesystem grows during boot. So it lands after a restart:

$ marina disk resize 80GiB   # rewrites vm.disk and the Lima instance config
$ marina down && marina up   # Lima expands the image; the guest FS grows on boot
$ marina shell df -h /       # confirm the new headroom

The image-cache disk (vm.imageDisk, mounted over /var/lib/containerd) is a separate disk and grows with its own command. Images live there rather than on the root disk, so this is usually the one that fills. It must be stopped first — Lima locks the backing file while an instance holds it:

$ marina down
$ marina disk resize-image 30GiB   # keeps the cached images
$ marina up                        # guest partition and filesystem grow on boot
💾

Raising vm.imageDisk in the config on its own does nothing to a disk that already exists — the size applies when the disk is first created. marina up warns when the two disagree and quotes the command above.

⚠

Shrinking is refused — neither Lima nor the guest filesystem supports it. Requesting the current size is a no-op. If the VM doesn't exist yet, only the config is updated and the next marina up creates the disk at the new size.

Reclaiming space

Removes files marina can re-create: superseded Lima guest agents under ~/.marina/share/lima, and registry cache directories whose mirror is no longer in your config (after renaming or removing one). It lists what it found, grouped and sized, and confirms before deleting.

FlagDescription
--dry-runShow what would be removed, remove nothing.
--downloadsAlso clear Lima's image download cache — shared with every other Lima instance on the host.
-y, --yesSkip the confirmation prompt (required to run non-interactively).
$ marina prune --dry-run     # show what would go
$ marina prune               # confirm, then remove
$ marina prune --downloads   # also Lima's shared image download cache
⚠

--downloads clears a cache in the OS cache directory that Lima shares across tools — limactl, Colima, Rancher Desktop. Their next start re-downloads its base images too.

❄

Caches of configured mirrors are never touched by prune — that's marina registry clean-cache. And prune keeps the guest agent matching the Lima version of the binary you run it with, so pruning with a different marina build removes that build's agent; harmless, it re-downloads on its next marina up.

Host setup

Two commands that configure the Mac rather than the VM: one grants marina up the single privilege it needs, the other starts the VM at login.

CommandDescription
marina sudoersPrint a sudoers snippet so marina up can manage the host route without a password.
marina sudoers --checkReport whether those rules are in effect.
marina autostart installInstall and load a per-user launchd agent that runs marina up at login.
marina autostart statusShow whether the agent is installed and loaded.
marina autostart uninstallUnload and remove the agent (alias remove).

Passwordless host route

marina up needs root for exactly one thing: the macOS route for the kind bridge CIDR. marina sudoers prints NOPASSWD rules scoped to those two /sbin/route invocations — the add and the delete, with the gateway wildcarded, because macOS assigns the VM's lima0 IP dynamically. Grant that and up stops prompting:

$ marina sudoers | sudo tee /etc/sudoers.d/marina >/dev/null
$ sudo chmod 0440 /etc/sudoers.d/marina
$ sudo visudo -c -f /etc/sudoers.d/marina   # verify the syntax
$ marina sudoers --check
✓ Passwordless route rules for 172.30.0.0/16 are in effect.
🔑

The rules are scoped to the configured CIDR, so regenerate them after changing network.kindBridgeCIDR. --check reads the sudo policy rather than trying the commands — a cached sudo credential would let a trial run succeed whether or not the rules exist.

Starting at login

Installs a per-user launchd agent, dev.marina.autostart, at ~/Library/LaunchAgents/ that runs marina up when you log in. Output is appended to ~/.marina/logs/autostart.log.

$ marina autostart install           # write the plist and load it
$ marina autostart install --print   # emit the plist to stdout instead
$ marina autostart status
$ marina autostart uninstall
🔑

Install the sudoers rules first. launchd cannot answer a password prompt, so without them the VM comes up at login without the host route and nothing in 172.30.0.0/16 is reachable from the Mac. marina sudoers --check confirms you're set.

🍺

The plist records the marina binary by the path you invoked — with the Homebrew cask that's the stable /opt/homebrew/bin/marina symlink, so the agent keeps working across brew upgrade --cask marina. The --config path is baked in the same way.

Docker access

Point your host's docker CLI at the daemon inside the VM, either per-shell with an environment variable or persistently with a Docker context.

CommandDescription
marina docker-envPrint the export command to point DOCKER_HOST at the marina VM.
marina docker-env --unsetPrint commands to unset the Docker environment.
marina docker-contextCreate/switch to the marina Docker context.
marina docker-context --unsetSwitch back to the default Docker context.
# Option A — environment variable, current shell only
$ eval $(marina docker-env)
$ eval $(marina docker-env --unset)

# Option B — Docker context, persistent across shells
$ marina docker-context
$ marina docker-context --unset
🐳

If DOCKER_HOST is set it overrides the active Docker context — use one or the other.

Clusters

Cluster lifecycle lives entirely under marina cluster — there is no cluster list in the config file. For declarative, multi-cluster workflows see Fleet management and the Fleet resource.

CommandDescription
marina cluster create <name>Create a new kind cluster in the running VM.
marina cluster apply -f <file>Create a fleet of clusters from a Fleet manifest (additive; honours dependsOn; --adopt relabels listed clusters that already exist).
marina cluster delete [name]Delete a kind cluster (interactive picker when no name is given).
marina cluster delete -f <file>Delete every cluster listed in a Fleet manifest (reverse-dependency order).
marina cluster delete -l <selector>Delete clusters whose nodes match a label selector.
marina cluster listList kind clusters running in the VM (filter with -l <selector>).
marina cluster label <name>Add, overwrite, or remove node labels on an existing cluster.
marina cluster e2e-test-nginxDeploy nginx and curl it via LoadBalancer to verify the cluster end-to-end.
marina cluster use / mergeDeprecated — use kubeconfig env / merge (or kubeconfig use to switch context).

cluster create flags

FlagDescription
--region <r>topology.kubernetes.io/region label (default europe-west<N>).
--zone <z>topology.kubernetes.io/zone label (default europe-west<N>-b).
-l, --label <k=v>Extra node label; repeatable. All nodes also get managed-by=marina.

The cluster num (subnet/port slot) is always auto-assigned to the lowest free value. To pin one, use a Fleet manifest's per-cluster num: field.

$ marina cluster create dev
$ marina cluster create dev --region us-east1 --zone us-east1-a
$ marina cluster create dev -l team=search -l env=dev

Fleets — apply & delete -f

Create or tear down a whole fleet of clusters from one Fleet manifest. apply is additive — it creates the clusters that don't exist yet, in dependsOn order, up to maxParallel at a time — and never mutates running clusters.

FlagApplies toDescription
-f, --filename <path>apply, deletePath to a Fleet manifest; - reads stdin.
--dry-runapplyValidate and print the resolved plan, then exit without creating anything.
--max-parallel <N>applyOverride spec.maxParallel (concurrent cluster creations).
-y, --yesdeleteSkip the confirmation prompt.
$ marina cluster apply -f fleet.yaml --dry-run   # preview the plan
$ marina cluster apply -f fleet.yaml              # create what's missing
$ cat fleet.yaml | marina cluster apply -f -      # from stdin
$ marina cluster delete -f fleet.yaml -y          # tear the fleet down

Listing, switching, merging

cluster list takes -o / --output with text (default), json, or yaml, and -l / --selector to filter by a kubectl-style node-label selector.

$ marina cluster list
$ marina cluster list -o json
$ marina cluster list -l env=dev                    # filter by label selector
$ marina cluster list -l marina.run/fleet=dev-fleet

Pointing kubectl at a cluster now lives under marina kubeconfig:

# Use one cluster's isolated kubeconfig in this shell
$ eval $(marina kubeconfig env dev)

# Or merge it into ~/.kube/config and switch to it
$ marina kubeconfig use dev

Labeling clusters

Relabel the nodes of a cluster that's already running — no recreate needed. Repeatable -l key=value sets or overwrites a label (--overwrite is the default); -l key- removes one. It runs kubectl label nodes --all under the hood.

$ marina cluster label dev -l tier=frontend -l disktype=ssd
$ marina cluster label dev -l disktype-              # remove the label

Deleting clusters

Pass a name to delete one cluster, run it bare for an interactive multi-select picker, or match a set with -l / --selector (confirms unless -y).

$ marina cluster delete staging
$ marina cluster delete                    # interactive picker (Space toggles)
$ marina cluster delete -l env=test --yes   # delete all matching, no prompt

End-to-end smoke test

Runs against your current kubectl context. --cleanup removes the test workload instead of deploying it.

$ marina cluster e2e-test-nginx
$ marina cluster e2e-test-nginx --cleanup   # delete the nginx pod and service

Kubeconfig

Every cluster keeps an isolated kubeconfig. The marina kubeconfig family (alias marina kc) prints its path, exports it, or merges it into your default ~/.kube/config.

CommandDescription
marina kubeconfig path <name>Print the path to the cluster's kubeconfig file.
marina kubeconfig env <name>Print export KUBECONFIG=<path> — eval it to use the cluster's isolated kubeconfig in the current shell.
marina kubeconfig merge <name>Merge the cluster's context into ~/.kube/config.
marina kubeconfig use <name>Merge and switch the active kubectl context to it.
marina kubeconfig remove <name>Remove the cluster's context, cluster, and user from ~/.kube/config (alias rm).
$ eval $(marina kubeconfig env dev)   # use dev's isolated kubeconfig here
$ marina kubeconfig use dev           # merge + switch active context
$ marina kubeconfig path dev
$ marina kubeconfig remove dev        # clean it out of ~/.kube/config
♻

marina cluster use and cluster merge still work as deprecated aliases — cluster use maps to kubeconfig env, cluster merge to kubeconfig merge. Prefer the kubeconfig forms.

Fleets

The top-level marina fleet command operates on live clusters grouped by the marina.run/fleet=<name> node label (membership is derived from running clusters, not the manifest). See Fleet management and the Fleet resource.

CommandDescription
marina fleet listGroup clusters by marina.run/fleet (-o text/json/yaml).
marina fleet describe <name>Show a fleet's members with their num, ports, nodes, and labels (aliases desc, show).
marina fleet create -f <file>Create a manifest's clusters — delegates to cluster apply -f (--dry-run, --max-parallel, --adopt).
marina fleet adopt <name> <cluster>…Adopt running clusters into a fleet by setting their marina.run/fleet node label.
marina fleet export [cluster…]Write a Fleet manifest describing live clusters — by name, by -l selector, or from an interactive picker.
marina fleet delete <name>Delete a fleet's clusters, resolved by label (-y to skip the prompt).
marina fleet delete -f <file>Delete a manifest's clusters — same as cluster delete -f.
marina fleet label <name> -l <k=v>Apply node labels to every cluster in the fleet (-l key- removes).
$ marina fleet list
$ marina fleet describe dev-fleet
$ marina fleet create -f fleet.yaml --dry-run
$ marina fleet adopt dev-fleet edge-1 edge-2
$ marina fleet create -f fleet.yaml --adopt    # relabel listed clusters that already exist
$ marina fleet label dev-fleet -l tier=frontend
$ marina fleet delete dev-fleet -y

DNS

Inspect the local DNS zone (network.dns, on by default).

CommandDescription
marina dns listList every published name and its IP. -o json|yaml for tooling.
marina dns attach <cluster>…Install ExternalDNS and the CoreDNS forward on clusters created before network.dns was on. Restarts their CoreDNS.
$ marina dns list
$ marina dns attach dev staging

CA

Manage marina's local certificate authority (network.dns.tls, on by default).

CommandDescription
marina ca statusRoot CA path, expiry and keychain trust, plus each cluster's and fleet's wildcard and its expiry. -o json|yaml for tooling.
marina ca certPrint the root CA certificate (PEM) — for a pod's or a tool's trust store.
marina ca attach <cluster>…Issue or renew the cluster's *.<cluster>.demo.internal wildcard and install it; adds the marina-ca ClusterIssuer when cert-manager is installed. Restarts the nodes' containerd to trust the root.
marina ca secret <cluster> -n <ns> [--fleet]Copy default/marina-wildcard-tls — or, with --fleet, the fleet's marina-fleet-wildcard-tls — into another namespace.
marina ca trust / untrustAdd or remove the root's trust in the macOS System keychain (sudo).
$ marina ca status
$ marina ca secret dev -n ingress-nginx
$ marina ca cert | kubectl create configmap marina-root-ca -n my-app --from-file=ca.crt=/dev/stdin

Registry

CommandDescription
marina registry clean-cacheRemove all registry mirror cache data and their containers.
$ marina registry clean-cache
$ marina up                       # restart the mirrors afterwards
❄

With the default cacheStorage: "host", mirror blobs live at ~/.marina/registry-cache/ and survive marina destroy. clean-cache is how you wipe them on purpose. See Registry mirrors.

Skill

Install the marina Agent Skill so AI coding tools like Claude Code know how to drive marina.

CommandDescription
marina skill installInstall the bundled SKILL.md into an AI tool's skills directory (Claude Code by default).
marina skill pathPrint where the skill is installed for Claude Code.
Flag (on install)Description
--claudeInstall into ~/.claude/skills/marina/ (default true).
--printWrite the skill to stdout instead of installing.
-f, --forceOverwrite an already-installed skill.
$ marina skill install            # → ~/.claude/skills/marina/SKILL.md
$ marina skill install --print     # emit to stdout for other tools
$ marina skill path

Completion

Generate a shell auto-completion script for bash, zsh, fish, or powershell.

# zsh — add to ~/.zshrc to persist
$ source <(marina completion zsh)

# bash
$ source <(marina completion bash)

# fish
$ marina completion fish > ~/.config/fish/completions/marina.fish

See also