1# User Guide
2
3While you are welcome to provide your own organization, typically a Cobra-based
4application will follow the following organizational structure:
5
6```
7 ▾ appName/
8 ▾ cmd/
9 add.go
10 your.go
11 commands.go
12 here.go
13 main.go
14```
15
16In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra.
17
18```go
19package main
20
21import (
22 "{pathToYourApp}/cmd"
23)
24
25func main() {
26 cmd.Execute()
27}
28```
29
30## Using the Cobra Generator
31
32Cobra-CLI is its own program that will create your application and add any commands you want.
33It's the easiest way to incorporate Cobra into your application.
34
35For 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)
36
37## Using the Cobra Library
38
39To manually implement Cobra you need to create a bare main.go file and a rootCmd file.
40You will optionally provide additional commands as you see fit.
41
42### Create rootCmd
43
44Cobra doesn't require any special constructors. Simply create your commands.
45
46Ideally you place this in app/cmd/root.go:
47
48```go
49var rootCmd = &cobra.Command{
50 Use: "hugo",
51 Short: "Hugo is a very fast static site generator",
52 Long: `A Fast and Flexible Static Site Generator built with
53 love by spf13 and friends in Go.
54 Complete documentation is available at https://gohugo.io/documentation/`,
55 Run: func(cmd *cobra.Command, args []string) {
56 // Do Stuff Here
57 },
58}
59
60func Execute() {
61 if err := rootCmd.Execute(); err != nil {
62 fmt.Fprintln(os.Stderr, err)
63 os.Exit(1)
64 }
65}
66```
67
68You will additionally define flags and handle configuration in your init() function.
69
70For example cmd/root.go:
71
72```go
73package cmd
74
75import (
76 "fmt"
77 "os"
78
79 "github.com/spf13/cobra"
80 "github.com/spf13/viper"
81)
82
83var (
84 // Used for flags.
85 cfgFile string
86 userLicense string
87
88 rootCmd = &cobra.Command{
89 Use: "cobra-cli",
90 Short: "A generator for Cobra based Applications",
91 Long: `Cobra is a CLI library for Go that empowers applications.
92This application is a tool to generate the needed files
93to quickly create a Cobra application.`,
94 }
95)
96
97// Execute executes the root command.
98func Execute() error {
99 return rootCmd.Execute()
100}
101
102func init() {
103 cobra.OnInitialize(initConfig)
104
105 rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
106 rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
107 rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
108 rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")
109 viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
110 viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
111 viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
112 viper.SetDefault("license", "apache")
113
114 rootCmd.AddCommand(addCmd)
115 rootCmd.AddCommand(initCmd)
116}
117
118func initConfig() {
119 if cfgFile != "" {
120 // Use config file from the flag.
121 viper.SetConfigFile(cfgFile)
122 } else {
123 // Find home directory.
124 home, err := os.UserHomeDir()
125 cobra.CheckErr(err)
126
127 // Search config in home directory with name ".cobra" (without extension).
128 viper.AddConfigPath(home)
129 viper.SetConfigType("yaml")
130 viper.SetConfigName(".cobra")
131 }
132
133 viper.AutomaticEnv()
134
135 if err := viper.ReadInConfig(); err == nil {
136 fmt.Println("Using config file:", viper.ConfigFileUsed())
137 }
138}
139```
140
141### Create your main.go
142
143With the root command you need to have your main function execute it.
144Execute should be run on the root for clarity, though it can be called on any command.
145
146In a Cobra app, typically the main.go file is very bare. It serves one purpose: to initialize Cobra.
147
148```go
149package main
150
151import (
152 "{pathToYourApp}/cmd"
153)
154
155func main() {
156 cmd.Execute()
157}
158```
159
160### Create additional commands
161
162Additional commands can be defined and typically are each given their own file
163inside of the cmd/ directory.
164
165If you wanted to create a version command you would create cmd/version.go and
166populate it with the following:
167
168```go
169package cmd
170
171import (
172 "fmt"
173
174 "github.com/spf13/cobra"
175)
176
177func init() {
178 rootCmd.AddCommand(versionCmd)
179}
180
181var versionCmd = &cobra.Command{
182 Use: "version",
183 Short: "Print the version number of Hugo",
184 Long: `All software has versions. This is Hugo's`,
185 Run: func(cmd *cobra.Command, args []string) {
186 fmt.Println("Hugo Static Site Generator v0.9 -- HEAD")
187 },
188}
189```
190
191### Organizing subcommands
192
193A command may have subcommands which in turn may have other subcommands. This is achieved by using
194`AddCommand`. In some cases, especially in larger applications, each subcommand may be defined in
195its own go package.
196
197The suggested approach is for the parent command to use `AddCommand` to add its most immediate
198subcommands. For example, consider the following directory structure:
199
200```text
201├── cmd
202│ ├── root.go
203│ └── sub1
204│ ├── sub1.go
205│ └── sub2
206│ ├── leafA.go
207│ ├── leafB.go
208│ └── sub2.go
209└── main.go
210```
211
212In this case:
213
214* The `init` function of `root.go` adds the command defined in `sub1.go` to the root command.
215* The `init` function of `sub1.go` adds the command defined in `sub2.go` to the sub1 command.
216* The `init` function of `sub2.go` adds the commands defined in `leafA.go` and `leafB.go` to the
217 sub2 command.
218
219This approach ensures the subcommands are always included at compile time while avoiding cyclic
220references.
221
222### Returning and handling errors
223
224If you wish to return an error to the caller of a command, `RunE` can be used.
225
226```go
227package cmd
228
229import (
230 "fmt"
231
232 "github.com/spf13/cobra"
233)
234
235func init() {
236 rootCmd.AddCommand(tryCmd)
237}
238
239var tryCmd = &cobra.Command{
240 Use: "try",
241 Short: "Try and possibly fail at something",
242 RunE: func(cmd *cobra.Command, args []string) error {
243 if err := someFunc(); err != nil {
244 return err
245 }
246 return nil
247 },
248}
249```
250
251The error can then be caught at the execute function call.
252
253## Working with Flags
254
255Flags provide modifiers to control how the action command operates.
256
257### Assign flags to a command
258
259Since the flags are defined and used in different locations, we need to
260define a variable outside with the correct scope to assign the flag to
261work with.
262
263```go
264var Verbose bool
265var Source string
266```
267
268There are two different approaches to assign a flag.
269
270### Persistent Flags
271
272A flag can be 'persistent', meaning that this flag will be available to the
273command it's assigned to as well as every command under that command. For
274global flags, assign a flag as a persistent flag on the root.
275
276```go
277rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
278```
279
280### Local Flags
281
282A flag can also be assigned locally, which will only apply to that specific command.
283
284```go
285localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
286```
287
288### Local Flag on Parent Commands
289
290By default, Cobra only parses local flags on the target command, and any local flags on
291parent commands are ignored. By enabling `Command.TraverseChildren`, Cobra will
292parse local flags on each command before executing the target command.
293
294```go
295command := cobra.Command{
296 Use: "print [OPTIONS] [COMMANDS]",
297 TraverseChildren: true,
298}
299```
300
301### Bind Flags with Config
302
303You can also bind your flags with [viper](https://github.com/spf13/viper):
304```go
305var author string
306
307func init() {
308 rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
309 viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
310}
311```
312
313In this example, the persistent flag `author` is bound with `viper`.
314**Note**: the variable `author` will not be set to the value from config,
315when the `--author` flag is provided by user.
316
317More in [viper documentation](https://github.com/spf13/viper#working-with-flags).
318
319### Required flags
320
321Flags are optional by default. If instead you wish your command to report an error
322when a flag has not been set, mark it as required:
323```go
324rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
325rootCmd.MarkFlagRequired("region")
326```
327
328Or, for persistent flags:
329```go
330rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
331rootCmd.MarkPersistentFlagRequired("region")
332```
333
334### Flag Groups
335
336If 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
337Cobra can enforce that requirement:
338```go
339rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)")
340rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)")
341rootCmd.MarkFlagsRequiredTogether("username", "password")
342```
343
344You can also prevent different flags from being provided together if they represent mutually
345exclusive options such as specifying an output format as either `--json` or `--yaml` but never both:
346```go
347rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON")
348rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML")
349rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")
350```
351
352If you want to require at least one flag from a group to be present, you can use `MarkFlagsOneRequired`.
353This can be combined with `MarkFlagsMutuallyExclusive` to enforce exactly one flag from a given group:
354```go
355rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON")
356rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML")
357rootCmd.MarkFlagsOneRequired("json", "yaml")
358rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")
359```
360
361In these cases:
362 - both local and persistent flags can be used
363 - **NOTE:** the group is only enforced on commands where every flag is defined
364 - a flag may appear in multiple groups
365 - a group may contain any number of flags
366
367## Positional and Custom Arguments
368
369Validation of positional arguments can be specified using the `Args` field of `Command`.
370The following validators are built in:
371
372- Number of arguments:
373 - `NoArgs` - report an error if there are any positional args.
374 - `ArbitraryArgs` - accept any number of args.
375 - `MinimumNArgs(int)` - report an error if less than N positional args are provided.
376 - `MaximumNArgs(int)` - report an error if more than N positional args are provided.
377 - `ExactArgs(int)` - report an error if there are not exactly N positional args.
378 - `RangeArgs(min, max)` - report an error if the number of args is not between `min` and `max`.
379- Content of the arguments:
380 - `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.
381
382If `Args` is undefined or `nil`, it defaults to `ArbitraryArgs`.
383
384Moreover, `MatchAll(pargs ...PositionalArgs)` enables combining existing checks with arbitrary other checks.
385For instance, if you want to report an error if there are not exactly N positional args OR if there are any positional
386args that are not in the `ValidArgs` field of `Command`, you can call `MatchAll` on `ExactArgs` and `OnlyValidArgs`, as
387shown below:
388
389```go
390var cmd = &cobra.Command{
391 Short: "hello",
392 Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs),
393 Run: func(cmd *cobra.Command, args []string) {
394 fmt.Println("Hello, World!")
395 },
396}
397```
398
399It is possible to set any custom validator that satisfies `func(cmd *cobra.Command, args []string) error`.
400For example:
401
402```go
403var cmd = &cobra.Command{
404 Short: "hello",
405 Args: func(cmd *cobra.Command, args []string) error {
406 // Optionally run one of the validators provided by cobra
407 if err := cobra.MinimumNArgs(1)(cmd, args); err != nil {
408 return err
409 }
410 // Run the custom validation logic
411 if myapp.IsValidColor(args[0]) {
412 return nil
413 }
414 return fmt.Errorf("invalid color specified: %s", args[0])
415 },
416 Run: func(cmd *cobra.Command, args []string) {
417 fmt.Println("Hello, World!")
418 },
419}
420```
421
422## Example
423
424In the example below, we have defined three commands. Two are at the top level
425and one (cmdTimes) is a child of one of the top commands. In this case the root
426is not executable, meaning that a subcommand is required. This is accomplished
427by not providing a 'Run' for the 'rootCmd'.
428
429We have only defined one flag for a single command.
430
431More documentation about flags is available at https://github.com/spf13/pflag
432
433```go
434package main
435
436import (
437 "fmt"
438 "strings"
439
440 "github.com/spf13/cobra"
441)
442
443func main() {
444 var echoTimes int
445
446 var cmdPrint = &cobra.Command{
447 Use: "print [string to print]",
448 Short: "Print anything to the screen",
449 Long: `print is for printing anything back to the screen.
450For many years people have printed back to the screen.`,
451 Args: cobra.MinimumNArgs(1),
452 Run: func(cmd *cobra.Command, args []string) {
453 fmt.Println("Print: " + strings.Join(args, " "))
454 },
455 }
456
457 var cmdEcho = &cobra.Command{
458 Use: "echo [string to echo]",
459 Short: "Echo anything to the screen",
460 Long: `echo is for echoing anything back.
461Echo works a lot like print, except it has a child command.`,
462 Args: cobra.MinimumNArgs(1),
463 Run: func(cmd *cobra.Command, args []string) {
464 fmt.Println("Echo: " + strings.Join(args, " "))
465 },
466 }
467
468 var cmdTimes = &cobra.Command{
469 Use: "times [string to echo]",
470 Short: "Echo anything to the screen more times",
471 Long: `echo things multiple times back to the user by providing
472a count and a string.`,
473 Args: cobra.MinimumNArgs(1),
474 Run: func(cmd *cobra.Command, args []string) {
475 for i := 0; i < echoTimes; i++ {
476 fmt.Println("Echo: " + strings.Join(args, " "))
477 }
478 },
479 }
480
481 cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input")
482
483 var rootCmd = &cobra.Command{Use: "app"}
484 rootCmd.AddCommand(cmdPrint, cmdEcho)
485 cmdEcho.AddCommand(cmdTimes)
486 rootCmd.Execute()
487}
488```
489
490For a more complete example of a larger application, please checkout [Hugo](https://gohugo.io/).
491
492## Help Command
493
494Cobra automatically adds a help command to your application when you have subcommands.
495This will be called when a user runs 'app help'. Additionally, help will also
496support all other commands as input. Say, for instance, you have a command called
497'create' without any additional configuration; Cobra will work when 'app help
498create' is called. Every command will automatically have the '--help' flag added.
499
500### Example
501
502The following output is automatically generated by Cobra. Nothing beyond the
503command and flag definitions are needed.
504
505 $ cobra-cli help
506
507 Cobra is a CLI library for Go that empowers applications.
508 This application is a tool to generate the needed files
509 to quickly create a Cobra application.
510
511 Usage:
512 cobra-cli [command]
513
514 Available Commands:
515 add Add a command to a Cobra Application
516 completion Generate the autocompletion script for the specified shell
517 help Help about any command
518 init Initialize a Cobra Application
519
520 Flags:
521 -a, --author string author name for copyright attribution (default "YOUR NAME")
522 --config string config file (default is $HOME/.cobra.yaml)
523 -h, --help help for cobra-cli
524 -l, --license string name of license for the project
525 --viper use Viper for configuration
526
527 Use "cobra-cli [command] --help" for more information about a command.
528
529
530Help is just a command like any other. There is no special logic or behavior
531around it. In fact, you can provide your own if you want.
532
533### Grouping commands in help
534
535Cobra supports grouping of available commands in the help output. To group commands, each group must be explicitly
536defined using `AddGroup()` on the parent command. Then a subcommand can be added to a group using the `GroupID` element
537of that subcommand. The groups will appear in the help output in the same order as they are defined using different
538calls to `AddGroup()`. If you use the generated `help` or `completion` commands, you can set their group ids using
539`SetHelpCommandGroupId()` and `SetCompletionCommandGroupId()` on the root command, respectively.
540
541### Defining your own help
542
543You can provide your own Help command or your own template for the default command to use
544with the following functions:
545
546```go
547cmd.SetHelpCommand(cmd *Command)
548cmd.SetHelpFunc(f func(*Command, []string))
549cmd.SetHelpTemplate(s string)
550```
551
552The latter two will also apply to any children commands.
553
554## Usage Message
555
556When the user provides an invalid flag or invalid command, Cobra responds by
557showing the user the 'usage'.
558
559### Example
560You may recognize this from the help above. That's because the default help
561embeds the usage as part of its output.
562
563 $ cobra-cli --invalid
564 Error: unknown flag: --invalid
565 Usage:
566 cobra-cli [command]
567
568 Available Commands:
569 add Add a command to a Cobra Application
570 completion Generate the autocompletion script for the specified shell
571 help Help about any command
572 init Initialize a Cobra Application
573
574 Flags:
575 -a, --author string author name for copyright attribution (default "YOUR NAME")
576 --config string config file (default is $HOME/.cobra.yaml)
577 -h, --help help for cobra-cli
578 -l, --license string name of license for the project
579 --viper use Viper for configuration
580
581 Use "cobra [command] --help" for more information about a command.
582
583### Defining your own usage
584You can provide your own usage function or template for Cobra to use.
585Like help, the function and template are overridable through public methods:
586
587```go
588cmd.SetUsageFunc(f func(*Command) error)
589cmd.SetUsageTemplate(s string)
590```
591
592## Version Flag
593
594Cobra adds a top-level '--version' flag if the Version field is set on the root command.
595Running an application with the '--version' flag will print the version to stdout using
596the version template. The template can be customized using the
597`cmd.SetVersionTemplate(s string)` function.
598
599## Error Message Prefix
600
601Cobra prints an error message when receiving a non-nil error value.
602The default error message is `Error: <error contents>`.
603The Prefix, `Error:` can be customized using the `cmd.SetErrPrefix(s string)` function.
604
605## PreRun and PostRun Hooks
606
607It 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:
608
609- `PersistentPreRun`
610- `PreRun`
611- `Run`
612- `PostRun`
613- `PersistentPostRun`
614
615An 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`:
616
617```go
618package main
619
620import (
621 "fmt"
622
623 "github.com/spf13/cobra"
624)
625
626func main() {
627
628 var rootCmd = &cobra.Command{
629 Use: "root [sub]",
630 Short: "My root command",
631 PersistentPreRun: func(cmd *cobra.Command, args []string) {
632 fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args)
633 },
634 PreRun: func(cmd *cobra.Command, args []string) {
635 fmt.Printf("Inside rootCmd PreRun with args: %v\n", args)
636 },
637 Run: func(cmd *cobra.Command, args []string) {
638 fmt.Printf("Inside rootCmd Run with args: %v\n", args)
639 },
640 PostRun: func(cmd *cobra.Command, args []string) {
641 fmt.Printf("Inside rootCmd PostRun with args: %v\n", args)
642 },
643 PersistentPostRun: func(cmd *cobra.Command, args []string) {
644 fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args)
645 },
646 }
647
648 var subCmd = &cobra.Command{
649 Use: "sub [no options!]",
650 Short: "My subcommand",
651 PreRun: func(cmd *cobra.Command, args []string) {
652 fmt.Printf("Inside subCmd PreRun with args: %v\n", args)
653 },
654 Run: func(cmd *cobra.Command, args []string) {
655 fmt.Printf("Inside subCmd Run with args: %v\n", args)
656 },
657 PostRun: func(cmd *cobra.Command, args []string) {
658 fmt.Printf("Inside subCmd PostRun with args: %v\n", args)
659 },
660 PersistentPostRun: func(cmd *cobra.Command, args []string) {
661 fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args)
662 },
663 }
664
665 rootCmd.AddCommand(subCmd)
666
667 rootCmd.SetArgs([]string{""})
668 rootCmd.Execute()
669 fmt.Println()
670 rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
671 rootCmd.Execute()
672}
673```
674
675Output:
676```
677Inside rootCmd PersistentPreRun with args: []
678Inside rootCmd PreRun with args: []
679Inside rootCmd Run with args: []
680Inside rootCmd PostRun with args: []
681Inside rootCmd PersistentPostRun with args: []
682
683Inside rootCmd PersistentPreRun with args: [arg1 arg2]
684Inside subCmd PreRun with args: [arg1 arg2]
685Inside subCmd Run with args: [arg1 arg2]
686Inside subCmd PostRun with args: [arg1 arg2]
687Inside subCmd PersistentPostRun with args: [arg1 arg2]
688```
689
690By default, only the first persistent hook found in the command chain is executed.
691That is why in the above output, the `rootCmd PersistentPostRun` was not called for a child command.
692Set `EnableTraverseRunHooks` global variable to `true` if you want to execute all parents' persistent hooks.
693
694## Suggestions when "unknown command" happens
695
696Cobra 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:
697
698```
699$ hugo srever
700Error: unknown command "srever" for "hugo"
701
702Did you mean this?
703 server
704
705Run 'hugo --help' for usage.
706```
707
708Suggestions 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.
709
710If you need to disable suggestions or tweak the string distance in your command, use:
711
712```go
713command.DisableSuggestions = true
714```
715
716or
717
718```go
719command.SuggestionsMinimumDistance = 1
720```
721
722You 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
723you don't want aliases. Example:
724
725```
726$ kubectl remove
727Error: unknown command "remove" for "kubectl"
728
729Did you mean this?
730 delete
731
732Run 'kubectl help' for usage.
733```
734
735## Generating documentation for your command
736
737Cobra can generate documentation based on subcommands, flags, etc.
738Read more about it in the [docs generation documentation](docgen/_index.md).
739
740## Generating shell completions
741
742Cobra can generate a shell-completion file for the following shells: bash, zsh, fish, PowerShell.
743If you add more information to your commands, these completions can be amazingly powerful and flexible.
744Read more about it in [Shell Completions](completions/_index.md).
745
746## Providing Active Help
747
748Cobra makes use of the shell-completion system to define a framework allowing you to provide Active Help to your users.
749Active Help are messages (hints, warnings, etc) printed as the program is being used.
750Read more about it in [Active Help](active_help.md).
View as plain text