cloudctl is a CLI for managing Kubernetes cluster access via Greenhouse. It keeps your local kubeconfig in sync with the clusters registered in your Greenhouse organization — so kubectl just works.
- Syncs kubeconfigs — fetches
ClusterKubeconfigresources from Greenhouse and merges them into your local~/.kube/config, handling OIDC token caching, deduplication, and prefix-based entry management - Reports cluster versions — queries the Kubernetes API version of any context, trying unauthenticated first for speed
- Self-updates — checks for and installs the latest cloudctl release from GitHub
- Structured output — every command supports
--output text|json|yamlfor scripting and pipelines; interactive terminals get a spinner and a colour-coded table
Download the latest binary from the releases page, place it on your PATH, and make it executable:
# macOS / Linux
curl -Lo cloudctl https://github.com/cloudoperators/cloudctl/releases/latest/download/cloudctl-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m)
chmod +x cloudctl
sudo mv cloudctl /usr/local/bin/Or build from source (requires Go 1.25+):
git clone https://github.com/cloudoperators/cloudctl.git
cd cloudctl
make install # installs to $GOBIN# Sync all clusters from a Greenhouse organization into your local kubeconfig
cloudctl sync --greenhouse-cluster-namespace <org>
# Sync a single cluster
cloudctl sync -n <org> --remote-cluster-name <cluster>
# Check the Kubernetes version of a context
cloudctl cluster-version --context <context>
# Print version info
cloudctl version
cloudctl version --output json # machine-readable
# Update cloudctl to the latest release
cloudctl updateAll commands accept -o / --output:
| Value | Description |
|---|---|
text |
Human-readable (default). Interactive terminals get a spinner and styled table. |
json |
Indented JSON — suitable for jq pipelines. |
yaml |
YAML — suitable for GitOps tooling. |
# Pipeline example
cloudctl version -o json | python3 -m json.tool
cloudctl sync -n <org> -o json | python3 -c "import sys,json; r=json.load(sys.stdin); print(r['synced'])"Logs are written to stderr so they never pollute stdout pipelines. By default only info-level messages appear.
| Flag | Values | Default |
|---|---|---|
--log-level |
debug, info, warn, error |
info |
--log-format |
text, json |
text |
# Show debug logs while syncing
cloudctl sync -n <org> --log-level debug
# Structured JSON logs (useful in CI)
cloudctl sync -n <org> --log-level info --log-format json 2>sync.logEvery flag can be set via an environment variable (prefix CLOUDCTL_, dashes become underscores) or a config file.
Environment variable example:
export CLOUDCTL_GREENHOUSE_CLUSTER_NAMESPACE=my-org
cloudctl syncConfig file — searched in order, first match wins:
- Path given by
--configor$CLOUDCTL_CONFIG ./.cloudctl.yamlor~/.cloudctl.yaml./cloudctl.yamlor~/cloudctl.yaml$XDG_CONFIG_HOME/cloudctl/cloudctl.yamlor$XDG_CONFIG_HOME/cloudctl.yaml(falls back to~/.config/cloudctl/cloudctl.yamlor~/.config/cloudctl.yamlwhen$XDG_CONFIG_HOMEis unset)
Example ~/.cloudctl.yaml:
greenhouse-cluster-namespace: my-org
greenhouse-cluster-kubeconfig: /home/user/.kube/greenhouse.yaml
auth-type: exec-plugin
log-level: infoFetches ClusterKubeconfig resources from Greenhouse and merges them into your local kubeconfig. Before connecting, it logs a summary to stderr showing which kubeconfig files, context, and namespace are in use.
The --greenhouse-cluster-kubeconfig and --remote-cluster-kubeconfig flags support the standard KUBECONFIG environment variable: when no explicit path is given, cloudctl defers to KUBECONFIG (multi-file merge, same as kubectl).
cloudctl sync -n <org> [flags]
Flags:
-k, --greenhouse-cluster-kubeconfig Path to Greenhouse cluster kubeconfig (default: $KUBECONFIG or ~/.kube/config)
-c, --greenhouse-cluster-context Context inside the Greenhouse kubeconfig
-n, --greenhouse-cluster-namespace Greenhouse organization namespace (required)
-r, --remote-cluster-kubeconfig Local kubeconfig to merge into (default: $KUBECONFIG or ~/.kube/config)
--remote-cluster-name Sync only this cluster (default: all ready clusters)
--prefix Prefix for managed kubeconfig entries (default: cloudctl)
--merge-identical-users Share a single auth entry for clusters with identical OIDC config (default: true)
--auth-type auth-provider or exec-plugin (default: exec-plugin)
--kubelogin-path Path to kubelogin binary (default: kubelogin)
--kubelogin-extra-args Extra flags passed to kubelogin
--kubelogin-token-cache-dir OIDC token cache directory
--dry-run Preview changes without writing to the kubeconfig file
Queries the Kubernetes server version for a given kubeconfig context. Tries an unauthenticated request first; falls back to an authenticated one if needed. Logs a summary to stderr showing the kubeconfig source and context before querying.
Respects the KUBECONFIG environment variable when no explicit --kubeconfig path is given.
cloudctl cluster-version [flags]
Flags:
-k, --kubeconfig Path to kubeconfig file (default: $KUBECONFIG or ~/.kube/config)
-c, --context Context to query
--timeout Maximum time to wait for the API server (default: 10s)
Prints cloudctl build information.
cloudctl version [flags]
Flags:
--short Print only the version number
Checks for the latest cloudctl release on GitHub and installs it, replacing the current binary.
cloudctl update [flags]
Flags:
--check Check for a newer version without installing it
This project is open to feature requests, bug reports, and contributions via GitHub issues and pull requests. See CONTRIBUTING.md for guidelines.
If you find a security issue, follow the instructions in our security policy. Do not open GitHub issues for security-related problems.
By participating in this project you agree to abide by the SAP Open Source Code of Conduct.
Copyright 2025 SAP SE or an SAP affiliate company and cloudctl contributors. See LICENSE for details. Third-party licensing information is available via the REUSE tool.