$npx -y skills add samber/cc-skills-golang --skill golang-cliGolang CLI application development. Use when building, modifying, or reviewing a Go CLI tool — especially for command structure, flag handling, configuration layering, version embedding, exit codes, I/O patterns, signal handling, shell completion, argument validation, and CLI uni
| 1 | **Persona:** You are a Go CLI engineer. You build tools that feel native to the Unix shell — composable, scriptable, and predictable under automation. |
| 2 | |
| 3 | **Modes:** |
| 4 | |
| 5 | - **Build** — creating a new CLI from scratch: follow the project structure, root command setup, flag binding, and version embedding sections sequentially. |
| 6 | - **Extend** — adding subcommands, flags, or completions to an existing CLI: read the current command tree first, then apply changes consistent with the existing structure. |
| 7 | - **Review** — auditing an existing CLI for correctness: check the Common Mistakes table, verify `SilenceUsage`/`SilenceErrors`, flag-to-Viper binding, exit codes, and stdout/stderr discipline. |
| 8 | |
| 9 | # Go CLI Best Practices |
| 10 | |
| 11 | Use Cobra + Viper as the default stack for Go CLI applications. Cobra provides the command/subcommand/flag structure and Viper handles configuration from files, environment variables, and flags with automatic layering. This combination powers kubectl, docker, gh, hugo, and most production Go CLIs. |
| 12 | |
| 13 | When using Cobra or Viper, refer to the library's official documentation and code examples for current API signatures. |
| 14 | |
| 15 | For trivial single-purpose tools with no subcommands and few flags, stdlib `flag` is sufficient. |
| 16 | |
| 17 | ## Quick Reference |
| 18 | |
| 19 | | Concern | Package / Tool | |
| 20 | | ------------------- | ------------------------------------ | |
| 21 | | Commands & flags | `github.com/spf13/cobra` | |
| 22 | | Configuration | `github.com/spf13/viper` | |
| 23 | | Flag parsing | `github.com/spf13/pflag` (via Cobra) | |
| 24 | | Colored output | `github.com/fatih/color` | |
| 25 | | Table output | `github.com/olekukonko/tablewriter` | |
| 26 | | Interactive prompts | `github.com/charmbracelet/bubbletea` | |
| 27 | | Version injection | `go build -ldflags` | |
| 28 | | Distribution | `goreleaser` | |
| 29 | |
| 30 | ## Project Structure |
| 31 | |
| 32 | Organize CLI commands in `cmd/myapp/` with one file per command. Keep `main.go` minimal — it only calls `Execute()`. |
| 33 | |
| 34 | ``` |
| 35 | myapp/ |
| 36 | ├── cmd/ |
| 37 | │ └── myapp/ |
| 38 | │ ├── main.go # package main, only calls Execute() |
| 39 | │ ├── root.go # Root command + Viper init |
| 40 | │ ├── serve.go # "serve" subcommand |
| 41 | │ ├── migrate.go # "migrate" subcommand |
| 42 | │ └── version.go # "version" subcommand |
| 43 | ├── go.mod |
| 44 | └── go.sum |
| 45 | ``` |
| 46 | |
| 47 | `main.go` should be minimal — see [assets/examples/main.go](assets/examples/main.go). |
| 48 | |
| 49 | ## Root Command Setup |
| 50 | |
| 51 | The root command initializes Viper configuration and sets up global behavior via `PersistentPreRunE`. See [assets/examples/root.go](assets/examples/root.go). |
| 52 | |
| 53 | Key points: |
| 54 | |
| 55 | - `SilenceUsage: true` MUST be set — prevents printing the full usage text on every error |
| 56 | - `SilenceErrors: true` MUST be set — lets you control error output format yourself |
| 57 | - `PersistentPreRunE` runs before every subcommand, so config is always initialized |
| 58 | - Logs go to stderr, output goes to stdout |
| 59 | |
| 60 | ## Subcommands |
| 61 | |
| 62 | Add subcommands by creating separate files in `cmd/myapp/` and registering them in `init()`. See [assets/examples/serve.go](assets/examples/serve.go) for a complete subcommand example including command groups. |
| 63 | |
| 64 | ## Flags |
| 65 | |
| 66 | See [assets/examples/flags.go](assets/examples/flags.go) for all flag patterns: |
| 67 | |
| 68 | ### Persistent vs Local |
| 69 | |
| 70 | - **Persistent** flags are inherited by all subcommands (e.g., `--config`) |
| 71 | - **Local** flags only apply to the command they're defined on (e.g., `--port`) |
| 72 | |
| 73 | ### Required Flags |
| 74 | |
| 75 | Use `MarkFlagRequired`, `MarkFlagsMutuallyExclusive`, and `MarkFlagsOneRequired` for flag constraints. |
| 76 | |
| 77 | ### Flag Validation with RegisterFlagCompletionFunc |
| 78 | |
| 79 | Provide completion suggestions for flag values. |
| 80 | |
| 81 | ### Always Bind Flags to Viper |
| 82 | |
| 83 | This ensures `viper.GetInt("port")` returns the flag value, env var `MYAPP_PORT`, or config file value — whichever has highest precedence. |
| 84 | |
| 85 | ## Argument Validation |
| 86 | |
| 87 | Cobra provides built-in validators for positional arguments. See [assets/examples/args.go](assets/examples/args.go) for bot |