# Cobra User Guide

Cobra is a library for building modern command-line interface (CLI) applications in Go. It powers the command structure behind tools such as `kubectl`, `hugo`, the GitHub CLI (`gh`), and the `go` toolchain's cousins. If you are writing a Go program that needs subcommands, flags, automatic help text, shell completions, and generated documentation, Cobra gives you all of it from a small amount of declarative code.

This guide is written for the **developer who consumes Cobra** — you import it into your Go program and use its API. It shows you how to install Cobra, define commands, wire up flags and arguments, control the execution lifecycle, and ship polished extras like shell completion and man pages. Every command, field, function, and environment variable described here comes directly from the Cobra source.

> [!NOTE]
> Cobra is a **library**, not a standalone program. You do not "run Cobra" — you build a Go binary that imports Cobra. Throughout this guide, "your program" or "your CLI" means the application you are building, and `app` is used as a placeholder for its name.

---

## Table of Contents

1. [Quick Start](#1-quick-start)
2. [Installation & Requirements](#2-installation--requirements)
3. [Core Concepts](#3-core-concepts)
4. [Defining Commands](#4-defining-commands)
5. [Working with Flags](#5-working-with-flags)
6. [Validating Positional Arguments](#6-validating-positional-arguments)
7. [The Run Lifecycle (Hooks)](#7-the-run-lifecycle-hooks)
8. [Organizing Commands](#8-organizing-commands)
9. [Shell Completions](#9-shell-completions)
10. [Active Help](#10-active-help)
11. [Generating Documentation](#11-generating-documentation)
12. [Versioning, Help, and Error Output](#12-versioning-help-and-error-output)
13. [Global Behavior Toggles](#13-global-behavior-toggles)
14. [Common Recipes](#14-common-recipes)
15. [Troubleshooting](#15-troubleshooting)
16. [FAQ](#16-faq)
17. [Quick Reference](#17-quick-reference)

---

## 1. Quick Start

A minimal Cobra program is a single root command that you execute from `main`.

```go
package main

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
)

func main() {
	rootCmd := &cobra.Command{
		Use:   "hello",
		Short: "Hello prints a friendly greeting",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Fprintln(cmd.OutOrStdout(), "Hello, world!")
		},
	}

	if err := rootCmd.Execute(); err != nil {
		os.Exit(1)
	}
}
```

Build and run it:

```bash
go run . 
```

```text
Hello, world!
```

Ask for help — Cobra wires this up automatically:

```bash
go run . --help
```

```text
Hello prints a friendly greeting

Usage:
  hello [flags]

Flags:
  -h, --help   help for hello
```

> [!TIP]
> You never have to write a `--help` flag or a usage message yourself. Cobra adds the `-h, --help` flag to every command automatically the first time it executes (see [InitDefaultHelpFlag](#12-versioning-help-and-error-output)).

That is the whole loop: build a `*cobra.Command`, give it a `Run` function, and call `Execute()`. Everything else in this guide is about adding structure — subcommands, flags, validation, and polish — on top of this foundation.

---

## 2. Installation & Requirements

### Requirements

| Requirement | Detail |
|-------------|--------|
| Go version | **Go 1.15 or newer** (declared in Cobra's `go.mod`) |
| Module mode | Go modules must be enabled (the default since Go 1.16) |
| Platforms | Linux, macOS, Windows (a Windows-specific helper is built in — see [mousetrap](#13-global-behavior-toggles)) |

Cobra pulls in a small set of dependencies automatically when you `go get` it:

| Dependency | Role |
|------------|------|
| `github.com/spf13/pflag` | POSIX/GNU-style flag parsing. Cobra's flag API is a thin layer over pflag. |
| `github.com/cpuguy83/go-md2man/v2` | Renders man pages (used by the `doc` package). |
| `github.com/inconshreveable/mousetrap` | Detects when a Windows program was launched from Explorer. |
| `go.yaml.in/yaml/v3` | Marshals YAML documentation (used by the `doc` package). |

### Add Cobra to your project

=== "New project"

    ```bash
    mkdir myapp && cd myapp
    go mod init github.com/you/myapp
    go get github.com/spf13/cobra@latest
    ```

=== "Existing module"

    ```bash
    go get github.com/spf13/cobra@latest
    ```

Then import it in your code:

```go
import "github.com/spf13/cobra"
```

> [!NOTE]
> Cobra ships a companion generator tool (`cobra-cli`) in a separate repository for scaffolding a command tree. It is optional — this guide builds everything by hand so you understand exactly what each piece does. Nothing in this guide requires the generator.

### Verify the installation

```bash
go build ./...
```

```text
# (no output on success)
```

A clean build with no `cannot find package` errors confirms Cobra and its dependencies resolved correctly.

---

## 3. Core Concepts

Cobra is built around three ideas. Understanding them makes the rest of the API obvious.

**Command**
: A `*cobra.Command` represents a single action your program can perform — `git commit`, `kubectl get`, or your own `app serve`. Commands nest: a root command has children, which can have their own children. The first word of a command's `Use` field is its name.

**Flag**
: A named option such as `--verbose` or `-o json`. Flags are parsed by `pflag` and attached to commands. A flag is either **local** (applies only to the command it is set on) or **persistent** (also applies to all descendant commands).

**Argument**
: A positional value left over after flags are removed — e.g. the `main.go` in `app build main.go`. You can validate how many arguments a command accepts and which values are allowed.

A Cobra application is a **tree of commands**. Execution always starts at the root, walks the tree to find the command that matches the user's input, parses the flags, validates the arguments, and runs the matched command's `Run` function.

```text
app                 (root command)
├── serve           (subcommand)
├── migrate         (subcommand)
│   ├── up          (sub-subcommand)
│   └── down        (sub-subcommand)
└── version         (subcommand)
```

> [!IMPORTANT]
> The first word of `Use` is the command's **name**. `Use: "serve [flags]"` produces a command named `serve`. Cobra derives the name with `Command.Name()`, which returns everything up to the first space.

---

## 4. Defining Commands

### The Command struct

You configure a command by setting fields on a `cobra.Command` literal. These are the fields you will use most often:

| Field | Type | Purpose |
|-------|------|---------|
| `Use` | `string` | One-line usage. First word is the command name. |
| `Aliases` | `[]string` | Alternate names that invoke this command. |
| `Short` | `string` | One-line description shown in the parent's command list. |
| `Long` | `string` | Full description shown in this command's own `help`. |
| `Example` | `string` | Example invocations shown under an `Examples:` heading. |
| `Run` | `func(cmd *Command, args []string)` | The work function. |
| `RunE` | `func(cmd *Command, args []string) error` | Like `Run` but returns an error. Prefer this. |
| `Args` | `PositionalArgs` | Argument count/validity rule (see [§6](#6-validating-positional-arguments)). |
| `ValidArgs` | `[]Completion` | Allowed non-flag arguments, offered in completion. |
| `Version` | `string` | Enables a `--version` flag for this command. |
| `Deprecated` | `string` | Marks the command deprecated; the message prints when used. |
| `Hidden` | `bool` | Hides the command from help output (it still works). |
| `GroupID` | `string` | Groups this subcommand under a heading in the parent's help. |
| `SuggestFor` | `[]string` | Names for which this command is suggested. |
| `Annotations` | `map[string]string` | Arbitrary key/value metadata for your own use. |

> [!TIP]
> Use `RunE` rather than `Run` in real applications. Returning an error lets Cobra print it consistently and lets `Execute()` signal failure to your `main`. Reserve `Run` for trivial commands that cannot fail.

### Usage string syntax

The `Use` field documents the command's arguments. Cobra recommends this notation (taken from the field's own documentation):

| Notation | Meaning |
|----------|---------|
| `[ ]` | An optional argument. Arguments not in brackets are required. |
| `...` | You may specify multiple values for the previous argument. |
| `\|` | Mutually exclusive — use the left argument or the right, not both. |
| `{ }` | A set of mutually exclusive arguments, one of which is required. |

```text
Use: "add [-F file | -D dir]... [-f format] profile"
```

### Adding subcommands

Build child commands and attach them with `AddCommand`:

```go
var rootCmd = &cobra.Command{Use: "app"}

var serveCmd = &cobra.Command{
	Use:   "serve",
	Short: "Start the HTTP server",
	RunE: func(cmd *cobra.Command, args []string) error {
		return startServer()
	},
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Print the version number",
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Fprintln(cmd.OutOrStdout(), "app v1.0.0")
	},
}

func init() {
	rootCmd.AddCommand(serveCmd, versionCmd)
}
```

```bash
app serve
app version
```

> [!NOTE]
> `AddCommand` accepts one or more commands in a single call: `rootCmd.AddCommand(serveCmd, versionCmd, migrateCmd)`. A command may not be added as a child of itself — Cobra panics with `Command can't be a child of itself` if you try.

### Aliases and suggestions

```go
var listCmd = &cobra.Command{
	Use:        "list",
	Aliases:    []string{"ls", "l"},
	SuggestFor: []string{"show"},
	Short:      "List all items",
	Run:        func(cmd *cobra.Command, args []string) { /* ... */ },
}
```

- **`Aliases`** — `app ls` and `app l` both invoke `list`.
- **`SuggestFor`** — if the user types `app show`, Cobra suggests `list` in its "Did you mean this?" message.

Cobra automatically suggests near-matches for mistyped commands using Levenshtein distance:

```bash
app serv
```

```text
Error: unknown command "serv" for "app"

Did you mean this?
	serve

Run 'app --help' for usage.
```

The suggestion threshold is controlled by `SuggestionsMinimumDistance` (default `2`). Set `DisableSuggestions: true` on a command to turn the feature off.

---

## 5. Working with Flags

Cobra exposes flags through `pflag`. You declare flags on a command's flag set inside `init()` (or before calling `Execute`).

### Local vs. persistent flags

| Method | Scope |
|--------|-------|
| `cmd.Flags()` | **Local** — applies only to this command. |
| `cmd.PersistentFlags()` | **Persistent** — applies to this command and all of its children. |

```go
func init() {
	// Persistent: available on rootCmd and every subcommand
	rootCmd.PersistentFlags().BoolP("verbose", "v", false, "enable verbose logging")

	// Local: only valid on serveCmd
	serveCmd.Flags().IntP("port", "p", 8080, "port to listen on")
	serveCmd.Flags().StringP("host", "H", "localhost", "host to bind to")
}
```

The four arguments to a typed flag constructor are **name**, **shorthand**, **default value**, and **usage string**. The `P` suffix (`BoolP`, `IntP`, `StringP`, …) means "with a shorthand". Without the `P`, omit the shorthand:

```go
serveCmd.Flags().Bool("tls", false, "enable TLS")   // long form only: --tls
```

### Reading flag values

Inside a `Run`/`RunE` function, read flags from the command:

```go
RunE: func(cmd *cobra.Command, args []string) error {
	port, _ := cmd.Flags().GetInt("port")
	verbose, _ := cmd.Flags().GetBool("verbose")  // works: persistent flag is inherited
	host, _ := cmd.Flags().GetString("host")
	fmt.Fprintf(cmd.OutOrStdout(), "serving on %s:%d (verbose=%t)\n", host, port, verbose)
	return nil
}
```

Alternatively, bind a flag to a variable with the `*Var` constructors:

```go
var port int
serveCmd.Flags().IntVarP(&port, "port", "p", 8080, "port to listen on")
// `port` now holds the parsed value after flag parsing
```

### Required flags

Mark a flag required so Cobra errors if it is missing:

```go
serveCmd.Flags().String("config", "", "path to config file")
serveCmd.MarkFlagRequired("config")
```

```text
Error: required flag(s) "config" not set
```

For a persistent flag, use `MarkPersistentFlagRequired`.

### Flag groups

Express relationships between flags. Cobra validates them before running the command:

| Method | Rule enforced |
|--------|---------------|
| `cmd.MarkFlagsRequiredTogether("a", "b")` | If any of these flags is set, all must be set. |
| `cmd.MarkFlagsOneRequired("a", "b")` | At least one of these flags must be set. |
| `cmd.MarkFlagsMutuallyExclusive("a", "b")` | At most one of these flags may be set. |

```go
func init() {
	serveCmd.Flags().String("tls-cert", "", "TLS certificate file")
	serveCmd.Flags().String("tls-key", "", "TLS key file")
	serveCmd.MarkFlagsRequiredTogether("tls-cert", "tls-key")

	serveCmd.Flags().Bool("json", false, "JSON output")
	serveCmd.Flags().Bool("yaml", false, "YAML output")
	serveCmd.MarkFlagsMutuallyExclusive("json", "yaml")
}
```

The exact errors Cobra produces (from source):

```text
if any flags in the group [tls-cert tls-key] are set they must all be set; missing [tls-key]
```

```text
if any flags in the group [json yaml] are set none of the others can be; [json yaml] were all set
```

```text
at least one of the flags in the group [a b] is required
```

> [!WARNING]
> The flags named in a group must already be defined on the command (or be persistent flags reachable from it) when you call the `MarkFlags*` method. If a named flag does not exist, Cobra **panics** — for example `Failed to find flag "tls-key" and mark it as being required in a flag group`. Define flags first, then group them.

### Tying file/directory completion to a flag

These helpers tell shell completion how to complete a flag's value:

| Method | Effect |
|--------|--------|
| `cmd.MarkFlagFilename("f", "json", "yaml")` | Complete only files ending in the given extensions. |
| `cmd.MarkFlagDirname("d")` | Complete only directory names. |

```go
serveCmd.Flags().String("config", "", "config file")
serveCmd.MarkFlagFilename("config", "yaml", "yml", "json")
```

---

## 6. Validating Positional Arguments

Set a command's `Args` field to one of Cobra's built-in validators. They run after flag parsing and before `Run`.

| Validator | Passes when… |
|-----------|--------------|
| `cobra.NoArgs` | No positional arguments are given. |
| `cobra.ArbitraryArgs` | Always (any number of arguments). |
| `cobra.MinimumNArgs(n)` | At least `n` arguments. |
| `cobra.MaximumNArgs(n)` | At most `n` arguments. |
| `cobra.ExactArgs(n)` | Exactly `n` arguments. |
| `cobra.RangeArgs(min, max)` | Between `min` and `max` arguments (inclusive). |
| `cobra.OnlyValidArgs` | Every argument is listed in the command's `ValidArgs`. |
| `cobra.NoDuplicateArgs` | No argument value is repeated. |
| `cobra.MatchAll(v1, v2, …)` | All of the supplied validators pass. |

```go
var deleteCmd = &cobra.Command{
	Use:  "delete [names...]",
	Args: cobra.MinimumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		for _, name := range args {
			// args holds the validated positional values
		}
		return nil
	},
}
```

The exact error messages each validator emits (from source):

| Validator | Error message format |
|-----------|----------------------|
| `MinimumNArgs(n)` | `requires at least %d arg(s), only received %d` |
| `MaximumNArgs(n)` | `accepts at most %d arg(s), received %d` |
| `ExactArgs(n)` | `accepts %d arg(s), received %d` |
| `RangeArgs(min,max)` | `accepts between %d and %d arg(s), received %d` |
| `NoArgs` | `unknown command %q for %q` |
| `OnlyValidArgs` | `invalid argument %q for %q` |
| `NoDuplicateArgs` | `duplicate argument %q for %q` |

### Combining validators with MatchAll

`MatchAll` runs several validators in sequence. Use it to require both a count and a value constraint:

```go
var pickCmd = &cobra.Command{
	Use:       "pick",
	ValidArgs: []string{"red", "green", "blue"},
	Args:      cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
	Run:       func(cmd *cobra.Command, args []string) { /* ... */ },
}
```

> [!NOTE]
> If you leave `Args` unset (`nil`), Cobra applies legacy behavior: a command with **no** subcommands accepts arbitrary arguments, while a root command **with** subcommands rejects unknown commands. Setting `Args` explicitly is recommended for predictable behavior.

> [!CAUTION]
> `cobra.ExactValidArgs(n)` still exists but is **deprecated**. Use `cobra.MatchAll(cobra.ExactArgs(n), cobra.OnlyValidArgs)` instead — it is the exact replacement.

---

## 7. The Run Lifecycle (Hooks)

A command can define hook functions that run around its main `Run`. The order is fixed and documented in the Cobra source:

1. `PersistentPreRun` / `PersistentPreRunE`
2. `PreRun` / `PreRunE`
3. `Run` / `RunE`
4. `PostRun` / `PostRunE`
5. `PersistentPostRun` / `PersistentPostRunE`

Every hook has a plain form and an `E` form that returns an error. **If both are defined on a command, only the `E` form runs.** All hooks receive the same arguments (the positional args after the command name).

```go
var rootCmd = &cobra.Command{
	Use: "app",
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		return loadConfig()          // runs before every subcommand
	},
}

var serveCmd = &cobra.Command{
	Use: "serve",
	PreRun:  func(cmd *cobra.Command, args []string) { openLogFile() },
	RunE:    func(cmd *cobra.Command, args []string) error { return serve() },
	PostRun: func(cmd *cobra.Command, args []string) { closeLogFile() },
}
```

### Inheritance of persistent hooks

`PersistentPreRun(E)` and `PersistentPostRun(E)` are inherited by children — but with an important default: **only the first one found while walking up the tree executes.** If both the root and a subcommand define `PersistentPreRunE`, only the subcommand's runs.

> [!IMPORTANT]
> To run **every** persistent hook from the root down to the executed command (and every persistent post-run back up), set the package variable `cobra.EnableTraverseRunHooks = true`. With it off (the default), inner persistent hooks override outer ones rather than chaining.

> [!WARNING]
> `PersistentPostRun(E)` and `PostRun(E)` do **not** run if `RunE` (or `PreRunE`) returns an error — execution stops at the failing hook. This is a frequent source of confusion when using post-run hooks for cleanup; put unconditional cleanup in a `defer` inside `RunE` instead, or handle it explicitly.

### Per-command initializers

For setup that should run on **every** command's `Execute`, register a function with `OnInitialize`; for teardown, use `OnFinalize`:

```go
func init() {
	cobra.OnInitialize(initLogging)
	cobra.OnFinalize(flushLogging)
}
```

---

## 8. Organizing Commands

### Grouping subcommands in help

When a command has many children, group them under headings. Define a group on the parent, then set each child's `GroupID`:

```go
func init() {
	rootCmd.AddGroup(&cobra.Group{ID: "ops", Title: "Operations:"})
	rootCmd.AddGroup(&cobra.Group{ID: "info", Title: "Information:"})

	serveCmd.GroupID = "ops"
	migrateCmd.GroupID = "ops"
	versionCmd.GroupID = "info"

	rootCmd.AddCommand(serveCmd, migrateCmd, versionCmd)
}
```

```text
Operations:
  migrate     Run database migrations
  serve       Start the HTTP server

Information:
  version     Print the version number
```

> [!CAUTION]
> If you set a `GroupID` on a child but never register that group on the parent with `AddGroup`, Cobra **panics** at startup: `group id 'ops' is not defined for subcommand 'app serve'`. Always add the group before assigning its ID.

### Additional help topics

A command with a `Short`/`Long` description but no `Run` function and no runnable children becomes an **additional help topic** — it appears under "Additional help topics" in help output and can be read with `app help <topic>` but cannot be executed.

### Controlling output streams

Cobra commands write through accessor methods so you can redirect output (useful in tests):

| Method | Returns |
|--------|---------|
| `cmd.OutOrStdout()` | The configured out writer, or `os.Stdout`. |
| `cmd.ErrOrStderr()` | The configured err writer, or `os.Stderr`. |
| `cmd.InOrStdin()` | The configured in reader, or `os.Stdin`. |

Set them with `cmd.SetOut(w)`, `cmd.SetErr(w)`, and `cmd.SetIn(r)`. There are also convenience print helpers that honor these streams: `cmd.Print`, `cmd.Println`, `cmd.Printf`, `cmd.PrintErr`, `cmd.PrintErrln`, `cmd.PrintErrf`.

> [!TIP]
> Always write through `cmd.OutOrStdout()` instead of `fmt.Println`. It makes your command testable (you can capture output with `cmd.SetOut(buf)`) and lets a parent command redirect a child's output.

---

## 9. Shell Completions

This is one of Cobra's signature features. **Any Cobra program automatically gains a `completion` command** that emits a completion script for bash, zsh, fish, or PowerShell — you do not write any of it.

```bash
app completion --help
```

```text
Generate the autocompletion script for app for the specified shell.
See each sub-command's help for details on how to use the generated script.

Usage:
  app completion [command]

Available Commands:
  bash        Generate the autocompletion script for bash
  fish        Generate the autocompletion script for fish
  powershell  Generate the autocompletion script for powershell
  zsh         Generate the autocompletion script for zsh
```

### Enabling completion for your shell

The `Long` help of each subcommand contains exact, copy-pasteable instructions. The essentials:

=== "bash"

    ```bash
    # current session
    source <(app completion bash)

    # every session (Linux)
    app completion bash > /etc/bash_completion.d/app

    # every session (macOS, Homebrew)
    app completion bash > $(brew --prefix)/etc/bash_completion.d/app
    ```

=== "zsh"

    ```bash
    # enable completion once, if not already enabled
    echo "autoload -U compinit; compinit" >> ~/.zshrc

    # current session
    source <(app completion zsh)

    # every session (Linux)
    app completion zsh > "${fpath[1]}/_app"

    # every session (macOS, Homebrew)
    app completion zsh > $(brew --prefix)/share/zsh/site-functions/_app
    ```

=== "fish"

    ```bash
    # current session
    app completion fish | source

    # every session
    app completion fish > ~/.config/fish/completions/app.fish
    ```

=== "powershell"

    ```powershell
    # current session
    app completion powershell | Out-String | Invoke-Expression

    # every session: add the above line's output to your PowerShell profile
    ```

> [!NOTE]
> The bash script depends on the `bash-completion` package. If completion does not work in bash, install `bash-completion` via your OS package manager and start a new shell.

### Completing your command's arguments

Out of the box, completion suggests subcommand names, flag names, and required flags. To complete **argument values**, provide them via `ValidArgs` (static) or `ValidArgsFunction` (dynamic).

**Static** — a fixed list:

```go
var setCmd = &cobra.Command{
	Use:       "set-level",
	ValidArgs: []string{"debug", "info", "warn", "error"},
	Args:      cobra.OnlyValidArgs,
	Run:       func(cmd *cobra.Command, args []string) { /* ... */ },
}
```

**Dynamic** — computed at completion time:

```go
var openCmd = &cobra.Command{
	Use: "open",
	ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
		// e.g. list open projects matching `toComplete`
		return []cobra.Completion{"alpha", "beta"}, cobra.ShellCompDirectiveNoFileComp
	},
	Run: func(cmd *cobra.Command, args []string) { /* ... */ },
}
```

Add descriptions to completions with `cobra.CompletionWithDesc("choice", "description")` (zsh and fish display the description).

### Completing flag values

Register a completion function for a specific flag with `RegisterFlagCompletionFunc`:

```go
serveCmd.Flags().String("region", "", "deployment region")
serveCmd.RegisterFlagCompletionFunc("region",
	func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
		return []cobra.Completion{"us-east-1", "eu-west-1"}, cobra.ShellCompDirectiveNoFileComp
	})
```

> [!WARNING]
> `RegisterFlagCompletionFunc` returns an error if the flag does not exist (`RegisterFlagCompletionFunc: flag '...' does not exist`) or if you register the same flag twice (`... already registered`). Register completion only after the flag is defined, and only once per flag.

### Completion directives

A completion function returns a `ShellCompDirective` bitmask that tells the shell how to behave. Combine them with `|`.

| Directive | Effect |
|-----------|--------|
| `ShellCompDirectiveDefault` | Let the shell do its default (file) completion. The zero value. |
| `ShellCompDirectiveNoSpace` | Do not append a space after the completion. |
| `ShellCompDirectiveNoFileComp` | Do not fall back to file completion. |
| `ShellCompDirectiveFilterFileExt` | Treat the returned values as file-extension filters. |
| `ShellCompDirectiveFilterDirs` | Complete directory names only. |
| `ShellCompDirectiveKeepOrder` | Preserve the order you returned completions in (don't sort). |
| `ShellCompDirectiveError` | Signal an error; completions are ignored. |

Two ready-made completion functions cover common cases:

- `cobra.NoFileCompletions` — disables file completion for a command/flag that takes no completable value.
- `cobra.FixedCompletions(choices, directive)` — always returns the same list.

```go
cmd.ValidArgsFunction = cobra.NoFileCompletions
```

### Controlling the generated completion command

Customize or disable the built-in `completion` command via the root command's `CompletionOptions`:

| Field | Effect |
|-------|--------|
| `DisableDefaultCmd` | Do not create the `completion` command at all. |
| `DisableNoDescFlag` | Do not add the `--no-descriptions` flag. |
| `DisableDescriptions` | Turn off completion descriptions entirely. |
| `HiddenDefaultCmd` | Keep the `completion` command but hide it from help. |

```go
rootCmd.CompletionOptions.DisableDefaultCmd = true
```

---

## 10. Active Help

Active Help lets you push contextual messages to users **during completion** — for example, a hint when no completions are available. Build the messages onto your completion slice with `AppendActiveHelp`:

```go
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
	var comps []cobra.Completion
	if len(args) == 0 {
		comps = cobra.AppendActiveHelp(comps, "You must specify a project name")
	}
	return comps, cobra.ShellCompDirectiveNoFileComp
},
```

Users (or you) can disable Active Help through environment variables, read at completion time:

| Variable | Effect |
|----------|--------|
| `COBRA_ACTIVE_HELP=0` | Globally disable Active Help for any Cobra program. |
| `<PROGRAM>_ACTIVE_HELP=0` | Disable Active Help for your program specifically. `<PROGRAM>` is your root command's name, upper-cased, with non-alphanumeric characters replaced by `_`. |

> [!NOTE]
> The `<PROGRAM>` prefix is derived from `rootCmd.Name()`. A program named `my-app` reads `MY_APP_ACTIVE_HELP`.

---

## 11. Generating Documentation

The `github.com/spf13/cobra/doc` subpackage turns your command tree into documentation files. It supports four formats, each with a single-file and a whole-tree generator.

| Format | Tree generator | Single-command generator |
|--------|----------------|--------------------------|
| Man pages | `doc.GenManTree(cmd, header, dir)` | `doc.GenMan(cmd, header, w)` |
| Markdown | `doc.GenMarkdownTree(cmd, dir)` | `doc.GenMarkdown(cmd, w)` |
| reStructuredText | `doc.GenReSTTree(cmd, dir)` | `doc.GenReST(cmd, w)` |
| YAML | `doc.GenYamlTree(cmd, dir)` | `doc.GenYaml(cmd, w)` |

Generate a full Markdown tree:

```go
package main

import (
	"log"

	"github.com/spf13/cobra/doc"
)

func main() {
	if err := doc.GenMarkdownTree(rootCmd, "./docs"); err != nil {
		log.Fatal(err)
	}
}
```

Generate man pages with a header:

```go
header := &doc.GenManHeader{
	Title:   "APP",
	Section: "1",
	Source:  "App 1.0",
}
if err := doc.GenManTree(rootCmd, header, "./man"); err != nil {
	log.Fatal(err)
}
```

Each generator has a `*Custom` variant (`GenMarkdownTreeCustom`, `GenManTreeFromOpts`, `GenReSTTreeCustom`, `GenYamlTreeCustom`) that accepts a `filePrepender` and `linkHandler` so you can add front-matter or rewrite cross-links.

> [!NOTE]
> By default the generated docs end with an "Auto generated by spf13/cobra" tag (and man pages add a `HISTORY` section). Set `DisableAutoGenTag: true` on a command to omit it.

> [!WARNING]
> The tree generators may produce ambiguous filenames if your command names contain `-`. As the source notes: with a `cmd` that has subcommands `sub` and `sub-third`, where `sub` also has a child `third`, it is undefined which output lands in `cmd-sub-third`. Avoid `-` in command names if you generate per-command files.

---

## 12. Versioning, Help, and Error Output

### Version flag

Set the `Version` field on your root command and Cobra adds a `--version` flag (and a `-v` shorthand, if free):

```go
var rootCmd = &cobra.Command{
	Use:     "app",
	Version: "1.4.2",
}
```

```bash
app --version
```

```text
app version 1.4.2
```

Customize the format with `rootCmd.SetVersionTemplate(...)`.

> [!NOTE]
> The `--version` flag and `version` template are tied to whichever command has a non-empty `Version`. A known limitation (community-reported) is that `--version` does not propagate to subcommands automatically — set `Version` on the specific command if you want `app sub --version` to work.

### Help

Cobra adds a `-h, --help` flag to every command and a `help` command to any command that has subcommands. Override the default behavior with `cmd.SetHelpFunc(...)`, `cmd.SetHelpTemplate(...)`, `cmd.SetUsageFunc(...)`, or `cmd.SetUsageTemplate(...)`.

### Quieting output

| Field | Effect |
|-------|--------|
| `SilenceErrors: true` | Cobra does not print errors returned from `RunE` (you handle them). |
| `SilenceUsage: true` | Cobra does not print the usage string after an error. |

```go
var rootCmd = &cobra.Command{
	Use:           "app",
	SilenceUsage:  true,   // don't dump usage on every runtime error
	SilenceErrors: false,
}
```

> [!TIP]
> Setting `SilenceUsage: true` is almost always what you want once your CLI is stable. Without it, every runtime error (e.g. "file not found") prints the full usage text, which is noise for users who already know the command.

### Custom error prefix

The default error prefix is `Error:`. Change it with `cmd.SetErrPrefix("myapp:")`.

### Helper: CheckErr

`cobra.CheckErr(err)` prints `Error: <msg>` to stderr and exits with code 1 if `err` is non-nil — a concise replacement for the `if err != nil { ... os.Exit(1) }` boilerplate in small programs.

```go
func main() {
	cobra.CheckErr(rootCmd.Execute())
}
```

---

## 13. Global Behavior Toggles

These are **package-level variables** in the `cobra` package. Set them once (typically in `init()`) to change behavior program-wide.

| Variable | Default | Effect |
|----------|---------|--------|
| `EnablePrefixMatching` | `false` | Allow invoking a command by an unambiguous prefix of its name. |
| `EnableCommandSorting` | `true` | Sort commands alphabetically in help. Set `false` to keep insertion order. |
| `EnableCaseInsensitive` | `false` | Match command names and aliases case-insensitively. |
| `EnableTraverseRunHooks` | `false` | Run all persistent hooks along the command path (see [§7](#7-the-run-lifecycle-hooks)). |
| `MousetrapHelpText` | (a message) | Text shown on Windows when the program is launched from Explorer. Set to `""` to disable the splash. |
| `MousetrapDisplayDuration` | `5 * time.Second` | How long that Windows message shows. `0` waits for the Enter key. |

```go
func init() {
	cobra.EnableCommandSorting = false
	cobra.EnablePrefixMatching = true
}
```

> [!CAUTION]
> Cobra's own documentation warns that `EnablePrefixMatching` "can be a dangerous thing to automatically enable in CLI tools" — a new command added later could make a previously-unambiguous prefix ambiguous, silently changing behavior. Enable it deliberately.

> [!NOTE]
> The mousetrap feature only affects Windows binaries launched by double-clicking in Explorer. It shows the help text so users realize the program is a command-line tool. It has no effect on Linux or macOS.

---

## 14. Common Recipes

### A complete multi-command program

```go
package main

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
)

var verbose bool

var rootCmd = &cobra.Command{
	Use:     "app",
	Short:   "App does useful things",
	Version: "1.0.0",
	SilenceUsage: true,
}

var serveCmd = &cobra.Command{
	Use:   "serve",
	Short: "Start the server",
	Args:  cobra.NoArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		port, _ := cmd.Flags().GetInt("port")
		fmt.Fprintf(cmd.OutOrStdout(), "listening on :%d\n", port)
		return nil
	},
}

func init() {
	rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")
	serveCmd.Flags().IntP("port", "p", 8080, "port to listen on")
	rootCmd.AddCommand(serveCmd)
}

func main() {
	if err := rootCmd.Execute(); err != nil {
		os.Exit(1)
	}
}
```

### Pass a context into commands

```go
func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	if err := rootCmd.ExecuteContext(ctx); err != nil {
		os.Exit(1)
	}
}

// inside a Run/RunE function:
RunE: func(cmd *cobra.Command, args []string) error {
	ctx := cmd.Context()   // the context passed to ExecuteContext
	return doWork(ctx)
}
```

### Testing a command

```go
func TestServe(t *testing.T) {
	buf := new(bytes.Buffer)
	rootCmd.SetOut(buf)
	rootCmd.SetArgs([]string{"serve", "--port", "9000"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(buf.String(), ":9000") {
		t.Errorf("unexpected output: %q", buf.String())
	}
}
```

`SetArgs` overrides `os.Args[1:]`, and `SetOut`/`SetErr` capture output — together they make commands fully testable without spawning a process.

---

## 15. Troubleshooting

### Error: `required flag(s) "X" not set`

**Cause:** A flag marked with `MarkFlagRequired` (or required as part of a one-required group) was not provided.
**Solution:** Pass the flag, e.g. `app serve --config app.yaml`.
**Prevention:** Document required flags in the command's `Long`/`Example`.

### Error: `unknown command "X" for "app"`

**Cause:** The user typed a name that matches no subcommand or alias. Often a typo.
**Solution:** Run `app --help` to list valid commands; Cobra usually prints a "Did you mean this?" suggestion.
**Prevention:** Add common misspellings to a command's `SuggestFor`, or `Aliases` for legitimate alternates.

### Error: `if any flags in the group [a b] are set they must all be set; missing [b]`

**Cause:** You used `MarkFlagsRequiredTogether("a", "b")` and supplied only one of them.
**Solution:** Provide all flags in the group, or none.
**Prevention:** Group only flags that are genuinely interdependent.

### Error: `if any flags in the group [a b] are set none of the others can be; [a b] were all set`

**Cause:** `MarkFlagsMutuallyExclusive("a", "b")` and the user set more than one.
**Solution:** Pass at most one of the mutually exclusive flags.

### Panic: `group id 'X' is not defined for subcommand 'app Y'`

**Cause:** A subcommand has a `GroupID` whose group was never registered on the parent with `AddGroup`.
**Solution:** Call `parent.AddGroup(&cobra.Group{ID: "X", Title: "..."})` before adding the child.
**Prevention:** Define groups and assign `GroupID`s in the same `init()`.

### Panic: `Command can't be a child of itself`

**Cause:** You passed a command to its own `AddCommand`.
**Solution:** Build distinct command values; don't add `rootCmd` to `rootCmd`.

### `PersistentPostRun` / `PostRun` never runs

**Cause:** Post-run hooks are skipped when `RunE` (or an earlier `*RunE`) returns an error. (Community issue #1893.)
**Solution:** Put unconditional cleanup in a `defer` inside `RunE`, not in a post-run hook.

### Shell completion does nothing in bash

**Cause:** The `bash-completion` package is not installed, or the script was not sourced.
**Solution:** Install `bash-completion`, then `source <(app completion bash)` and start a new shell.

### Completion debugging

**Cause:** You want to see why a custom completion function returns nothing.
**Solution:** Set the `BASH_COMP_DEBUG_FILE` environment variable to a writable path; Cobra (and your calls to `cobra.CompDebugln`) append debug logs there during completion.

```bash
export BASH_COMP_DEBUG_FILE=/tmp/app-comp.log
```

### `--version` works on the root but not a subcommand

**Cause:** The version flag is added only to the command whose `Version` field is non-empty. (Community issue #1860.)
**Solution:** Set `Version` on the specific subcommand if you need `app sub --version`.

---

## 16. FAQ

**Q: Is Cobra a program I install and run, or a library?**
It is a Go library. You import `github.com/spf13/cobra` and build your own binary with it. There is no `cobra` executable to run your commands.

**Q: Do I have to use `Run` or can I return errors?**
Use `RunE`, which returns an `error`. Cobra prints the error consistently and `Execute()` returns it so your `main` can set the exit code. `Run` (no error) is fine only for commands that cannot fail.

**Q: What is the difference between `Flags()` and `PersistentFlags()`?**
`Flags()` defines a flag local to one command. `PersistentFlags()` defines a flag that is also inherited by all of that command's descendants. Use persistent flags for cross-cutting options like `--verbose` on the root.

**Q: How do I make a flag required?**
`cmd.MarkFlagRequired("name")` for a local flag, or `cmd.MarkPersistentFlagRequired("name")` for a persistent one. Cobra then errors if it is missing.

**Q: How do positional arguments differ from flags?**
Flags are named (`--port 80`); positional arguments are the leftover values after flags are removed. Validate their count/values with the `Args` field (e.g. `cobra.ExactArgs(1)`).

**Q: Where does my command read its arguments?**
From the `args []string` parameter of `Run`/`RunE` — it contains the validated positional arguments after the command name and flags.

**Q: How do I add tab completion?**
You don't have to write any scripts — every Cobra program already has a `completion` command for bash/zsh/fish/PowerShell. To complete argument or flag *values*, supply `ValidArgs`, a `ValidArgsFunction`, or `RegisterFlagCompletionFunc`.

**Q: Can I generate man pages or Markdown docs from my commands?**
Yes. Import `github.com/spf13/cobra/doc` and call `GenManTree`, `GenMarkdownTree`, `GenReSTTree`, or `GenYamlTree`.

**Q: In what order do the Run hooks fire?**
`PersistentPreRun` → `PreRun` → `Run` → `PostRun` → `PersistentPostRun`. The `E` variant takes precedence over the non-`E` form when both are set.

**Q: Why do my root command's persistent pre-run hooks stop firing when a subcommand also defines one?**
By default only the first persistent hook found while walking the tree runs. Set `cobra.EnableTraverseRunHooks = true` to run all of them along the path.

**Q: How do I stop Cobra from printing usage on every error?**
Set `SilenceUsage: true` (and optionally `SilenceErrors: true` to handle error printing yourself).

**Q: How do I pass a `context.Context` into my commands?**
Call `rootCmd.ExecuteContext(ctx)` and read it inside a command with `cmd.Context()`.

**Q: Can I invoke a command by a shortened name?**
Set `cobra.EnablePrefixMatching = true` to allow unambiguous prefixes. Use with care — adding commands later can make a prefix ambiguous.

---

## 17. Quick Reference

### Execution entry points

| Call | Purpose |
|------|---------|
| `cmd.Execute()` | Run the command tree from the root using `os.Args[1:]`. |
| `cmd.ExecuteContext(ctx)` | `Execute` with a context attached. |
| `cmd.ExecuteC()` | `Execute` and also return the matched command. |
| `cobra.CheckErr(err)` | Print `Error: ...` and `os.Exit(1)` if `err != nil`. |

### Defining structure

| Call | Purpose |
|------|---------|
| `parent.AddCommand(child...)` | Attach subcommands. |
| `parent.AddGroup(&cobra.Group{...})` | Register a help group. |
| `cmd.SetArgs([]string{...})` | Override the args (testing). |
| `cmd.SetOut/SetErr/SetIn(...)` | Redirect I/O streams. |

### Flags

| Call | Purpose |
|------|---------|
| `cmd.Flags()` | Local flag set. |
| `cmd.PersistentFlags()` | Inherited flag set. |
| `cmd.MarkFlagRequired("f")` | Require a flag. |
| `cmd.MarkFlagsRequiredTogether(...)` | All-or-none flag group. |
| `cmd.MarkFlagsOneRequired(...)` | At-least-one flag group. |
| `cmd.MarkFlagsMutuallyExclusive(...)` | At-most-one flag group. |
| `cmd.MarkFlagFilename("f", exts...)` | Complete files by extension. |
| `cmd.MarkFlagDirname("d")` | Complete directories. |

### Argument validators

`NoArgs` · `ArbitraryArgs` · `MinimumNArgs(n)` · `MaximumNArgs(n)` · `ExactArgs(n)` · `RangeArgs(min,max)` · `OnlyValidArgs` · `NoDuplicateArgs` · `MatchAll(...)`

### Completion

| Call | Purpose |
|------|---------|
| `cmd.ValidArgsFunction = fn` | Dynamic argument completion. |
| `cmd.RegisterFlagCompletionFunc("f", fn)` | Flag-value completion. |
| `cobra.NoFileCompletions` | Disable file completion. |
| `cobra.FixedCompletions(choices, dir)` | Always return the same list. |
| `cobra.AppendActiveHelp(comps, msg)` | Add an Active Help message. |

### Documentation generators (`doc` package)

`GenManTree` · `GenMarkdownTree` · `GenReSTTree` · `GenYamlTree` (each with a `*Custom` variant)

### Environment variables (consumed at runtime)

| Variable | Effect |
|----------|--------|
| `BASH_COMP_DEBUG_FILE` | Path for completion debug logs. |
| `COBRA_ACTIVE_HELP=0` | Disable Active Help globally. |
| `<PROGRAM>_ACTIVE_HELP=0` | Disable Active Help for your program. |
| `<PROGRAM>_COMPLETION_DESCRIPTIONS=false` | Turn off completion descriptions. |

---

_Generated June 2026 from spf13/cobra at ad460ea. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
