Cobra CLI Framework

Cobra is a powerful library for creating modern CLI applications in Go. Used by kubectl, Hugo, GitHub CLI, and many other popular tools. Provides commands, subcommands, flags, and automatic help generation.

Use Case

Use Cobra when you need to:

  • Build complex CLI tools with subcommands
  • Provide consistent flag handling
  • Generate automatic help and documentation
  • Create professional command-line interfaces

Installation

1go get -u github.com/spf13/cobra@latest

Code

Basic Structure

 1package main
 2
 3import (
 4    "fmt"
 5    "os"
 6    
 7    "github.com/spf13/cobra"
 8)
 9
10var rootCmd = &cobra.Command{
11    Use:   "myapp",
12    Short: "A brief description of your application",
13    Long:  `A longer description that spans multiple lines and likely contains
14examples and usage of using your application.`,
15}
16
17func main() {
18    if err := rootCmd.Execute(); err != nil {
19        fmt.Fprintln(os.Stderr, err)
20        os.Exit(1)
21    }
22}

Examples

Example 1: Simple Command with Flags

 1package main
 2
 3import (
 4    "fmt"
 5    "github.com/spf13/cobra"
 6)
 7
 8var (
 9    verbose bool
10    output  string
11)
12
13var rootCmd = &cobra.Command{
14    Use:   "greet [name]",
15    Short: "Greet someone",
16    Args:  cobra.ExactArgs(1),
17    Run: func(cmd *cobra.Command, args []string) {
18        name := args[0]
19        greeting := fmt.Sprintf("Hello, %s!", name)
20        
21        if verbose {
22            greeting = fmt.Sprintf("Hello there, %s! Nice to meet you!", name)
23        }
24        
25        if output == "json" {
26            fmt.Printf(`{"greeting": "%s"}`, greeting)
27        } else {
28            fmt.Println(greeting)
29        }
30    },
31}
32
33func init() {
34    rootCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Verbose output")
35    rootCmd.Flags().StringVarP(&output, "output", "o", "text", "Output format (text|json)")
36}
37
38func main() {
39    rootCmd.Execute()
40}

Usage:

1$ myapp greet John
2Hello, John!
3
4$ myapp greet John --verbose
5Hello there, John! Nice to meet you!
6
7$ myapp greet John -o json
8{"greeting": "Hello, John!"}

Example 2: Subcommands

 1package main
 2
 3import (
 4    "fmt"
 5    "github.com/spf13/cobra"
 6)
 7
 8var rootCmd = &cobra.Command{
 9    Use:   "app",
10    Short: "My application",
11}
12
13var initCmd = &cobra.Command{
14    Use:   "init",
15    Short: "Initialize the application",
16    Run: func(cmd *cobra.Command, args []string) {
17        fmt.Println("Initializing...")
18    },
19}
20
21var runCmd = &cobra.Command{
22    Use:   "run",
23    Short: "Run the application",
24    Run: func(cmd *cobra.Command, args []string) {
25        fmt.Println("Running...")
26    },
27}
28
29var configCmd = &cobra.Command{
30    Use:   "config",
31    Short: "Manage configuration",
32}
33
34var configGetCmd = &cobra.Command{
35    Use:   "get [key]",
36    Short: "Get configuration value",
37    Args:  cobra.ExactArgs(1),
38    Run: func(cmd *cobra.Command, args []string) {
39        fmt.Printf("Getting config: %s\n", args[0])
40    },
41}
42
43var configSetCmd = &cobra.Command{
44    Use:   "set [key] [value]",
45    Short: "Set configuration value",
46    Args:  cobra.ExactArgs(2),
47    Run: func(cmd *cobra.Command, args []string) {
48        fmt.Printf("Setting %s = %s\n", args[0], args[1])
49    },
50}
51
52func init() {
53    // Add commands to root
54    rootCmd.AddCommand(initCmd)
55    rootCmd.AddCommand(runCmd)
56    rootCmd.AddCommand(configCmd)
57    
58    // Add subcommands to config
59    configCmd.AddCommand(configGetCmd)
60    configCmd.AddCommand(configSetCmd)
61}
62
63func main() {
64    rootCmd.Execute()
65}

Usage:

1$ app init
2Initializing...
3
4$ app config get database.host
5Getting config: database.host
6
7$ app config set database.host localhost
8Setting database.host = localhost

Example 3: Persistent Flags and PreRun

 1package main
 2
 3import (
 4    "fmt"
 5    "github.com/spf13/cobra"
 6)
 7
 8var (
 9    cfgFile string
10    debug   bool
11)
12
13var rootCmd = &cobra.Command{
14    Use:   "app",
15    Short: "My application",
16    PersistentPreRun: func(cmd *cobra.Command, args []string) {
17        // Runs before any command
18        if debug {
19            fmt.Println("Debug mode enabled")
20        }
21        if cfgFile != "" {
22            fmt.Printf("Using config file: %s\n", cfgFile)
23        }
24    },
25}
26
27var serveCmd = &cobra.Command{
28    Use:   "serve",
29    Short: "Start the server",
30    PreRun: func(cmd *cobra.Command, args []string) {
31        // Runs before this specific command
32        fmt.Println("Preparing to serve...")
33    },
34    Run: func(cmd *cobra.Command, args []string) {
35        fmt.Println("Server started!")
36    },
37    PostRun: func(cmd *cobra.Command, args []string) {
38        // Runs after this specific command
39        fmt.Println("Server stopped")
40    },
41}
42
43func init() {
44    // Persistent flags available to all commands
45    rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file")
46    rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "debug mode")
47    
48    rootCmd.AddCommand(serveCmd)
49}
50
51func main() {
52    rootCmd.Execute()
53}

Example 4: Required Flags and Validation

 1package main
 2
 3import (
 4    "fmt"
 5    "github.com/spf13/cobra"
 6)
 7
 8var (
 9    username string
10    password string
11    port     int
12)
13
14var loginCmd = &cobra.Command{
15    Use:   "login",
16    Short: "Login to the service",
17    PreRunE: func(cmd *cobra.Command, args []string) error {
18        // Validation before running
19        if port < 1 || port > 65535 {
20            return fmt.Errorf("invalid port: %d", port)
21        }
22        return nil
23    },
24    RunE: func(cmd *cobra.Command, args []string) error {
25        // Use RunE to return errors
26        fmt.Printf("Logging in as %s on port %d\n", username, port)
27        return nil
28    },
29}
30
31func init() {
32    loginCmd.Flags().StringVarP(&username, "username", "u", "", "Username (required)")
33    loginCmd.Flags().StringVarP(&password, "password", "p", "", "Password (required)")
34    loginCmd.Flags().IntVar(&port, "port", 8080, "Port number")
35    
36    // Mark flags as required
37    loginCmd.MarkFlagRequired("username")
38    loginCmd.MarkFlagRequired("password")
39}
40
41func main() {
42    rootCmd := &cobra.Command{Use: "app"}
43    rootCmd.AddCommand(loginCmd)
44    rootCmd.Execute()
45}

Example 5: Cobra Generator (Quick Start)

 1# Install cobra-cli
 2go install github.com/spf13/cobra-cli@latest
 3
 4# Initialize new CLI app
 5cobra-cli init
 6
 7# Add commands
 8cobra-cli add serve
 9cobra-cli add config
10cobra-cli add create
11
12# Project structure created:
13# β”œβ”€β”€ cmd/
14# β”‚   β”œβ”€β”€ root.go
15# β”‚   β”œβ”€β”€ serve.go
16# β”‚   β”œβ”€β”€ config.go
17# β”‚   └── create.go
18# β”œβ”€β”€ main.go
19# └── go.mod

Common Patterns

Argument Validation

 1var cmd = &cobra.Command{
 2    Use: "example",
 3    Args: cobra.MinimumNArgs(1),        // At least 1 arg
 4    // Args: cobra.ExactArgs(2),        // Exactly 2 args
 5    // Args: cobra.RangeArgs(1, 3),     // Between 1 and 3 args
 6    // Args: cobra.NoArgs,              // No args allowed
 7    Run: func(cmd *cobra.Command, args []string) {
 8        // ...
 9    },
10}

Custom Validation

 1var cmd = &cobra.Command{
 2    Use: "example",
 3    Args: func(cmd *cobra.Command, args []string) error {
 4        if len(args) < 1 {
 5            return fmt.Errorf("requires at least 1 arg")
 6        }
 7        if args[0] != "valid" {
 8            return fmt.Errorf("invalid argument: %s", args[0])
 9        }
10        return nil
11    },
12    Run: func(cmd *cobra.Command, args []string) {
13        // ...
14    },
15}

Version Command

 1var version = "1.0.0"
 2
 3var versionCmd = &cobra.Command{
 4    Use:   "version",
 5    Short: "Print the version number",
 6    Run: func(cmd *cobra.Command, args []string) {
 7        fmt.Printf("Version: %s\n", version)
 8    },
 9}
10
11func init() {
12    rootCmd.AddCommand(versionCmd)
13}

Notes

  • Use PersistentFlags for flags available to all subcommands
  • Use Flags for command-specific flags
  • PreRun, Run, PostRun provide lifecycle hooks
  • Use RunE instead of Run to return errors
  • Cobra automatically generates help and usage

Gotchas/Warnings

  • ⚠️ Flag parsing: Flags must come after the command name
  • ⚠️ Required flags: Use MarkFlagRequired() for validation
  • ⚠️ Persistent flags: Defined on parent, available to children
  • ⚠️ Args validation: Use built-in validators or custom functions
comments powered by Disqus