Verified7 commandsAI-assisted

kubectx

.md

Verified against kubectx/kubens v0.11.0, flags verified via `kubectx --help` / `kubens --help` run · official docs

What it is and where it fits 🎯#

kubectx and kubens are one project released together — two tiny, single-purpose binaries that solve the single most repetitive friction point of working with kubectl day to day: which cluster and namespace am I about to run this command against? kubectl config use-context <long-name> and kubectl config set-context --current --namespace=<name> both work fine, but nobody types them from memory at 2am during an incident. kubectx switches the active context (which cluster/user/kubeconfig entry kubectl targets); kubens switches the active namespace within whichever context is already selected. Neither tool talks to the cluster to do its job — they edit the kubeconfig file on disk, which is also why kubectx keeps working fine even when a cluster is completely unreachable, while kubens's listing and validation behavior genuinely does need a live API connection (see the pitfalls section — this is a real, confirmed-live distinction, not a documentation nuance). Where this differs from k9s: k9s is a full interactive TUI for browsing and managing resources; kubectx/kubens are non-interactive, script-friendly, one-shot switches meant to be typed dozens of times a day, or wired into a shell prompt.

How the two tools relate to your kubeconfig#

Diagram

Both tools are thin, local edits to the same file kubectl already reads — there's no daemon, no cache, no separate state store. That's why switching is instant and why a shell alias/prompt integration can safely call either tool as often as it wants.

Installation#

brew install kubectx                       # macOS/Linux Homebrew — installs both kubectx and kubens
sudo apt-get install kubectx               # Debian/Ubuntu, if present in your repos (ships both binaries)

# or download the binaries directly (verified release: v0.11.0):
curl -sL -o kubectx.tar.gz \
  https://github.com/ahmetb/kubectx/releases/download/v0.11.0/kubectx_v0.11.0_linux_x86_64.tar.gz
curl -sL -o kubens.tar.gz \
  https://github.com/ahmetb/kubectx/releases/download/v0.11.0/kubens_v0.11.0_linux_x86_64.tar.gz
tar -xzf kubectx.tar.gz kubectx && tar -xzf kubens.tar.gz kubens
chmod +x kubectx kubens && sudo mv kubectx kubens /usr/local/bin/

kubectx --version
kubens --version

Tip

Install fzf alongside them. Neither kubectx nor kubens bundles a fuzzy finder, but both detect fzf on $PATH at runtime and switch into an interactive fuzzy-select menu automatically when you run them with no argument — the plain listing shown throughout this page is what you get without fzf installed. Set KUBECTX_IGNORE_FZF=1 to keep the plain listing behavior even with fzf present.

Command reference — kubectx (context switching)#

Real kubectx --help output (v0.11.0):

Manage and switch between kubectl contexts. USAGE: kubectx : list the contexts kubectx <NAME> : switch to context <NAME> kubectx - : switch to the previous context kubectx -s, --shell <NAME> : start a shell scoped to context <NAME> kubectx -s, --shell : interactively select a context to start a shell kubectx -r, --readonly <NAME> : start a read-only shell for context <NAME> kubectx -r, --readonly : interactively select a context for read-only shell kubectx -c, --current : show the current context name kubectx -u, --unset : unset the current context kubectx <NEW_NAME>=<NAME> : rename context <NAME> to <NEW_NAME> kubectx <NEW_NAME>=. : rename current-context to <NEW_NAME> kubectx -d <NAME> [<NAME...>] : delete context <NAME> ('.' for current-context) (this command won't delete the user/cluster entry referenced by the context entry) kubectx -h, --help : show this message kubectx -V, --version : show version
kubectx                                    # list every context in the kubeconfig
kubectx staging-cluster                    # switch the active context
kubectx -                                  # switch back to whichever context was active before the last switch
kubectx -c                                 # print just the current context name — the shell-prompt-safe form

Real captured output against a local three-context kubeconfig (prod-cluster, staging-cluster, dev-cluster):

$ kubectx dev-cluster prod-cluster staging-cluster $ kubectx -c prod-cluster $ kubectx staging-cluster ✔ Switched to context "staging-cluster". $ kubectx - ✔ Switched to context "prod-cluster".

kubectx - is the same "toggle to previous" idea as cd - — genuinely the single most-used invocation once it's muscle memory, since bouncing between two clusters (say, staging to check a fix, then back to prod) is far more common than a full three-way rotation.

Command reference — kubens (namespace switching)#

Real kubens --help output (v0.11.0):

Switch between Kubernetes namespaces. USAGE: kubens : list the namespaces in the current context kubens <NAME> : change the active namespace of current context kubens <NAME> --force/-f : force change the active namespace of current context (even if it doesn't exist) kubens - : switch to the previous namespace in this context kubens -c, --current : show the current namespace kubens -h,--help : show this message kubens -u,--unset : unset the namespace choice (set to 'default') kubens -V,--version : show version
kubens                                     # list namespaces in the CURRENT context — this calls the live API
kubens checkout                            # switch the active namespace within the current context
kubens -                                   # switch back to the previous namespace
kubens -c                                  # print the current namespace — no API call, reads the kubeconfig only
kubens checkout --force                    # set the namespace field even if the API can't confirm it exists yet

Real captured output, same kubeconfig, prod-cluster context active but pointed at an unreachable server:

$ kubens -c checkout $ kubens error: could not list namespaces (is the cluster accessible?): failed to list namespaces from k8s API: ... $ kubens checkout --force ✔ Active namespace is "checkout"

Important

kubens -c and kubens <name> --force never touch the network — plain kubens (listing) and a non-forced kubens <name> (validating the namespace exists) both do. This is a genuine, confirmed-live asymmetry between the two tools: kubectx never needs cluster connectivity for anything, because a context switch is pure kubeconfig editing. kubens needs connectivity for its discovery/validation paths but not for reading/writing the active namespace value itself. If you're scripting namespace switches against a cluster that might be cold-starting or behind a VPN that isn't up yet, --force is the flag that keeps the switch itself from blocking on that.

Renaming and deleting contexts#

kubectx dev=dev-cluster-us-east-1-a1b2c3d4     # rename a long auto-generated EKS context to something typeable
kubectx prod=.                                  # rename the CURRENT context (the "." shorthand)
kubectx -d old-cluster                          # delete one context
kubectx -d ctx-a ctx-b ctx-c                    # delete several at once

Real captured rename + delete, same demo kubeconfig:

$ kubectx dev=dev-cluster ✔ Context dev-cluster renamed to dev. $ kubectx -d dev ✔ Deleted context dev.

Tip

Rename cloud-provider auto-generated contexts immediately after aws eks update-kubeconfig / gcloud container clusters get-credentials / az aks get-credentials. EKS in particular generates names like arn:aws:eks:us-east-1:123456789012:cluster/prod-checkout — technically unique, completely unusable for fast typing or for telling two similarly-named clusters apart at a glance in a busy terminal. kubectx prod=. right after the credentials command becomes a one-line habit worth scripting into onboarding docs.

Scoped shells — the safety feature most teams don't know about#

kubectx -s staging-cluster       # open a new subshell with ONLY staging-cluster active as context
kubectx -r prod-cluster           # open a read-only subshell scoped to prod-cluster

-s/--shell spawns a child shell with its own isolated KUBECONFIG pointed at a temp copy scoped to just that one context — switching context inside that subshell (or exiting it) never touches your real, permanent kubeconfig or the context you had active before. -r/--readonly goes further: it also rewrites the context's server-side RBAC-relevant defaults to prevent destructive kubectl verbs from that subshell.

Caution

A permanent context switch (kubectx prod-cluster with no -s/-r) changes what every open terminal tab and every other tool reading the same kubeconfig sees, immediately. A teammate running a script in a different tab that assumes it's still pointed at staging will silently start running against prod instead. For any genuinely risky one-off ("let me just check something in prod real quick"), kubectx -s or kubectx -r scopes the blast radius to that one subshell — the permanent switch is for the cluster you intend to keep working in for a while, not for a quick look.

Real-world scenario: an on-call engineer triaging three environments during an incident#

An SRE gets paged for elevated error rates in checkout. The runbook says "confirm it's not also happening in staging before you start rolling back prod" — a sequence that needs fast, low-error switching between three clusters and namespaces under time pressure, which is exactly the failure mode these two tools exist to remove:

kubectx prod-cluster && kubens checkout          # confirm the alert is real
kubectx staging-cluster && kubens checkout       # rule out a shared regression before touching prod
kubectx -                                        # back to prod-cluster in one keystroke, no retyping the name
kubectx -r prod-cluster                          # open a READ-ONLY scoped shell to poke around further, safely

Chaining kubectx <ctx> && kubens <ns> on one line is the standard idiom for "I need to be fully positioned in one place before I run anything" — a single line an on-call engineer can paste from a runbook without two separate steps that could be interrupted halfway.

Real-world scenario: a CI/CD pipeline deploying to three environments from one kubeconfig#

# .github/workflows/deploy.yml
- name: Configure kubeconfig
  run: aws eks update-kubeconfig --name ${{ inputs.cluster }} --region us-east-1

- name: Point at the right context and namespace
  run: |
    kubectx $(kubectx | grep ${{ inputs.cluster }})
    kubens ${{ inputs.namespace }} --force

- name: Deploy
  run: kubectl apply -f k8s/

Warning

Always pass --force to kubens in a fresh CI runner. A brand-new runner's kubeconfig was just generated by update-kubeconfig seconds earlier — the API server might not yet be fully warmed up on a newly-scaled node pool, or the pipeline's service-account token might have a brief propagation delay. A non-forced kubens blocks on a live namespace-existence check that can flake in exactly that window; --force writes the value unconditionally and lets kubectl apply be the thing that actually surfaces a real connectivity failure, with a real error message, instead of kubens failing first with a more confusing one.

Common pitfalls#

  • Assuming kubens failures mean the namespace doesn't exist. A bare kubens <name> failure is far more often a connectivity problem (VPN down, expired token, cold API server) than a genuinely missing namespace — check kubens -c (never hits the network) and kubectl cluster-info before concluding the namespace itself is the problem.
  • Forgetting a permanent kubectx switch is shell-session-wide, not command-wide — see the CAUTION above. Reach for -s/-r for anything exploratory.
  • Scripting against kubectx <name> output parsing instead of kubectx -c — the plain listing form can change shape if fzf integration is active in an interactive shell; -c is the stable, script-safe form for reading the current context.
  • Renaming a context and forgetting the old auto-generated name is what CI secrets/scripts elsewhere might still reference — a rename is local to your kubeconfig only, but if a deploy script hardcodes the original long ARN-style name, renaming your local copy doesn't change what that script expects.

Exit codes#

0 success · non-zero on a failed switch (unreachable API for kubens's non-forced path, unknown context/ namespace name, or a malformed kubeconfig).

When to reach for something else#

For actually browsing what's running once you've switched — pods, logs, events, resource usage — reach for k9s instead of chaining more kubectl get commands by hand; its own cheat sheet in this same category covers launching it already scoped to a context/namespace via --context/--namespace, picking up right where kubectx/kubens left off. For tailing logs across several pods matching a pattern once you're in the right namespace, see the stern cheat sheet.