Hazem Allbabidi

June 5, 2023 | 10 min read


Building a CLI Tool Using Go and Cobra-CLI

Developing fast applications these days has never been easier with the help of all the tools we have access to. Go is a programming language built by some of the greatest Software Engineers of our time. It helps build anything back-end related, from CLI tools to APIs to even Blockchains and tools like Docker.

In this tutorial, I will go through how to build a simple CLI tool using Go, with the help of Cobra, and how you can use it on the most famous operating system for software development, Linux.

Prerequisites

The things you need in order to complete this tutorial include:

Installation

In this section, we will be installing the two tools we will be using, which are Go and Cobra CLI.

Go Installation

To download Go, you first have to download the tar.gz file for your OS from this page: https://go.dev/dl/

Once downloaded, run the below command to remove any order versions and install this version:

rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.4.linux-amd64.tar.gz

Once that is done, you should export the PATH for the binaries file of Go. You can do that by running the below line in your terminal, or adding it at the bottom of your ~/.bashrc file:

export PATH=$PATH:/usr/local/go/bin

You should now have Go installed on your machine, and you should be able to use it globally, to ensure it has been downloaded, run the below command:

go version

If the output shows the version you attempted to install, it means that the installation was successful!

Cobra CLI Installation

Since you have Go downloaded, it should now be easy to install Cobra CLI. You can run the below command to install the binary:

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

Once that is complete, you can test the installation by running:

cobra-cli

If that displays a description of the application, it means the installation was a success.

Project Setup

In this section, we create the main files of the application.

Creating The Main Directory & Initializing The Go Modules

We will be building a “Quotes” app that contains a few quotes, along with an ID for each one. The tool will be able to:

We will first create a directory called quotes and access it:

mkdir quotes
cd quotes

Then we need to initialize a Go Modules file, you can do it by running the command below:

go mod init quotes

This is the file that includes the dependencies of the tool, as well as the Go version you have. The quotes in the command refers to the name of the tool or module.

You should now see a file called go.mod in your directory.

Setting Up The Cobra CLI Tool

The Cobra CLI tool makes it very easy to get started with building CLI-based tools. You can run the following command to create the necessary files to start using the tool:

cobra-cli init

The above command will create a bunch of files, including:

We can build and run the tool by running the commands below:

go build .
./quotes

The first command builds the tool, and the second command runs it. You should see the long description of the application which was in the root.go file.

Understanding The Cobra Command Code

If we remove all the comments in the file, it should look like this:

package cmd

import (
	"os"
	"github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
	Use:   "quotes",
	Short: "A brief description of your application",
	Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
}

func Execute() {
	err := rootCmd.Execute()
	if err != nil {
		os.Exit(1)
	}
}

func init() {
	rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

The first part of the file includes the package name and the imports.

The second part that starts with var rootCmd = &cobra.Command{ is an initialization of a struct type in Go. The struct is taken from the cobra package and currently includes three things:

Note: there are more values that we will be adding later to other files

The third part consists of two functions Execute and init. The Execute simply runs the tool. The init sets up any necessary values, as well as accept flags, just like the toggle flag we see in the file.

Creating The Show Command

We will start by creating a command show which will be the main part of the tool. It will:

While in the root directory of the tool, we can run the following command to create the show.go file and command:

cobra-cli add show

Once that is done, you should see a new file show.go in the cmd directory.

This file will include a new value inside the cobra.Command which is the Run value. This is the function that basically runs when the command is triggered.

If you are interested, you can change the descriptions of both the root.go and show.go to something more fitting. But for now, I will be skipping that part.

We can start working on the actual functionality now.

Adding & Showing The Quotes

We will be writing all of the code in the show.go file and inside the Run function.

We can start by creating a Struct type that describes a Quote:

type  Quote  struct {
	ID int
	Author string
	Text string
}

The ID will be a unique, numerical value describing the quote. It will be in a series of sequential numbers starting from 1.

Then we can create an array of Quotes:

quotes  := []Quote{
	{
		ID: 1,
		Author: "Alan Kay",
		Text: "Simple things should be simple, complex things should be possible",
	},
	{
		ID: 2,
		Author: "Edsger W. Dijkstra",
		Text: "Simplicity is prerequisite for reliability.",
	},
	{
		ID: 3,
		Author: "Ralph Johnson",
		Text: "Before software can be reusable it first has to be usable.",
	},
}

The code above uses the Quote struct to create an array of quotes. I chose my favorite quotes from this page: https://hackernoon.com/40-thought-provoking-software-engineering-quotes-xp2z3tdr

Since we have the quotes set, we can now start printing them. We can do it by adding the lines below:

for  _, quote  :=  range quotes {
	fmt.Printf("%d. %s - %s\n", quote.ID, quote.Text, quote.Author)
}

The for loop above basically loops over the quotes and prints them in a specific way.

We can now build and run the tool by running the commands below:

go build .
./quotes show

After running the above commands, you should see this output:

1. Simple things should be simple, complex things should be possible - Alan Kay
2. Simplicity is prerequisite for reliability. - Edsger W. Dijkstra
3. Before software can be reusable it first has to be usable. - Ralph Johnson

Great! We managed to create our first command and run it by using the keyword specified in the show.go file under the Use in the cobra.Command struct. We can now expand and add an option to display a specific quote from the list.

Adding an ID Flag & Option

Now that we have the quotes in a specified Struct, we can add a flag that allows choosing which quote to display, based on the ID that was provided. We can start doing it by adding a flag at the end of the init function in the show.go file:

showCmd.Flags().Int("id", 0, "ID of the quote to show")

The line has three parts:

We can start implementing the functionality of it in the Run command.

Create a new file right before the for loop we added previously, and add the following commands:

...

id, _  := cmd.Flags().GetInt("id") // skipping error for simplicity

if id >  0 {
	var  printableQuote Quote
	for  _, quote  :=  range quotes {
		if quote.ID == id {
			printableQuote  = quote
			break
		}
	}

	if printableQuote.ID !=  0 {
		fmt.Printf("%d. %s - %s\n", printableQuote.ID, printableQuote.Text, printableQuote.Author)
	}
	return
}
...

We start off by retrieving the ID (it returns an Error but we will skip it for now).

id, _  := cmd.Flags().GetInt("id")

We access the command flags, and retrieve an Int with the key id, just like how it was specified previously.

We then check if the value of id is greater than 0. Keep in mind 0 was the default value, meaning we have to skip this piece of code if id was equal to 0.

Once it pass by the if statement, it will find the quote using the id. Once it finds it, it will print it using the same format we use previously in the for loop. If the quote with the specified id was not found, nothing happens.

We can run the command by first building the tool:

go build .

Then running the command:

./quotes show --id 3

We should see the quote with ID 3 get printed to the screen:

user@ubuntu ~/quotes> ./quotes show --id 3
3. Before software can be reusable it first has to be usable. - Ralph Johnson

If we try to run it with an id that does not exist in the quotes array (e.g. 4) nothing will happen.

Conclusion

I hope you found it easy building a CLI tool with Go and Cobra. It currently is my favorite way of building CLI-based tools for whatever purpose. Combining the features of Cobra with the speed and ease-of-use of Go makes it very entertaining to build a tool this way, while guaranteeing high speeds in the execution of the tool.

You can find the documentation for the Cobra tool in the link below: https://github.com/spf13/cobra

Thank you for reading this tutorial. I hope you enjoyed it.


Previous

How To Use Ansible and Ansible Playbooks

Next

Structure of a Command in Linux
Sign Up To Binance To Get 10% Off Commission Fees Sign Up To Kucoin