Captain is a Kubernetes client for iOS that dynamically discovers every resource type in your cluster — CRDs included — and lets you browse, edit and delete any of them. With native auth for EKS, GKE and AKS. No backend, no agent, no compromise.
Captain doesn't ship a hard-coded list of resource kinds. It asks your cluster what it can do — and renders all of it.
All resource types are discovered live via /api/v1 and /apis/… — Pods, Deployments and every CRD your cluster defines. If the API server knows it, Captain shows it.
A Lens-style browser with collapsible categories: Cluster, Workloads, Config, Network, Storage, Access Control — and Custom Resources grouped automatically by API group.
Lists with namespace filter, pagination and search. Full YAML detail view, an in-app YAML editor (PUT/replace) and delete with confirmation.
Run one-shot commands in any container over the kubectl exec WebSocket protocol (v4.channel.k8s.io) — natively, with full cluster-CA trust and quick-command chips.
A local TCP listener (Network.framework) bridges onto the cluster's portforward WebSocket endpoint. Active forwards show up in the Browse tab and can be stopped individually.
Node and pod usage via the metrics-server API (metrics.k8s.io): CPU/memory bars in the node list, a CPU column in the pod list. Hides itself automatically when metrics-server isn't installed.
Captain auto-discovers Prometheus in the cluster and queries it through the API-server proxy — no extra networking or auth. One-hour CPU/memory sparklines and currently firing alerts, sorted by severity.
Paste a kubeconfig, pick contexts, done — or scan it as a QR code. Exec plugins (aws, gke-gcloud-auth-plugin, kubelogin) are detected and mapped to the matching native auth method.
A dark indigo theme with soft gradient cards, iOS-Settings-style squircle icons, a health-ring dashboard, a floating tab bar and bottom sheets for cluster and namespace switching.
No CLI, no exec plugins, no jump host. Captain implements each provider's token flow directly on the device.
Captain produces k8s-aws-v1.… tokens on-device — the exact equivalent of aws eks get-token — and refreshes them automatically. Supports temporary STS credentials with a session token.
Sign in with Google using an iOS OAuth client. Refresh tokens are stored securely and renewed automatically.
Authenticates against the AKS AAD server app for clusters with managed Entra ID integration.
Use ServiceAccount tokens or any other bearer token for self-hosted and on-prem clusters.
PKCS#12 client certificates, handled natively via URLSession. The native KubeHttp module also validates server certificates against your cluster's own CA — essential for EKS, GKE and AKS endpoints.
Requirements: macOS with Xcode 16+, Node 20+, CocoaPods.
# clone the repository git clone https://github.com/dpfaffenbauer/captain.git cd captain npm install npx expo run:ios # builds the iOS app incl. the native KubeHttp module
kubectl create serviceaccount captain -n kube-system kubectl create clusterrolebinding captain \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:captain kubectl create token captain -n kube-system --duration=8760h
kubectl config view --minify --raw | qrencode -t png # scan it in Captain
npx expo run:ios). In Expo Go, Captain falls back to fetch(),
which only works against API servers with a publicly trusted certificate.
For a physical device, set a signing team in Xcode or run
npx expo run:ios --device.
A TypeScript app on Expo Router, with a small native Swift module where iOS networking needs to go beyond what JavaScript can do.
app/ Screens (expo-router) index.tsx Cluster overview cluster-form.tsx Add/edit clusters incl. cloud auth kubeconfig-import.tsx Kubeconfig import cluster/[id]/index.tsx Resource types (discovery, grouped, search) cluster/[id]/list.tsx Resource lists (namespace, pagination, search) cluster/[id]/item.tsx YAML detail, editor, delete src/ auth/ EKS SigV4, Google/Azure OAuth, token cache kube/ Transport, discovery, CRUD, kubeconfig parser, metrics-server + Prometheus state/, storage/, ui/, util/ modules/kube-http/ Native iOS module (Swift): TLS with custom CA, insecure-skip-verify, mTLS via PKCS#12
There is no backend. Captain talks directly to your API server — nothing else ever sees your cluster.
Keychain only. All credentials are stored exclusively in the device's iOS Keychain via expo-secure-store.
Real TLS validation. Server certificates are checked against the cluster CA through a native URLSession delegate. Skipping TLS is possible — but clearly flagged as insecure.
Direct connection. No proxy, no relay, no telemetry. The app speaks to the Kubernetes API server and nothing in between.