1cli v1 manual
2===
3
4<!-- toc -->
5
6- [Getting Started](#getting-started)
7- [Examples](#examples)
8  * [Arguments](#arguments)
9  * [Flags](#flags)
10    + [Placeholder Values](#placeholder-values)
11    + [Alternate Names](#alternate-names)
12    + [Ordering](#ordering)
13    + [Values from the Environment](#values-from-the-environment)
14    + [Values from files](#values-from-files)
15    + [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others)
16    + [Precedence](#precedence)
17  * [Subcommands](#subcommands)
18  * [Subcommands categories](#subcommands-categories)
19  * [Exit code](#exit-code)
20  * [Combining short options](#combining-short-options)
21  * [Bash Completion](#bash-completion)
22    + [Enabling](#enabling)
23    + [Distribution](#distribution)
24    + [Customization](#customization)
25  * [Generated Help Text](#generated-help-text)
26    + [Customization](#customization-1)
27  * [Version Flag](#version-flag)
28    + [Customization](#customization-2)
29    + [Full API Example](#full-api-example)
30  * [Migrating to V2](#migrating-to-v2)
31
32<!-- tocstop -->
33
34## Getting Started
35
36One of the philosophies behind cli is that an API should be playful and full of
37discovery. So a cli app can be as little as one line of code in `main()`.
38
39<!-- {
40  "args": ["&#45;&#45;help"],
41  "output": "A new cli application"
42} -->
43``` go
44package main
45
46import (
47  "log"
48  "os"
49
50  "github.com/urfave/cli"
51)
52
53func main() {
54  err := cli.NewApp().Run(os.Args)
55  if err != nil {
56    log.Fatal(err)
57  }
58}
59```
60
61This app will run and show help text, but is not very useful. Let's give an
62action to execute and some help documentation:
63
64<!-- {
65  "output": "boom! I say!"
66} -->
67``` go
68package main
69
70import (
71  "fmt"
72  "log"
73  "os"
74
75  "github.com/urfave/cli"
76)
77
78func main() {
79  app := cli.NewApp()
80  app.Name = "boom"
81  app.Usage = "make an explosive entrance"
82  app.Action = func(c *cli.Context) error {
83    fmt.Println("boom! I say!")
84    return nil
85  }
86
87  err := app.Run(os.Args)
88  if err != nil {
89    log.Fatal(err)
90  }
91}
92```
93
94Running this already gives you a ton of functionality, plus support for things
95like subcommands and flags, which are covered below.
96
97## Examples
98
99Being a programmer can be a lonely job. Thankfully by the power of automation
100that is not the case! Let's create a greeter app to fend off our demons of
101loneliness!
102
103Start by creating a directory named `greet`, and within it, add a file,
104`greet.go` with the following code in it:
105
106<!-- {
107  "output": "Hello friend!"
108} -->
109``` go
110package main
111
112import (
113  "fmt"
114  "log"
115  "os"
116
117  "github.com/urfave/cli"
118)
119
120func main() {
121  app := cli.NewApp()
122  app.Name = "greet"
123  app.Usage = "fight the loneliness!"
124  app.Action = func(c *cli.Context) error {
125    fmt.Println("Hello friend!")
126    return nil
127  }
128
129  err := app.Run(os.Args)
130  if err != nil {
131    log.Fatal(err)
132  }
133}
134```
135
136Install our command to the `$GOPATH/bin` directory:
137
138```
139$ go install
140```
141
142Finally run our new command:
143
144```
145$ greet
146Hello friend!
147```
148
149cli also generates neat help text:
150
151```
152$ greet help
153NAME:
154    greet - fight the loneliness!
155
156USAGE:
157    greet [global options] command [command options] [arguments...]
158
159VERSION:
160    0.0.0
161
162COMMANDS:
163    help, h  Shows a list of commands or help for one command
164
165GLOBAL OPTIONS
166    --version Shows version information
167```
168
169### Arguments
170
171You can lookup arguments by calling the `Args` function on `cli.Context`, e.g.:
172
173<!-- {
174  "output": "Hello \""
175} -->
176``` go
177package main
178
179import (
180  "fmt"
181  "log"
182  "os"
183
184  "github.com/urfave/cli"
185)
186
187func main() {
188  app := cli.NewApp()
189
190  app.Action = func(c *cli.Context) error {
191    fmt.Printf("Hello %q", c.Args().Get(0))
192    return nil
193  }
194
195  err := app.Run(os.Args)
196  if err != nil {
197    log.Fatal(err)
198  }
199}
200```
201
202### Flags
203
204Setting and querying flags is simple.
205
206<!-- {
207  "output": "Hello Nefertiti"
208} -->
209``` go
210package main
211
212import (
213  "fmt"
214  "log"
215  "os"
216
217  "github.com/urfave/cli"
218)
219
220func main() {
221  app := cli.NewApp()
222
223  app.Flags = []cli.Flag {
224    cli.StringFlag{
225      Name: "lang",
226      Value: "english",
227      Usage: "language for the greeting",
228    },
229  }
230
231  app.Action = func(c *cli.Context) error {
232    name := "Nefertiti"
233    if c.NArg() > 0 {
234      name = c.Args().Get(0)
235    }
236    if c.String("lang") == "spanish" {
237      fmt.Println("Hola", name)
238    } else {
239      fmt.Println("Hello", name)
240    }
241    return nil
242  }
243
244  err := app.Run(os.Args)
245  if err != nil {
246    log.Fatal(err)
247  }
248}
249```
250
251You can also set a destination variable for a flag, to which the content will be
252scanned.
253
254<!-- {
255  "output": "Hello someone"
256} -->
257``` go
258package main
259
260import (
261  "log"
262  "os"
263  "fmt"
264
265  "github.com/urfave/cli"
266)
267
268func main() {
269  var language string
270
271  app := cli.NewApp()
272
273  app.Flags = []cli.Flag {
274    cli.StringFlag{
275      Name:        "lang",
276      Value:       "english",
277      Usage:       "language for the greeting",
278      Destination: &language,
279    },
280  }
281
282  app.Action = func(c *cli.Context) error {
283    name := "someone"
284    if c.NArg() > 0 {
285      name = c.Args()[0]
286    }
287    if language == "spanish" {
288      fmt.Println("Hola", name)
289    } else {
290      fmt.Println("Hello", name)
291    }
292    return nil
293  }
294
295  err := app.Run(os.Args)
296  if err != nil {
297    log.Fatal(err)
298  }
299}
300```
301
302See full list of flags at http://godoc.org/github.com/urfave/cli
303
304#### Placeholder Values
305
306Sometimes it's useful to specify a flag's value within the usage string itself.
307Such placeholders are indicated with back quotes.
308
309For example this:
310
311<!-- {
312  "args": ["&#45;&#45;help"],
313  "output": "&#45;&#45;config FILE, &#45;c FILE"
314} -->
315```go
316package main
317
318import (
319  "log"
320  "os"
321
322  "github.com/urfave/cli"
323)
324
325func main() {
326  app := cli.NewApp()
327
328  app.Flags = []cli.Flag{
329    cli.StringFlag{
330      Name:  "config, c",
331      Usage: "Load configuration from `FILE`",
332    },
333  }
334
335  err := app.Run(os.Args)
336  if err != nil {
337    log.Fatal(err)
338  }
339}
340```
341
342Will result in help output like:
343
344```
345--config FILE, -c FILE   Load configuration from FILE
346```
347
348Note that only the first placeholder is used. Subsequent back-quoted words will
349be left as-is.
350
351#### Alternate Names
352
353You can set alternate (or short) names for flags by providing a comma-delimited
354list for the `Name`. e.g.
355
356<!-- {
357  "args": ["&#45;&#45;help"],
358  "output": "&#45;&#45;lang value, &#45;l value.*language for the greeting.*default: \"english\""
359} -->
360``` go
361package main
362
363import (
364  "log"
365  "os"
366
367  "github.com/urfave/cli"
368)
369
370func main() {
371  app := cli.NewApp()
372
373  app.Flags = []cli.Flag {
374    cli.StringFlag{
375      Name: "lang, l",
376      Value: "english",
377      Usage: "language for the greeting",
378    },
379  }
380
381  err := app.Run(os.Args)
382  if err != nil {
383    log.Fatal(err)
384  }
385}
386```
387
388That flag can then be set with `--lang spanish` or `-l spanish`. Note that
389giving two different forms of the same flag in the same command invocation is an
390error.
391
392#### Ordering
393
394Flags for the application and commands are shown in the order they are defined.
395However, it's possible to sort them from outside this library by using `FlagsByName`
396or `CommandsByName` with `sort`.
397
398For example this:
399
400<!-- {
401  "args": ["&#45;&#45;help"],
402  "output": "add a task to the list\n.*complete a task on the list\n.*\n\n.*\n.*Load configuration from FILE\n.*Language for the greeting.*"
403} -->
404``` go
405package main
406
407import (
408  "log"
409  "os"
410  "sort"
411
412  "github.com/urfave/cli"
413)
414
415func main() {
416  app := cli.NewApp()
417
418  app.Flags = []cli.Flag {
419    cli.StringFlag{
420      Name: "lang, l",
421      Value: "english",
422      Usage: "Language for the greeting",
423    },
424    cli.StringFlag{
425      Name: "config, c",
426      Usage: "Load configuration from `FILE`",
427    },
428  }
429
430  app.Commands = []cli.Command{
431    {
432      Name:    "complete",
433      Aliases: []string{"c"},
434      Usage:   "complete a task on the list",
435      Action:  func(c *cli.Context) error {
436        return nil
437      },
438    },
439    {
440      Name:    "add",
441      Aliases: []string{"a"},
442      Usage:   "add a task to the list",
443      Action:  func(c *cli.Context) error {
444        return nil
445      },
446    },
447  }
448
449  sort.Sort(cli.FlagsByName(app.Flags))
450  sort.Sort(cli.CommandsByName(app.Commands))
451
452  err := app.Run(os.Args)
453  if err != nil {
454    log.Fatal(err)
455  }
456}
457```
458
459Will result in help output like:
460
461```
462--config FILE, -c FILE  Load configuration from FILE
463--lang value, -l value  Language for the greeting (default: "english")
464```
465
466#### Values from the Environment
467
468You can also have the default value set from the environment via `EnvVar`.  e.g.
469
470<!-- {
471  "args": ["&#45;&#45;help"],
472  "output": "language for the greeting.*APP_LANG"
473} -->
474``` go
475package main
476
477import (
478  "log"
479  "os"
480
481  "github.com/urfave/cli"
482)
483
484func main() {
485  app := cli.NewApp()
486
487  app.Flags = []cli.Flag {
488    cli.StringFlag{
489      Name: "lang, l",
490      Value: "english",
491      Usage: "language for the greeting",
492      EnvVar: "APP_LANG",
493    },
494  }
495
496  err := app.Run(os.Args)
497  if err != nil {
498    log.Fatal(err)
499  }
500}
501```
502
503The `EnvVar` may also be given as a comma-delimited "cascade", where the first
504environment variable that resolves is used as the default.
505
506<!-- {
507  "args": ["&#45;&#45;help"],
508  "output": "language for the greeting.*LEGACY_COMPAT_LANG.*APP_LANG.*LANG"
509} -->
510``` go
511package main
512
513import (
514  "log"
515  "os"
516
517  "github.com/urfave/cli"
518)
519
520func main() {
521  app := cli.NewApp()
522
523  app.Flags = []cli.Flag {
524    cli.StringFlag{
525      Name: "lang, l",
526      Value: "english",
527      Usage: "language for the greeting",
528      EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG",
529    },
530  }
531
532  err := app.Run(os.Args)
533  if err != nil {
534    log.Fatal(err)
535  }
536}
537```
538
539#### Values from files
540
541You can also have the default value set from file via `FilePath`.  e.g.
542
543<!-- {
544  "args": ["&#45;&#45;help"],
545  "output": "password for the mysql database"
546} -->
547``` go
548package main
549
550import (
551  "log"
552  "os"
553
554  "github.com/urfave/cli"
555)
556
557func main() {
558  app := cli.NewApp()
559
560  app.Flags = []cli.Flag {
561    cli.StringFlag{
562      Name: "password, p",
563      Usage: "password for the mysql database",
564      FilePath: "/etc/mysql/password",
565    },
566  }
567
568  err := app.Run(os.Args)
569  if err != nil {
570    log.Fatal(err)
571  }
572}
573```
574
575Note that default values set from file (e.g. `FilePath`) take precedence over
576default values set from the environment (e.g. `EnvVar`).
577
578#### Values from alternate input sources (YAML, TOML, and others)
579
580There is a separate package altsrc that adds support for getting flag values
581from other file input sources.
582
583Currently supported input source formats:
584* YAML
585* JSON
586* TOML
587
588In order to get values for a flag from an alternate input source the following
589code would be added to wrap an existing cli.Flag like below:
590
591``` go
592  altsrc.NewIntFlag(cli.IntFlag{Name: "test"})
593```
594
595Initialization must also occur for these flags. Below is an example initializing
596getting data from a yaml file below.
597
598``` go
599  command.Before = altsrc.InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
600```
601
602The code above will use the "load" string as a flag name to get the file name of
603a yaml file from the cli.Context.  It will then use that file name to initialize
604the yaml input source for any flags that are defined on that command.  As a note
605the "load" flag used would also have to be defined on the command flags in order
606for this code snippet to work.
607
608Currently only YAML, JSON, and TOML files are supported but developers can add support
609for other input sources by implementing the altsrc.InputSourceContext for their
610given sources.
611
612Here is a more complete sample of a command using YAML support:
613
614<!-- {
615  "args": ["test-cmd", "&#45;&#45;help"],
616  "output": "&#45&#45;test value.*default: 0"
617} -->
618``` go
619package notmain
620
621import (
622  "fmt"
623  "log"
624  "os"
625
626  "github.com/urfave/cli"
627  "github.com/urfave/cli/altsrc"
628)
629
630func main() {
631  app := cli.NewApp()
632
633  flags := []cli.Flag{
634    altsrc.NewIntFlag(cli.IntFlag{Name: "test"}),
635    cli.StringFlag{Name: "load"},
636  }
637
638  app.Action = func(c *cli.Context) error {
639    fmt.Println("yaml ist rad")
640    return nil
641  }
642
643  app.Before = altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load"))
644  app.Flags = flags
645
646  err := app.Run(os.Args)
647  if err != nil {
648    log.Fatal(err)
649  }
650}
651```
652
653#### Precedence
654
655The precedence for flag value sources is as follows (highest to lowest):
656
6570. Command line flag value from user
6580. Environment variable (if specified)
6590. Configuration file (if specified)
6600. Default defined on the flag
661
662### Subcommands
663
664Subcommands can be defined for a more git-like command line app.
665
666<!-- {
667  "args": ["template", "add"],
668  "output": "new task template: .+"
669} -->
670```go
671package main
672
673import (
674  "fmt"
675  "log"
676  "os"
677
678  "github.com/urfave/cli"
679)
680
681func main() {
682  app := cli.NewApp()
683
684  app.Commands = []cli.Command{
685    {
686      Name:    "add",
687      Aliases: []string{"a"},
688      Usage:   "add a task to the list",
689      Action:  func(c *cli.Context) error {
690        fmt.Println("added task: ", c.Args().First())
691        return nil
692      },
693    },
694    {
695      Name:    "complete",
696      Aliases: []string{"c"},
697      Usage:   "complete a task on the list",
698      Action:  func(c *cli.Context) error {
699        fmt.Println("completed task: ", c.Args().First())
700        return nil
701      },
702    },
703    {
704      Name:        "template",
705      Aliases:     []string{"t"},
706      Usage:       "options for task templates",
707      Subcommands: []cli.Command{
708        {
709          Name:  "add",
710          Usage: "add a new template",
711          Action: func(c *cli.Context) error {
712            fmt.Println("new task template: ", c.Args().First())
713            return nil
714          },
715        },
716        {
717          Name:  "remove",
718          Usage: "remove an existing template",
719          Action: func(c *cli.Context) error {
720            fmt.Println("removed task template: ", c.Args().First())
721            return nil
722          },
723        },
724      },
725    },
726  }
727
728  err := app.Run(os.Args)
729  if err != nil {
730    log.Fatal(err)
731  }
732}
733```
734
735### Subcommands categories
736
737For additional organization in apps that have many subcommands, you can
738associate a category for each command to group them together in the help
739output.
740
741E.g.
742
743```go
744package main
745
746import (
747  "log"
748  "os"
749
750  "github.com/urfave/cli"
751)
752
753func main() {
754  app := cli.NewApp()
755
756  app.Commands = []cli.Command{
757    {
758      Name: "noop",
759    },
760    {
761      Name:     "add",
762      Category: "Template actions",
763    },
764    {
765      Name:     "remove",
766      Category: "Template actions",
767    },
768  }
769
770  err := app.Run(os.Args)
771  if err != nil {
772    log.Fatal(err)
773  }
774}
775```
776
777Will include:
778
779```
780COMMANDS:
781  noop
782
783  Template actions:
784    add
785    remove
786```
787
788### Exit code
789
790Calling `App.Run` will not automatically call `os.Exit`, which means that by
791default the exit code will "fall through" to being `0`.  An explicit exit code
792may be set by returning a non-nil error that fulfills `cli.ExitCoder`, *or* a
793`cli.MultiError` that includes an error that fulfills `cli.ExitCoder`, e.g.:
794<!-- {
795  "error": "Ginger croutons are not in the soup"
796} -->
797``` go
798package main
799
800import (
801  "log"
802  "os"
803
804  "github.com/urfave/cli"
805)
806
807func main() {
808  app := cli.NewApp()
809  app.Flags = []cli.Flag{
810    cli.BoolFlag{
811      Name:  "ginger-crouton",
812      Usage: "Add ginger croutons to the soup",
813    },
814  }
815  app.Action = func(ctx *cli.Context) error {
816    if !ctx.Bool("ginger-crouton") {
817      return cli.NewExitError("Ginger croutons are not in the soup", 86)
818    }
819    return nil
820  }
821
822  err := app.Run(os.Args)
823  if err != nil {
824    log.Fatal(err)
825  }
826}
827```
828
829### Combining short options
830
831Traditional use of options using their shortnames look like this:
832
833```
834$ cmd -s -o -m "Some message"
835```
836
837Suppose you want users to be able to combine options with their shortnames. This
838can be done using the `UseShortOptionHandling` bool in your app configuration,
839or for individual commands by attaching it to the command configuration. For
840example:
841
842<!-- {
843  "args": ["short", "&#45;som", "Some message"],
844  "output": "serve: true\noption: true\nmessage: Some message\n"
845} -->
846``` go
847package main
848
849import (
850  "fmt"
851  "log"
852  "os"
853
854  "github.com/urfave/cli"
855)
856
857func main() {
858  app := cli.NewApp()
859  app.UseShortOptionHandling = true
860  app.Commands = []cli.Command{
861    {
862      Name:  "short",
863      Usage: "complete a task on the list",
864      Flags: []cli.Flag{
865        cli.BoolFlag{Name: "serve, s"},
866        cli.BoolFlag{Name: "option, o"},
867        cli.StringFlag{Name: "message, m"},
868      },
869      Action: func(c *cli.Context) error {
870        fmt.Println("serve:", c.Bool("serve"))
871        fmt.Println("option:", c.Bool("option"))
872        fmt.Println("message:", c.String("message"))
873        return nil
874      },
875    },
876  }
877
878  err := app.Run(os.Args)
879  if err != nil {
880    log.Fatal(err)
881  }
882}
883```
884
885If your program has any number of bool flags such as `serve` and `option`, and
886optionally one non-bool flag `message`, with the short options of `-s`, `-o`,
887and `-m` respectively, setting `UseShortOptionHandling` will also support the
888following syntax:
889
890```
891$ cmd -som "Some message"
892```
893
894If you enable `UseShortOptionHandling`, then you must not use any flags that
895have a single leading `-` or this will result in failures. For example,
896`-option` can no longer be used. Flags with two leading dashes (such as
897`--options`) are still valid.
898
899### Bash Completion
900
901You can enable completion commands by setting the `EnableBashCompletion`
902flag on the `App` object.  By default, this setting will only auto-complete to
903show an app's subcommands, but you can write your own completion methods for
904the App or its subcommands.
905
906<!-- {
907  "args": ["complete", "&#45;&#45;generate&#45;bash&#45;completion"],
908  "output": "laundry"
909} -->
910``` go
911package main
912
913import (
914  "fmt"
915  "log"
916  "os"
917
918  "github.com/urfave/cli"
919)
920
921func main() {
922  tasks := []string{"cook", "clean", "laundry", "eat", "sleep", "code"}
923
924  app := cli.NewApp()
925  app.EnableBashCompletion = true
926  app.Commands = []cli.Command{
927    {
928      Name:  "complete",
929      Aliases: []string{"c"},
930      Usage: "complete a task on the list",
931      Action: func(c *cli.Context) error {
932         fmt.Println("completed task: ", c.Args().First())
933         return nil
934      },
935      BashComplete: func(c *cli.Context) {
936        // This will complete if no args are passed
937        if c.NArg() > 0 {
938          return
939        }
940        for _, t := range tasks {
941          fmt.Println(t)
942        }
943      },
944    },
945  }
946
947  err := app.Run(os.Args)
948  if err != nil {
949    log.Fatal(err)
950  }
951}
952```
953
954#### Enabling
955
956Source the `autocomplete/bash_autocomplete` file in your `.bashrc` file while
957setting the `PROG` variable to the name of your program:
958
959`PROG=myprogram source /.../cli/autocomplete/bash_autocomplete`
960
961#### Distribution
962
963Copy `autocomplete/bash_autocomplete` into `/etc/bash_completion.d/` and rename
964it to the name of the program you wish to add autocomplete support for (or
965automatically install it there if you are distributing a package). Don't forget
966to source the file to make it active in the current shell.
967
968```
969sudo cp src/bash_autocomplete /etc/bash_completion.d/<myprogram>
970source /etc/bash_completion.d/<myprogram>
971```
972
973Alternatively, you can just document that users should source the generic
974`autocomplete/bash_autocomplete` in their bash configuration with `$PROG` set
975to the name of their program (as above).
976
977#### Customization
978
979The default bash completion flag (`--generate-bash-completion`) is defined as
980`cli.BashCompletionFlag`, and may be redefined if desired, e.g.:
981
982<!-- {
983  "args": ["&#45;&#45;compgen"],
984  "output": "wat\nhelp\nh"
985} -->
986``` go
987package main
988
989import (
990  "log"
991  "os"
992
993  "github.com/urfave/cli"
994)
995
996func main() {
997  cli.BashCompletionFlag = cli.BoolFlag{
998    Name:   "compgen",
999    Hidden: true,
1000  }
1001
1002  app := cli.NewApp()
1003  app.EnableBashCompletion = true
1004  app.Commands = []cli.Command{
1005    {
1006      Name: "wat",
1007    },
1008  }
1009  err := app.Run(os.Args)
1010  if err != nil {
1011    log.Fatal(err)
1012  }
1013}
1014```
1015
1016### Generated Help Text
1017
1018The default help flag (`-h/--help`) is defined as `cli.HelpFlag` and is checked
1019by the cli internals in order to print generated help text for the app, command,
1020or subcommand, and break execution.
1021
1022#### Customization
1023
1024All of the help text generation may be customized, and at multiple levels.  The
1025templates are exposed as variables `AppHelpTemplate`, `CommandHelpTemplate`, and
1026`SubcommandHelpTemplate` which may be reassigned or augmented, and full override
1027is possible by assigning a compatible func to the `cli.HelpPrinter` variable,
1028e.g.:
1029
1030<!-- {
1031  "output": "Ha HA.  I pwnd the help!!1"
1032} -->
1033``` go
1034package main
1035
1036import (
1037  "fmt"
1038  "log"
1039  "io"
1040  "os"
1041
1042  "github.com/urfave/cli"
1043)
1044
1045func main() {
1046  // EXAMPLE: Append to an existing template
1047  cli.AppHelpTemplate = fmt.Sprintf(`%s
1048
1049WEBSITE: http://awesometown.example.com
1050
1051SUPPORT: support@awesometown.example.com
1052
1053`, cli.AppHelpTemplate)
1054
1055  // EXAMPLE: Override a template
1056  cli.AppHelpTemplate = `NAME:
1057   {{.Name}} - {{.Usage}}
1058USAGE:
1059   {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
1060   {{if len .Authors}}
1061AUTHOR:
1062   {{range .Authors}}{{ . }}{{end}}
1063   {{end}}{{if .Commands}}
1064COMMANDS:
1065{{range .Commands}}{{if not .HideHelp}}   {{join .Names ", "}}{{ "\t"}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
1066GLOBAL OPTIONS:
1067   {{range .VisibleFlags}}{{.}}
1068   {{end}}{{end}}{{if .Copyright }}
1069COPYRIGHT:
1070   {{.Copyright}}
1071   {{end}}{{if .Version}}
1072VERSION:
1073   {{.Version}}
1074   {{end}}
1075`
1076
1077  // EXAMPLE: Replace the `HelpPrinter` func
1078  cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
1079    fmt.Println("Ha HA.  I pwnd the help!!1")
1080  }
1081
1082  err := cli.NewApp().Run(os.Args)
1083  if err != nil {
1084    log.Fatal(err)
1085  }
1086}
1087```
1088
1089The default flag may be customized to something other than `-h/--help` by
1090setting `cli.HelpFlag`, e.g.:
1091
1092<!-- {
1093  "args": ["&#45;&#45halp"],
1094  "output": "haaaaalp.*HALP"
1095} -->
1096``` go
1097package main
1098
1099import (
1100  "log"
1101  "os"
1102
1103  "github.com/urfave/cli"
1104)
1105
1106func main() {
1107  cli.HelpFlag = cli.BoolFlag{
1108    Name: "halp, haaaaalp",
1109    Usage: "HALP",
1110    EnvVar: "SHOW_HALP,HALPPLZ",
1111  }
1112
1113  err := cli.NewApp().Run(os.Args)
1114  if err != nil {
1115    log.Fatal(err)
1116  }
1117}
1118```
1119
1120### Version Flag
1121
1122The default version flag (`-v/--version`) is defined as `cli.VersionFlag`, which
1123is checked by the cli internals in order to print the `App.Version` via
1124`cli.VersionPrinter` and break execution.
1125
1126#### Customization
1127
1128The default flag may be customized to something other than `-v/--version` by
1129setting `cli.VersionFlag`, e.g.:
1130
1131<!-- {
1132  "args": ["&#45;&#45print-version"],
1133  "output": "partay version 19\\.99\\.0"
1134} -->
1135``` go
1136package main
1137
1138import (
1139  "log"
1140  "os"
1141
1142  "github.com/urfave/cli"
1143)
1144
1145func main() {
1146  cli.VersionFlag = cli.BoolFlag{
1147    Name: "print-version, V",
1148    Usage: "print only the version",
1149  }
1150
1151  app := cli.NewApp()
1152  app.Name = "partay"
1153  app.Version = "19.99.0"
1154  err := app.Run(os.Args)
1155  if err != nil {
1156    log.Fatal(err)
1157  }
1158}
1159```
1160
1161Alternatively, the version printer at `cli.VersionPrinter` may be overridden, e.g.:
1162
1163<!-- {
1164  "args": ["&#45;&#45version"],
1165  "output": "version=19\\.99\\.0 revision=fafafaf"
1166} -->
1167``` go
1168package main
1169
1170import (
1171  "fmt"
1172  "log"
1173  "os"
1174
1175  "github.com/urfave/cli"
1176)
1177
1178var (
1179  Revision = "fafafaf"
1180)
1181
1182func main() {
1183  cli.VersionPrinter = func(c *cli.Context) {
1184    fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision)
1185  }
1186
1187  app := cli.NewApp()
1188  app.Name = "partay"
1189  app.Version = "19.99.0"
1190  err := app.Run(os.Args)
1191  if err != nil {
1192    log.Fatal(err)
1193  }
1194}
1195```
1196
1197#### Full API Example
1198
1199**Notice**: This is a contrived (functioning) example meant strictly for API
1200demonstration purposes.  Use of one's imagination is encouraged.
1201
1202<!-- {
1203  "output": "made it!\nPhew!"
1204} -->
1205``` go
1206package main
1207
1208import (
1209  "errors"
1210  "flag"
1211  "fmt"
1212  "io"
1213  "io/ioutil"
1214  "os"
1215  "time"
1216
1217  "github.com/urfave/cli"
1218)
1219
1220func init() {
1221  cli.AppHelpTemplate += "\nCUSTOMIZED: you bet ur muffins\n"
1222  cli.CommandHelpTemplate += "\nYMMV\n"
1223  cli.SubcommandHelpTemplate += "\nor something\n"
1224
1225  cli.HelpFlag = cli.BoolFlag{Name: "halp"}
1226  cli.BashCompletionFlag = cli.BoolFlag{Name: "compgen", Hidden: true}
1227  cli.VersionFlag = cli.BoolFlag{Name: "print-version, V"}
1228
1229  cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
1230    fmt.Fprintf(w, "best of luck to you\n")
1231  }
1232  cli.VersionPrinter = func(c *cli.Context) {
1233    fmt.Fprintf(c.App.Writer, "version=%s\n", c.App.Version)
1234  }
1235  cli.OsExiter = func(c int) {
1236    fmt.Fprintf(cli.ErrWriter, "refusing to exit %d\n", c)
1237  }
1238  cli.ErrWriter = ioutil.Discard
1239  cli.FlagStringer = func(fl cli.Flag) string {
1240    return fmt.Sprintf("\t\t%s", fl.GetName())
1241  }
1242}
1243
1244type hexWriter struct{}
1245
1246func (w *hexWriter) Write(p []byte) (int, error) {
1247  for _, b := range p {
1248    fmt.Printf("%x", b)
1249  }
1250  fmt.Printf("\n")
1251
1252  return len(p), nil
1253}
1254
1255type genericType struct{
1256  s string
1257}
1258
1259func (g *genericType) Set(value string) error {
1260  g.s = value
1261  return nil
1262}
1263
1264func (g *genericType) String() string {
1265  return g.s
1266}
1267
1268func main() {
1269  app := cli.NewApp()
1270  app.Name = "kənˈtrīv"
1271  app.Version = "19.99.0"
1272  app.Compiled = time.Now()
1273  app.Authors = []cli.Author{
1274    cli.Author{
1275      Name:  "Example Human",
1276      Email: "human@example.com",
1277    },
1278  }
1279  app.Copyright = "(c) 1999 Serious Enterprise"
1280  app.HelpName = "contrive"
1281  app.Usage = "demonstrate available API"
1282  app.UsageText = "contrive - demonstrating the available API"
1283  app.ArgsUsage = "[args and such]"
1284  app.Commands = []cli.Command{
1285    cli.Command{
1286      Name:        "doo",
1287      Aliases:     []string{"do"},
1288      Category:    "motion",
1289      Usage:       "do the doo",
1290      UsageText:   "doo - does the dooing",
1291      Description: "no really, there is a lot of dooing to be done",
1292      ArgsUsage:   "[arrgh]",
1293      Flags: []cli.Flag{
1294        cli.BoolFlag{Name: "forever, forevvarr"},
1295      },
1296      Subcommands: cli.Commands{
1297        cli.Command{
1298          Name:   "wop",
1299          Action: wopAction,
1300        },
1301      },
1302      SkipFlagParsing: false,
1303      HideHelp:        false,
1304      Hidden:          false,
1305      HelpName:        "doo!",
1306      BashComplete: func(c *cli.Context) {
1307        fmt.Fprintf(c.App.Writer, "--better\n")
1308      },
1309      Before: func(c *cli.Context) error {
1310        fmt.Fprintf(c.App.Writer, "brace for impact\n")
1311        return nil
1312      },
1313      After: func(c *cli.Context) error {
1314        fmt.Fprintf(c.App.Writer, "did we lose anyone?\n")
1315        return nil
1316      },
1317      Action: func(c *cli.Context) error {
1318        c.Command.FullName()
1319        c.Command.HasName("wop")
1320        c.Command.Names()
1321        c.Command.VisibleFlags()
1322        fmt.Fprintf(c.App.Writer, "dodododododoodododddooooododododooo\n")
1323        if c.Bool("forever") {
1324          c.Command.Run(c)
1325        }
1326        return nil
1327      },
1328      OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error {
1329        fmt.Fprintf(c.App.Writer, "for shame\n")
1330        return err
1331      },
1332    },
1333  }
1334  app.Flags = []cli.Flag{
1335    cli.BoolFlag{Name: "fancy"},
1336    cli.BoolTFlag{Name: "fancier"},
1337    cli.DurationFlag{Name: "howlong, H", Value: time.Second * 3},
1338    cli.Float64Flag{Name: "howmuch"},
1339    cli.GenericFlag{Name: "wat", Value: &genericType{}},
1340    cli.Int64Flag{Name: "longdistance"},
1341    cli.Int64SliceFlag{Name: "intervals"},
1342    cli.IntFlag{Name: "distance"},
1343    cli.IntSliceFlag{Name: "times"},
1344    cli.StringFlag{Name: "dance-move, d"},
1345    cli.StringSliceFlag{Name: "names, N"},
1346    cli.UintFlag{Name: "age"},
1347    cli.Uint64Flag{Name: "bigage"},
1348  }
1349  app.EnableBashCompletion = true
1350  app.UseShortOptionHandling = true
1351  app.HideHelp = false
1352  app.HideVersion = false
1353  app.BashComplete = func(c *cli.Context) {
1354    fmt.Fprintf(c.App.Writer, "lipstick\nkiss\nme\nlipstick\nringo\n")
1355  }
1356  app.Before = func(c *cli.Context) error {
1357    fmt.Fprintf(c.App.Writer, "HEEEERE GOES\n")
1358    return nil
1359  }
1360  app.After = func(c *cli.Context) error {
1361    fmt.Fprintf(c.App.Writer, "Phew!\n")
1362    return nil
1363  }
1364  app.CommandNotFound = func(c *cli.Context, command string) {
1365    fmt.Fprintf(c.App.Writer, "Thar be no %q here.\n", command)
1366  }
1367  app.OnUsageError = func(c *cli.Context, err error, isSubcommand bool) error {
1368    if isSubcommand {
1369      return err
1370    }
1371
1372    fmt.Fprintf(c.App.Writer, "WRONG: %#v\n", err)
1373    return nil
1374  }
1375  app.Action = func(c *cli.Context) error {
1376    cli.DefaultAppComplete(c)
1377    cli.HandleExitCoder(errors.New("not an exit coder, though"))
1378    cli.ShowAppHelp(c)
1379    cli.ShowCommandCompletions(c, "nope")
1380    cli.ShowCommandHelp(c, "also-nope")
1381    cli.ShowCompletions(c)
1382    cli.ShowSubcommandHelp(c)
1383    cli.ShowVersion(c)
1384
1385    categories := c.App.Categories()
1386    categories.AddCommand("sounds", cli.Command{
1387      Name: "bloop",
1388    })
1389
1390    for _, category := range c.App.Categories() {
1391      fmt.Fprintf(c.App.Writer, "%s\n", category.Name)
1392      fmt.Fprintf(c.App.Writer, "%#v\n", category.Commands)
1393      fmt.Fprintf(c.App.Writer, "%#v\n", category.VisibleCommands())
1394    }
1395
1396    fmt.Printf("%#v\n", c.App.Command("doo"))
1397    if c.Bool("infinite") {
1398      c.App.Run([]string{"app", "doo", "wop"})
1399    }
1400
1401    if c.Bool("forevar") {
1402      c.App.RunAsSubcommand(c)
1403    }
1404    c.App.Setup()
1405    fmt.Printf("%#v\n", c.App.VisibleCategories())
1406    fmt.Printf("%#v\n", c.App.VisibleCommands())
1407    fmt.Printf("%#v\n", c.App.VisibleFlags())
1408
1409    fmt.Printf("%#v\n", c.Args().First())
1410    if len(c.Args()) > 0 {
1411      fmt.Printf("%#v\n", c.Args()[1])
1412    }
1413    fmt.Printf("%#v\n", c.Args().Present())
1414    fmt.Printf("%#v\n", c.Args().Tail())
1415
1416    set := flag.NewFlagSet("contrive", 0)
1417    nc := cli.NewContext(c.App, set, c)
1418
1419    fmt.Printf("%#v\n", nc.Args())
1420    fmt.Printf("%#v\n", nc.Bool("nope"))
1421    fmt.Printf("%#v\n", nc.BoolT("nerp"))
1422    fmt.Printf("%#v\n", nc.Duration("howlong"))
1423    fmt.Printf("%#v\n", nc.Float64("hay"))
1424    fmt.Printf("%#v\n", nc.Generic("bloop"))
1425    fmt.Printf("%#v\n", nc.Int64("bonk"))
1426    fmt.Printf("%#v\n", nc.Int64Slice("burnks"))
1427    fmt.Printf("%#v\n", nc.Int("bips"))
1428    fmt.Printf("%#v\n", nc.IntSlice("blups"))
1429    fmt.Printf("%#v\n", nc.String("snurt"))
1430    fmt.Printf("%#v\n", nc.StringSlice("snurkles"))
1431    fmt.Printf("%#v\n", nc.Uint("flub"))
1432    fmt.Printf("%#v\n", nc.Uint64("florb"))
1433    fmt.Printf("%#v\n", nc.GlobalBool("global-nope"))
1434    fmt.Printf("%#v\n", nc.GlobalBoolT("global-nerp"))
1435    fmt.Printf("%#v\n", nc.GlobalDuration("global-howlong"))
1436    fmt.Printf("%#v\n", nc.GlobalFloat64("global-hay"))
1437    fmt.Printf("%#v\n", nc.GlobalGeneric("global-bloop"))
1438    fmt.Printf("%#v\n", nc.GlobalInt("global-bips"))
1439    fmt.Printf("%#v\n", nc.GlobalIntSlice("global-blups"))
1440    fmt.Printf("%#v\n", nc.GlobalString("global-snurt"))
1441    fmt.Printf("%#v\n", nc.GlobalStringSlice("global-snurkles"))
1442
1443    fmt.Printf("%#v\n", nc.FlagNames())
1444    fmt.Printf("%#v\n", nc.GlobalFlagNames())
1445    fmt.Printf("%#v\n", nc.GlobalIsSet("wat"))
1446    fmt.Printf("%#v\n", nc.GlobalSet("wat", "nope"))
1447    fmt.Printf("%#v\n", nc.NArg())
1448    fmt.Printf("%#v\n", nc.NumFlags())
1449    fmt.Printf("%#v\n", nc.Parent())
1450
1451    nc.Set("wat", "also-nope")
1452
1453    ec := cli.NewExitError("ohwell", 86)
1454    fmt.Fprintf(c.App.Writer, "%d", ec.ExitCode())
1455    fmt.Printf("made it!\n")
1456    return nil
1457  }
1458
1459  if os.Getenv("HEXY") != "" {
1460    app.Writer = &hexWriter{}
1461    app.ErrWriter = &hexWriter{}
1462  }
1463
1464  app.Metadata = map[string]interface{}{
1465    "layers":     "many",
1466    "explicable": false,
1467    "whatever-values": 19.99,
1468  }
1469
1470
1471  // ignore error so we don't exit non-zero and break gfmrun README example tests
1472  _ = app.Run(os.Args)
1473}
1474
1475func wopAction(c *cli.Context) error {
1476  fmt.Fprintf(c.App.Writer, ":wave: over here, eh\n")
1477  return nil
1478}
1479```
1480
1481## Migrating to V2
1482
1483There are a small set of breaking changes between v1 and v2.
1484Converting is relatively straightforward and typically takes less than
1485an hour. Specific steps are included in
1486[Migration Guide: v1 to v2](../migrate-v1-to-v2.md).
1487