Generates, explains, and debugs CLI applications using Cobra (github.com/spf13/cobra) for Go. Use when building command-line tools with subcommands, flags, persistent flags, hooks, shell completions, help generation, argument validation, or migrating from other CLI libraries. Covers Command struct, AddCommand, flags (local/persistent), PreRun/PostRun hooks, ValidArgs, completions for bash/zsh/fish/powershell, and integration with viper.
Cobra is a library for creating powerful modern CLI applications in Go, used by Kubernetes, Hugo, GitHub CLI, and many more.
Commands represent actions, Args are things, Flags are modifiers. Follow the pattern: APPNAME COMMAND ARG --FLAG.
appName/
cmd/
root.go
subcommand.go
main.go
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "myapp",
Short: "Brief description",
Long: `Detailed description...`,
Run: func(cmd *cobra.Command, args []string) {
// Action here
},
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print version",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("v1.0.0")
},
}
func init() {
rootCmd.AddCommand(versionCmd)
}
var cmd = &cobra.Command{
Use: "delete [name]",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("name required")
}
return deleteResource(args[0])
},
}
var verbose bool
func init() {
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")
}
var source string
func init() {
cmd.Flags().StringVarP(&source, "source", "s", "", "source directory")
}
func init() {
rootCmd.Flags().StringVarP(®ion, "region", "r", "", "AWS region")
rootCmd.MarkFlagRequired("region")
}
func init() {
rootCmd.Flags().StringVarP(&user, "username", "u", "", "Username")
rootCmd.Flags().StringVarP(&pass, "password", "p", "", "Password")
rootCmd.MarkFlagsRequiredTogether("username", "password")
rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")
}
var verbose int
var files []string
func init() {
rootCmd.PersistentFlags().CountVarP(&verbose, "verbose", "v", "verbosity (-v, -vv, -vvv)")
rootCmd.Flags().StringArrayVarP(&files, "file", "f", []string{}, "input files")
}
var cmd = &cobra.Command{
Use: "create [name]",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) { ... },
}
Built-in validators:
NoArgs - no positional args allowedArbitraryArgs - any number (default)MinimumNArgs(int) - at least N argsMaximumNArgs(int) - at most N argsExactArgs(int) - exactly N argsRangeArgs(min, max) - between min and maxOnlyValidArgs - only values in ValidArgsCombined validation:
Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs),
Execution order: PersistentPreRun -> PreRun -> Run -> PostRun -> PersistentPostRun
var rootCmd = &cobra.Command{
Use: "myapp",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
// Runs before any child command
},
PreRun: func(cmd *cobra.Command, args []string) {
// Runs before this command's Run
},
Run: func(cmd *cobra.Command, args []string) {
// Main logic
},
PostRun: func(cmd *cobra.Command, args []string) {
// Runs after Run
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
// Runs after any child command
},
}
var cmd = &cobra.Command{
Use: "get [resource]",
ValidArgs: []string{"pod", "service", "deployment"},
Run: func(cmd *cobra.Command, args []string) { ... },
}
var cmd = &cobra.Command{
Use: "status [release]",
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
return getReleases(toComplete), cobra.ShellCompDirectiveNoFileComp
},
Run: func(cmd *cobra.Command, args []string) { ... },
}
cmd.RegisterFlagCompletionFunc("output", func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
return []cobra.Completion{"json", "yaml", "table"}, cobra.ShellCompDirectiveNoFileComp
})
ShellCompDirectiveDefault - default behaviorShellCompDirectiveNoSpace - no space after completionShellCompDirectiveNoFileComp - no file completionShellCompDirectiveFilterFileExt - filter by file extensionShellCompDirectiveFilterDirs - directory names onlycmd.SetHelpCommand(customHelpCmd)
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { ... })
cmd.SetHelpTemplate(customTemplate)
cmd.SetUsageFunc(func(cmd *cobra.Command) error { ... })
cmd.SetUsageTemplate(customTemplate)
var rootCmd = &cobra.Command{
Use: "myapp",
Version: "1.0.0",
}
func init() {
rootCmd.AddGroup(
&cobra.Group{ID: "management", Title: "Management Commands:"},
&cobra.Group{ID: "query", Title: "Query Commands:"},
)
listCmd.GroupID = "query"
createCmd.GroupID = "management"
rootCmd.AddCommand(listCmd, createCmd)
}
rootCmd := &cobra.Command{
Use: "kubectl-myplugin",
Annotations: map[string]string{
cobra.CommandDisplayNameAnnotation: "kubectl myplugin",
},
}
rootCmd := &cobra.Command{
Use: "myapp",
TraverseChildren: true, // Parse parent flags before child command
}
cmd.SilenceErrors = true // Don't print error prefix
cmd.SilenceUsage = true // Don't print usage on error
cmd.Hidden = true
cmd.Deprecated = "use 'newcmd' instead"
| File | Description |
|---|---|
| references/_examples/basic_app.go | Minimal CLI application |
| references/_examples/subcommands.go | Nested subcommands |
| references/_examples/flags.go | Flag patterns |
| references/_examples/hooks.go | PreRun/PostRun hooks |
| references/_examples/completions.go | Shell completions |
import "github.com/spf13/viper"
func init() {
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file")
rootCmd.PersistentFlags().StringP("author", "a", "", "author name")
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
}