Introduction

A few months ago, I wrote a set of shell scripts to bootstrap Kubernetes on Multipass VMs. While they worked well, I found it challenging to present them in a user-friendly way. I wanted a clean solution to package these scripts into a single binary, complete with self-contained documentation, that people could easily install and use without cloning a repository. After some research, I discovered Cobra, a popular Go framework for creating CLIs. Seeing that well-known applications like Kubernetes, Hugo, and GitHub CLI use Cobra, I decided to give it a try.

Cobra-cli is a feature rich package built on top of the flag package. It allows you to focus on your core CLI logic while adding convenient out-of-the-box features like command hierarchy, flag parsing, autocompletion and command suggestions.

All the command examples will be related to the multi-k8s CLI. The code for this CLI is hosted at multi-k8s, feel free to install the binary and give it a try. The steps outlined in the guide below are intended to demonstrate the capabilities of cobra-cli at a high level, rather than providing you with a fully functional CLI.

Getting started

Given that you have your GOPATH setup, run the command below to install cobra-cli:

go install github.com/spf13/cobra-cli@latest

cobra-cli should now be installed in your $GOPATH/bin folder. You can add the Go bin directory in your PATH with:

export PATH=$PATH:$(go env GOPATH)/bin

With cobra-cli installed you can now create the scaffold for your CLI:

mkdir multi-k8s && cd multi-k8s
go mod init multi-k8s
cobra-cli init multi-k8s

The commands above will create a folder for your Go application, a Go module, and a separate directory for the code generated by cobra-cli. Since we only plan to create a single CLI app, you can move all the contents from the multi-k8s folder (created by cobra-cli) to the parent folder (which is also named multi-k8s).

Adding Kubernetes specific commands

Before you start development of your CLI, you have a clear idea of the problem it aims to solve. In my case, I wanted to deploy clusters with a specified number of controller and worker nodes, list the nodes, and delete existing clusters.

With cobra-cli it is very easy to add a new command. To add the deploy command, I ran the following:

cobra-cli add deploy

This command created a deploy.go file inside the cmd folder. It included the necessary code to attach the deploy command to the root command and provided boilerplate code for adding flags to the command.

A CLI is composed of several commands and, depending on the desired configuration, flags. To specify the number of nodes to be deployed, I needed to add flags to the deploy command. This is done inside the init function in the deploy.go file, using methods corresponding to the cobra.Command type:

func init() {
	rootCmd.AddCommand(deployCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	deployCmd.Flags().IntVarP(&controlNodes, "control-nodes", "c", 1, "Number of control nodes (1 or 3)")
	deployCmd.Flags().IntVarP(&workerNodes, "worker-nodes", "w", 1, "Number of worker nodes (1-3)")
}

The cobra-cli add command was then used to create additional commands for destroying nodes, listing nodes, and displaying the version of the CLI tool.

Run your main.go file and check the output of the root command:

$ go run main.go 

multi-k8s is a CLI tool which deploys single/multi-node k8s clusters. 

Run the deploy command to create a cluster:
multi-k8s deploy

Run the destroy command to destroy a cluster:
multi-k8s destroy

Usage:
  multi-k8s [command]

Available Commands:
  completion  Generate the autocompletion script for the specified shell
  deploy      Command for deploying a cluster.
  destroy     Command for destroying a cluster.
  help        Help about any command
  list        Command for listing nodes of your cluster.
  version     Command for showing the version for multi-k8s.

Flags:
  -h, --help     help for multi-k8s
  -t, --toggle   Help message for toggle

Use "multi-k8s [command] --help" for more information about a command.

You could see that in addition to the deploy, destroy, list and version commands, cobra adds the help flag which returns the Long field from the Command type that I modified as part of my command. It also adds the completion flag which generates the autocomplete script for the CLI:

echo "source <(multi-k8s completion zsh)" | tee -a ~/.zshrc
source ~/.zshrc

The nice thing about cobra is that it adds command suggestions in case you have a typo in your command:

$ go run main.go dloy          
Error: unknown command "dloy" for "multi-k8s"

Did you mean this?
        deploy

Run 'multi-k8s --help' for usage.
exit status 1

In my opinion, Cobra is the perfect tool for getting started with CLI development. It makes it easy to add new commands and flags, both at the root level and for individual commands. Plus, it helps you generate clear and helpful documentation. Overall, Cobra is a great choice for building efficient and user-friendly CLIs.