Ever wondered how all the popular CLI tools work? They are all designed in a way that makes them easy and convenient to use.
In this article, I will show you the Cobra library in Go, used for building CLI systems with ease!
What is Cobra?
Cobra is basically a Go library to build command-line interfaces, for example, docker run -d nginx.
Cobra gives you the following:
- Commands & subcommands
- Flags (
--name,-n) - Help text
- Shell completion
- Cleaner structure
The mental model behind Cobra
You can think of the CLI interface like the tree below:
cli-tool
├── view
│ ├── --action
│ └── --format
├── run
│ └── --job-id
└── version
Each node in this tree is a command.
So this gives you the following:
cli-toolcli-tool viewcli-tool view --actioncli-tool view --formatcli-tool runcli-tool run --job-idcli-tool version
Getting Cobra on your machine
You can get this library via the following command:
go get github.com/spf13/cobra@latest
Quick example to understand the needful
Creating the root command
Consider the following main.go file:
package main
import "mycli/cmd"
func main() {
cmd.Execute()
}
In cmd/root.go:
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "mycli",
Short: "MyCLI is a demo tool",
Long: "MyCLI is a demo CLI application built using Cobra",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hello from root command")
},
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
When you run this:
go run main.go
You will get the result from the root command, since there aren't any subcommands:
Hello from root command
Creating the subcommand
Now let's add a subcommand.
cmd/version.go
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("mycli version 1.0.0")
},
}
func init() {
rootCmd.AddCommand(versionCmd)
}
You can notice that versionCmd is added to rootCmd. That is how the hierarchy is set up.
Now, if you run the command:
go run main.go version
Output
mycli version 1.0.0
Creating a subcommand within a subcommand, and adding flags
We can nest the commands as much as we like, so let's create a view subcommand.
We will also provide an option to use flags.
cmd/view.go
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var someFlag bool
var viewCmd = &cobra.Command{
Use: "view",
Short: "View data",
Run: func(cmd *cobra.Command, args []string) {
// This runs ONLY when no subcommand is provided
fmt.Println("view command executed")
fmt.Println("someFlag:", someFlag)
},
}
func init() {
// Flag for: mycli view --someflag
viewCmd.Flags().BoolVar(
&someFlag,
"someflag",
false,
"Enable special behavior",
)
rootCmd.AddCommand(viewCmd)
}
Here viewCmd.Flags().BoolVar(...) Creates a local flag attached to view.
Run executes only if no further subcommands are provided.
The subcommand for view is defined here.
cmd/view_count.go
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var viewCountCmd = &cobra.Command{
Use: "count",
Short: "Count records",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Counting records...")
},
}
func init() {
viewCmd.AddCommand(viewCountCmd)
}
So, based on the above, this is how Cobra behaves:
| Command | What runs |
|---|---|
mycli view |
viewCmd.Run |
mycli view --someflag |
viewCmd.Run |
mycli view count |
viewCountCmd.Run |
mycli view count --someflag |
flag NOT available |
Wrapping up
So that is some of the basics of the Cobra framework.
You can find the example in this repository under the following path:
https://github.com/RijulTP/blog-examples/tree/main/cobra-blog/mycli
It is very handy when you are designing a CLI tool for the first time, as it puts a solid foundation in place for you to work on.
If you have read till here, I have another handy resource for you.
If you’ve ever struggled with repetitive tasks, obscure commands, or debugging headaches, this platform is here to make your life easier. It’s free, open-source, and built with developers in mind.
👉 Explore the tools: FreeDevTools
👉 Star the repo: freedevtools

Top comments (0)