CLI frameworks for Go (Golang): a detailed guide
Go (Golang) is a language that is ideal for creating command-line tools (CLI). Thanks to fast compilation, built-in concurrency support, and easy distribution as a single binary file, Go has become the de facto standard for developing CLI applications. However, to create complex, user-friendly, and scalable command-line interfaces, the standard flag library is often not enough. Specialized frameworks come to the rescue. In this article, we will take a detailed look at the three most popular CLI frameworks for Go: Cobra, urfave/cli, and Kong, compare their capabilities, and show usage examples.
Why use a CLI framework?
Developing a CLI application from scratch can quickly turn into chaos, especially when it comes to:
- Support for nested commands (subcommands) and flags.
- Automatic help generation (
--help). - Error handling and argument validation.
- Autocompletion (bash/zsh completion).
Frameworks solve these problems by providing a ready-made architecture and a set of tools.
1. Cobra — the king of CLI in Go
Cobra is the most popular framework for creating CLI in Go. It is used in giants such as Kubernetes, Hugo, Docker, and GitHub CLI. Cobra is built on the concept of commands, arguments, and flags.
Key features of Cobra:
- Commands and subcommands: Any action is a command (
app serve,app init). - Flags: Global (
--verbose) and local to the command. - Automatic help: Generated from command descriptions.
- Autocompletion: Built-in support for bash, zsh, fish, and PowerShell.
- Code generator: The
cobra-cliutility creates a project skeleton.
Code example in Cobra:
package main
import ( "fmt" "github.com/spf13/cobra")
func main() { var rootCmd = &cobra.Command{ Use: "greet", Short: "Greet is a simple CLI tool", Long: "A simple CLI tool to greet people.", Run: func(cmd *cobra.Command, args []string) { fmt.Println("Hello! Use 'greet hello --name' to greet someone.") }, }
var name string var helloCmd = &cobra.Command{ Use: "hello", Short: "Greet a person", Run: func(cmd *cobra.Command, args []string) { fmt.Printf("Hello, %s!", name) }, }
helloCmd.Flags().StringVarP(&name, "name", "n", "World", "Name to greet") rootCmd.AddCommand(helloCmd) rootCmd.Execute()}Run: go run main.go hello --name=PythonLib will output Hello, PythonLib!.
2. urfave/cli — simplicity and minimalism
Previously known as codegangsta/cli, this framework is famous for its simplicity and elegant API. It is perfect for small and medium-sized projects where all the power of Cobra is not needed.
Key features of urfave/cli:
- Declarative style: The application is described as a data structure.
- Automatic help generation: Beautiful and readable.
- Action support: Each command has its own handler function.
- Built-in flag types: Strings, numbers, boolean values, duration, and even files.
Code example in urfave/cli:
package main
import ( "fmt" "log" "os"
"github.com/urfave/cli/v2")
func main() { app := &cli.App{ Name: "calc", Usage: "A simple calculator", Comman