CLI command tree library for Golang using spf13/cobra — cobra.Command, RunE vs Run, PreRun hooks, Args validators, persistent vs local flags, shell completion, testing via SetArgs. Apply when using/adopting cobra or the codebase imports github.com/spf13/cobra. Config: golang-spf13-viper.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
The command stays on one line. Scroll horizontally to inspect it before copying.
Prefer a local copy? Download the files currently available to SkillsMP.
File Explorer
7 files
Showing SKILL.md
SKILL.md
Source instructions · Read-only preview
name
golang-spf13-cobra
description
CLI command tree library for Golang using spf13/cobra — cobra.Command, RunE vs Run, PreRun hooks, Args validators, persistent vs local flags, shell completion, testing via SetArgs. Apply when using/adopting cobra or the codebase imports github.com/spf13/cobra. Config: golang-spf13-viper.
user-invocable
true
license
MIT
compatibility
Designed for Claude Code, Codex or similar harness, and for projects using Golang.
Persona: You are a Go CLI engineer building command trees that feel native to the Unix shell. You design the user-facing surface first, then wire behavior into the right hook.
Modes:
Build — creating a new CLI from scratch: follow command tree setup, hook wiring, and flag sections sequentially.
Extend — adding subcommands, flags, or completions to an existing CLI: read the current command tree first, then apply changes consistent with the existing structure.
Review — auditing an existing CLI: check the Common Mistakes table, verify RunE usage, OutOrStdout(), hook chain ordering, and args validation.
Using spf13/cobra for CLI command trees in Go
Cobra is the de facto standard for Go CLI applications. It provides the command/subcommand tree, flag parsing (via pflag), args validation, shell completion generation, and documentation generation. It does not handle configuration layering — that's viper's job.
This skill is not exhaustive. Please refer to library documentation and code examples for more information. For Go package docs, symbols, versions, importers, and known vulnerabilities, → See samber/cc-skills-golang@golang-pkg-go-dev skill (godig) — prefer it over Context7 for Go package facts. To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See samber/cc-skills-golang@golang-gopls skill (gopls). Context7 remains a fallback for docs not indexed on pkg.go.dev.
go get github.com/spf13/cobra@latest
Cobra vs. viper
These libraries do fundamentally different things and can be used independently.
Concern
cobra
viper
Owns
Command tree, flags, arg validation, completions
Configuration value resolution
User-facing?
Yes — subcommands, flags, help text
No — purely a key-value resolver
Without the other?
Yes — a CLI with flags only needs cobra
Yes — a daemon reading YAML + env needs only viper
Integration seam
Hands pflag.Flag to viper via BindPFlag
Treats the cobra flag as the highest-precedence layer
Use cobra alone when your binary takes flags and args but needs no config file or env resolution. Use viper alone when you have a long-running service reading config from YAML + env with no CLI subcommands. Use both when you need both — bind at PersistentPreRunE on the root command.
→ See samber/cc-skills-golang@golang-spf13-viper for the viper side of this integration.
Command tree
Every cobra CLI has a root command plus zero or more subcommands registered with AddCommand. The root command name is the binary name.
var rootCmd = &cobra.Command{
Use: "myapp",
Short: "One-line summary",
SilenceUsage: true, // ✓ prevents usage wall on every error
SilenceErrors: true, // ✓ lets you control error output format
}
Use AddGroup to label subcommands in help output — register groups before the AddCommand calls that reference them; cobra does not retroactively assign groups.
The Run* family
Cobra commands have five run hooks executed in order:
Cobra validates positional arguments before RunE runs. Never write len(args) checks inside RunE — that bypasses cobra's standard error messages and arg count tracking.
For the full validator set with examples and MatchAll patterns, see commands-and-args.md.
Flags primer
Cobra delegates flag parsing to pflag. Persistent flags (PersistentFlags()) are inherited by all subcommands; local flags (Flags()) apply only to the declaring command.
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file path") // inherited by all subcommands
serveCmd.Flags().IntVar(&port, "port", 8080, "listen port") // local to serveCmd only
serveCmd.MarkFlagRequired("port")
serveCmd.MarkFlagsMutuallyExclusive("json", "yaml")
For pflag types, custom flag values, flag groups, and viper binding, see flags.md.
Completions primer
Cobra generates shell completions automatically. Extend them with:
RegisterFlagCompletionFunc(name, fn) — flag value completion.
For ShellCompDirective values, annotations, and testing, see completions.md.
Testing commands
Test commands by executing them programmatically. Never use os.Stdout / os.Stderr directly in command handlers — use cmd.OutOrStdout() / cmd.ErrOrStderr() so tests can redirect output.
Cobra accumulates flag state across Execute() calls — build a fresh command tree per test. For isolation patterns, golden files, and testing completions, see testing.md.
Best Practices
Always use RunE, never Run — Run cannot return an error; the only escape is os.Exit or panic, bypassing defers.
Put config initialization in PersistentPreRunE — it runs before every subcommand; the right place for viper binding and auth checks.
Validate positional args with Args, not inside RunE — Args gives cobra's standard error messages; MatchAll composes validators.
Use cmd.OutOrStdout() / cmd.ErrOrStderr() for all output — direct os.Stdout writes cannot be captured by tests.
Re-create the command tree per test — cobra accumulates flag state across Execute() calls on the same instance.
Common Mistakes
Mistake
Why it fails
Fix
Using Run instead of RunE
Cannot return an error — only escape is os.Exit or panic, bypassing defers
Use RunE — return the error, let cobra handle the exit
Writing len(args) checks in RunE
Bypasses cobra's standard error messages ("accepts 1 arg, received 2")