| # User Guide | |
| While you are welcome to provide your own organization, typically a Cobra-based | |
| application will follow the following organizational structure: | |
| ```console | |
| ▾ appName/ | |
| ▾ cmd/ | |
| add.go | |
| your.go | |
| commands.go | |
| here.go | |
| main.go | |
| ``` | |
| In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra. | |
| ```go | |
| package main | |
| import "{pathToYourApp}/cmd" | |
| func main() { | |
| cmd.Execute() | |
| } | |
| ``` | |
| ## Using the Cobra Generator | |
| Cobra-CLI is its own program that will create your application and add any commands you want. | |
| It's the easiest way to incorporate Cobra into your application. | |
| For complete details on using the Cobra generator, please refer to [The Cobra-CLI Generator README](https://github.com/spf13/cobra-cli/blob/main/README.md) | |
| ## Using the Cobra Library | |
| To manually implement Cobra you need to create a bare main.go file and a rootCmd file. | |
| You will optionally provide additional commands as you see fit. | |
| ### Create rootCmd | |
| Cobra doesn't require any special constructors. Simply create your commands. | |
| Ideally you place this in app/cmd/root.go: | |
| ```go | |
| var rootCmd = &cobra.Command{ | |
| Use: "hugo", | |
| Short: "Hugo is a very fast static site generator", | |
| Long: `A Fast and Flexible Static Site Generator built with | |
| love by spf13 and friends in Go. | |
| Complete documentation is available at https://gohugo.io/documentation/`, | |
| Run: func(cmd *cobra.Command, args []string) { | |
| // Do Stuff Here | |
| }, | |
| } | |
| func Execute() { | |
| if err := rootCmd.Execute(); err != nil { | |
| fmt.Fprintln(os.Stderr, err) | |
| os.Exit(1) | |
| } | |
| } | |
| ``` | |
| You will additionally define flags and handle configuration in your init() function. | |
| For example cmd/root.go: | |
| ```go | |
| package cmd | |
| import ( | |
| "fmt" | |
| "os" | |
| "github.com/spf13/cobra" | |
| "github.com/spf13/viper" | |
| ) | |
| var ( | |
| // Used for flags. | |
| cfgFile string | |
| userLicense string | |
| rootCmd = &cobra.Command{ | |
| Use: "cobra-cli", | |
| Short: "A generator for Cobra based Applications", | |
| Long: `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.`, | |
| } | |
| ) | |
| // Execute executes the root command. | |
| func Execute() error { | |
| return rootCmd.Execute() | |
| } | |
| func init() { | |
| cobra.OnInitialize(initConfig) | |
| rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") | |
| rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution") | |
| rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project") | |
| rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration") | |
| viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) | |
| viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper")) | |
| viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>") | |
| viper.SetDefault("license", "apache") | |
| rootCmd.AddCommand(addCmd) | |
| rootCmd.AddCommand(initCmd) | |
| } | |
| func initConfig() { | |
| if cfgFile != "" { | |
| // Use config file from the flag. | |
| viper.SetConfigFile(cfgFile) | |
| } else { | |
| // Find home directory. | |
| home, err := os.UserHomeDir() | |
| cobra.CheckErr(err) | |
| // Search config in home directory with name ".cobra" (without extension). | |
| viper.AddConfigPath(home) | |
| viper.SetConfigType("yaml") | |
| viper.SetConfigName(".cobra") | |
| } | |
| viper.AutomaticEnv() | |
| if err := viper.ReadInConfig(); err == nil { | |
| fmt.Println("Using config file:", viper.ConfigFileUsed()) | |
| } | |
| } | |
| ``` | |
| ### Create your main.go | |
| With the root command you need to have your main function execute it. | |
| Execute should be run on the root for clarity, though it can be called on any command. | |
| In a Cobra app, typically the main.go file is very bare. It serves one purpose: to initialize Cobra. | |
| ```go | |
| package main | |
| import "{pathToYourApp}/cmd" | |
| func main() { | |
| cmd.Execute() | |
| } | |
| ``` | |
| ### Create additional commands | |
| Additional commands can be defined and typically are each given their own file | |
| inside of the cmd/ directory. | |
| If you wanted to create a version command you would create cmd/version.go and | |
| populate it with the following: | |
| ```go | |
| package cmd | |
| import ( | |
| "fmt" | |
| "github.com/spf13/cobra" | |
| ) | |
| func init() { | |
| rootCmd.AddCommand(versionCmd) | |
| } | |
| var versionCmd = &cobra.Command{ | |
| Use: "version", | |
| Short: "Print the version number of Hugo", | |
| Long: `All software has versions. This is Hugo's`, | |
| Run: func(cmd *cobra.Command, args []string) { | |
| fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") | |
| }, | |
| } | |
| ``` | |
| ### Organizing subcommands | |
| A command may have subcommands which in turn may have other subcommands. This is achieved by using | |
| `AddCommand`. In some cases, especially in larger applications, each subcommand may be defined in | |
| its own go package. | |
| The suggested approach is for the parent command to use `AddCommand` to add its most immediate | |
| subcommands. For example, consider the following directory structure: | |
| ```console | |
| ├── cmd | |
| │ ├── root.go | |
| │ └── sub1 | |
| │ ├── sub1.go | |
| │ └── sub2 | |
| │ ├── leafA.go | |
| │ ├── leafB.go | |
| │ └── sub2.go | |
| └── main.go | |
| ``` | |
| In this case: | |
| * The `init` function of `root.go` adds the command defined in `sub1.go` to the root command. | |
| * The `init` function of `sub1.go` adds the command defined in `sub2.go` to the sub1 command. | |
| * The `init` function of `sub2.go` adds the commands defined in `leafA.go` and `leafB.go` to the | |
| sub2 command. | |
| This approach ensures the subcommands are always included at compile time while avoiding cyclic | |
| references. | |
| ### Returning and handling errors | |
| If you wish to return an error to the caller of a command, `RunE` can be used. | |
| ```go | |
| package cmd | |
| import ( | |
| "fmt" | |
| "github.com/spf13/cobra" | |
| ) | |
| func init() { | |
| rootCmd.AddCommand(tryCmd) | |
| } | |
| var tryCmd = &cobra.Command{ | |
| Use: "try", | |
| Short: "Try and possibly fail at something", | |
| RunE: func(cmd *cobra.Command, args []string) error { | |
| if err := someFunc(); err != nil { | |
| return err | |
| } | |
| return nil | |
| }, | |
| } | |
| ``` | |
| The error can then be caught at the execute function call. | |
| ## Working with Flags | |
| Flags provide modifiers to control how the action command operates. | |
| ### Assign flags to a command | |
| Since the flags are defined and used in different locations, we need to | |
| define a variable outside with the correct scope to assign the flag to | |
| work with. | |
| ```go | |
| var Verbose bool | |
| var Source string | |
| ``` | |
| There are two different approaches to assign a flag. | |
| ### Persistent Flags | |
| A flag can be 'persistent', meaning that this flag will be available to the | |
| command it's assigned to as well as every command under that command. For | |
| global flags, assign a flag as a persistent flag on the root. | |
| ```go | |
| rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output") | |
| ``` | |
| ### Local Flags | |
| A flag can also be assigned locally, which will only apply to that specific command. | |
| ```go | |
| localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") | |
| ``` | |
| ### Local Flag on Parent Commands | |
| By default, Cobra only parses local flags on the target command, and any local flags on | |
| parent commands are ignored. By enabling `Command.TraverseChildren`, Cobra will | |
| parse local flags on each command before executing the target command. | |
| ```go | |
| command := cobra.Command{ | |
| Use: "print [OPTIONS] [COMMANDS]", | |
| TraverseChildren: true, | |
| } | |
| ``` | |
| ### Bind Flags with Config | |
| You can also bind your flags with [viper](https://github.com/spf13/viper): | |
| ```go | |
| var author string | |
| func init() { | |
| rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution") | |
| viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) | |
| } | |
| ``` | |
| In this example, the persistent flag `author` is bound with `viper`. | |
| **Note**: the variable `author` will not be set to the value from config, | |
| when the `--author` flag is provided by user. | |
| More in [viper documentation](https://github.com/spf13/viper#working-with-flags). | |
| ### Required flags | |
| Flags are optional by default. If instead you wish your command to report an error | |
| when a flag has not been set, mark it as required: | |
| ```go | |
| rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)") | |
| rootCmd.MarkFlagRequired("region") | |
| ``` | |
| Or, for persistent flags: | |
| ```go | |
| rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)") | |
| rootCmd.MarkPersistentFlagRequired("region") | |
| ``` | |
| ### Flag Groups | |
| If you have different flags that must be provided together (e.g. if they provide the `--username` flag they MUST provide the `--password` flag as well) then | |
| Cobra can enforce that requirement: | |
| ```go | |
| rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)") | |
| rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)") | |
| rootCmd.MarkFlagsRequiredTogether("username", "password") | |
| ``` | |
| You can also prevent different flags from being provided together if they represent mutually | |
| exclusive options such as specifying an output format as either `--json` or `--yaml` but never both: | |
| ```go | |
| rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON") | |
| rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML") | |
| rootCmd.MarkFlagsMutuallyExclusive("json", "yaml") | |
| ``` | |
| If you want to require at least one flag from a group to be present, you can use `MarkFlagsOneRequired`. | |
| This can be combined with `MarkFlagsMutuallyExclusive` to enforce exactly one flag from a given group: | |
| ```go | |
| rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON") | |
| rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML") | |
| rootCmd.MarkFlagsOneRequired("json", "yaml") | |
| rootCmd.MarkFlagsMutuallyExclusive("json", "yaml") | |
| ``` | |
| In these cases: | |
| - both local and persistent flags can be used | |
| - **NOTE:** the group is only enforced on commands where every flag is defined | |
| - a flag may appear in multiple groups | |
| - a group may contain any number of flags | |
| ### Repeated Flags | |
| Cobra supports two types of repeated flags, useful for implementing SSH-like verbose flags (`-v`, `-vv`, `-vvv`) or collecting multiple values. | |
| #### Count Flags | |
| For implementing verbose-style flags where repeated usage increases a counter (like SSH's `-v`, `-vv`, `-vvv`): | |
| ```go | |
| var verbose int | |
| func init() { | |
| // CountVarP allows the flag to be repeated to increment the counter | |
| rootCmd.PersistentFlags().CountVarP(&verbose, "verbose", "v", "verbose output (can be repeated: -v, -vv, -vvv)") | |
| } | |
| ``` | |
| Usage examples: | |
| - `myapp -v` → verbose = 1 (info level) | |
| - `myapp -vv` or `myapp -v -v` → verbose = 2 (debug level) | |
| - `myapp -vvv` or `myapp -v -v -v` → verbose = 3 (trace level) | |
| Then in your command logic: | |
| ```go | |
| Run: func(cmd *cobra.Command, args []string) { | |
| switch verbose { | |
| case 0: | |
| // Default: no verbose output | |
| case 1: | |
| // Info level logging | |
| log.SetLevel(log.InfoLevel) | |
| case 2: | |
| // Debug level logging | |
| log.SetLevel(log.DebugLevel) | |
| case 3: | |
| // Trace level logging | |
| log.SetLevel(log.TraceLevel) | |
| default: | |
| // Maximum verbosity | |
| log.SetLevel(log.TraceLevel) | |
| } | |
| }, | |
| ``` | |
| #### Array/Slice Flags | |
| For collecting multiple values of the same flag: | |
| ```go | |
| var inputFiles []string | |
| func init() { | |
| // StringArrayVarP allows multiple values: --input file1.txt --input file2.txt | |
| rootCmd.Flags().StringArrayVarP(&inputFiles, "input", "i", []string{}, "input files (can be repeated)") | |
| // Alternative: StringSliceVarP for comma-separated values | |
| // rootCmd.Flags().StringSliceVarP(&inputFiles, "input", "i", []string{}, "input files (comma-separated or repeated)") | |
| } | |
| ``` | |
| Usage examples: | |
| - `myapp --input file1.txt --input file2.txt` | |
| - `myapp -i file1.txt -i file2.txt` | |
| - With StringSlice: `myapp --input file1.txt,file2.txt,file3.txt` | |
| **Note**: Both `CountVar` and array flags leverage the underlying [pflag](https://github.com/spf13/pflag) library's support for repeated flags. | |
| ## Positional and Custom Arguments | |
| Validation of positional arguments can be specified using the `Args` field of `Command`. | |
| The following validators are built in: | |
| - Number of arguments: | |
| - `NoArgs` - report an error if there are any positional args. | |
| - `ArbitraryArgs` - accept any number of args. | |
| - `MinimumNArgs(int)` - report an error if less than N positional args are provided. | |
| - `MaximumNArgs(int)` - report an error if more than N positional args are provided. | |
| - `ExactArgs(int)` - report an error if there are not exactly N positional args. | |
| - `RangeArgs(min, max)` - report an error if the number of args is not between `min` and `max`. | |
| - Content of the arguments: | |
| - `OnlyValidArgs` - report an error if there are any positional args not specified in the `ValidArgs` field of `Command`, which can optionally be set to a list of valid values for positional args. | |
| - `NoDuplicateArgs` - report an error if any positional argument value is provided more than once. | |
| If `Args` is undefined or `nil`, it defaults to `ArbitraryArgs`. | |
| Moreover, `MatchAll(pargs ...PositionalArgs)` enables combining existing checks with arbitrary other checks. | |
| For instance, if you want to report an error if there are not exactly N positional args OR if there are any positional | |
| args that are not in the `ValidArgs` field of `Command`, you can call `MatchAll` on `ExactArgs` and `OnlyValidArgs`, as | |
| shown below: | |
| ```go | |
| var cmd = &cobra.Command{ | |
| Short: "hello", | |
| Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs), | |
| Run: func(cmd *cobra.Command, args []string) { | |
| fmt.Println("Hello, World!") | |
| }, | |
| } | |
| ``` | |
| It is possible to set any custom validator that satisfies `func(cmd *cobra.Command, args []string) error`. | |
| For example: | |
| ```go | |
| var cmd = &cobra.Command{ | |
| Short: "hello", | |
| Args: func(cmd *cobra.Command, args []string) error { | |
| // Optionally run one of the validators provided by cobra | |
| if err := cobra.MinimumNArgs(1)(cmd, args); err != nil { | |
| return err | |
| } | |
| // Run the custom validation logic | |
| if myapp.IsValidColor(args[0]) { | |
| return nil | |
| } | |
| return fmt.Errorf("invalid color specified: %s", args[0]) | |
| }, | |
| Run: func(cmd *cobra.Command, args []string) { | |
| fmt.Println("Hello, World!") | |
| }, | |
| } | |
| ``` | |
| ## Example | |
| In the example below, we have defined three commands. Two are at the top level | |
| and one (cmdTimes) is a child of one of the top commands. In this case the root | |
| is not executable, meaning that a subcommand is required. This is accomplished | |
| by not providing a 'Run' for the 'rootCmd'. | |
| We have only defined one flag for a single command. | |
| More documentation about flags is available at https://github.com/spf13/pflag. | |
| ```go | |
| package main | |
| import ( | |
| "fmt" | |
| "strings" | |
| "github.com/spf13/cobra" | |
| ) | |
| func main() { | |
| var echoTimes int | |
| var cmdPrint = &cobra.Command{ | |
| Use: "print [string to print]", | |
| Short: "Print anything to the screen", | |
| Long: `print is for printing anything back to the screen. | |
| For many years people have printed back to the screen.`, | |
| Args: cobra.MinimumNArgs(1), | |
| Run: func(cmd *cobra.Command, args []string) { | |
| fmt.Println("Print: " + strings.Join(args, " ")) | |
| }, | |
| } | |
| var cmdEcho = &cobra.Command{ | |
| Use: "echo [string to echo]", | |
| Short: "Echo anything to the screen", | |
| Long: `echo is for echoing anything back. | |
| Echo works a lot like print, except it has a child command.`, | |
| Args: cobra.MinimumNArgs(1), | |
| Run: func(cmd *cobra.Command, args []string) { | |
| fmt.Println("Echo: " + strings.Join(args, " ")) | |
| }, | |
| } | |
| var cmdTimes = &cobra.Command{ | |
| Use: "times [string to echo]", | |
| Short: "Echo anything to the screen more times", | |
| Long: `echo things multiple times back to the user by providing | |
| a count and a string.`, | |
| Args: cobra.MinimumNArgs(1), | |
| Run: func(cmd *cobra.Command, args []string) { | |
| for i := 0; i < echoTimes; i++ { | |
| fmt.Println("Echo: " + strings.Join(args, " ")) | |
| } | |
| }, | |
| } | |
| cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") | |
| var rootCmd = &cobra.Command{Use: "app"} | |
| rootCmd.AddCommand(cmdPrint, cmdEcho) | |
| cmdEcho.AddCommand(cmdTimes) | |
| rootCmd.Execute() | |
| } | |
| ``` | |
| For a more complete example of a larger application, please checkout [Hugo](https://gohugo.io/). | |
| ## Help Command | |
| Cobra automatically adds a help command to your application when you have subcommands. | |
| This will be called when a user runs 'app help'. Additionally, help will also | |
| support all other commands as input. Say, for instance, you have a command called | |
| 'create' without any additional configuration; Cobra will work when 'app help | |
| create' is called. Every command will automatically have the '--help' flag added. | |
| ### Example | |
| The following output is automatically generated by Cobra. Nothing beyond the | |
| command and flag definitions are needed. | |
| ```console | |
| $ cobra-cli help | |
| 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. | |
| Usage: | |
| cobra-cli [command] | |
| Available Commands: | |
| add Add a command to a Cobra Application | |
| completion Generate the autocompletion script for the specified shell | |
| help Help about any command | |
| init Initialize a Cobra Application | |
| Flags: | |
| -a, --author string author name for copyright attribution (default "YOUR NAME") | |
| --config string config file (default is $HOME/.cobra.yaml) | |
| -h, --help help for cobra-cli | |
| -l, --license string name of license for the project | |
| --viper use Viper for configuration | |
| Use "cobra-cli [command] --help" for more information about a command. | |
| ``` | |
| Help is just a command like any other. There is no special logic or behavior | |
| around it. In fact, you can provide your own if you want. | |
| ### Grouping commands in help | |
| Cobra supports grouping of available commands in the help output. To group commands, each group must be explicitly | |
| defined using `AddGroup()` on the parent command. Then a subcommand can be added to a group using the `GroupID` element | |
| of that subcommand. The groups will appear in the help output in the same order as they are defined using different | |
| calls to `AddGroup()`. If you use the generated `help` or `completion` commands, you can set their group ids using | |
| `SetHelpCommandGroupId()` and `SetCompletionCommandGroupId()` on the root command, respectively. | |
| ### Defining your own help | |
| You can provide your own Help command or your own template for the default command to use | |
| with the following functions: | |
| ```go | |
| cmd.SetHelpCommand(cmd *Command) | |
| cmd.SetHelpFunc(f func(*Command, []string)) | |
| cmd.SetHelpTemplate(s string) | |
| ``` | |
| The latter two will also apply to any children commands. | |
| Note that templates specified with `SetHelpTemplate` are evaluated using | |
| `text/template` which can increase the size of the compiled executable. | |
| ## Usage Message | |
| When the user provides an invalid flag or invalid command, Cobra responds by | |
| showing the user the 'usage'. | |
| ### Example | |
| You may recognize this from the help above. That's because the default help | |
| embeds the usage as part of its output. | |
| ```console | |
| $ cobra-cli --invalid | |
| Error: unknown flag: --invalid | |
| Usage: | |
| cobra-cli [command] | |
| Available Commands: | |
| add Add a command to a Cobra Application | |
| completion Generate the autocompletion script for the specified shell | |
| help Help about any command | |
| init Initialize a Cobra Application | |
| Flags: | |
| -a, --author string author name for copyright attribution (default "YOUR NAME") | |
| --config string config file (default is $HOME/.cobra.yaml) | |
| -h, --help help for cobra-cli | |
| -l, --license string name of license for the project | |
| --viper use Viper for configuration | |
| Use "cobra [command] --help" for more information about a command. | |
| ``` | |
| ### Defining your own usage | |
| You can provide your own usage function or template for Cobra to use. | |
| Like help, the function and template are overridable through public methods: | |
| ```go | |
| cmd.SetUsageFunc(f func(*Command) error) | |
| cmd.SetUsageTemplate(s string) | |
| ``` | |
| Note that templates specified with `SetUsageTemplate` are evaluated using | |
| `text/template` which can increase the size of the compiled executable. | |
| ## Version Flag | |
| Cobra adds a top-level '--version' flag if the Version field is set on the root command. | |
| Running an application with the '--version' flag will print the version to stdout using | |
| the version template. The template can be customized using the | |
| `cmd.SetVersionTemplate(s string)` function. | |
| Note that templates specified with `SetVersionTemplate` are evaluated using | |
| `text/template` which can increase the size of the compiled executable. | |
| ## Error Message Prefix | |
| Cobra prints an error message when receiving a non-nil error value. | |
| The default error message is `Error: <error contents>`. | |
| The Prefix, `Error:` can be customized using the `cmd.SetErrPrefix(s string)` function. | |
| ## PreRun and PostRun Hooks | |
| It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. The `*PreRun` and `*PostRun` functions will only be executed if the `Run` function of the current command has been declared. These functions are run in the following order: | |
| - `PersistentPreRun` | |
| - `PreRun` | |
| - `Run` | |
| - `PostRun` | |
| - `PersistentPostRun` | |
| An example of two commands which use all of these features is below. When the subcommand is executed, it will run the root command's `PersistentPreRun` but not the root command's `PersistentPostRun`: | |
| ```go | |
| package main | |
| import ( | |
| "fmt" | |
| "github.com/spf13/cobra" | |
| ) | |
| func main() { | |
| var rootCmd = &cobra.Command{ | |
| Use: "root [sub]", | |
| Short: "My root command", | |
| PersistentPreRun: func(cmd *cobra.Command, args []string) { | |
| fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) | |
| }, | |
| PreRun: func(cmd *cobra.Command, args []string) { | |
| fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) | |
| }, | |
| Run: func(cmd *cobra.Command, args []string) { | |
| fmt.Printf("Inside rootCmd Run with args: %v\n", args) | |
| }, | |
| PostRun: func(cmd *cobra.Command, args []string) { | |
| fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) | |
| }, | |
| PersistentPostRun: func(cmd *cobra.Command, args []string) { | |
| fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) | |
| }, | |
| } | |
| var subCmd = &cobra.Command{ | |
| Use: "sub [no options!]", | |
| Short: "My subcommand", | |
| PreRun: func(cmd *cobra.Command, args []string) { | |
| fmt.Printf("Inside subCmd PreRun with args: %v\n", args) | |
| }, | |
| Run: func(cmd *cobra.Command, args []string) { | |
| fmt.Printf("Inside subCmd Run with args: %v\n", args) | |
| }, | |
| PostRun: func(cmd *cobra.Command, args []string) { | |
| fmt.Printf("Inside subCmd PostRun with args: %v\n", args) | |
| }, | |
| PersistentPostRun: func(cmd *cobra.Command, args []string) { | |
| fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) | |
| }, | |
| } | |
| rootCmd.AddCommand(subCmd) | |
| rootCmd.SetArgs([]string{""}) | |
| rootCmd.Execute() | |
| fmt.Println() | |
| rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) | |
| rootCmd.Execute() | |
| } | |
| ``` | |
| Output: | |
| ``` | |
| Inside rootCmd PersistentPreRun with args: [] | |
| Inside rootCmd PreRun with args: [] | |
| Inside rootCmd Run with args: [] | |
| Inside rootCmd PostRun with args: [] | |
| Inside rootCmd PersistentPostRun with args: [] | |
| Inside rootCmd PersistentPreRun with args: [arg1 arg2] | |
| Inside subCmd PreRun with args: [arg1 arg2] | |
| Inside subCmd Run with args: [arg1 arg2] | |
| Inside subCmd PostRun with args: [arg1 arg2] | |
| Inside subCmd PersistentPostRun with args: [arg1 arg2] | |
| ``` | |
| By default, only the first persistent hook found in the command chain is executed. | |
| That is why in the above output, the `rootCmd PersistentPostRun` was not called for a child command. | |
| Set `EnableTraverseRunHooks` global variable to `true` if you want to execute all parents' persistent hooks. | |
| ## Suggestions when "unknown command" happens | |
| Cobra will print automatic suggestions when "unknown command" errors happen. This allows Cobra to behave similarly to the `git` command when a typo happens. For example: | |
| ```console | |
| $ hugo srever | |
| Error: unknown command "srever" for "hugo" | |
| Did you mean this? | |
| server | |
| Run 'hugo --help' for usage. | |
| ``` | |
| Suggestions are automatically generated based on existing subcommands and use an implementation of [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion. | |
| If you need to disable suggestions or tweak the string distance in your command, use: | |
| ```go | |
| command.DisableSuggestions = true | |
| ``` | |
| or | |
| ```go | |
| command.SuggestionsMinimumDistance = 1 | |
| ``` | |
| You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but make sense in your set of commands but for which | |
| you don't want aliases. Example: | |
| ```console | |
| $ kubectl remove | |
| Error: unknown command "remove" for "kubectl" | |
| Did you mean this? | |
| delete | |
| Run 'kubectl help' for usage. | |
| ``` | |
| ## Generating documentation for your command | |
| Cobra can generate documentation based on subcommands, flags, etc. | |
| Read more about it in the [docs generation documentation](docgen/_index.md). | |
| ## Generating shell completions | |
| Cobra can generate a shell-completion file for the following shells: bash, zsh, fish, PowerShell. | |
| If you add more information to your commands, these completions can be amazingly powerful and flexible. | |
| Read more about it in [Shell Completions](completions/_index.md). | |
| ## Providing Active Help | |
| Cobra makes use of the shell-completion system to define a framework allowing you to provide Active Help to your users. | |
| Active Help are messages (hints, warnings, etc) printed as the program is being used. | |
| Read more about it in [Active Help](active_help.md). | |
| ## Creating a plugin | |
| When creating a plugin for tools like *kubectl*, the executable is named | |
| `kubectl-myplugin`, but it is used as `kubectl myplugin`. To fix help | |
| messages and completions, annotate the root command with the | |
| `cobra.CommandDisplayNameAnnotation` annotation. | |
| ### Example kubectl plugin | |
| ```go | |
| package main | |
| import ( | |
| "fmt" | |
| "github.com/spf13/cobra" | |
| ) | |
| func main() { | |
| rootCmd := &cobra.Command{ | |
| Use: "kubectl-myplugin", | |
| Annotations: map[string]string{ | |
| cobra.CommandDisplayNameAnnotation: "kubectl myplugin", | |
| }, | |
| } | |
| subCmd := &cobra.Command{ | |
| Use: "subcmd", | |
| Run: func(cmd *cobra.Command, args []string) { | |
| fmt.Println("kubectl myplugin subcmd") | |
| }, | |
| } | |
| rootCmd.AddCommand(subCmd) | |
| rootCmd.Execute() | |
| } | |
| ``` | |
| Example run as a kubectl plugin: | |
| ```console | |
| $ kubectl myplugin | |
| Usage: | |
| kubectl myplugin [command] | |
| Available Commands: | |
| completion Generate the autocompletion script for the specified shell | |
| help Help about any command | |
| subcmd | |
| Flags: | |
| -h, --help help for kubectl myplugin | |
| Use "kubectl myplugin [command] --help" for more information about a command. | |
| ``` |