KSW (Kubeconfig Switcher)

2 minute read

A while ago I created and published my own CLI tool to switch Kubeconfig. I wrote it in Go and it’s installable easily using Homebrew:

brew install chickenzord/tap/ksw

Project repo: https://github.com/chickenzord/ksw

How it works

When you run the command and pass the context’s name:

ksw context-name
  1. Try loading kubeconfig file from these locations:
    1. Path set in KSW_KUBECONFIG_ORIGINAL (more on this below)
    2. Path set in KUBECONFIG
    3. Default location $HOME/.kube/config
  2. Minify and flatten the config so it only contains clusters and users used by the specificed “context-name”, then put it in a temp file
  3. Start a new shell (same with the currently used) with KUBECONFIG set to the temp file
  4. Additionally, these environment variables also set in the sub-shell:
    • KSW_KUBECONFIG_ORIGINAL: To keep track of original kubeconfig file when starting recursive shells
    • KSW_ACTIVE: Always set to “true”
    • KSW_SHELL: Path to the shell (e.g. /bin/zsh)
    • KSW_LEVEL: Nesting level of the shell, starting at 1 when first running ksw
    • KSW_CONTEXT: Kube context name used when running ksw


  • Supports recursive shell (starting ksw shell within ksw shell)
  • Shows a built-in fuzzy finder (like fzf) when no contexts specified in the argument
  • No automatic indicator in prompt, use the provided environment variables to set it depending on your setup

Some thoughts on the reason

You might think why am I reinventing the wheel? Some tools solve the same problem already.

I want a Kubeconfig switcher that simple (as in Unix philosophy) and can integrate easily with my existing ZSH and Prezto setup without getting in the way. Must also be able to integrate with other Kubernetes tools without many changes.

Other existing solutions I have tried:

  • kubectx and kubens: They are good, but I switch and use multiple contexts concurrently a lot. Changing the context in one terminal will change other terminals as well because they share the same kubeconfig file.
  • kubie: Took a lot of inspiration from this project. But somehow it’s doing too much and messing with ZDOTDIR breaking my ZSH setup.
  • kube_ps1: I am still using this for showing current context, and it integrates well with ksw

Additionally, this project has also taught me several interesting things:

  • Spawning and interacting with sub-processes in Go
  • Understanding kubectl configurations. I dived into Kubernetes source code to get an idea of how it is working. And if you checked my code, it’s reusing Kubectl’s code as a dependency to mimic its config handling behavior.
  • Automatic tests, build, and release using Goreleaser in GitHub. It was such a breeze I used Goreleaser in all of my Go projects.
  • Managing and publishing my own Homebrew tap. It allows more people to try and use my tools quickly.

I have been using it on my own for several months. Using separate shells for different contexts seems a good fit for my workflow. I set the default context in the default kubeconfig (~/.kube/config) to the non-production cluster I’m working on the most. Anytime I need to work on another cluster (especially the production one), I just need to run ksw to start a new shell with that specific cluster. This conscious effort to switch the context has reduced the risk of doing something bad on the wrong cluster.