What it is
Cobra is the CLI framework behind kubectl, Hugo, GitHub CLI and Docker, providing nested subcommands, flag parsing, help generation and shell completion.
Commands are structs arranged in a tree. Cobra handles argument parsing, help text, usage errors, and generates completion scripts for bash, zsh, fish and PowerShell.
Installation
go get -u github.com/spf13/cobra@latestGetting started
The smallest useful thing you can do with it, and what each part means.
go
var rootCmd = &cobra.Command{
Use: "library",
Short: "Manage a book library",
}
var addCmd = &cobra.Command{
Use: "add [title]",
Short: "Add a book",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
year, _ := cmd.Flags().GetInt("year")
return store.Add(args[0], year)
},
}
func init() {
addCmd.Flags().IntP("year", "y", 0, "publication year")
rootCmd.AddCommand(addCmd)
}go
rootCmd.PersistentFlags().Bool("verbose", false, "verbose output")
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
if err := rootCmd.ExecuteContext(ctx); err != nil {
os.Exit(1) // Cobra already printed the error
}
}Advanced usage
Where the library earns its place over a simpler alternative.
go
var getCmd = &cobra.Command{
Use: "get [name]",
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return store.NamesWithPrefix(toComplete), cobra.ShellCompDirectiveNoFileComp
},
RunE: run,
}Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- The error is printed twice
- Cobra prints errors returned from RunE. Set SilenceErrors or SilenceUsage on the root command if you also print them yourself.
- Flag values are empty inside Run
- Flags registered on a child are not visible on the parent. Use PersistentFlags for shared options, and read them via cmd.Flags() rather than a package-level variable bound too early.
Best practices
- Use RunE instead of Run so failures set a non-zero exit code.
- Validate arguments with the built-in Args validators rather than checking len(args) by hand.
- Print user-facing output with cmd.OutOrStdout() so tests can capture it.
- Pair with Viper when you need flags, environment variables and a config file to layer together.
Background
Why it exists, and what it was reacting to.
Written by Steve Francia, Cobra became the de facto standard for Go command-line tools. Its command tree model is why so many Go CLIs share the same 'verb noun --flag' feel.
