Adding Commands With the Cobra Generator

In this lesson, you'll learn how to use the Cobra generator to generate an application skeleton from scratch.

We will build our simple calculator on top of the skeleton. Next, we will add a couple more options like pre-run and post-run hooks that we skipped over in the previous lesson. Let’s start by understanding what the Cobra generator is, how it works, and when you should use it.

Adding commands to the application

The cobra add will create new commands for us, and even hook it up to a parent command. By default, the parent is the root command. Our calculator application needs two commands add and subtract.

If you want to follow along, there is a terminal window at the bottom of the lesson that is already set up with the Cobra application skeleton. Feel free to type in the commands and check out the results for yourself.

Let’s create the calculator’s add command using Cobra’s add command. Don’t be confused. Our calculator command to add two numbers is called add, and the Cobra command to add sub-commands is also called add.

$ cobra add add -l none -a Gigi --viper=false
add created at /Users/gigi.sayfan/git/cobra-generator-demo/calc-app

Cobra generated the cmd/add.go file for us. It contains a copyright notice (If you choose a license, it will include the license, too.), a variable for the addCmd itself, and an init() function that hooks it up to the root command. This is all the scaffolding we need.

/*
Copyright © 2020 Gigi

*/
package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)

// addCmd represents the add command
var addCmd = &cobra.Command{
	Use:   "add",
	Short: "A brief description of your command",
	Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. 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.`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("add called")
	},
}

func init() {
	rootCmd.AddCommand(addCmd)

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

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// addCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// addCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

Let’s generate the subtract command, too:

$ cobra add subtract -l none -a Gigi --viper=false
subtract created at /Users/gigi.sayfan/git/cobra-generator-demo/calc-app

It looks virtually identical except that the name of the generated command is subtractCmd.

At this point, we have a complete skeleton. Let’s try to run our application:

Running the application

$ go run main.go add 4 5
main.go:7:8: cannot find package "calc-app/cmd" in any of:
	/usr/local/go/src/calc-app/cmd (from $GOROOT)
	/Users/gigi.sayfan/go/src/calc-app/cmd (from $GOPATH)

Oh, no. What happened? Cobra expects our application to be in the GOPATH. This is the old way. Changing this to the modern way, using Go modules, requires some manual intervention. Let’s create a go.mod file:

$ go mod init calc-app
go: creating new go.mod: module calc-app

Then, let’s call go mod tidy to pick up all the dependencies:

$ go mod tidy
$ cat go.mod

module calc-app

go 1.14

require github.com/spf13/cobra v1.0.0

We need to update main.go to use the new path for the cmd package:

package main

import "calc-app/cmd"

func main() {
	cmd.Execute()
}

Let’s try again:

$ go run main.go add 4 5
add called

Yeah, it works. It doesn’t actually add the numbers yet, because we didn’t implement the calculator logic, but the add command is hooked up properly and can be invoked.

You can try it yourself in the terminal below.

Get hands-on with 1200+ tech skills courses.