golang-spf13-cobra

작성자: samber

Golang CLI command tree library using spf13/cobra — cobra.Command, RunE vs Run, PersistentPreRunE hook chain, Args validators (NoArgs, ExactArgs, MatchAll, custom), persistent vs local flags, command groups, ValidArgsFunction, RegisterFlagCompletionFunc, ShellCompDirective, usage/help template customization, man-page and markdown doc generation, and testing with SetArgs/SetOut/SetErr. Apply when using or adopting spf13/cobra, or when the codebase imports `github.com/spf13/cobra`. For...

npx skills add https://github.com/samber/cc-skills-golang --skill golang-spf13-cobra

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.

Official Resources:

This skill is not exhaustive. Please refer to library documentation and code examples for more information. Context7 can help as a discoverability platform.

go get github.com/spf13/cobra@latest

Cobra vs. viper

These libraries do fundamentally different things and can be used independently.

Concerncobraviper
OwnsCommand tree, flags, arg validation, completionsConfiguration value resolution
User-facing?Yes — subcommands, flags, help textNo — purely a key-value resolver
Without the other?Yes — a CLI with flags only needs cobraYes — a daemon reading YAML + env needs only viper
Integration seamHands pflag.Flag to viper via BindPFlagTreats 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:

PersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE

Always use *E variants — the non-E forms cannot return errors. Key rules:

  • PersistentPreRunE on the root runs before every subcommand — use it for config init and auth checks.
  • A child PersistentPreRunE replaces the parent's entirely — call the parent explicitly if you need both.
  • PostRunE runs only if RunE succeeded.

For the full lifecycle and inheritance rules, see commands-and-args.md.

Args validators

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.

Built-ins: NoArgs, ExactArgs(n), MinimumNArgs(n), MaximumNArgs(n), RangeArgs(min,max), OnlyValidArgs, ExactValidArgs(n). Compose with MatchAll(v1, v2). Custom validator: func(cmd *cobra.Command, args []string) error.

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:

  • ValidArgs []string — static positional arg completion.
  • ValidArgsFunction — dynamic: func(cmd, args, toComplete string) ([]string, ShellCompDirective). Return ShellCompDirectiveNoFileComp to suppress file fallback.
  • 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.

func TestServeCmd(t *testing.T) {
    buf := new(bytes.Buffer)
    rootCmd.SetOut(buf)
    rootCmd.SetArgs([]string{"serve", "--port", "9090"})
    require.NoError(t, rootCmd.Execute())
    assert.Contains(t, buf.String(), "listening on :9090")
}

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

  1. Always use RunE, never RunRun cannot return an error; the only escape is os.Exit or panic, bypassing defers.
  2. Put config initialization in PersistentPreRunE — it runs before every subcommand; the right place for viper binding and auth checks.
  3. Validate positional args with Args, not inside RunEArgs gives cobra's standard error messages; MatchAll composes validators.
  4. Use cmd.OutOrStdout() / cmd.ErrOrStderr() for all output — direct os.Stdout writes cannot be captured by tests.
  5. Re-create the command tree per test — cobra accumulates flag state across Execute() calls on the same instance.

Common Mistakes

MistakeWhy it failsFix
Using Run instead of RunECannot return an error — only escape is os.Exit or panic, bypassing defersUse RunE — return the error, let cobra handle the exit
Writing len(args) checks in RunEBypasses cobra's standard error messages ("accepts 1 arg, received 2")Declare Args: cobra.ExactArgs(1) on the command
Writing to os.Stdout directlyTests cannot capture output — os-level file handles can't be redirectedUse cmd.OutOrStdout() / cmd.ErrOrStderr()
Child PersistentPreRunE silently drops parent'sCobra does not chain — the child replaces the parent's hook entirelyCall parent.PersistentPreRunE(cmd, args) from the child's hook
Reusing a root command across testsCobra accumulates flag state; second Execute() sees flags from the firstBuild a fresh command tree per test

Further Reading

  • commands-and-args.md — full PreRun*/PostRun* chain, every Args validator, PersistentPreRunE inheritance rules
  • flags.md — pflag types, required/exclusive/oneRequired groups, custom value types, viper binding
  • completions.md — ShellCompDirective set, annotation-based completions, testing completions
  • generators.md — man page, markdown, YAML, RST doc generation; cobra-cli scaffolder
  • testing.md — isolation patterns, golden files, testing completions, table-driven command tests

Cross-References

  • → See samber/cc-skills-golang@golang-cli skill for general CLI architecture — project layout, exit codes, signal handling, I/O patterns
  • → See samber/cc-skills-golang@golang-spf13-viper skill for configuration layering alongside cobra (flag → env → file → default precedence)
  • → See samber/cc-skills-golang@golang-testing skill for general Go testing patterns

If you encounter a bug or unexpected behavior in spf13/cobra, open an issue at https://github.com/spf13/cobra/issues.

samber의 다른 스킬

golang-code-style
samber
Golang code style conventions — line length and breaking, variable declarations, control flow clarity, when comments help vs hurt. Use when writing or reviewing Go code, asking about style or clarity, or establishing project coding standards. Not for naming conventions (→ See `samber/cc-skills-golang@golang-naming` skill), linter configuration (→ See `samber/cc-skills-golang@golang-lint` skill), or doc comments (→ See `samber/cc-skills-golang@golang-documentation` skill).
developmentcode-review
golang-testing
samber
Production-ready Golang tests — table-driven tests, testify suites and mocks, parallel tests, fuzzing, fixtures, goroutine leak detection with goleak, snapshot testing, code coverage, integration tests, idiomatic test naming. Use when writing or reviewing Go tests, choosing a testing approach, setting up Go test CI, or debugging flaky/slow tests. For testify-specific APIs see `samber/cc-skills-golang@golang-stretchr-testify`; for measurement methodology see...
developmenttestingcode-review
golang-design-patterns
samber
관용적인 Golang 디자인 패턴 — 함수형 옵션, 생성자, 오류 흐름 및 연쇄, 리소스 관리 및 생명주기, 정상 종료, 복원력, 아키텍처, 의존성 주입, 데이터 처리, 스트리밍 등. 아키텍처 패턴을 명시적으로 선택할 때, 함수형 옵션을 구현할 때, 생성자 API를 설계할 때, 정상 종료를 설정할 때, 복원력 패턴을 적용할 때, 또는 특정 문제에 맞는 관용적인 Go 패턴을 질문할 때 적용하세요.
developmentdesigncode-review
golang-error-handling
samber
Idiomatic Golang error handling — creation, wrapping with %w, errors.Is/As, errors.Join, custom error types, sentinel errors, panic/recover, the single handling rule, structured logging with slog, HTTP request logging middleware, and samber/oops for production errors. Built to make logs usable at scale with log aggregation 3rd-party tools. Apply when creating, wrapping, inspecting, or logging errors in Go code. For samber/oops specifics → See `samber/cc-skills-golang@golang-samber-oops`...
developmentcode-review
golang-performance
samber
Golang 성능 최적화 패턴 및 방법론 - X 병목이 발생하면 Y를 적용. 할당 감소, CPU 효율성, 메모리 레이아웃, GC 튜닝, 풀링, 캐싱, 핫패스 최적화를 다룹니다. 프로파일링이나 벤치마크에서 병목이 확인되어 이를 해결할 적절한 최적화 패턴이 필요할 때 사용합니다. 또한 성능 코드 리뷰 시 개선 사항이나 빠른 성능 향상을 식별하는 데 도움이 될 벤치마크를 제안할 때 사용합니다. 측정 방법론에는 해당하지 않습니다(→...
developmentcode-review
golang-security
samber
Golang의 보안 모범 사례와 취약점 방지. 인젝션(SQL, 명령어, XSS), 암호화, 파일 시스템 안전, 네트워크 보안, 쿠키, 비밀 관리, 메모리 안전, 로깅을 다룹니다. 보안을 위해 Go 코드를 작성, 검토 또는 감사할 때, 또는 암호화, I/O, 비밀 관리, 사용자 입력 처리, 인증과 관련된 위험한 코드 작업 시 적용하세요. 보안 도구 구성도 포함됩니다.
securitycode-reviewdevelopment
golang-database
samber
Go 데이터베이스 접근에 대한 종합 가이드 — 매개변수화된 쿼리, 구조체 스캐닝, NULL 가능 컬럼, 트랜잭션, 격리 수준, SELECT FOR UPDATE, 연결 풀, 배치 처리, 컨텍스트 전파, 마이그레이션 도구. PostgreSQL, MariaDB, MySQL, SQLite와 상호작용하는 Golang 코드를 작성, 검토, 디버깅할 때 사용하거나, 데이터베이스 테스트 시, 또는 database/sql, sqlx, pgx에 대한 질문이 있을 때 사용합니다. 데이터베이스 스키마나 마이그레이션 SQL은 생성하지 않습니다.
developmentdatabase
golang-lint
samber
Golang 프로젝트를 위한 린팅 모범 사례와 golangci-lint 설정 — 린터 실행, .golangci.yml 구성, nolint 지시어로 경고 억제, 린트 출력 해석, 린터 선택. golangci-lint를 구성할 때, 린트 경고나 nolint 억제에 대해 질문할 때, 코드 품질 도구를 설정할 때, 또는 린터를 선택할 때 사용합니다. 또한 사용자가 golangci-lint, go vet, staticcheck, revive를 언급할 때 사용합니다.
developmentcode-reviewtesting