How to Create a CLI in Golang

In Go
July 18, 2023

TL;DR

Some developers like to read and make sense of the code. So if you are that kind of developer then you can have a look at my repository on GitHub:

https://github.com/ufukguler/spotify-go-cli

Since I’m the kind of developer I just mentioned, I’ll keep it short and straightforward.

Let’s Get Started

First of all; start a new project:

$ mkdir my-cli && cd my-cli
$ go mod init my-cli

Then we need a library called Cobra to help us create a CLI application. Cobra is a library providing a simple interface to create powerful modern CLI interfaces similar to git & go tools.

$ go get -u github.com/spf13/cobra/cobra

After initializing the project, let me add the root command:

var rootCmd = &cobra.Command{
      Use: "spotify-go-client",
      Run: func(cmd *cobra.Command, args []string) {
          fmt.Println("Hello CLI")
      },
   }

And add this to main.go:

func main() {
   if err := rootCmd.Execute(); err != nil {
      fmt.Println(err.Error())
   }
}

Now, we have created our base structure. When we run the project we will call the Execute method on rootCmd which will do nothing but print “Hello CLI” to the command line.

$ go run main.go
Hello CLI

Our folder structure will be like this:

.
├── cmd
│   ├── root.go
│   ├── version.go
│   └── ...
├── go.mod
├── go.sum
└── main.go

So, that was easy but how can we add more commands? In order to be able to add more commands, we can create more cobra.Command{} and add this command to our rootCmd.

Create a file called version.go and add these into it:

var versionCmd = &cobra.Command{
   Use:     "version",
   Short:   "Get CLI version",
   Example: "spotify-go-client version",
   Aliases: []string{"v"},
   Run: func(cmd *cobra.Command, args []string) {
      fmt.Println("1.0.0")
   },
}

func init() {
   rootCmd.AddCommand(versionCmd)
}

You might notice that there are some options in cobra.Command{} which lets you add descriptions about the command. You can check this URL to see what options are available to use: Cobra Command

  • Use keyword is the one-line usage message which you will use as a CLI command like .\my-cli version
  • Aliases field is an array of aliases that can be used instead of Use.
  • Short is the short message shown in the ‘ — help’ output.
  • Long field is the long message shown in the ‘ — help’ output.
  • Example is examples of how to use the command.
  • ValidArgs is a list of all valid non-flag arguments.

How to get user input with a command?

In Command’s Run, we can get the arguments that passed along with the command. You can use the arguments in the args[] variable as you wish.

Let me show you how to do it:

var repeatCmd = &cobra.Command{
   Use: "repeat",
   Run: func(cmd *cobra.Command, args []string) {
      input := strings.Join(args, " ")
      fmt.Printf("User input is: %v", input)
   },
}

Run it:

$ .\my-cli repeat Hi there! 
User input is: Hi there!