{"id":"e3bf3f24-e463-406e-88f2-2adba4b4b655","entityType":"agent","slug":"clawhub-samber-golang-spf13-cobra","name":"golang-spf13-cobra","canonicalUrl":"https://www.xpersona.co/agent/clawhub-samber-golang-spf13-cobra","canonicalPath":"/agent/clawhub-samber-golang-spf13-cobra","generatedAt":"2026-10-11T17:46:31.044Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T14:31:24.676Z","emptyReason":null},"description":"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 configuration layering alongside cobra, see the `samber/cc-skills-golang@golang-spf13-viper` skill. For general CLI architecture (project layout, exit codes, signal handling, I/O patterns), see `samber/cc-skills-golang@golang-cli`.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s173arkhs3131fq5jf769qq75583hdgt:golang-spf13-cobra","sourceUrl":"https://clawhub.ai/samber/golang-spf13-cobra","homepage":"https://clawhub.ai/samber/skills/golang-spf13-cobra","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/samber/golang-spf13-cobra","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/samber/skills/golang-spf13-cobra","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"golang-spf13-cobra technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T14:31:24.676Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T14:31:24.676Z","emptyReason":null},"stars":null,"forks":null,"downloads":1049,"packageName":null,"latestVersion":"1.1.0","tractionLabel":"1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T14:31:24.609Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T14:31:24.676Z","lastCrawledAt":"2026-10-11T14:31:24.609Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T14:31:24.609Z","lastVerifiedAt":null,"highlights":[{"version":"1.1.0","createdAt":"2026-08-23T01:33:33.168Z","changelog":"- Added explicit compatibility and navigation guidance for Go package and symbol documentation, referencing the `golang-pkg-go-dev` and `golang-gopls` skills. - Updated compatibility section to mention Codex and similar harnesses (not just Claude Code). - Expanded allowed tools, adding support for Bash(godig:*), Bash(gopls:*), LSP, and gopls MCP tools. - Introduced a `paths` section to scope skill application to `**/*.go`. - Bumped version to 1.1.0 and removed the obsolete `skill-card.md` file.","fileCount":9,"zipByteSize":19649},{"version":"1.0.1","createdAt":"2026-05-23T20:02:58.665Z","changelog":"- Version bump to 1.0.1 (metadata updated). - No functional or instructional changes to content. - Updated internal version identifiers for clarity and consistency.","fileCount":9,"zipByteSize":19508},{"version":"1.0.0","createdAt":"2026-05-01T11:57:11.150Z","changelog":"golang-spf13-cobra v1.0.0 - Initial release providing comprehensive documentation and usage patterns for spf13/cobra in Go CLI projects. - Covers command tree structure, RunE vs Run hooks, PersistentPreRunE chaining, args validators, persistent vs local flags, command groups, and shell completions. - Includes guidelines for integrating cobra with viper, testing command handlers, and best practices for CLI application design. - Lists official resources and references for further learning. - Designed for Go developers creating or reviewing CLI apps using cobra.","fileCount":8,"zipByteSize":18176}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s173arkhs3131fq5jf769qq75583hdgt:golang-spf13-cobra","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s173arkhs3131fq5jf769qq75583hdgt:golang-spf13-cobra` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/samber/golang-spf13-cobra before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-spf13-cobra/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-spf13-cobra/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-spf13-cobra/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-spf13-cobra/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-spf13-cobra/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-spf13-cobra/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T17:46:31.038Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-spf13-cobra/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-spf13-cobra/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-spf13-cobra/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-spf13-cobra/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T14:31:24.676Z","emptyReason":null},"readme":"Skill: golang-spf13-cobra\n\nOwner: samber\n\nSummary: 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 configuration layering alongside cobra, see the `samber/cc-skills-golang@golang-spf13-viper` skill. For general CLI architecture (project layout, exit codes, signal handling, I/O patterns), see `samber/cc-skills-golang@golang-cli`.\n\nTags: latest:1.1.0\n\nVersion history:\n\nv1.1.0 | 2026-08-23T01:33:33.168Z | auto\n\n- Added explicit compatibility and navigation guidance for Go package and symbol documentation, referencing the `golang-pkg-go-dev` and `golang-gopls` skills.\n- Updated compatibility section to mention Codex and similar harnesses (not just Claude Code).\n- Expanded allowed tools, adding support for Bash(godig:*), Bash(gopls:*), LSP, and gopls MCP tools.\n- Introduced a `paths` section to scope skill application to `**/*.go`.\n- Bumped version to 1.1.0 and removed the obsolete `skill-card.md` file.\n\nv1.0.1 | 2026-05-23T20:02:58.665Z | auto\n\n- Version bump to 1.0.1 (metadata updated).\n- No functional or instructional changes to content.\n- Updated internal version identifiers for clarity and consistency.\n\nv1.0.0 | 2026-05-01T11:57:11.150Z | auto\n\ngolang-spf13-cobra v1.0.0\n\n- Initial release providing comprehensive documentation and usage patterns for spf13/cobra in Go CLI projects.\n- Covers command tree structure, RunE vs Run hooks, PersistentPreRunE chaining, args validators, persistent vs local flags, command groups, and shell completions.\n- Includes guidelines for integrating cobra with viper, testing command handlers, and best practices for CLI application design.\n- Lists official resources and references for further learning.\n- Designed for Go developers creating or reviewing CLI apps using cobra.\n\nArchive index:\n\nArchive v1.1.0: 9 files, 19649 bytes\n\nFiles: evals/evals.json (19592b), references/commands-and-args.md (5009b), references/completions.md (4007b), references/flags.md (3921b), references/generators.md (2266b), references/testing.md (3800b), skill-card.md (2557b), SKILL.md (10432b), _meta.json (137b)\n\nFile v1.1.0:SKILL.md\n\n---\nname: golang-spf13-cobra\ndescription: \"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 configuration layering alongside cobra, see the `samber/cc-skills-golang@golang-spf13-viper` skill. For general CLI architecture (project layout, exit codes, signal handling, I/O patterns), see `samber/cc-skills-golang@golang-cli`.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.1.0\"\n  openclaw:\n    emoji: \"🐍\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n    install: []\n    skill-library-version: \"1.10.2\"\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs Bash(godig:*) Bash(gopls:*) LSP mcp__gopls__*\npaths:\n  - \"**/*.go\"\n---\n\n**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.\n\n**Modes:**\n\n- **Build** — creating a new CLI from scratch: follow command tree setup, hook wiring, and flag sections sequentially.\n- **Extend** — adding subcommands, flags, or completions to an existing CLI: read the current command tree first, then apply changes consistent with the existing structure.\n- **Review** — auditing an existing CLI: check the Common Mistakes table, verify `RunE` usage, `OutOrStdout()`, hook chain ordering, and args validation.\n\n# Using spf13/cobra for CLI command trees in Go\n\nCobra 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.\n\n**Official Resources:**\n\n- [pkg.go.dev/github.com/spf13/cobra](https://pkg.go.dev/github.com/spf13/cobra)\n- [github.com/spf13/cobra](https://github.com/spf13/cobra)\n- [cobra.dev](https://cobra.dev)\n\nThis 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.\n\n```bash\ngo get github.com/spf13/cobra@latest\n```\n\n## Cobra vs. viper\n\nThese libraries do fundamentally different things and can be used independently.\n\n| Concern | cobra | viper |\n| --- | --- | --- |\n| Owns | Command tree, flags, arg validation, completions | Configuration value resolution |\n| User-facing? | Yes — subcommands, flags, help text | No — purely a key-value resolver |\n| Without the other? | Yes — a CLI with flags only needs cobra | Yes — a daemon reading YAML + env needs only viper |\n| Integration seam | Hands `pflag.Flag` to viper via `BindPFlag` | Treats the cobra flag as the highest-precedence layer |\n\n**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.\n\n→ See `samber/cc-skills-golang@golang-spf13-viper` for the viper side of this integration.\n\n## Command tree\n\nEvery cobra CLI has a root command plus zero or more subcommands registered with `AddCommand`. The root command name is the binary name.\n\n```go\nvar rootCmd = &cobra.Command{\n    Use:          \"myapp\",\n    Short:        \"One-line summary\",\n    SilenceUsage: true,  // ✓ prevents usage wall on every error\n    SilenceErrors: true, // ✓ lets you control error output format\n}\n```\n\nUse `AddGroup` to label subcommands in help output — register groups **before** the `AddCommand` calls that reference them; cobra does not retroactively assign groups.\n\n## The Run\\* family\n\nCobra commands have five run hooks executed in order:\n\n```\nPersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE\n```\n\nAlways use `*E` variants — the non-`E` forms cannot return errors. Key rules:\n\n- `PersistentPreRunE` on the root runs before **every** subcommand — use it for config init and auth checks.\n- A child `PersistentPreRunE` **replaces** the parent's entirely — call the parent explicitly if you need both.\n- `PostRunE` runs only if `RunE` succeeded.\n\nFor the full lifecycle and inheritance rules, see [commands-and-args.md](references/commands-and-args.md).\n\n## Args validators\n\nCobra validates positional arguments before `RunE` runs. Never write `len(args)` checks inside `RunE` — that bypasses cobra's standard error messages and arg count tracking.\n\nBuilt-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`.\n\nFor the full validator set with examples and `MatchAll` patterns, see [commands-and-args.md](references/commands-and-args.md).\n\n## Flags primer\n\nCobra delegates flag parsing to `pflag`. **Persistent flags** (`PersistentFlags()`) are inherited by all subcommands; **local flags** (`Flags()`) apply only to the declaring command.\n\n```go\nrootCmd.PersistentFlags().StringVar(&cfgFile, \"config\", \"\", \"config file path\") // inherited by all subcommands\nserveCmd.Flags().IntVar(&port, \"port\", 8080, \"listen port\")                     // local to serveCmd only\nserveCmd.MarkFlagRequired(\"port\")\nserveCmd.MarkFlagsMutuallyExclusive(\"json\", \"yaml\")\n```\n\nFor pflag types, custom flag values, flag groups, and viper binding, see [flags.md](references/flags.md).\n\n## Completions primer\n\nCobra generates shell completions automatically. Extend them with:\n\n- **`ValidArgs []string`** — static positional arg completion.\n- **`ValidArgsFunction`** — dynamic: `func(cmd, args, toComplete string) ([]string, ShellCompDirective)`. Return `ShellCompDirectiveNoFileComp` to suppress file fallback.\n- **`RegisterFlagCompletionFunc(name, fn)`** — flag value completion.\n\nFor `ShellCompDirective` values, annotations, and testing, see [completions.md](references/completions.md).\n\n## Testing commands\n\nTest 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.\n\n```go\nfunc TestServeCmd(t *testing.T) {\n    buf := new(bytes.Buffer)\n    rootCmd.SetOut(buf)\n    rootCmd.SetArgs([]string{\"serve\", \"--port\", \"9090\"})\n    require.NoError(t, rootCmd.Execute())\n    assert.Contains(t, buf.String(), \"listening on :9090\")\n}\n```\n\nCobra accumulates flag state across `Execute()` calls — build a fresh command tree per test. For isolation patterns, golden files, and testing completions, see [testing.md](references/testing.md).\n\n## Best Practices\n\n1. **Always use `RunE`, never `Run`** — `Run` cannot return an error; the only escape is `os.Exit` or panic, bypassing defers.\n2. **Put config initialization in `PersistentPreRunE`** — it runs before every subcommand; the right place for viper binding and auth checks.\n3. **Validate positional args with `Args`, not inside `RunE`** — `Args` gives cobra's standard error messages; `MatchAll` composes validators.\n4. **Use `cmd.OutOrStdout()` / `cmd.ErrOrStderr()` for all output** — direct `os.Stdout` writes cannot be captured by tests.\n5. **Re-create the command tree per test** — cobra accumulates flag state across `Execute()` calls on the same instance.\n\n## Common Mistakes\n\n| Mistake | Why it fails | Fix |\n| --- | --- | --- |\n| 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 |\n| Writing `len(args)` checks in `RunE` | Bypasses cobra's standard error messages (\"accepts 1 arg, received 2\") | Declare `Args: cobra.ExactArgs(1)` on the command |\n| Writing to `os.Stdout` directly | Tests cannot capture output — os-level file handles can't be redirected | Use `cmd.OutOrStdout()` / `cmd.ErrOrStderr()` |\n| Child `PersistentPreRunE` silently drops parent's | Cobra does not chain — the child replaces the parent's hook entirely | Call `parent.PersistentPreRunE(cmd, args)` from the child's hook |\n| Reusing a root command across tests | Cobra accumulates flag state; second `Execute()` sees flags from the first | Build a fresh command tree per test |\n\n## Further Reading\n\n- [commands-and-args.md](references/commands-and-args.md) — full PreRun\\*/PostRun\\* chain, every Args validator, PersistentPreRunE inheritance rules\n- [flags.md](references/flags.md) — pflag types, required/exclusive/oneRequired groups, custom value types, viper binding\n- [completions.md](references/completions.md) — ShellCompDirective set, annotation-based completions, testing completions\n- [generators.md](references/generators.md) — man page, markdown, YAML, RST doc generation; `cobra-cli` scaffolder\n- [testing.md](references/testing.md) — isolation patterns, golden files, testing completions, table-driven command tests\n\n## Cross-References\n\n- → See `samber/cc-skills-golang@golang-cli` skill for general CLI architecture — project layout, exit codes, signal handling, I/O patterns\n- → See `samber/cc-skills-golang@golang-spf13-viper` skill for configuration layering alongside cobra (flag → env → file → default precedence)\n- → See `samber/cc-skills-golang@golang-testing` skill for general Go testing patterns\n\nIf you encounter a bug or unexpected behavior in spf13/cobra, open an issue at <https://github.com/spf13/cobra/issues>.\n\nFile v1.1.0:_meta.json\n\n{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-spf13-cobra\",\n  \"version\": \"1.1.0\",\n  \"publishedAt\": 1787448813168\n}\n\nFile v1.1.0:references/commands-and-args.md\n\n# Cobra Commands, Hooks, and Args Validators\n\n## The Run\\* lifecycle\n\nCobra commands have five run hooks. Cobra executes them in this fixed order:\n\n```\nPersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE\n```\n\nEach `*E` hook returns `error`. The non-`*E` variants (`PersistentPreRun`, `PreRun`, `Run`, `PostRun`, `PersistentPostRun`) have signature `func(cmd *cobra.Command, args []string)` — they cannot signal failure without `os.Exit` or panic. **Always use the `*E` variants.**\n\n### Which hook to use\n\n| Hook | Scope | When to use |\n| --- | --- | --- |\n| `PersistentPreRunE` | Parent + all descendants | Config init, auth check, telemetry setup — must run before every subcommand |\n| `PreRunE` | This command only | Validation that runs only for this command before `RunE` |\n| `RunE` | This command only | Main handler — the primary business logic |\n| `PostRunE` | This command only | Cleanup that runs only if `RunE` succeeded |\n| `PersistentPostRunE` | Parent + all descendants | Global cleanup (close connections, flush buffers) |\n\n### Inheritance rules\n\n`PersistentPreRunE` defined on the root command runs before every subcommand. But if a child command defines **its own** `PersistentPreRunE`, it **replaces** (does not chain) the parent's hook. Call the parent explicitly if you need both:\n\n```go\nvar childCmd = &cobra.Command{\n    PersistentPreRunE: func(cmd *cobra.Command, args []string) error {\n        // call parent's hook first\n        if err := rootCmd.PersistentPreRunE(cmd, args); err != nil {\n            return err\n        }\n        // child-specific logic\n        return nil\n    },\n}\n```\n\n### Execution stops on first error\n\nIf `PersistentPreRunE` returns an error, cobra stops — `RunE` and later hooks never run. Use this for fail-fast auth checks.\n\n## Args validators\n\nArgs validators run before `RunE`. Cobra prints a clear error message and exits without calling `RunE` when validation fails.\n\n### Built-in validators\n\n```go\ncobra.NoArgs                        // fails if any positional args provided\ncobra.ArbitraryArgs                 // accepts any number of args (default)\ncobra.ExactArgs(n int)              // requires exactly n args\ncobra.MinimumNArgs(n int)           // requires at least n args\ncobra.MaximumNArgs(n int)           // requires at most n args\ncobra.RangeArgs(min, max int)       // requires between min and max args\ncobra.OnlyValidArgs                 // all args must be in ValidArgs list\ncobra.ExactValidArgs(n int)         // exactly n args, all in ValidArgs\n```\n\n### Composing validators with MatchAll\n\n```go\nvar deleteCmd = &cobra.Command{\n    Use:       \"delete <resource>\",\n    Args:      cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),\n    ValidArgs: []string{\"pod\", \"service\", \"deployment\"},\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return doDelete(args[0])\n    },\n}\n```\n\n### Custom validators\n\nSignature: `func(cmd *cobra.Command, args []string) error`\n\n```go\nfunc validatePositiveInt(cmd *cobra.Command, args []string) error {\n    if len(args) != 1 {\n        return fmt.Errorf(\"requires exactly 1 arg, got %d\", len(args))\n    }\n    n, err := strconv.Atoi(args[0])\n    if err != nil || n <= 0 {\n        return fmt.Errorf(\"argument must be a positive integer, got %q\", args[0])\n    }\n    return nil\n}\n\nvar cmd = &cobra.Command{\n    Args: validatePositiveInt,\n    RunE: func(cmd *cobra.Command, args []string) error { /* ... */ },\n}\n```\n\nCombine custom validators with built-in ones using `MatchAll`:\n\n```go\nArgs: cobra.MatchAll(cobra.MinimumNArgs(1), validateAllPositive),\n```\n\n## Command registration and ordering\n\n```go\nfunc init() {\n    // groups must be registered before AddCommand\n    rootCmd.AddGroup(&cobra.Group{ID: \"core\", Title: \"Core Commands:\"})\n    rootCmd.AddGroup(&cobra.Group{ID: \"management\", Title: \"Management Commands:\"})\n\n    serveCmd.GroupID = \"core\"\n    migrateCmd.GroupID = \"management\"\n\n    rootCmd.AddCommand(serveCmd, migrateCmd, versionCmd)\n}\n```\n\n`versionCmd` has no `GroupID` — it appears in the default section.\n\n## Annotations\n\nCobra supports arbitrary command annotations for framework-level metadata:\n\n```go\nvar serveCmd = &cobra.Command{\n    Annotations: map[string]string{\n        \"category\": \"network\",\n        \"requires-auth\": \"true\",\n    },\n}\n\n// read in a middleware hook:\nif serveCmd.Annotations[\"requires-auth\"] == \"true\" {\n    // enforce auth\n}\n```\n\n## Hidden and deprecated commands\n\n```go\nvar internalCmd = &cobra.Command{\n    Hidden: true,      // not shown in help, still executable\n}\n\nvar oldCmd = &cobra.Command{\n    Deprecated: \"use `newcmd` instead\",  // shown in help, prints warning on use\n}\n```\n\n## cobra.CheckErr\n\n`cobra.CheckErr(err)` is a convenience function: if `err != nil`, it prints the error to `cmd.ErrOrStderr()` and calls `os.Exit(1)`. Use it only in `main()` where you want a hard exit — not inside `RunE` where returning the error is preferred.\n\n```go\nfunc main() {\n    cobra.CheckErr(rootCmd.Execute())\n}\n```\n\nFile v1.1.0:references/completions.md\n\n# Cobra Shell Completions Reference\n\nCobra generates shell completion scripts for bash, zsh, fish, and PowerShell automatically. Subcommand names and flag names are completed for free. You add completions for flag values and positional arguments.\n\n## Built-in completion command\n\nCobra registers a `completion` subcommand automatically:\n\n```bash\nmyapp completion bash   # generate bash script\nmyapp completion zsh    # generate zsh script\nmyapp completion fish   # generate fish script\nmyapp completion powershell\n\n# Install (example for zsh):\nmyapp completion zsh > \"${fpath[1]}/_myapp\"\n```\n\n## ShellCompDirective\n\nThe `ShellCompDirective` controls shell behavior after your completion function returns:\n\n| Directive | Meaning |\n| --- | --- |\n| `ShellCompDirectiveDefault` | Fall back to file completion after your results |\n| `ShellCompDirectiveNoFileComp` | Disable file completion fallback |\n| `ShellCompDirectiveNoSpace` | Don't add a space after the completion |\n| `ShellCompDirectiveFilterFileExt(exts)` | Only show files with given extensions |\n| `ShellCompDirectiveFilterDirs(dirs)` | Only show directories |\n| `ShellCompDirectiveError` | Signal an error (show no completions) |\n\nCombine with bitwise OR: `cobra.ShellCompDirectiveNoFileComp | cobra.ShellCompDirectiveNoSpace`.\n\nUse `ShellCompDirectiveNoFileComp` whenever your list is exhaustive — it prevents the shell from appending irrelevant files.\n\n## Static arg completions\n\n```go\nvar getCmd = &cobra.Command{\n    Use:       \"get <resource>\",\n    ValidArgs: []string{\"pod\", \"service\", \"deployment\", \"configmap\"},\n    Args:      cobra.OnlyValidArgs,\n    RunE: func(cmd *cobra.Command, args []string) error { /* ... */ },\n}\n```\n\n## Dynamic arg completions\n\n```go\nvar getCmd = &cobra.Command{\n    ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        if len(args) > 0 {\n            // first arg already provided — no more completions\n            return nil, cobra.ShellCompDirectiveNoFileComp\n        }\n        resources, err := listResources(toComplete)\n        if err != nil {\n            return nil, cobra.ShellCompDirectiveError\n        }\n        return resources, cobra.ShellCompDirectiveNoFileComp\n    },\n}\n```\n\n`toComplete` is the prefix the user has typed so far — filter your results by it for responsive completions.\n\n## Flag value completions\n\n```go\nfunc init() {\n    rootCmd.RegisterFlagCompletionFunc(\"output\", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        return []string{\"json\\tJSON output\", \"yaml\\tYAML output\", \"table\\tTable output\"}, cobra.ShellCompDirectiveNoFileComp\n    })\n\n    rootCmd.RegisterFlagCompletionFunc(\"namespace\", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        ns, err := listNamespaces()\n        if err != nil {\n            return nil, cobra.ShellCompDirectiveError\n        }\n        return ns, cobra.ShellCompDirectiveNoFileComp\n    })\n}\n```\n\nDescriptions after `\\t` are shown in zsh and fish menus.\n\n## Completion annotations\n\nMark a flag to complete as a file or directory:\n\n```go\ncmd.Flags().String(\"config\", \"\", \"config file\")\ncmd.MarkFlagFilename(\"config\", \"yaml\", \"yml\", \"json\")  // only those extensions\n\ncmd.Flags().String(\"dir\", \"\", \"output directory\")\ncmd.MarkFlagDirname(\"dir\")\n```\n\n## Testing completions\n\n```go\nfunc TestCompletion(t *testing.T) {\n    rootCmd.SetArgs([]string{\"__complete\", \"get\", \"\"})\n    buf := new(bytes.Buffer)\n    rootCmd.SetOut(buf)\n    rootCmd.Execute()\n    assert.Contains(t, buf.String(), \"pod\")\n    assert.Contains(t, buf.String(), \"service\")\n}\n```\n\n`__complete` is cobra's internal completion request verb. Pass the partial args as additional arguments.\n\n## Disabling the completion command\n\n```go\nrootCmd.CompletionOptions.DisableDefaultCmd = true   // remove the completion subcommand\nrootCmd.CompletionOptions.HiddenDefaultCmd = true    // keep it but hide from help\n```\n\nFile v1.1.0:references/flags.md\n\n# Cobra Flags Reference\n\nCobra delegates all flag parsing to `github.com/spf13/pflag`. `cobra.Command` exposes two `*pflag.FlagSet`s:\n\n- `cmd.Flags()` — local flags, only available on this command.\n- `cmd.PersistentFlags()` — inherited by all subcommands.\n\n## Common flag types\n\n```go\n// String\ncmd.Flags().String(\"name\", \"default\", \"description\")\ncmd.Flags().StringP(\"name\", \"n\", \"default\", \"description\")  // with shorthand\n\n// With pointer binding (no Lookup needed later)\nvar name string\ncmd.Flags().StringVar(&name, \"name\", \"default\", \"description\")\ncmd.Flags().StringVarP(&name, \"name\", \"n\", \"default\", \"description\")\n\n// Other types follow the same pattern:\ncmd.Flags().Int / IntVar / IntVarP\ncmd.Flags().Bool / BoolVar / BoolVarP\ncmd.Flags().Float64 / Float64Var\ncmd.Flags().Duration / DurationVar       // parses \"1h30m\", \"500ms\"\ncmd.Flags().StringSlice / StringSliceVar // comma-separated or repeated flags\ncmd.Flags().StringArray / StringArrayVar // repeated flags only (no comma splitting)\ncmd.Flags().IntSlice / IntSliceVar\ncmd.Flags().StringToString                // --label key=value --label k2=v2\n```\n\n## StringSlice vs StringArray\n\n| Flag type     | Input                 | Result                            |\n| ------------- | --------------------- | --------------------------------- |\n| `StringSlice` | `--tags a,b --tags c` | `[\"a\", \"b\", \"c\"]` — commas split  |\n| `StringArray` | `--tags a,b --tags c` | `[\"a,b\", \"c\"]` — commas NOT split |\n\nUse `StringArray` when values may legitimately contain commas.\n\n## Flag constraints\n\n```go\n// Fail if flag not provided\ncmd.MarkFlagRequired(\"output\")\n\n// Fail if both provided\ncmd.MarkFlagsMutuallyExclusive(\"json\", \"yaml\", \"table\")\n\n// Fail if none provided\ncmd.MarkFlagsOneRequired(\"file\", \"stdin\")\n\n// Require flag only if another flag is set\ncmd.MarkFlagsMutuallyExclusive(\"tls\", \"no-tls\")\n```\n\n## Persistent flag patterns\n\n```go\nfunc init() {\n    // global flags on root\n    rootCmd.PersistentFlags().StringVar(&cfgFile, \"config\", \"\", \"config file (default: $HOME/.myapp.yaml)\")\n    rootCmd.PersistentFlags().StringVar(&logLevel, \"log-level\", \"info\", \"log level (debug, info, warn, error)\")\n\n    // bind to viper immediately after defining\n    viper.BindPFlag(\"config\", rootCmd.PersistentFlags().Lookup(\"config\"))\n    viper.BindPFlag(\"log-level\", rootCmd.PersistentFlags().Lookup(\"log-level\"))\n}\n```\n\n## Custom flag value types\n\nImplement `pflag.Value` to parse arbitrary types:\n\n```go\ntype enumValue struct {\n    val     string\n    allowed []string\n}\n\nfunc (e *enumValue) String() string { return e.val }\nfunc (e *enumValue) Type() string   { return \"enum\" }\nfunc (e *enumValue) Set(s string) error {\n    for _, a := range e.allowed {\n        if s == a {\n            e.val = s\n            return nil\n        }\n    }\n    return fmt.Errorf(\"must be one of %v\", e.allowed)\n}\n\nvar outputFmt = &enumValue{val: \"table\", allowed: []string{\"table\", \"json\", \"yaml\"}}\ncmd.Flags().Var(outputFmt, \"output\", \"output format (table, json, yaml)\")\n```\n\n## Flag groups (required together)\n\nMark a set of flags that must all be provided if any one of them is provided:\n\n```go\ncmd.Flags().String(\"tls-cert\", \"\", \"TLS certificate file\")\ncmd.Flags().String(\"tls-key\", \"\", \"TLS key file\")\ncmd.MarkFlagsRequiredTogether(\"tls-cert\", \"tls-key\")\n```\n\n## Accessing flag values\n\nPrefer pointer binding (`StringVar`, `IntVar`, etc.) for type-safe access. When you need the flag post-parse:\n\n```go\nport, err := cmd.Flags().GetInt(\"port\")\nname, err := cmd.Flags().GetString(\"name\")\ntags, err := cmd.Flags().GetStringSlice(\"tags\")\n```\n\n## Flag changed vs default\n\n```go\nif cmd.Flags().Changed(\"port\") {\n    // user explicitly provided --port\n    // useful when distinguishing \"user set 0\" from \"flag not provided\"\n}\n```\n\n`Changed()` is also how viper knows which flags are explicit overrides — it only promotes a flag to the highest precedence layer if `Changed()` is true.\n\nFile v1.1.0:references/generators.md\n\n# Cobra Documentation and Scaffolding Generators\n\n## Doc generation\n\nCobra can generate documentation from your command tree in multiple formats. Import the `cobra/doc` sub-package:\n\n```bash\ngo get github.com/spf13/cobra/doc\n```\n\n### Markdown\n\n```go\nimport \"github.com/spf13/cobra/doc\"\n\nerr := doc.GenMarkdownTree(rootCmd, \"/tmp/docs/\")\n// generates /tmp/docs/myapp.md, /tmp/docs/myapp_serve.md, etc.\n\n// Single command\nvar buf bytes.Buffer\ndoc.GenMarkdown(rootCmd, &buf)\n```\n\n### Man pages\n\n```go\nheader := &doc.GenManHeader{\n    Title:   \"MYAPP\",\n    Section: \"1\",\n    Date:    &time.Time{},\n    Source:  \"myapp v1.0.0\",\n    Manual:  \"User Commands\",\n}\nerr := doc.GenManTree(rootCmd, header, \"/usr/local/share/man/man1/\")\n```\n\n### YAML\n\n```go\nerr := doc.GenYamlTree(rootCmd, \"/tmp/docs/\")\n```\n\n### RST (reStructuredText)\n\n```go\nerr := doc.GenReSTTree(rootCmd, \"/tmp/docs/\")\n```\n\n## cobra-cli scaffolder\n\n`cobra-cli` generates command files and wires them into your project:\n\n```bash\ngo get -tool github.com/spf13/cobra-cli@latest\n\n# Initialize a new cobra project\ngo tool cobra-cli init myapp\n\n# Add a subcommand\ngo tool cobra-cli add serve\ngo tool cobra-cli add migrate\n\n# Add with a parent other than root\ncobra-cli add list --parent serve\n```\n\nGenerated files follow the standard pattern:\n\n```go\n// cmd/serve.go\nvar serveCmd = &cobra.Command{\n    Use:   \"serve\",\n    Short: \"A brief description of your command\",\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return nil\n    },\n}\n\nfunc init() {\n    rootCmd.AddCommand(serveCmd)\n}\n```\n\n`cobra-cli` is optional — many teams write command files by hand following the same pattern.\n\n## Help and usage template customization\n\nOverride the default help template:\n\n```go\nrootCmd.SetHelpTemplate(`\nUsage:  {{.UseLine}}\n{{if .HasAvailableSubCommands}}\nCommands:\n{{range .Commands}}{{if .IsAvailableCommand}}  {{rpad .Name .NamePadding }} {{.Short}}\n{{end}}{{end}}{{end}}\nFlags:\n{{.LocalFlags.FlagUsages | trimRightSpace}}\n`)\n```\n\nOverride the usage function entirely:\n\n```go\nrootCmd.SetUsageFunc(func(cmd *cobra.Command) error {\n    fmt.Fprintf(cmd.OutOrStdout(), \"Custom usage for %s\\n\", cmd.Name())\n    return nil\n})\n```\n\nCommon template functions available: `rpad`, `trimRightSpace`, `gt`, `eq`.\n\nFile v1.1.0:references/testing.md\n\n# Testing Cobra Commands\n\n## Basic test pattern\n\n```go\nfunc TestServeCmd(t *testing.T) {\n    stdout := new(bytes.Buffer)\n    stderr := new(bytes.Buffer)\n\n    rootCmd.SetOut(stdout)\n    rootCmd.SetErr(stderr)\n    rootCmd.SetArgs([]string{\"serve\", \"--port\", \"9090\", \"--dry-run\"})\n\n    err := rootCmd.Execute()\n    require.NoError(t, err)\n    assert.Contains(t, stdout.String(), \"listening on :9090\")\n    assert.Empty(t, stderr.String())\n}\n```\n\n## Isolation between tests\n\nCobra accumulates flag state across `Execute()` calls on the same command instance. Tests must be isolated.\n\n### Option 1: Re-create the command tree per test (recommended for unit tests)\n\n```go\nfunc newRootCmd() *cobra.Command {\n    root := &cobra.Command{Use: \"myapp\", SilenceUsage: true, SilenceErrors: true}\n    root.AddCommand(newServeCmd())\n    return root\n}\n\nfunc TestServeCmd(t *testing.T) {\n    root := newRootCmd()\n    root.SetArgs([]string{\"serve\", \"--port\", \"9090\"})\n    err := root.Execute()\n    require.NoError(t, err)\n}\n```\n\n### Option 2: Reset flags between tests\n\n```go\nfunc TestWithReset(t *testing.T) {\n    t.Cleanup(func() {\n        rootCmd.ResetFlags()\n        // re-define flags if needed\n    })\n}\n```\n\nRe-creating is safer — `ResetFlags` only clears the flag set, not subcommand state.\n\n## Testing commands that write output\n\nCommands must use `cmd.OutOrStdout()` / `cmd.ErrOrStderr()` instead of `os.Stdout` / `os.Stderr` for this to work.\n\n```go\n// In command handler:\nfunc runServe(cmd *cobra.Command, args []string) error {\n    fmt.Fprintln(cmd.OutOrStdout(), \"Server started\")\n    fmt.Fprintln(cmd.ErrOrStderr(), \"Debug: listening on port 8080\")\n    return nil\n}\n\n// In test:\nbuf := new(bytes.Buffer)\nrootCmd.SetOut(buf)\nrootCmd.Execute()\nassert.Contains(t, buf.String(), \"Server started\")\n```\n\n## Golden file tests\n\nFor commands with structured or lengthy output, use golden files:\n\n```go\nfunc TestOutputFormat(t *testing.T) {\n    buf := new(bytes.Buffer)\n    rootCmd.SetOut(buf)\n    rootCmd.SetArgs([]string{\"list\", \"--output\", \"json\"})\n    require.NoError(t, rootCmd.Execute())\n\n    golden := \"testdata/list-json.golden\"\n    if *update {  // -update flag\n        os.WriteFile(golden, buf.Bytes(), 0644)\n    }\n    want, _ := os.ReadFile(golden)\n    assert.Equal(t, string(want), buf.String())\n}\n```\n\nRun with `-update` to regenerate golden files after intentional output changes.\n\n## Testing error paths\n\n```go\nfunc TestInvalidArgs(t *testing.T) {\n    stderr := new(bytes.Buffer)\n    rootCmd.SetErr(stderr)\n    rootCmd.SetArgs([]string{\"delete\"})  // missing required arg\n\n    err := rootCmd.Execute()\n    assert.Error(t, err)\n    assert.Contains(t, err.Error(), \"accepts 1 arg\")\n}\n```\n\n## Table-driven command tests\n\n```go\ntests := []struct {\n    name    string\n    args    []string\n    wantOut string\n    wantErr bool\n}{\n    {\"no flags\", []string{\"serve\"}, \"listening on :8080\", false},\n    {\"custom port\", []string{\"serve\", \"--port\", \"9090\"}, \"listening on :9090\", false},\n    {\"invalid port\", []string{\"serve\", \"--port\", \"abc\"}, \"\", true},\n}\n\nfor _, tt := range tests {\n    t.Run(tt.name, func(t *testing.T) {\n        root := newRootCmd()  // fresh command tree per test\n        buf := new(bytes.Buffer)\n        root.SetOut(buf)\n        root.SetArgs(tt.args)\n        err := root.Execute()\n        if tt.wantErr {\n            assert.Error(t, err)\n        } else {\n            require.NoError(t, err)\n            assert.Contains(t, buf.String(), tt.wantOut)\n        }\n    })\n}\n```\n\n## Testing completions\n\n```go\nfunc TestCompletion(t *testing.T) {\n    root := newRootCmd()\n    buf := new(bytes.Buffer)\n    root.SetOut(buf)\n    root.SetArgs([]string{\"__complete\", \"delete\", \"\"})\n    root.Execute()\n\n    assert.Contains(t, buf.String(), \"pod\")\n    assert.Contains(t, buf.String(), \"service\")\n}\n```\n\nFile v1.1.0:skill-card.md\n\n## Description:\n\nGuides agents working on Go command-line applications that use spf13/cobra, including command trees, RunE hooks, argument validators, flags, completions, documentation generation, and test patterns.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[samber](https://clawhub.ai/user/samber)\n\n### License/Terms of Use:\n\nMIT\n\n## Use Case:\n\nDevelopers and engineering agents use this skill to build, extend, or review Go CLIs that use spf13/cobra. It helps produce idiomatic command definitions, argument validation, flag handling, completions, generated docs, and testable command handlers.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Generated Go module or tool installation commands may use latest third-party versions.\n\nMitigation: Pin Go module and tool versions, then review `go.mod` and `go.sum` changes before committing or deploying.\n\nRisk: Scaffolding or generated commands can modify project files in ways that affect CLI behavior.\n\nMitigation: Run commands in normal project directories without elevated privileges and review the resulting diffs and tests.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/samber/skills/golang-spf13-cobra)\n- [Publisher profile](https://clawhub.ai/user/samber)\n- [Skill homepage](https://github.com/samber/cc-skills-golang)\n- [Cobra package documentation](https://pkg.go.dev/github.com/spf13/cobra)\n- [Cobra GitHub repository](https://github.com/spf13/cobra)\n- [Cobra documentation site](https://cobra.dev)\n- [Cobra commands, hooks, and args validators](references/commands-and-args.md)\n- [Cobra flags reference](references/flags.md)\n- [Cobra shell completions reference](references/completions.md)\n- [Cobra documentation and scaffolding generators](references/generators.md)\n- [Testing Cobra commands](references/testing.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with Go and shell code blocks]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May propose edits, command snippets, tests, and review findings for Go projects using spf13/cobra.]\n\n## Skill Version(s):\n\n1.1.0 (source: artifact frontmatter and ClawHub release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.1.0:evals/evals.json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"rune-vs-run-error-propagation\",\n    \"description\": \"Tests use of RunE instead of Run for error propagation\",\n    \"prompt\": \"I'm writing a cobra subcommand in Go that calls an external API. If the API returns an error, the command should exit non-zero. Should I use Run or RunE?\",\n    \"trap\": \"Without the skill, the model may say both work, suggest using Run with os.Exit(1), or not explain why Run is problematic. The correct answer is always RunE — it propagates the error through cobra's error handling chain.\",\n    \"assertions\": [\n      { \"id\": \"1.1\", \"text\": \"Recommends RunE, not Run\" },\n      {\n        \"id\": \"1.2\",\n        \"text\": \"Explains that Run cannot return an error — you'd need os.Exit or panic\"\n      },\n      {\n        \"id\": \"1.3\",\n        \"text\": \"Shows RunE returning the error from the handler\"\n      },\n      { \"id\": \"1.4\", \"text\": \"Does NOT suggest using os.Exit inside RunE\" },\n      {\n        \"id\": \"1.5\",\n        \"text\": \"Mentions that returning error from RunE causes cobra to exit non-zero\"\n      }\n    ]\n  },\n  {\n    \"id\": 2,\n    \"name\": \"args-validator-not-manual-check\",\n    \"description\": \"Tests use of cobra Args validators instead of manual len(args) checks in RunE\",\n    \"prompt\": \"I'm writing a Go CLI with cobra. My 'delete' command requires exactly one positional argument (the resource name). How should I validate this?\",\n    \"trap\": \"Without the skill, the model writes len(args) != 1 check inside RunE. The correct approach is Args: cobra.ExactArgs(1) on the command definition, which validates before RunE runs and gives a standard error message.\",\n    \"assertions\": [\n      {\n        \"id\": \"2.1\",\n        \"text\": \"Sets Args: cobra.ExactArgs(1) on the command struct\"\n      },\n      { \"id\": \"2.2\", \"text\": \"Does NOT write len(args) check inside RunE\" },\n      {\n        \"id\": \"2.3\",\n        \"text\": \"Mentions that cobra prints a standard error message when validation fails\"\n      },\n      {\n        \"id\": \"2.4\",\n        \"text\": \"RunE body accesses args[0] directly without re-validating length\"\n      }\n    ]\n  },\n  {\n    \"id\": 3,\n    \"name\": \"outOrStdout-not-os-stdout\",\n    \"description\": \"Tests use of cmd.OutOrStdout() instead of os.Stdout for testable output\",\n    \"prompt\": \"I'm writing a cobra command in Go that prints a table of results to the terminal. How should I write to stdout from inside RunE?\",\n    \"trap\": \"Without the skill, the model uses fmt.Println or os.Stdout directly. The correct approach is fmt.Fprintln(cmd.OutOrStdout(), ...) which can be redirected to a buffer in tests.\",\n    \"assertions\": [\n      { \"id\": \"3.1\", \"text\": \"Uses cmd.OutOrStdout() as the io.Writer target\" },\n      { \"id\": \"3.2\", \"text\": \"Does NOT use os.Stdout directly\" },\n      {\n        \"id\": \"3.3\",\n        \"text\": \"Does NOT use fmt.Println (which hardcodes os.Stdout)\"\n      },\n      {\n        \"id\": \"3.4\",\n        \"text\": \"Mentions testability as the reason — SetOut can redirect the writer in tests\"\n      }\n    ]\n  },\n  {\n    \"id\": 4,\n    \"name\": \"persistent-prerunE-hook-chain\",\n    \"description\": \"Tests PersistentPreRunE on root for global config init and the child override trap\",\n    \"prompt\": \"In my Go CLI with cobra, I want to initialize viper config before any subcommand runs. I also have one subcommand that needs its own PersistentPreRunE for extra setup. How do I make sure both run?\",\n    \"trap\": \"Without the skill, the model defines PersistentPreRunE on both root and child without noting that the child's hook replaces the parent's — so root's config init never runs for that subcommand.\",\n    \"assertions\": [\n      {\n        \"id\": \"4.1\",\n        \"text\": \"Explains that a child's PersistentPreRunE replaces (not chains) the parent's\"\n      },\n      {\n        \"id\": \"4.2\",\n        \"text\": \"Shows explicitly calling the parent's PersistentPreRunE from inside the child's hook\"\n      },\n      { \"id\": \"4.3\", \"text\": \"Does NOT claim both hooks run automatically\" },\n      {\n        \"id\": \"4.4\",\n        \"text\": \"Uses PersistentPreRunE (the *E variant) not PersistentPreRun\"\n      }\n    ]\n  },\n  {\n    \"id\": 5,\n    \"name\": \"silence-usage-and-errors\",\n    \"description\": \"Tests SilenceUsage and SilenceErrors on root command\",\n    \"prompt\": \"When my Go cobra CLI returns an error from RunE, the terminal shows the full usage/help text followed by the error. I only want to see the error message, not the usage. How do I fix this?\",\n    \"trap\": \"Without the skill, the model may suggest overriding SetUsageTemplate or wrapping the error. The correct fix is SilenceUsage: true on the root command.\",\n    \"assertions\": [\n      {\n        \"id\": \"5.1\",\n        \"text\": \"Sets SilenceUsage: true on the root cobra.Command\"\n      },\n      {\n        \"id\": \"5.2\",\n        \"text\": \"Optionally mentions SilenceErrors: true (for custom error formatting)\"\n      },\n      {\n        \"id\": \"5.3\",\n        \"text\": \"Does NOT suggest removing or wrapping the error in RunE\"\n      },\n      {\n        \"id\": \"5.4\",\n        \"text\": \"Explains that SilenceUsage only suppresses usage on error, not on --help\"\n      }\n    ]\n  },\n  {\n    \"id\": 6,\n    \"name\": \"command-group-registration-order\",\n    \"description\": \"Tests that AddGroup must be called before AddCommand that references it\",\n    \"prompt\": \"I want to group my cobra subcommands in the help output under labels like 'Core Commands:' and 'Management Commands:'. How do I set this up?\",\n    \"trap\": \"Without the skill, the model calls AddCommand first and AddGroup after, which doesn't work — groups must be registered before the commands that reference them.\",\n    \"assertions\": [\n      {\n        \"id\": \"6.1\",\n        \"text\": \"Calls AddGroup before AddCommand for commands that use that group\"\n      },\n      {\n        \"id\": \"6.2\",\n        \"text\": \"Sets GroupID on the subcommand matching the Group's ID field\"\n      },\n      { \"id\": \"6.3\", \"text\": \"Shows cobra.Group{ID: ..., Title: ...} struct\" },\n      {\n        \"id\": \"6.4\",\n        \"text\": \"Does NOT call AddCommand before AddGroup for the same group\"\n      }\n    ]\n  },\n  {\n    \"id\": 7,\n    \"name\": \"valid-args-function-dynamic-completion\",\n    \"description\": \"Tests ValidArgsFunction for dynamic shell completion instead of static ValidArgs\",\n    \"prompt\": \"My Go cobra 'get pod' command should complete pod names dynamically by querying the API server. ValidArgs only accepts a static list. How do I provide dynamic completions?\",\n    \"trap\": \"Without the skill, the model tries to populate ValidArgs at startup (querying the API at init time) or doesn't know about ValidArgsFunction.\",\n    \"assertions\": [\n      {\n        \"id\": \"7.1\",\n        \"text\": \"Uses ValidArgsFunction (not ValidArgs) for dynamic completions\"\n      },\n      {\n        \"id\": \"7.2\",\n        \"text\": \"Function signature returns ([]string, cobra.ShellCompDirective)\"\n      },\n      {\n        \"id\": \"7.3\",\n        \"text\": \"Returns cobra.ShellCompDirectiveNoFileComp to prevent file fallback\"\n      },\n      {\n        \"id\": \"7.4\",\n        \"text\": \"Does NOT query the API at init() or in ValidArgs (static list)\"\n      },\n      {\n        \"id\": \"7.5\",\n        \"text\": \"Handles errors by returning cobra.ShellCompDirectiveError\"\n      }\n    ]\n  },\n  {\n    \"id\": 8,\n    \"name\": \"register-flag-completion-func\",\n    \"description\": \"Tests RegisterFlagCompletionFunc for flag value completion\",\n    \"prompt\": \"My Go cobra command has an --output flag that accepts 'json', 'yaml', or 'table'. How do I make the shell complete valid values when the user types --output <TAB>?\",\n    \"trap\": \"Without the skill, the model does not know about RegisterFlagCompletionFunc and instead documents the valid values only in the flag description string.\",\n    \"assertions\": [\n      {\n        \"id\": \"8.1\",\n        \"text\": \"Calls cmd.RegisterFlagCompletionFunc(\\\"output\\\", func(...) ...)\"\n      },\n      {\n        \"id\": \"8.2\",\n        \"text\": \"The completion function returns []string{\\\"json\\\", \\\"yaml\\\", \\\"table\\\"} (or similar)\"\n      },\n      { \"id\": \"8.3\", \"text\": \"Returns cobra.ShellCompDirectiveNoFileComp\" },\n      {\n        \"id\": \"8.4\",\n        \"text\": \"Does NOT rely only on the flag usage string for user guidance\"\n      }\n    ]\n  },\n  {\n    \"id\": 9,\n    \"name\": \"test-isolation-fresh-root\",\n    \"description\": \"Tests that a fresh command tree must be created per test to avoid flag state leakage\",\n    \"prompt\": \"I'm writing tests for my Go cobra CLI. My first test runs 'myapp serve --port 9090' and passes. My second test runs 'myapp serve' without --port and expects the default 8080, but gets 9090. What's wrong and how do I fix it?\",\n    \"trap\": \"Without the skill, the model may suggest resetting the flag value manually or calling ResetFlags(). The correct fix is to create a fresh command tree per test.\",\n    \"assertions\": [\n      {\n        \"id\": \"9.1\",\n        \"text\": \"Identifies the root cause as reusing the same cobra.Command instance across tests\"\n      },\n      {\n        \"id\": \"9.2\",\n        \"text\": \"Recommends building a new command tree per test (constructor function)\"\n      },\n      {\n        \"id\": \"9.3\",\n        \"text\": \"Shows a newRootCmd() or similar factory function pattern\"\n      },\n      {\n        \"id\": \"9.4\",\n        \"text\": \"Does NOT suggest ResetFlags() as the primary solution\"\n      },\n      {\n        \"id\": \"9.5\",\n        \"text\": \"Each test calls the factory to get a fresh *cobra.Command\"\n      }\n    ]\n  },\n  {\n    \"id\": 10,\n    \"name\": \"match-all-validator-composition\",\n    \"description\": \"Tests MatchAll for composing multiple arg validators\",\n    \"prompt\": \"My Go cobra 'apply' command needs positional args that are all valid resource names (from a known list) AND there must be at least one. How do I express both constraints?\",\n    \"trap\": \"Without the skill, the model writes a custom validator function that manually checks both conditions with if statements. MatchAll composes built-in validators without custom code.\",\n    \"assertions\": [\n      { \"id\": \"10.1\", \"text\": \"Uses cobra.MatchAll to compose validators\" },\n      {\n        \"id\": \"10.2\",\n        \"text\": \"Combines cobra.MinimumNArgs(1) (or ExactArgs) with cobra.OnlyValidArgs\"\n      },\n      { \"id\": \"10.3\", \"text\": \"Sets ValidArgs with the known resource names\" },\n      {\n        \"id\": \"10.4\",\n        \"text\": \"Does NOT write a fully manual validator function for the combined check\"\n      }\n    ]\n  },\n  {\n    \"id\": 11,\n    \"name\": \"cobra-vs-viper-distinction\",\n    \"description\": \"Tests understanding of what cobra does vs what viper does\",\n    \"prompt\": \"I'm starting a Go CLI project. I need subcommands, flags, shell completions, AND the ability to read configuration from a YAML file and environment variables. I've heard of cobra and viper. Which library handles which concern?\",\n    \"trap\": \"Without the skill, the model may conflate the two or understate how they integrate. The correct answer clearly assigns cobra=command tree/flags/completions and viper=layered config resolution, with BindPFlag as the integration seam.\",\n    \"assertions\": [\n      {\n        \"id\": \"11.1\",\n        \"text\": \"Assigns cobra to command tree, flags, arg validation, shell completions\"\n      },\n      {\n        \"id\": \"11.2\",\n        \"text\": \"Assigns viper to config file, env var, and layered value resolution\"\n      },\n      {\n        \"id\": \"11.3\",\n        \"text\": \"Identifies BindPFlag (or similar) as the integration seam between them\"\n      },\n      {\n        \"id\": \"11.4\",\n        \"text\": \"Explains they can be used independently (cobra without viper, or viper without cobra)\"\n      },\n      {\n        \"id\": \"11.5\",\n        \"text\": \"Does NOT say cobra reads config files or viper defines subcommands\"\n      }\n    ]\n  },\n  {\n    \"id\": 12,\n    \"name\": \"cobra-cli-scaffolder\",\n    \"description\": \"Tests knowledge of the cobra-cli scaffolding tool\",\n    \"prompt\": \"I want to quickly scaffold a new Go CLI project with cobra. Is there a tool that generates the initial files and lets me add subcommands from the command line?\",\n    \"trap\": \"Without the skill, the model may say to create files manually or use a generic project generator. The cobra-cli tool is the canonical scaffolder for cobra projects.\",\n    \"assertions\": [\n      {\n        \"id\": \"12.1\",\n        \"text\": \"Mentions cobra-cli (github.com/spf13/cobra-cli)\"\n      },\n      {\n        \"id\": \"12.2\",\n        \"text\": \"Shows 'cobra-cli init <project>' for initialization\"\n      },\n      {\n        \"id\": \"12.3\",\n        \"text\": \"Shows 'cobra-cli add <command>' for adding subcommands\"\n      },\n      {\n        \"id\": \"12.4\",\n        \"text\": \"Explains that cobra-cli is separate from cobra itself (different import path)\"\n      }\n    ]\n  },\n  {\n    \"id\": 13,\n    \"name\": \"stringarray-vs-stringslice-commas\",\n    \"description\": \"Tests StringArray vs StringSlice when flag values contain commas\",\n    \"prompt\": \"My Go cobra CLI has a --label flag that users pass multiple times like --label 'env=prod,region=us'. With my current setup, passing --label 'env=prod,region=us' results in two separate values ['env=prod', 'region=us'] instead of one. What flag type should I use?\",\n    \"trap\": \"Without the skill, the model uses StringSlice which splits on commas. StringArray is the correct choice when values may legitimately contain commas.\",\n    \"assertions\": [\n      {\n        \"id\": \"13.1\",\n        \"text\": \"Recommends StringArray (or StringArrayVar) instead of StringSlice\"\n      },\n      {\n        \"id\": \"13.2\",\n        \"text\": \"Explains that StringSlice splits on commas while StringArray does not\"\n      },\n      {\n        \"id\": \"13.3\",\n        \"text\": \"Does NOT suggest quoting or escaping commas as the fix\"\n      },\n      {\n        \"id\": \"13.4\",\n        \"text\": \"Shows the correct flag definition using StringArray or StringArrayVar\"\n      }\n    ]\n  },\n  {\n    \"id\": 14,\n    \"name\": \"mutually-exclusive-flags\",\n    \"description\": \"Tests MarkFlagsMutuallyExclusive instead of manual RunE checks\",\n    \"prompt\": \"My Go cobra command has --json and --yaml flags for output format. Users should only be able to pass one of them. How do I prevent both from being passed at the same time?\",\n    \"trap\": \"Without the skill, the model writes an if statement checking both flags inside RunE. The correct approach is MarkFlagsMutuallyExclusive which cobra enforces at parse time before RunE.\",\n    \"assertions\": [\n      {\n        \"id\": \"14.1\",\n        \"text\": \"Calls cmd.MarkFlagsMutuallyExclusive(\\\"json\\\", \\\"yaml\\\")\"\n      },\n      {\n        \"id\": \"14.2\",\n        \"text\": \"Does NOT write a manual if-both-set check inside RunE\"\n      },\n      {\n        \"id\": \"14.3\",\n        \"text\": \"Explains cobra enforces this at flag parse time and returns a standard error\"\n      }\n    ]\n  },\n  {\n    \"id\": 15,\n    \"name\": \"required-together-flags\",\n    \"description\": \"Tests MarkFlagsRequiredTogether instead of manual RunE checks\",\n    \"prompt\": \"My Go cobra command has --tls-cert and --tls-key flags. If a user provides one, they must provide the other. How do I enforce this constraint?\",\n    \"trap\": \"Without the skill, the model writes manual validation in RunE checking if one is set without the other. MarkFlagsRequiredTogether enforces this at cobra's parse stage.\",\n    \"assertions\": [\n      {\n        \"id\": \"15.1\",\n        \"text\": \"Calls cmd.MarkFlagsRequiredTogether(\\\"tls-cert\\\", \\\"tls-key\\\")\"\n      },\n      {\n        \"id\": \"15.2\",\n        \"text\": \"Does NOT write manual if-one-without-the-other checks inside RunE\"\n      },\n      {\n        \"id\": \"15.3\",\n        \"text\": \"Explains cobra validates this before RunE runs\"\n      }\n    ]\n  },\n  {\n    \"id\": 16,\n    \"name\": \"one-required-flag-group\",\n    \"description\": \"Tests MarkFlagsOneRequired instead of manual RunE checks\",\n    \"prompt\": \"My Go cobra command accepts input from either --file or --stdin. At least one must be provided. How do I enforce that the user passes at least one of them?\",\n    \"trap\": \"Without the skill, the model checks flag presence inside RunE. MarkFlagsOneRequired enforces at parse time with a standard cobra error.\",\n    \"assertions\": [\n      {\n        \"id\": \"16.1\",\n        \"text\": \"Calls cmd.MarkFlagsOneRequired(\\\"file\\\", \\\"stdin\\\")\"\n      },\n      {\n        \"id\": \"16.2\",\n        \"text\": \"Does NOT write a manual check inside RunE for neither flag being set\"\n      },\n      {\n        \"id\": \"16.3\",\n        \"text\": \"Explains cobra enforces this before RunE runs\"\n      }\n    ]\n  },\n  {\n    \"id\": 17,\n    \"name\": \"flag-changed-distinguish-explicit-zero\",\n    \"description\": \"Tests cmd.Flags().Changed() to distinguish explicit zero from absent flag\",\n    \"prompt\": \"My Go cobra command has a --timeout flag defaulting to 30s. Users can pass --timeout 0 to disable timeouts entirely. In RunE, how do I tell whether the user explicitly passed --timeout 0 or simply didn't pass --timeout at all?\",\n    \"trap\": \"Without the skill, the model checks if timeout == 0, which conflates the two cases. The correct approach is cmd.Flags().Changed(\\\"timeout\\\") which returns true only when the user explicitly provided the flag.\",\n    \"assertions\": [\n      {\n        \"id\": \"17.1\",\n        \"text\": \"Uses cmd.Flags().Changed(\\\"timeout\\\") to detect explicit user input\"\n      },\n      {\n        \"id\": \"17.2\",\n        \"text\": \"Does NOT use if timeout == 0 as the sole distinguishing condition\"\n      },\n      {\n        \"id\": \"17.3\",\n        \"text\": \"Explains Changed() returns true only when the flag was explicitly set by the user\"\n      },\n      {\n        \"id\": \"17.4\",\n        \"text\": \"Shows the pattern: if Changed → apply value, else → use default behavior\"\n      }\n    ]\n  },\n  {\n    \"id\": 18,\n    \"name\": \"postrunE-success-only-use-defer\",\n    \"description\": \"Tests that PostRunE runs only on RunE success and defer is the right cleanup pattern\",\n    \"prompt\": \"My Go cobra command opens a database connection early in RunE and I want to close it when the command finishes, whether it succeeds or fails. I added cleanup in PostRunE but noticed it doesn't run when RunE returns an error. What's the right pattern?\",\n    \"trap\": \"Without the skill, the model may suggest PersistentPostRunE or not know PostRunE is success-only. The correct pattern is defer inside RunE for guaranteed cleanup regardless of outcome.\",\n    \"assertions\": [\n      {\n        \"id\": \"18.1\",\n        \"text\": \"Uses defer inside RunE to guarantee cleanup on both success and failure\"\n      },\n      {\n        \"id\": \"18.2\",\n        \"text\": \"Explains PostRunE only runs when RunE returns nil (success)\"\n      },\n      {\n        \"id\": \"18.3\",\n        \"text\": \"Does NOT present PostRunE as a solution for failure cleanup\"\n      }\n    ]\n  },\n  {\n    \"id\": 19,\n    \"name\": \"errOrStderr-not-os-stderr\",\n    \"description\": \"Tests cmd.ErrOrStderr() instead of os.Stderr for capturable error output\",\n    \"prompt\": \"My Go cobra command writes diagnostic details to stderr using fmt.Fprintf(os.Stderr, ...) before returning an error. This works fine at runtime but my tests can't capture the stderr output. How do I fix this?\",\n    \"trap\": \"Without the skill, the model uses os.Stderr directly. The correct approach is cmd.ErrOrStderr() which tests can redirect via rootCmd.SetErr(buf).\",\n    \"assertions\": [\n      {\n        \"id\": \"19.1\",\n        \"text\": \"Replaces os.Stderr with cmd.ErrOrStderr() as the write target\"\n      },\n      { \"id\": \"19.2\", \"text\": \"Does NOT use os.Stderr directly\" },\n      {\n        \"id\": \"19.3\",\n        \"text\": \"Shows rootCmd.SetErr(buf) in the test to capture stderr output\"\n      },\n      {\n        \"id\": \"19.4\",\n        \"text\": \"Explains the symmetry with cmd.OutOrStdout() / SetOut for stdout\"\n      }\n    ]\n  }\n]\n\nArchive v1.0.1: 9 files, 19508 bytes\n\nFiles: evals/evals.json (19592b), references/commands-and-args.md (5009b), references/completions.md (4007b), references/flags.md (3921b), references/generators.md (2266b), references/testing.md (3800b), skill-card.md (2776b), SKILL.md (10002b), _meta.json (137b)\n\nFile v1.0.1:SKILL.md\n\n---\nname: golang-spf13-cobra\ndescription: \"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 configuration layering alongside cobra, see the `samber/cc-skills-golang@golang-spf13-viper` skill. For general CLI architecture (project layout, exit codes, signal handling, I/O patterns), see `samber/cc-skills-golang@golang-cli`.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.0.1\"\n  openclaw:\n    emoji: \"🐍\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n    install: []\n    skill-library-version: \"1.10.2\"\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs\n---\n\n**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.\n\n**Modes:**\n\n- **Build** — creating a new CLI from scratch: follow command tree setup, hook wiring, and flag sections sequentially.\n- **Extend** — adding subcommands, flags, or completions to an existing CLI: read the current command tree first, then apply changes consistent with the existing structure.\n- **Review** — auditing an existing CLI: check the Common Mistakes table, verify `RunE` usage, `OutOrStdout()`, hook chain ordering, and args validation.\n\n# Using spf13/cobra for CLI command trees in Go\n\nCobra 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.\n\n**Official Resources:**\n\n- [pkg.go.dev/github.com/spf13/cobra](https://pkg.go.dev/github.com/spf13/cobra)\n- [github.com/spf13/cobra](https://github.com/spf13/cobra)\n- [cobra.dev](https://cobra.dev)\n\nThis skill is not exhaustive. Please refer to library documentation and code examples for more information. Context7 can help as a discoverability platform.\n\n```bash\ngo get github.com/spf13/cobra@latest\n```\n\n## Cobra vs. viper\n\nThese libraries do fundamentally different things and can be used independently.\n\n| Concern | cobra | viper |\n| --- | --- | --- |\n| Owns | Command tree, flags, arg validation, completions | Configuration value resolution |\n| User-facing? | Yes — subcommands, flags, help text | No — purely a key-value resolver |\n| Without the other? | Yes — a CLI with flags only needs cobra | Yes — a daemon reading YAML + env needs only viper |\n| Integration seam | Hands `pflag.Flag` to viper via `BindPFlag` | Treats the cobra flag as the highest-precedence layer |\n\n**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.\n\n→ See `samber/cc-skills-golang@golang-spf13-viper` for the viper side of this integration.\n\n## Command tree\n\nEvery cobra CLI has a root command plus zero or more subcommands registered with `AddCommand`. The root command name is the binary name.\n\n```go\nvar rootCmd = &cobra.Command{\n    Use:          \"myapp\",\n    Short:        \"One-line summary\",\n    SilenceUsage: true,  // ✓ prevents usage wall on every error\n    SilenceErrors: true, // ✓ lets you control error output format\n}\n```\n\nUse `AddGroup` to label subcommands in help output — register groups **before** the `AddCommand` calls that reference them; cobra does not retroactively assign groups.\n\n## The Run\\* family\n\nCobra commands have five run hooks executed in order:\n\n```\nPersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE\n```\n\nAlways use `*E` variants — the non-`E` forms cannot return errors. Key rules:\n\n- `PersistentPreRunE` on the root runs before **every** subcommand — use it for config init and auth checks.\n- A child `PersistentPreRunE` **replaces** the parent's entirely — call the parent explicitly if you need both.\n- `PostRunE` runs only if `RunE` succeeded.\n\nFor the full lifecycle and inheritance rules, see [commands-and-args.md](references/commands-and-args.md).\n\n## Args validators\n\nCobra validates positional arguments before `RunE` runs. Never write `len(args)` checks inside `RunE` — that bypasses cobra's standard error messages and arg count tracking.\n\nBuilt-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`.\n\nFor the full validator set with examples and `MatchAll` patterns, see [commands-and-args.md](references/commands-and-args.md).\n\n## Flags primer\n\nCobra delegates flag parsing to `pflag`. **Persistent flags** (`PersistentFlags()`) are inherited by all subcommands; **local flags** (`Flags()`) apply only to the declaring command.\n\n```go\nrootCmd.PersistentFlags().StringVar(&cfgFile, \"config\", \"\", \"config file path\") // inherited by all subcommands\nserveCmd.Flags().IntVar(&port, \"port\", 8080, \"listen port\")                     // local to serveCmd only\nserveCmd.MarkFlagRequired(\"port\")\nserveCmd.MarkFlagsMutuallyExclusive(\"json\", \"yaml\")\n```\n\nFor pflag types, custom flag values, flag groups, and viper binding, see [flags.md](references/flags.md).\n\n## Completions primer\n\nCobra generates shell completions automatically. Extend them with:\n\n- **`ValidArgs []string`** — static positional arg completion.\n- **`ValidArgsFunction`** — dynamic: `func(cmd, args, toComplete string) ([]string, ShellCompDirective)`. Return `ShellCompDirectiveNoFileComp` to suppress file fallback.\n- **`RegisterFlagCompletionFunc(name, fn)`** — flag value completion.\n\nFor `ShellCompDirective` values, annotations, and testing, see [completions.md](references/completions.md).\n\n## Testing commands\n\nTest 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.\n\n```go\nfunc TestServeCmd(t *testing.T) {\n    buf := new(bytes.Buffer)\n    rootCmd.SetOut(buf)\n    rootCmd.SetArgs([]string{\"serve\", \"--port\", \"9090\"})\n    require.NoError(t, rootCmd.Execute())\n    assert.Contains(t, buf.String(), \"listening on :9090\")\n}\n```\n\nCobra accumulates flag state across `Execute()` calls — build a fresh command tree per test. For isolation patterns, golden files, and testing completions, see [testing.md](references/testing.md).\n\n## Best Practices\n\n1. **Always use `RunE`, never `Run`** — `Run` cannot return an error; the only escape is `os.Exit` or panic, bypassing defers.\n2. **Put config initialization in `PersistentPreRunE`** — it runs before every subcommand; the right place for viper binding and auth checks.\n3. **Validate positional args with `Args`, not inside `RunE`** — `Args` gives cobra's standard error messages; `MatchAll` composes validators.\n4. **Use `cmd.OutOrStdout()` / `cmd.ErrOrStderr()` for all output** — direct `os.Stdout` writes cannot be captured by tests.\n5. **Re-create the command tree per test** — cobra accumulates flag state across `Execute()` calls on the same instance.\n\n## Common Mistakes\n\n| Mistake | Why it fails | Fix |\n| --- | --- | --- |\n| 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 |\n| Writing `len(args)` checks in `RunE` | Bypasses cobra's standard error messages (\"accepts 1 arg, received 2\") | Declare `Args: cobra.ExactArgs(1)` on the command |\n| Writing to `os.Stdout` directly | Tests cannot capture output — os-level file handles can't be redirected | Use `cmd.OutOrStdout()` / `cmd.ErrOrStderr()` |\n| Child `PersistentPreRunE` silently drops parent's | Cobra does not chain — the child replaces the parent's hook entirely | Call `parent.PersistentPreRunE(cmd, args)` from the child's hook |\n| Reusing a root command across tests | Cobra accumulates flag state; second `Execute()` sees flags from the first | Build a fresh command tree per test |\n\n## Further Reading\n\n- [commands-and-args.md](references/commands-and-args.md) — full PreRun\\*/PostRun\\* chain, every Args validator, PersistentPreRunE inheritance rules\n- [flags.md](references/flags.md) — pflag types, required/exclusive/oneRequired groups, custom value types, viper binding\n- [completions.md](references/completions.md) — ShellCompDirective set, annotation-based completions, testing completions\n- [generators.md](references/generators.md) — man page, markdown, YAML, RST doc generation; `cobra-cli` scaffolder\n- [testing.md](references/testing.md) — isolation patterns, golden files, testing completions, table-driven command tests\n\n## Cross-References\n\n- → See `samber/cc-skills-golang@golang-cli` skill for general CLI architecture — project layout, exit codes, signal handling, I/O patterns\n- → See `samber/cc-skills-golang@golang-spf13-viper` skill for configuration layering alongside cobra (flag → env → file → default precedence)\n- → See `samber/cc-skills-golang@golang-testing` skill for general Go testing patterns\n\nIf you encounter a bug or unexpected behavior in spf13/cobra, open an issue at <https://github.com/spf13/cobra/issues>.\n\nFile v1.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-spf13-cobra\",\n  \"version\": \"1.0.1\",\n  \"publishedAt\": 1779566578665\n}\n\nFile v1.0.1:references/commands-and-args.md\n\n# Cobra Commands, Hooks, and Args Validators\n\n## The Run\\* lifecycle\n\nCobra commands have five run hooks. Cobra executes them in this fixed order:\n\n```\nPersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE\n```\n\nEach `*E` hook returns `error`. The non-`*E` variants (`PersistentPreRun`, `PreRun`, `Run`, `PostRun`, `PersistentPostRun`) have signature `func(cmd *cobra.Command, args []string)` — they cannot signal failure without `os.Exit` or panic. **Always use the `*E` variants.**\n\n### Which hook to use\n\n| Hook | Scope | When to use |\n| --- | --- | --- |\n| `PersistentPreRunE` | Parent + all descendants | Config init, auth check, telemetry setup — must run before every subcommand |\n| `PreRunE` | This command only | Validation that runs only for this command before `RunE` |\n| `RunE` | This command only | Main handler — the primary business logic |\n| `PostRunE` | This command only | Cleanup that runs only if `RunE` succeeded |\n| `PersistentPostRunE` | Parent + all descendants | Global cleanup (close connections, flush buffers) |\n\n### Inheritance rules\n\n`PersistentPreRunE` defined on the root command runs before every subcommand. But if a child command defines **its own** `PersistentPreRunE`, it **replaces** (does not chain) the parent's hook. Call the parent explicitly if you need both:\n\n```go\nvar childCmd = &cobra.Command{\n    PersistentPreRunE: func(cmd *cobra.Command, args []string) error {\n        // call parent's hook first\n        if err := rootCmd.PersistentPreRunE(cmd, args); err != nil {\n            return err\n        }\n        // child-specific logic\n        return nil\n    },\n}\n```\n\n### Execution stops on first error\n\nIf `PersistentPreRunE` returns an error, cobra stops — `RunE` and later hooks never run. Use this for fail-fast auth checks.\n\n## Args validators\n\nArgs validators run before `RunE`. Cobra prints a clear error message and exits without calling `RunE` when validation fails.\n\n### Built-in validators\n\n```go\ncobra.NoArgs                        // fails if any positional args provided\ncobra.ArbitraryArgs                 // accepts any number of args (default)\ncobra.ExactArgs(n int)              // requires exactly n args\ncobra.MinimumNArgs(n int)           // requires at least n args\ncobra.MaximumNArgs(n int)           // requires at most n args\ncobra.RangeArgs(min, max int)       // requires between min and max args\ncobra.OnlyValidArgs                 // all args must be in ValidArgs list\ncobra.ExactValidArgs(n int)         // exactly n args, all in ValidArgs\n```\n\n### Composing validators with MatchAll\n\n```go\nvar deleteCmd = &cobra.Command{\n    Use:       \"delete <resource>\",\n    Args:      cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),\n    ValidArgs: []string{\"pod\", \"service\", \"deployment\"},\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return doDelete(args[0])\n    },\n}\n```\n\n### Custom validators\n\nSignature: `func(cmd *cobra.Command, args []string) error`\n\n```go\nfunc validatePositiveInt(cmd *cobra.Command, args []string) error {\n    if len(args) != 1 {\n        return fmt.Errorf(\"requires exactly 1 arg, got %d\", len(args))\n    }\n    n, err := strconv.Atoi(args[0])\n    if err != nil || n <= 0 {\n        return fmt.Errorf(\"argument must be a positive integer, got %q\", args[0])\n    }\n    return nil\n}\n\nvar cmd = &cobra.Command{\n    Args: validatePositiveInt,\n    RunE: func(cmd *cobra.Command, args []string) error { /* ... */ },\n}\n```\n\nCombine custom validators with built-in ones using `MatchAll`:\n\n```go\nArgs: cobra.MatchAll(cobra.MinimumNArgs(1), validateAllPositive),\n```\n\n## Command registration and ordering\n\n```go\nfunc init() {\n    // groups must be registered before AddCommand\n    rootCmd.AddGroup(&cobra.Group{ID: \"core\", Title: \"Core Commands:\"})\n    rootCmd.AddGroup(&cobra.Group{ID: \"management\", Title: \"Management Commands:\"})\n\n    serveCmd.GroupID = \"core\"\n    migrateCmd.GroupID = \"management\"\n\n    rootCmd.AddCommand(serveCmd, migrateCmd, versionCmd)\n}\n```\n\n`versionCmd` has no `GroupID` — it appears in the default section.\n\n## Annotations\n\nCobra supports arbitrary command annotations for framework-level metadata:\n\n```go\nvar serveCmd = &cobra.Command{\n    Annotations: map[string]string{\n        \"category\": \"network\",\n        \"requires-auth\": \"true\",\n    },\n}\n\n// read in a middleware hook:\nif serveCmd.Annotations[\"requires-auth\"] == \"true\" {\n    // enforce auth\n}\n```\n\n## Hidden and deprecated commands\n\n```go\nvar internalCmd = &cobra.Command{\n    Hidden: true,      // not shown in help, still executable\n}\n\nvar oldCmd = &cobra.Command{\n    Deprecated: \"use `newcmd` instead\",  // shown in help, prints warning on use\n}\n```\n\n## cobra.CheckErr\n\n`cobra.CheckErr(err)` is a convenience function: if `err != nil`, it prints the error to `cmd.ErrOrStderr()` and calls `os.Exit(1)`. Use it only in `main()` where you want a hard exit — not inside `RunE` where returning the error is preferred.\n\n```go\nfunc main() {\n    cobra.CheckErr(rootCmd.Execute())\n}\n```\n\nFile v1.0.1:references/completions.md\n\n# Cobra Shell Completions Reference\n\nCobra generates shell completion scripts for bash, zsh, fish, and PowerShell automatically. Subcommand names and flag names are completed for free. You add completions for flag values and positional arguments.\n\n## Built-in completion command\n\nCobra registers a `completion` subcommand automatically:\n\n```bash\nmyapp completion bash   # generate bash script\nmyapp completion zsh    # generate zsh script\nmyapp completion fish   # generate fish script\nmyapp completion powershell\n\n# Install (example for zsh):\nmyapp completion zsh > \"${fpath[1]}/_myapp\"\n```\n\n## ShellCompDirective\n\nThe `ShellCompDirective` controls shell behavior after your completion function returns:\n\n| Directive | Meaning |\n| --- | --- |\n| `ShellCompDirectiveDefault` | Fall back to file completion after your results |\n| `ShellCompDirectiveNoFileComp` | Disable file completion fallback |\n| `ShellCompDirectiveNoSpace` | Don't add a space after the completion |\n| `ShellCompDirectiveFilterFileExt(exts)` | Only show files with given extensions |\n| `ShellCompDirectiveFilterDirs(dirs)` | Only show directories |\n| `ShellCompDirectiveError` | Signal an error (show no completions) |\n\nCombine with bitwise OR: `cobra.ShellCompDirectiveNoFileComp | cobra.ShellCompDirectiveNoSpace`.\n\nUse `ShellCompDirectiveNoFileComp` whenever your list is exhaustive — it prevents the shell from appending irrelevant files.\n\n## Static arg completions\n\n```go\nvar getCmd = &cobra.Command{\n    Use:       \"get <resource>\",\n    ValidArgs: []string{\"pod\", \"service\", \"deployment\", \"configmap\"},\n    Args:      cobra.OnlyValidArgs,\n    RunE: func(cmd *cobra.Command, args []string) error { /* ... */ },\n}\n```\n\n## Dynamic arg completions\n\n```go\nvar getCmd = &cobra.Command{\n    ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        if len(args) > 0 {\n            // first arg already provided — no more completions\n            return nil, cobra.ShellCompDirectiveNoFileComp\n        }\n        resources, err := listResources(toComplete)\n        if err != nil {\n            return nil, cobra.ShellCompDirectiveError\n        }\n        return resources, cobra.ShellCompDirectiveNoFileComp\n    },\n}\n```\n\n`toComplete` is the prefix the user has typed so far — filter your results by it for responsive completions.\n\n## Flag value completions\n\n```go\nfunc init() {\n    rootCmd.RegisterFlagCompletionFunc(\"output\", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        return []string{\"json\\tJSON output\", \"yaml\\tYAML output\", \"table\\tTable output\"}, cobra.ShellCompDirectiveNoFileComp\n    })\n\n    rootCmd.RegisterFlagCompletionFunc(\"namespace\", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        ns, err := listNamespaces()\n        if err != nil {\n            return nil, cobra.ShellCompDirectiveError\n        }\n        return ns, cobra.ShellCompDirectiveNoFileComp\n    })\n}\n```\n\nDescriptions after `\\t` are shown in zsh and fish menus.\n\n## Completion annotations\n\nMark a flag to complete as a file or directory:\n\n```go\ncmd.Flags().String(\"config\", \"\", \"config file\")\ncmd.MarkFlagFilename(\"config\", \"yaml\", \"yml\", \"json\")  // only those extensions\n\ncmd.Flags().String(\"dir\", \"\", \"output directory\")\ncmd.MarkFlagDirname(\"dir\")\n```\n\n## Testing completions\n\n```go\nfunc TestCompletion(t *testing.T) {\n    rootCmd.SetArgs([]string{\"__complete\", \"get\", \"\"})\n    buf := new(bytes.Buffer)\n    rootCmd.SetOut(buf)\n    rootCmd.Execute()\n    assert.Contains(t, buf.String(), \"pod\")\n    assert.Contains(t, buf.String(), \"service\")\n}\n```\n\n`__complete` is cobra's internal completion request verb. Pass the partial args as additional arguments.\n\n## Disabling the completion command\n\n```go\nrootCmd.CompletionOptions.DisableDefaultCmd = true   // remove the completion subcommand\nrootCmd.CompletionOptions.HiddenDefaultCmd = true    // keep it but hide from help\n```\n\nFile v1.0.1:references/flags.md\n\n# Cobra Flags Reference\n\nCobra delegates all flag parsing to `github.com/spf13/pflag`. `cobra.Command` exposes two `*pflag.FlagSet`s:\n\n- `cmd.Flags()` — local flags, only available on this command.\n- `cmd.PersistentFlags()` — inherited by all subcommands.\n\n## Common flag types\n\n```go\n// String\ncmd.Flags().String(\"name\", \"default\", \"description\")\ncmd.Flags().StringP(\"name\", \"n\", \"default\", \"description\")  // with shorthand\n\n// With pointer binding (no Lookup needed later)\nvar name string\ncmd.Flags().StringVar(&name, \"name\", \"default\", \"description\")\ncmd.Flags().StringVarP(&name, \"name\", \"n\", \"default\", \"description\")\n\n// Other types follow the same pattern:\ncmd.Flags().Int / IntVar / IntVarP\ncmd.Flags().Bool / BoolVar / BoolVarP\ncmd.Flags().Float64 / Float64Var\ncmd.Flags().Duration / DurationVar       // parses \"1h30m\", \"500ms\"\ncmd.Flags().StringSlice / StringSliceVar // comma-separated or repeated flags\ncmd.Flags().StringArray / StringArrayVar // repeated flags only (no comma splitting)\ncmd.Flags().IntSlice / IntSliceVar\ncmd.Flags().StringToString                // --label key=value --label k2=v2\n```\n\n## StringSlice vs StringArray\n\n| Flag type     | Input                 | Result                            |\n| ------------- | --------------------- | --------------------------------- |\n| `StringSlice` | `--tags a,b --tags c` | `[\"a\", \"b\", \"c\"]` — commas split  |\n| `StringArray` | `--tags a,b --tags c` | `[\"a,b\", \"c\"]` — commas NOT split |\n\nUse `StringArray` when values may legitimately contain commas.\n\n## Flag constraints\n\n```go\n// Fail if flag not provided\ncmd.MarkFlagRequired(\"output\")\n\n// Fail if both provided\ncmd.MarkFlagsMutuallyExclusive(\"json\", \"yaml\", \"table\")\n\n// Fail if none provided\ncmd.MarkFlagsOneRequired(\"file\", \"stdin\")\n\n// Require flag only if another flag is set\ncmd.MarkFlagsMutuallyExclusive(\"tls\", \"no-tls\")\n```\n\n## Persistent flag patterns\n\n```go\nfunc init() {\n    // global flags on root\n    rootCmd.PersistentFlags().StringVar(&cfgFile, \"config\", \"\", \"config file (default: $HOME/.myapp.yaml)\")\n    rootCmd.PersistentFlags().StringVar(&logLevel, \"log-level\", \"info\", \"log level (debug, info, warn, error)\")\n\n    // bind to viper immediately after defining\n    viper.BindPFlag(\"config\", rootCmd.PersistentFlags().Lookup(\"config\"))\n    viper.BindPFlag(\"log-level\", rootCmd.PersistentFlags().Lookup(\"log-level\"))\n}\n```\n\n## Custom flag value types\n\nImplement `pflag.Value` to parse arbitrary types:\n\n```go\ntype enumValue struct {\n    val     string\n    allowed []string\n}\n\nfunc (e *enumValue) String() string { return e.val }\nfunc (e *enumValue) Type() string   { return \"enum\" }\nfunc (e *enumValue) Set(s string) error {\n    for _, a := range e.allowed {\n        if s == a {\n            e.val = s\n            return nil\n        }\n    }\n    return fmt.Errorf(\"must be one of %v\", e.allowed)\n}\n\nvar outputFmt = &enumValue{val: \"table\", allowed: []string{\"table\", \"json\", \"yaml\"}}\ncmd.Flags().Var(outputFmt, \"output\", \"output format (table, json, yaml)\")\n```\n\n## Flag groups (required together)\n\nMark a set of flags that must all be provided if any one of them is provided:\n\n```go\ncmd.Flags().String(\"tls-cert\", \"\", \"TLS certificate file\")\ncmd.Flags().String(\"tls-key\", \"\", \"TLS key file\")\ncmd.MarkFlagsRequiredTogether(\"tls-cert\", \"tls-key\")\n```\n\n## Accessing flag values\n\nPrefer pointer binding (`StringVar`, `IntVar`, etc.) for type-safe access. When you need the flag post-parse:\n\n```go\nport, err := cmd.Flags().GetInt(\"port\")\nname, err := cmd.Flags().GetString(\"name\")\ntags, err := cmd.Flags().GetStringSlice(\"tags\")\n```\n\n## Flag changed vs default\n\n```go\nif cmd.Flags().Changed(\"port\") {\n    // user explicitly provided --port\n    // useful when distinguishing \"user set 0\" from \"flag not provided\"\n}\n```\n\n`Changed()` is also how viper knows which flags are explicit overrides — it only promotes a flag to the highest precedence layer if `Changed()` is true.\n\nFile v1.0.1:references/generators.md\n\n# Cobra Documentation and Scaffolding Generators\n\n## Doc generation\n\nCobra can generate documentation from your command tree in multiple formats. Import the `cobra/doc` sub-package:\n\n```bash\ngo get github.com/spf13/cobra/doc\n```\n\n### Markdown\n\n```go\nimport \"github.com/spf13/cobra/doc\"\n\nerr := doc.GenMarkdownTree(rootCmd, \"/tmp/docs/\")\n// generates /tmp/docs/myapp.md, /tmp/docs/myapp_serve.md, etc.\n\n// Single command\nvar buf bytes.Buffer\ndoc.GenMarkdown(rootCmd, &buf)\n```\n\n### Man pages\n\n```go\nheader := &doc.GenManHeader{\n    Title:   \"MYAPP\",\n    Section: \"1\",\n    Date:    &time.Time{},\n    Source:  \"myapp v1.0.0\",\n    Manual:  \"User Commands\",\n}\nerr := doc.GenManTree(rootCmd, header, \"/usr/local/share/man/man1/\")\n```\n\n### YAML\n\n```go\nerr := doc.GenYamlTree(rootCmd, \"/tmp/docs/\")\n```\n\n### RST (reStructuredText)\n\n```go\nerr := doc.GenReSTTree(rootCmd, \"/tmp/docs/\")\n```\n\n## cobra-cli scaffolder\n\n`cobra-cli` generates command files and wires them into your project:\n\n```bash\ngo get -tool github.com/spf13/cobra-cli@latest\n\n# Initialize a new cobra project\ngo tool cobra-cli init myapp\n\n# Add a subcommand\ngo tool cobra-cli add serve\ngo tool cobra-cli add migrate\n\n# Add with a parent other than root\ncobra-cli add list --parent serve\n```\n\nGenerated files follow the standard pattern:\n\n```go\n// cmd/serve.go\nvar serveCmd = &cobra.Command{\n    Use:   \"serve\",\n    Short: \"A brief description of your command\",\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return nil\n    },\n}\n\nfunc init() {\n    rootCmd.AddCommand(serveCmd)\n}\n```\n\n`cobra-cli` is optional — many teams write command files by hand following the same pattern.\n\n## Help and usage template customization\n\nOverride the default help template:\n\n```go\nrootCmd.SetHelpTemplate(`\nUsage:  {{.UseLine}}\n{{if .HasAvailableSubCommands}}\nCommands:\n{{range .Commands}}{{if .IsAvailableCommand}}  {{rpad .Name .NamePadding }} {{.Short}}\n{{end}}{{end}}{{end}}\nFlags:\n{{.LocalFlags.FlagUsages | trimRightSpace}}\n`)\n```\n\nOverride the usage function entirely:\n\n```go\nrootCmd.SetUsageFunc(func(cmd *cobra.Command) error {\n    fmt.Fprintf(cmd.OutOrStdout(), \"Custom usage for %s\\n\", cmd.Name())\n    return nil\n})\n```\n\nCommon template functions available: `rpad`, `trimRightSpace`, `gt`, `eq`.\n\nFile v1.0.1:references/testing.md\n\n# Testing Cobra Commands\n\n## Basic test pattern\n\n```go\nfunc TestServeCmd(t *testing.T) {\n    stdout := new(bytes.Buffer)\n    stderr := new(bytes.Buffer)\n\n    rootCmd.SetOut(stdout)\n    rootCmd.SetErr(stderr)\n    rootCmd.SetArgs([]string{\"serve\", \"--port\", \"9090\", \"--dry-run\"})\n\n    err := rootCmd.Execute()\n    require.NoError(t, err)\n    assert.Contains(t, stdout.String(), \"listening on :9090\")\n    assert.Empty(t, stderr.String())\n}\n```\n\n## Isolation between tests\n\nCobra accumulates flag state across `Execute()` calls on the same command instance. Tests must be isolated.\n\n### Option 1: Re-create the command tree per test (recommended for unit tests)\n\n```go\nfunc newRootCmd() *cobra.Command {\n    root := &cobra.Command{Use: \"myapp\", SilenceUsage: true, SilenceErrors: true}\n    root.AddCommand(newServeCmd())\n    return root\n}\n\nfunc TestServeCmd(t *testing.T) {\n    root := newRootCmd()\n    root.SetArgs([]string{\"serve\", \"--port\", \"9090\"})\n    err := root.Execute()\n    require.NoError(t, err)\n}\n```\n\n### Option 2: Reset flags between tests\n\n```go\nfunc TestWithReset(t *testing.T) {\n    t.Cleanup(func() {\n        rootCmd.ResetFlags()\n        // re-define flags if needed\n    })\n}\n```\n\nRe-creating is safer — `ResetFlags` only clears the flag set, not subcommand state.\n\n## Testing commands that write output\n\nCommands must use `cmd.OutOrStdout()` / `cmd.ErrOrStderr()` instead of `os.Stdout` / `os.Stderr` for this to work.\n\n```go\n// In command handler:\nfunc runServe(cmd *cobra.Command, args []string) error {\n    fmt.Fprintln(cmd.OutOrStdout(), \"Server started\")\n    fmt.Fprintln(cmd.ErrOrStderr(), \"Debug: listening on port 8080\")\n    return nil\n}\n\n// In test:\nbuf := new(bytes.Buffer)\nrootCmd.SetOut(buf)\nrootCmd.Execute()\nassert.Contains(t, buf.String(), \"Server started\")\n```\n\n## Golden file tests\n\nFor commands with structured or lengthy output, use golden files:\n\n```go\nfunc TestOutputFormat(t *testing.T) {\n    buf := new(bytes.Buffer)\n    rootCmd.SetOut(buf)\n    rootCmd.SetArgs([]string{\"list\", \"--output\", \"json\"})\n    require.NoError(t, rootCmd.Execute())\n\n    golden := \"testdata/list-json.golden\"\n    if *update {  // -update flag\n        os.WriteFile(golden, buf.Bytes(), 0644)\n    }\n    want, _ := os.ReadFile(golden)\n    assert.Equal(t, string(want), buf.String())\n}\n```\n\nRun with `-update` to regenerate golden files after intentional output changes.\n\n## Testing error paths\n\n```go\nfunc TestInvalidArgs(t *testing.T) {\n    stderr := new(bytes.Buffer)\n    rootCmd.SetErr(stderr)\n    rootCmd.SetArgs([]string{\"delete\"})  // missing required arg\n\n    err := rootCmd.Execute()\n    assert.Error(t, err)\n    assert.Contains(t, err.Error(), \"accepts 1 arg\")\n}\n```\n\n## Table-driven command tests\n\n```go\ntests := []struct {\n    name    string\n    args    []string\n    wantOut string\n    wantErr bool\n}{\n    {\"no flags\", []string{\"serve\"}, \"listening on :8080\", false},\n    {\"custom port\", []string{\"serve\", \"--port\", \"9090\"}, \"listening on :9090\", false},\n    {\"invalid port\", []string{\"serve\", \"--port\", \"abc\"}, \"\", true},\n}\n\nfor _, tt := range tests {\n    t.Run(tt.name, func(t *testing.T) {\n        root := newRootCmd()  // fresh command tree per test\n        buf := new(bytes.Buffer)\n        root.SetOut(buf)\n        root.SetArgs(tt.args)\n        err := root.Execute()\n        if tt.wantErr {\n            assert.Error(t, err)\n        } else {\n            require.NoError(t, err)\n            assert.Contains(t, buf.String(), tt.wantOut)\n        }\n    })\n}\n```\n\n## Testing completions\n\n```go\nfunc TestCompletion(t *testing.T) {\n    root := newRootCmd()\n    buf := new(bytes.Buffer)\n    root.SetOut(buf)\n    root.SetArgs([]string{\"__complete\", \"delete\", \"\"})\n    root.Execute()\n\n    assert.Contains(t, buf.String(), \"pod\")\n    assert.Contains(t, buf.String(), \"service\")\n}\n```\n\nFile v1.0.1:skill-card.md\n\n## Description: <br>\nGuides agents working on Go CLI projects that use spf13/cobra, including command trees, RunE hooks, argument validators, flags, completions, documentation generation, and command testing. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[samber](https://clawhub.ai/user/samber) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and engineering agents use this skill to build, extend, or review Go command-line applications that rely on spf13/cobra. It helps produce idiomatic command definitions, flag handling, completions, documentation generation, and test patterns. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Generated changes to command wiring, flags, completions, or tests may alter CLI behavior in ways the user did not intend. <br>\nMitigation: Review proposed diffs before relying on them and run the project's Go test suite for affected commands. <br>\nRisk: The skill may guide an agent to run Go or git commands during implementation work. <br>\nMitigation: Keep command execution scoped to the project, inspect command intent before running it, and avoid commands that publish, push, or modify remote state unless explicitly requested. <br>\n\n\n## Reference(s): <br>\n- [ClawHub Skill Page](https://clawhub.ai/samber/golang-spf13-cobra) <br>\n- [Publisher Profile](https://clawhub.ai/user/samber) <br>\n- [Metadata Homepage](https://github.com/samber/cc-skills-golang) <br>\n- [spf13/cobra Package Documentation](https://pkg.go.dev/github.com/spf13/cobra) <br>\n- [spf13/cobra Repository](https://github.com/spf13/cobra) <br>\n- [Cobra Documentation](https://cobra.dev) <br>\n- [Commands and Arguments Reference](references/commands-and-args.md) <br>\n- [Flags Reference](references/flags.md) <br>\n- [Completions Reference](references/completions.md) <br>\n- [Generators Reference](references/generators.md) <br>\n- [Testing Reference](references/testing.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [guidance, code, shell commands, configuration] <br>\n**Output Format:** [Markdown guidance with Go code examples and inline shell commands] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May guide the agent to edit project files, run Go or git commands, and fetch official or library documentation when requested.] <br>\n\n## Skill Version(s): <br>\n1.0.1 (source: server release evidence and frontmatter metadata) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v1.0.1:evals/evals.json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"rune-vs-run-error-propagation\",\n    \"description\": \"Tests use of RunE instead of Run for error propagation\",\n    \"prompt\": \"I'm writing a cobra subcommand in Go that calls an external API. If the API returns an error, the command should exit non-zero. Should I use Run or RunE?\",\n    \"trap\": \"Without the skill, the model may say both work, suggest using Run with os.Exit(1), or not explain why Run is problematic. The correct answer is always RunE — it propagates the error through cobra's error handling chain.\",\n    \"assertions\": [\n      { \"id\": \"1.1\", \"text\": \"Recommends RunE, not Run\" },\n      {\n        \"id\": \"1.2\",\n        \"text\": \"Explains that Run cannot return an error — you'd need os.Exit or panic\"\n      },\n      {\n        \"id\": \"1.3\",\n        \"text\": \"Shows RunE returning the error from the handler\"\n      },\n      { \"id\": \"1.4\", \"text\": \"Does NOT suggest using os.Exit inside RunE\" },\n      {\n        \"id\": \"1.5\",\n        \"text\": \"Mentions that returning error from RunE causes cobra to exit non-zero\"\n      }\n    ]\n  },\n  {\n    \"id\": 2,\n    \"name\": \"args-validator-not-manual-check\",\n    \"description\": \"Tests use of cobra Args validators instead of manual len(args) checks in RunE\",\n    \"prompt\": \"I'm writing a Go CLI with cobra. My 'delete' command requires exactly one positional argument (the resource name). How should I validate this?\",\n    \"trap\": \"Without the skill, the model writes len(args) != 1 check inside RunE. The correct approach is Args: cobra.ExactArgs(1) on the command definition, which validates before RunE runs and gives a standard error message.\",\n    \"assertions\": [\n      {\n        \"id\": \"2.1\",\n        \"text\": \"Sets Args: cobra.ExactArgs(1) on the command struct\"\n      },\n      { \"id\": \"2.2\", \"text\": \"Does NOT write len(args) check inside RunE\" },\n      {\n        \"id\": \"2.3\",\n        \"text\": \"Mentions that cobra prints a standard error message when validation fails\"\n      },\n      {\n        \"id\": \"2.4\",\n        \"text\": \"RunE body accesses args[0] directly without re-validating length\"\n      }\n    ]\n  },\n  {\n    \"id\": 3,\n    \"name\": \"outOrStdout-not-os-stdout\",\n    \"description\": \"Tests use of cmd.OutOrStdout() instead of os.Stdout for testable output\",\n    \"prompt\": \"I'm writing a cobra command in Go that prints a table of results to the terminal. How should I write to stdout from inside RunE?\",\n    \"trap\": \"Without the skill, the model uses fmt.Println or os.Stdout directly. The correct approach is fmt.Fprintln(cmd.OutOrStdout(), ...) which can be redirected to a buffer in tests.\",\n    \"assertions\": [\n      { \"id\": \"3.1\", \"text\": \"Uses cmd.OutOrStdout() as the io.Writer target\" },\n      { \"id\": \"3.2\", \"text\": \"Does NOT use os.Stdout directly\" },\n      {\n        \"id\": \"3.3\",\n        \"text\": \"Does NOT use fmt.Println (which hardcodes os.Stdout)\"\n      },\n      {\n        \"id\": \"3.4\",\n        \"text\": \"Mentions testability as the reason — SetOut can redirect the writer in tests\"\n      }\n    ]\n  },\n  {\n    \"id\": 4,\n    \"name\": \"persistent-prerunE-hook-chain\",\n    \"description\": \"Tests PersistentPreRunE on root for global config init and the child override trap\",\n    \"prompt\": \"In my Go CLI with cobra, I want to initialize viper config before any subcommand runs. I also have one subcommand that needs its own PersistentPreRunE for extra setup. How do I make sure both run?\",\n    \"trap\": \"Without the skill, the model defines PersistentPreRunE on both root and child without noting that the child's hook replaces the parent's — so root's config init never runs for that subcommand.\",\n    \"assertions\": [\n      {\n        \"id\": \"4.1\",\n        \"text\": \"Explains that a child's PersistentPreRunE replaces (not chains) the parent's\"\n      },\n      {\n        \"id\": \"4.2\",\n        \"text\": \"Shows explicitly calling the parent's PersistentPreRunE from inside the child's hook\"\n      },\n      { \"id\": \"4.3\", \"text\": \"Does NOT claim both hooks run automatically\" },\n      {\n        \"id\": \"4.4\",\n        \"text\": \"Uses PersistentPreRunE (the *E variant) not PersistentPreRun\"\n      }\n    ]\n  },\n  {\n    \"id\": 5,\n    \"name\": \"silence-usage-and-errors\",\n    \"description\": \"Tests SilenceUsage and SilenceErrors on root command\",\n    \"prompt\": \"When my Go cobra CLI returns an error from RunE, the terminal shows the full usage/help text followed by the error. I only want to see the error message, not the usage. How do I fix this?\",\n    \"trap\": \"Without the skill, the model may suggest overriding SetUsageTemplate or wrapping the error. The correct fix is SilenceUsage: true on the root command.\",\n    \"assertions\": [\n      {\n        \"id\": \"5.1\",\n        \"text\": \"Sets SilenceUsage: true on the root cobra.Command\"\n      },\n      {\n        \"id\": \"5.2\",\n        \"text\": \"Optionally mentions SilenceErrors: true (for custom error formatting)\"\n      },\n      {\n        \"id\": \"5.3\",\n        \"text\": \"Does NOT suggest removing or wrapping the error in RunE\"\n      },\n      {\n        \"id\": \"5.4\",\n        \"text\": \"Explains that SilenceUsage only suppresses usage on error, not on --help\"\n      }\n    ]\n  },\n  {\n    \"id\": 6,\n    \"name\": \"command-group-registration-order\",\n    \"description\": \"Tests that AddGroup must be called before AddCommand that references it\",\n    \"prompt\": \"I want to group my cobra subcommands in the help output under labels like 'Core Commands:' and 'Management Commands:'. How do I set this up?\",\n    \"trap\": \"Without the skill, the model calls AddCommand first and AddGroup after, which doesn't work — groups must be registered before the commands that reference them.\",\n    \"assertions\": [\n      {\n        \"id\": \"6.1\",\n        \"text\": \"Calls AddGroup before AddCommand for commands that use that group\"\n      },\n      {\n        \"id\": \"6.2\",\n        \"text\": \"Sets GroupID on the subcommand matching the Group's ID field\"\n      },\n      { \"id\": \"6.3\", \"text\": \"Shows cobra.Group{ID: ..., Title: ...} struct\" },\n      {\n        \"id\": \"6.4\",\n        \"text\": \"Does NOT call AddCommand before AddGroup for the same group\"\n      }\n    ]\n  },\n  {\n    \"id\": 7,\n    \"name\": \"valid-args-function-dynamic-completion\",\n    \"description\": \"Tests ValidArgsFunction for dynamic shell completion instead of static ValidArgs\",\n    \"prompt\": \"My Go cobra 'get pod' command should complete pod names dynamically by querying the API server. ValidArgs only accepts a static list. How do I provide dynamic completions?\",\n    \"trap\": \"Without the skill, the model tries to populate ValidArgs at startup (querying the API at init time) or doesn't know about ValidArgsFunction.\",\n    \"assertions\": [\n      {\n        \"id\": \"7.1\",\n        \"text\": \"Uses ValidArgsFunction (not ValidArgs) for dynamic completions\"\n      },\n      {\n        \"id\": \"7.2\",\n        \"text\": \"Function signature returns ([]string, cobra.ShellCompDirective)\"\n      },\n      {\n        \"id\": \"7.3\",\n        \"text\": \"Returns cobra.ShellCompDirectiveNoFileComp to prevent file fallback\"\n      },\n      {\n        \"id\": \"7.4\",\n        \"text\": \"Does NOT query the API at init() or in ValidArgs (static list)\"\n      },\n      {\n        \"id\": \"7.5\",\n        \"text\": \"Handles errors by returning cobra.ShellCompDirectiveError\"\n      }\n    ]\n  },\n  {\n    \"id\": 8,\n    \"name\": \"register-flag-completion-func\",\n    \"description\": \"Tests RegisterFlagCompletionFunc for flag value completion\",\n    \"prompt\": \"My Go cobra command has an --output flag that accepts 'json', 'yaml', or 'table'. How do I make the shell complete valid values when the user types --output <TAB>?\",\n    \"trap\": \"Without the skill, the model does not know about RegisterFlagCompletionFunc and instead documents the valid values only in the flag description string.\",\n    \"assertions\": [\n      {\n        \"id\": \"8.1\",\n        \"text\": \"Calls cmd.RegisterFlagCompletionFunc(\\\"output\\\", func(...) ...)\"\n      },\n      {\n        \"id\": \"8.2\",\n        \"text\": \"The completion function returns []string{\\\"json\\\", \\\"yaml\\\", \\\"table\\\"} (or similar)\"\n      },\n      { \"id\": \"8.3\", \"text\": \"Returns cobra.ShellCompDirectiveNoFileComp\" },\n      {\n        \"id\": \"8.4\",\n        \"text\": \"Does NOT rely only on the flag usage string for user guidance\"\n      }\n    ]\n  },\n  {\n    \"id\": 9,\n    \"name\": \"test-isolation-fresh-root\",\n    \"description\": \"Tests that a fresh command tree must be created per test to avoid flag state leakage\",\n    \"prompt\": \"I'm writing tests for my Go cobra CLI. My first test runs 'myapp serve --port 9090' and passes. My second test runs 'myapp serve' without --port and expects the default 8080, but gets 9090. What's wrong and how do I fix it?\",\n    \"trap\": \"Without the skill, the model may suggest resetting the flag value manually or calling ResetFlags(). The correct fix is to create a fresh command tree per test.\",\n    \"assertions\": [\n      {\n        \"id\": \"9.1\",\n        \"text\": \"Identifies the root cause as reusing the same cobra.Command instance across tests\"\n      },\n      {\n        \"id\": \"9.2\",\n        \"text\": \"Recommends building a new command tree per test (constructor function)\"\n      },\n      {\n        \"id\": \"9.3\",\n        \"text\": \"Shows a newRootCmd() or similar factory function pattern\"\n      },\n      {\n        \"id\": \"9.4\",\n        \"text\": \"Does NOT suggest ResetFlags() as the primary solution\"\n      },\n      {\n        \"id\": \"9.5\",\n        \"text\": \"Each test calls the factory to get a fresh *cobra.Command\"\n      }\n    ]\n  },\n  {\n    \"id\": 10,\n    \"name\": \"match-all-validator-composition\",\n    \"description\": \"Tests MatchAll for composing multiple arg validators\",\n    \"prompt\": \"My Go cobra 'apply' command needs positional args that are all valid resource names (from a known list) AND there must be at least one. How do I express both constraints?\",\n    \"trap\": \"Without the skill, the model writes a custom validator function that manually checks both conditions with if statements. MatchAll composes built-in validators without custom code.\",\n    \"assertions\": [\n      { \"id\": \"10.1\", \"text\": \"Uses cobra.MatchAll to compose validators\" },\n      {\n        \"id\": \"10.2\",\n        \"text\": \"Combines cobra.MinimumNArgs(1) (or ExactArgs) with cobra.OnlyValidArgs\"\n      },\n      { \"id\": \"10.3\", \"text\": \"Sets ValidArgs with the known resource names\" },\n      {\n        \"id\": \"10.4\",\n        \"text\": \"Does NOT write a fully manual validator function for the combined check\"\n      }\n    ]\n  },\n  {\n    \"id\": 11,\n    \"name\": \"cobra-vs-viper-distinction\",\n    \"description\": \"Tests understanding of what cobra does vs what viper does\",\n    \"prompt\": \"I'm starting a Go CLI project. I need subcommands, flags, shell completions, AND the ability to read configuration from a YAML file and environment variables. I've heard of cobra and viper. Which library handles which concern?\",\n    \"trap\": \"Without the skill, the model may conflate the two or understate how they integrate. The correct answer clearly assigns cobra=command tree/flags/completions and viper=layered config resolution, with BindPFlag as the integration seam.\",\n    \"assertions\": [\n      {\n        \"id\": \"11.1\",\n        \"text\": \"Assigns cobra to command tree, flags, arg validation, shell completions\"\n      },\n      {\n        \"id\": \"11.2\",\n        \"text\": \"Assigns viper to config file, env var, and layered value resolution\"\n      },\n      {\n        \"id\": \"11.3\",\n        \"text\": \"Identifies BindPFlag (or similar) as the integration seam between them\"\n      },\n      {\n        \"id\": \"11.4\",\n        \"text\": \"Explains they can be used independently (cobra without viper, or viper without cobra)\"\n      },\n      {\n        \"id\": \"11.5\",\n        \"text\": \"Does NOT say cobra reads config files or viper defines subcommands\"\n      }\n    ]\n  },\n  {\n    \"id\": 12,\n    \"name\": \"cobra-cli-scaffolder\",\n    \"description\": \"Tests knowledge of the cobra-cli scaffolding tool\",\n    \"prompt\": \"I want to quickly scaffold a new Go CLI project with cobra. Is there a tool that generates the initial files and lets me add subcommands from the command line?\",\n    \"trap\": \"Without the skill, the model may say to create files manually or use a generic project generator. The cobra-cli tool is the canonical scaffolder for cobra projects.\",\n    \"assertions\": [\n      {\n        \"id\": \"12.1\",\n        \"text\": \"Mentions cobra-cli (github.com/spf13/cobra-cli)\"\n      },\n      {\n        \"id\": \"12.2\",\n        \"text\": \"Shows 'cobra-cli init <project>' for initialization\"\n      },\n      {\n        \"id\": \"12.3\",\n        \"text\": \"Shows 'cobra-cli add <command>' for adding subcommands\"\n      },\n      {\n        \"id\": \"12.4\",\n        \"text\": \"Explains that cobra-cli is separate from cobra itself (different import path)\"\n      }\n    ]\n  },\n  {\n    \"id\": 13,\n    \"name\": \"stringarray-vs-stringslice-commas\",\n    \"description\": \"Tests StringArray vs StringSlice when flag values contain commas\",\n    \"prompt\": \"My Go cobra CLI has a --label flag that users pass multiple times like --label 'env=prod,region=us'. With my current setup, passing --label 'env=prod,region=us' results in two separate values ['env=prod', 'region=us'] instead of one. What flag type should I use?\",\n    \"trap\": \"Without the skill, the model uses StringSlice which splits on commas. StringArray is the correct choice when values may legitimately contain commas.\",\n    \"assertions\": [\n      {\n        \"id\": \"13.1\",\n        \"text\": \"Recommends StringArray (or StringArrayVar) instead of StringSlice\"\n      },\n      {\n        \"id\": \"13.2\",\n        \"text\": \"Explains that StringSlice splits on commas while StringArray does not\"\n      },\n      {\n        \"id\": \"13.3\",\n        \"text\": \"Does NOT suggest quoting or escaping commas as the fix\"\n      },\n      {\n        \"id\": \"13.4\",\n        \"text\": \"Shows the correct flag definition using StringArray or StringArrayVar\"\n      }\n    ]\n  },\n  {\n    \"id\": 14,\n    \"name\": \"mutually-exclusive-flags\",\n    \"description\": \"Tests MarkFlagsMutuallyExclusive instead of manual RunE checks\",\n    \"prompt\": \"My Go cobra command has --json and --yaml flags for output format. Users should only be able to pass one of them. How do I prevent both from being passed at the same time?\",\n    \"trap\": \"Without the skill, the model writes an if statement checking both flags inside RunE. The correct approach is MarkFlagsMutuallyExclusive which cobra enforces at parse time before RunE.\",\n    \"assertions\": [\n      {\n        \"id\": \"14.1\",\n        \"text\": \"Calls cmd.MarkFlagsMutuallyExclusive(\\\"json\\\", \\\"yaml\\\")\"\n      },\n      {\n        \"id\": \"14.2\",\n        \"text\": \"Does NOT write a manual if-both-set check inside RunE\"\n      },\n      {\n        \"id\": \"14.3\",\n        \"text\": \"Explains cobra enforces this at flag parse time and returns a standard error\"\n      }\n    ]\n  },\n  {\n    \"id\": 15,\n    \"name\": \"required-together-flags\",\n    \"description\": \"Tests MarkFlagsRequiredTogether instead of manual RunE checks\",\n    \"prompt\": \"My Go cobra command has --tls-cert and --tls-key flags. If a user provides one, they must provide the other. How do I enforce this constraint?\",\n    \"trap\": \"Without the skill, the model writes manual validation in RunE checking if one is set without the other. MarkFlagsRequiredTogether enforces this at cobra's parse stage.\",\n    \"assertions\": [\n      {\n        \"id\": \"15.1\",\n        \"text\": \"Calls cmd.MarkFlagsRequiredTogether(\\\"tls-cert\\\", \\\"tls-key\\\")\"\n      },\n      {\n        \"id\": \"15.2\",\n        \"text\": \"Does NOT write manual if-one-without-the-other checks inside RunE\"\n      },\n      {\n        \"id\": \"15.3\",\n        \"text\": \"Explains cobra validates this before RunE runs\"\n      }\n    ]\n  },\n  {\n    \"id\": 16,\n    \"name\": \"one-required-flag-group\",\n    \"description\": \"Tests MarkFlagsOneRequired instead of manual RunE checks\",\n    \"prompt\": \"My Go cobra command accepts input from either --file or --stdin. At least one must be provided. How do I enforce that the user passes at least one of them?\",\n    \"trap\": \"Without the skill, the model checks flag presence inside RunE. MarkFlagsOneRequired enforces at parse time with a standard cobra error.\",\n    \"assertions\": [\n      {\n        \"id\": \"16.1\",\n        \"text\": \"Calls cmd.MarkFlagsOneRequired(\\\"file\\\", \\\"stdin\\\")\"\n      },\n      {\n        \"id\": \"16.2\",\n        \"text\": \"Does NOT write a manual check inside RunE for neither flag being set\"\n      },\n      {\n        \"id\": \"16.3\",\n        \"text\": \"Explains cobra enforces this before RunE runs\"\n      }\n    ]\n  },\n  {\n    \"id\": 17,\n    \"name\": \"flag-changed-distinguish-explicit-zero\",\n    \"description\": \"Tests cmd.Flags().Changed() to distinguish explicit zero from absent flag\",\n    \"prompt\": \"My Go cobra command has a --timeout flag defaulting to 30s. Users can pass --timeout 0 to disable timeouts entirely. In RunE, how do I tell whether the user explicitly passed --timeout 0 or simply didn't pass --timeout at all?\",\n    \"trap\": \"Without the skill, the model checks if timeout == 0, which conflates the two cases. The correct approach is cmd.Flags().Changed(\\\"timeout\\\") which returns true only when the user explicitly provided the flag.\",\n    \"assertions\": [\n      {\n        \"id\": \"17.1\",\n        \"text\": \"Uses cmd.Flags().Changed(\\\"timeout\\\") to detect explicit user input\"\n      },\n      {\n        \"id\": \"17.2\",\n        \"text\": \"Does NOT use if timeout == 0 as the sole distinguishing condition\"\n      },\n      {\n        \"id\": \"17.3\",\n        \"text\": \"Explains Changed() returns true only when the flag was explicitly set by the user\"\n      },\n      {\n        \"id\": \"17.4\",\n        \"text\": \"Shows the pattern: if Changed → apply value, else → use default behavior\"\n      }\n    ]\n  },\n  {\n    \"id\": 18,\n    \"name\": \"postrunE-success-only-use-defer\",\n    \"description\": \"Tests that PostRunE runs only on RunE success and defer is the right cleanup pattern\",\n    \"prompt\": \"My Go cobra command opens a database connection early in RunE and I want to close it when the command finishes, whether it succeeds or fails. I added cleanup in PostRunE but noticed it doesn't run when RunE returns an error. What's the right pattern?\",\n    \"trap\": \"Without the skill, the model may suggest PersistentPostRunE or not know PostRunE is success-only. The correct pattern is defer inside RunE for guaranteed cleanup regardless of outcome.\",\n    \"assertions\": [\n      {\n        \"id\": \"18.1\",\n        \"text\": \"Uses defer inside RunE to guarantee cleanup on both success and failure\"\n      },\n      {\n        \"id\": \"18.2\",\n        \"text\": \"Explains PostRunE only runs when RunE returns nil (success)\"\n      },\n      {\n        \"id\": \"18.3\",\n        \"text\": \"Does NOT present PostRunE as a solution for failure cleanup\"\n      }\n    ]\n  },\n  {\n    \"id\": 19,\n    \"name\": \"errOrStderr-not-os-stderr\",\n    \"description\": \"Tests cmd.ErrOrStderr() instead of os.Stderr for capturable error output\",\n    \"prompt\": \"My Go cobra command writes diagnostic details to stderr using fmt.Fprintf(os.Stderr, ...) before returning an error. This works fine at runtime but my tests can't capture the stderr output. How do I fix this?\",\n    \"trap\": \"Without the skill, the model uses os.Stderr directly. The correct approach is cmd.ErrOrStderr() which tests can redirect via rootCmd.SetErr(buf).\",\n    \"assertions\": [\n      {\n        \"id\": \"19.1\",\n        \"text\": \"Replaces os.Stderr with cmd.ErrOrStderr() as the write target\"\n      },\n      { \"id\": \"19.2\", \"text\": \"Does NOT use os.Stderr directly\" },\n      {\n        \"id\": \"19.3\",\n        \"text\": \"Shows rootCmd.SetErr(buf) in the test to capture stderr output\"\n      },\n      {\n        \"id\": \"19.4\",\n        \"text\": \"Explains the symmetry with cmd.OutOrStdout() / SetOut for stdout\"\n      }\n    ]\n  }\n]\n\nArchive v1.0.0: 8 files, 18176 bytes\n\nFiles: evals/evals.json (19592b), references/commands-and-args.md (5009b), references/completions.md (4007b), references/flags.md (3921b), references/generators.md (2240b), references/testing.md (3800b), SKILL.md (10002b), _meta.json (137b)\n\nFile v1.0.0:SKILL.md\n\n---\nname: golang-spf13-cobra\ndescription: \"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 configuration layering alongside cobra, see the `samber/cc-skills-golang@golang-spf13-viper` skill. For general CLI architecture (project layout, exit codes, signal handling, I/O patterns), see `samber/cc-skills-golang@golang-cli`.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.0.0\"\n  openclaw:\n    emoji: \"🐍\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n    install: []\n    skill-library-version: \"1.10.2\"\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs\n---\n\n**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.\n\n**Modes:**\n\n- **Build** — creating a new CLI from scratch: follow command tree setup, hook wiring, and flag sections sequentially.\n- **Extend** — adding subcommands, flags, or completions to an existing CLI: read the current command tree first, then apply changes consistent with the existing structure.\n- **Review** — auditing an existing CLI: check the Common Mistakes table, verify `RunE` usage, `OutOrStdout()`, hook chain ordering, and args validation.\n\n# Using spf13/cobra for CLI command trees in Go\n\nCobra 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.\n\n**Official Resources:**\n\n- [pkg.go.dev/github.com/spf13/cobra](https://pkg.go.dev/github.com/spf13/cobra)\n- [github.com/spf13/cobra](https://github.com/spf13/cobra)\n- [cobra.dev](https://cobra.dev)\n\nThis skill is not exhaustive. Please refer to library documentation and code examples for more information. Context7 can help as a discoverability platform.\n\n```bash\ngo get github.com/spf13/cobra@latest\n```\n\n## Cobra vs. viper\n\nThese libraries do fundamentally different things and can be used independently.\n\n| Concern | cobra | viper |\n| --- | --- | --- |\n| Owns | Command tree, flags, arg validation, completions | Configuration value resolution |\n| User-facing? | Yes — subcommands, flags, help text | No — purely a key-value resolver |\n| Without the other? | Yes — a CLI with flags only needs cobra | Yes — a daemon reading YAML + env needs only viper |\n| Integration seam | Hands `pflag.Flag` to viper via `BindPFlag` | Treats the cobra flag as the highest-precedence layer |\n\n**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.\n\n→ See `samber/cc-skills-golang@golang-spf13-viper` for the viper side of this integration.\n\n## Command tree\n\nEvery cobra CLI has a root command plus zero or more subcommands registered with `AddCommand`. The root command name is the binary name.\n\n```go\nvar rootCmd = &cobra.Command{\n    Use:          \"myapp\",\n    Short:        \"One-line summary\",\n    SilenceUsage: true,  // ✓ prevents usage wall on every error\n    SilenceErrors: true, // ✓ lets you control error output format\n}\n```\n\nUse `AddGroup` to label subcommands in help output — register groups **before** the `AddCommand` calls that reference them; cobra does not retroactively assign groups.\n\n## The Run\\* family\n\nCobra commands have five run hooks executed in order:\n\n```\nPersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE\n```\n\nAlways use `*E` variants — the non-`E` forms cannot return errors. Key rules:\n\n- `PersistentPreRunE` on the root runs before **every** subcommand — use it for config init and auth checks.\n- A child `PersistentPreRunE` **replaces** the parent's entirely — call the parent explicitly if you need both.\n- `PostRunE` runs only if `RunE` succeeded.\n\nFor the full lifecycle and inheritance rules, see [commands-and-args.md](references/commands-and-args.md).\n\n## Args validators\n\nCobra validates positional arguments before `RunE` runs. Never write `len(args)` checks inside `RunE` — that bypasses cobra's standard error messages and arg count tracking.\n\nBuilt-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`.\n\nFor the full validator set with examples and `MatchAll` patterns, see [commands-and-args.md](references/commands-and-args.md).\n\n## Flags primer\n\nCobra delegates flag parsing to `pflag`. **Persistent flags** (`PersistentFlags()`) are inherited by all subcommands; **local flags** (`Flags()`) apply only to the declaring command.\n\n```go\nrootCmd.PersistentFlags().StringVar(&cfgFile, \"config\", \"\", \"config file path\") // inherited by all subcommands\nserveCmd.Flags().IntVar(&port, \"port\", 8080, \"listen port\")                     // local to serveCmd only\nserveCmd.MarkFlagRequired(\"port\")\nserveCmd.MarkFlagsMutuallyExclusive(\"json\", \"yaml\")\n```\n\nFor pflag types, custom flag values, flag groups, and viper binding, see [flags.md](references/flags.md).\n\n## Completions primer\n\nCobra generates shell completions automatically. Extend them with:\n\n- **`ValidArgs []string`** — static positional arg completion.\n- **`ValidArgsFunction`** — dynamic: `func(cmd, args, toComplete string) ([]string, ShellCompDirective)`. Return `ShellCompDirectiveNoFileComp` to suppress file fallback.\n- **`RegisterFlagCompletionFunc(name, fn)`** — flag value completion.\n\nFor `ShellCompDirective` values, annotations, and testing, see [completions.md](references/completions.md).\n\n## Testing commands\n\nTest 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.\n\n```go\nfunc TestServeCmd(t *testing.T) {\n    buf := new(bytes.Buffer)\n    rootCmd.SetOut(buf)\n    rootCmd.SetArgs([]string{\"serve\", \"--port\", \"9090\"})\n    require.NoError(t, rootCmd.Execute())\n    assert.Contains(t, buf.String(), \"listening on :9090\")\n}\n```\n\nCobra accumulates flag state across `Execute()` calls — build a fresh command tree per test. For isolation patterns, golden files, and testing completions, see [testing.md](references/testing.md).\n\n## Best Practices\n\n1. **Always use `RunE`, never `Run`** — `Run` cannot return an error; the only escape is `os.Exit` or panic, bypassing defers.\n2. **Put config initialization in `PersistentPreRunE`** — it runs before every subcommand; the right place for viper binding and auth checks.\n3. **Validate positional args with `Args`, not inside `RunE`** — `Args` gives cobra's standard error messages; `MatchAll` composes validators.\n4. **Use `cmd.OutOrStdout()` / `cmd.ErrOrStderr()` for all output** — direct `os.Stdout` writes cannot be captured by tests.\n5. **Re-create the command tree per test** — cobra accumulates flag state across `Execute()` calls on the same instance.\n\n## Common Mistakes\n\n| Mistake | Why it fails | Fix |\n| --- | --- | --- |\n| 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 |\n| Writing `len(args)` checks in `RunE` | Bypasses cobra's standard error messages (\"accepts 1 arg, received 2\") | Declare `Args: cobra.ExactArgs(1)` on the command |\n| Writing to `os.Stdout` directly | Tests cannot capture output — os-level file handles can't be redirected | Use `cmd.OutOrStdout()` / `cmd.ErrOrStderr()` |\n| Child `PersistentPreRunE` silently drops parent's | Cobra does not chain — the child replaces the parent's hook entirely | Call `parent.PersistentPreRunE(cmd, args)` from the child's hook |\n| Reusing a root command across tests | Cobra accumulates flag state; second `Execute()` sees flags from the first | Build a fresh command tree per test |\n\n## Further Reading\n\n- [commands-and-args.md](references/commands-and-args.md) — full PreRun\\*/PostRun\\* chain, every Args validator, PersistentPreRunE inheritance rules\n- [flags.md](references/flags.md) — pflag types, required/exclusive/oneRequired groups, custom value types, viper binding\n- [completions.md](references/completions.md) — ShellCompDirective set, annotation-based completions, testing completions\n- [generators.md](references/generators.md) — man page, markdown, YAML, RST doc generation; `cobra-cli` scaffolder\n- [testing.md](references/testing.md) — isolation patterns, golden files, testing completions, table-driven command tests\n\n## Cross-References\n\n- → See `samber/cc-skills-golang@golang-cli` skill for general CLI architecture — project layout, exit codes, signal handling, I/O patterns\n- → See `samber/cc-skills-golang@golang-spf13-viper` skill for configuration layering alongside cobra (flag → env → file → default precedence)\n- → See `samber/cc-skills-golang@golang-testing` skill for general Go testing patterns\n\nIf you encounter a bug or unexpected behavior in spf13/cobra, open an issue at <https://github.com/spf13/cobra/issues>.\n\nFile v1.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-spf13-cobra\",\n  \"version\": \"1.0.0\",\n  \"publishedAt\": 1777636631150\n}\n\nFile v1.0.0:references/commands-and-args.md\n\n# Cobra Commands, Hooks, and Args Validators\n\n## The Run\\* lifecycle\n\nCobra commands have five run hooks. Cobra executes them in this fixed order:\n\n```\nPersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE\n```\n\nEach `*E` hook returns `error`. The non-`*E` variants (`PersistentPreRun`, `PreRun`, `Run`, `PostRun`, `PersistentPostRun`) have signature `func(cmd *cobra.Command, args []string)` — they cannot signal failure without `os.Exit` or panic. **Always use the `*E` variants.**\n\n### Which hook to use\n\n| Hook | Scope | When to use |\n| --- | --- | --- |\n| `PersistentPreRunE` | Parent + all descendants | Config init, auth check, telemetry setup — must run before every subcommand |\n| `PreRunE` | This command only | Validation that runs only for this command before `RunE` |\n| `RunE` | This command only | Main handler — the primary business logic |\n| `PostRunE` | This command only | Cleanup that runs only if `RunE` succeeded |\n| `PersistentPostRunE` | Parent + all descendants | Global cleanup (close connections, flush buffers) |\n\n### Inheritance rules\n\n`PersistentPreRunE` defined on the root command runs before every subcommand. But if a child command defines **its own** `PersistentPreRunE`, it **replaces** (does not chain) the parent's hook. Call the parent explicitly if you need both:\n\n```go\nvar childCmd = &cobra.Command{\n    PersistentPreRunE: func(cmd *cobra.Command, args []string) error {\n        // call parent's hook first\n        if err := rootCmd.PersistentPreRunE(cmd, args); err != nil {\n            return err\n        }\n        // child-specific logic\n        return nil\n    },\n}\n```\n\n### Execution stops on first error\n\nIf `PersistentPreRunE` returns an error, cobra stops — `RunE` and later hooks never run. Use this for fail-fast auth checks.\n\n## Args validators\n\nArgs validators run before `RunE`. Cobra prints a clear error message and exits without calling `RunE` when validation fails.\n\n### Built-in validators\n\n```go\ncobra.NoArgs                        // fails if any positional args provided\ncobra.ArbitraryArgs                 // accepts any number of args (default)\ncobra.ExactArgs(n int)              // requires exactly n args\ncobra.MinimumNArgs(n int)           // requires at least n args\ncobra.MaximumNArgs(n int)           // requires at most n args\ncobra.RangeArgs(min, max int)       // requires between min and max args\ncobra.OnlyValidArgs                 // all args must be in ValidArgs list\ncobra.ExactValidArgs(n int)         // exactly n args, all in ValidArgs\n```\n\n### Composing validators with MatchAll\n\n```go\nvar deleteCmd = &cobra.Command{\n    Use:       \"delete <resource>\",\n    Args:      cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),\n    ValidArgs: []string{\"pod\", \"service\", \"deployment\"},\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return doDelete(args[0])\n    },\n}\n```\n\n### Custom validators\n\nSignature: `func(cmd *cobra.Command, args []string) error`\n\n```go\nfunc validatePositiveInt(cmd *cobra.Command, args []string) error {\n    if len(args) != 1 {\n        return fmt.Errorf(\"requires exactly 1 arg, got %d\", len(args))\n    }\n    n, err := strconv.Atoi(args[0])\n    if err != nil || n <= 0 {\n        return fmt.Errorf(\"argument must be a positive integer, got %q\", args[0])\n    }\n    return nil\n}\n\nvar cmd = &cobra.Command{\n    Args: validatePositiveInt,\n    RunE: func(cmd *cobra.Command, args []string) error { /* ... */ },\n}\n```\n\nCombine custom validators with built-in ones using `MatchAll`:\n\n```go\nArgs: cobra.MatchAll(cobra.MinimumNArgs(1), validateAllPositive),\n```\n\n## Command registration and ordering\n\n```go\nfunc init() {\n    // groups must be registered before AddCommand\n    rootCmd.AddGroup(&cobra.Group{ID: \"core\", Title: \"Core Commands:\"})\n    rootCmd.AddGroup(&cobra.Group{ID: \"management\", Title: \"Management Commands:\"})\n\n    serveCmd.GroupID = \"core\"\n    migrateCmd.GroupID = \"management\"\n\n    rootCmd.AddCommand(serveCmd, migrateCmd, versionCmd)\n}\n```\n\n`versionCmd` has no `GroupID` — it appears in the default section.\n\n## Annotations\n\nCobra supports arbitrary command annotations for framework-level metadata:\n\n```go\nvar serveCmd = &cobra.Command{\n    Annotations: map[string]string{\n        \"category\": \"network\",\n        \"requires-auth\": \"true\",\n    },\n}\n\n// read in a middleware hook:\nif serveCmd.Annotations[\"requires-auth\"] == \"true\" {\n    // enforce auth\n}\n```\n\n## Hidden and deprecated commands\n\n```go\nvar internalCmd = &cobra.Command{\n    Hidden: true,      // not shown in help, still executable\n}\n\nvar oldCmd = &cobra.Command{\n    Deprecated: \"use `newcmd` instead\",  // shown in help, prints warning on use\n}\n```\n\n## cobra.CheckErr\n\n`cobra.CheckErr(err)` is a convenience function: if `err != nil`, it prints the error to `cmd.ErrOrStderr()` and calls `os.Exit(1)`. Use it only in `main()` where you want a hard exit — not inside `RunE` where returning the error is preferred.\n\n```go\nfunc main() {\n    cobra.CheckErr(rootCmd.Execute())\n}\n```\n\nFile v1.0.0:references/completions.md\n\n# Cobra Shell Completions Reference\n\nCobra generates shell completion scripts for bash, zsh, fish, and PowerShell automatically. Subcommand names and flag names are completed for free. You add completions for flag values and positional arguments.\n\n## Built-in completion command\n\nCobra registers a `completion` subcommand automatically:\n\n```bash\nmyapp completion bash   # generate bash script\nmyapp completion zsh    # generate zsh script\nmyapp completion fish   # generate fish script\nmyapp completion powershell\n\n# Install (example for zsh):\nmyapp completion zsh > \"${fpath[1]}/_myapp\"\n```\n\n## ShellCompDirective\n\nThe `ShellCompDirective` controls shell behavior after your completion function returns:\n\n| Directive | Meaning |\n| --- | --- |\n| `ShellCompDirectiveDefault` | Fall back to file completion after your results |\n| `ShellCompDirectiveNoFileComp` | Disable file completion fallback |\n| `ShellCompDirectiveNoSpace` | Don't add a space after the completion |\n| `ShellCompDirectiveFilterFileExt(exts)` | Only show files with given extensions |\n| `ShellCompDirectiveFilterDirs(dirs)` | Only show directories |\n| `ShellCompDirectiveError` | Signal an error (show no completions) |\n\nCombine with bitwise OR: `cobra.ShellCompDirectiveNoFileComp | cobra.ShellCompDirectiveNoSpace`.\n\nUse `ShellCompDirectiveNoFileComp` whenever your list is exhaustive — it prevents the shell from appending irrelevant files.\n\n## Static arg completions\n\n```go\nvar getCmd = &cobra.Command{\n    Use:       \"get <resource>\",\n    ValidArgs: []string{\"pod\", \"service\", \"deployment\", \"configmap\"},\n    Args:      cobra.OnlyValidArgs,\n    RunE: func(cmd *cobra.Command, args []string) error { /* ... */ },\n}\n```\n\n## Dynamic arg completions\n\n```go\nvar getCmd = &cobra.Command{\n    ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        if len(args) > 0 {\n            // first arg already provided — no more completions\n            return nil, cobra.ShellCompDirectiveNoFileComp\n        }\n        resources, err := listResources(toComplete)\n        if err != nil {\n            return nil, cobra.ShellCompDirectiveError\n        }\n        return resources, cobra.ShellCompDirectiveNoFileComp\n    },\n}\n```\n\n`toComplete` is the prefix the user has typed so far — filter your results by it for responsive completions.\n\n## Flag value completions\n\n```go\nfunc init() {\n    rootCmd.RegisterFlagCompletionFunc(\"output\", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        return []string{\"json\\tJSON output\", \"yaml\\tYAML output\", \"table\\tTable output\"}, cobra.ShellCompDirectiveNoFileComp\n    })\n\n    rootCmd.RegisterFlagCompletionFunc(\"namespace\", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        ns, err := listNamespaces()\n        if err != nil {\n            return nil, cobra.ShellCompDirectiveError\n        }\n        return ns, cobra.ShellCompDirectiveNoFileComp\n    })\n}\n```\n\nDescriptions after `\\t` are shown in zsh and fish menus.\n\n## Completion annotations\n\nMark a flag to complete as a file or directory:\n\n```go\ncmd.Flags().String(\"config\", \"\", \"config file\")\ncmd.MarkFlagFilename(\"config\", \"yaml\", \"yml\", \"json\")  // only those extensions\n\ncmd.Flags().String(\"dir\", \"\", \"output directory\")\ncmd.MarkFlagDirname(\"dir\")\n```\n\n## Testing completions\n\n```go\nfunc TestCompletion(t *testing.T) {\n    rootCmd.SetArgs([]string{\"__complete\", \"get\", \"\"})\n    buf := new(bytes.Buffer)\n    rootCmd.SetOut(buf)\n    rootCmd.Execute()\n    assert.Contains(t, buf.String(), \"pod\")\n    assert.Contains(t, buf.String(), \"service\")\n}\n```\n\n`__complete` is cobra's internal completion request verb. Pass the partial args as additional arguments.\n\n## Disabling the completion command\n\n```go\nrootCmd.CompletionOptions.DisableDefaultCmd = true   // remove the completion subcommand\nrootCmd.CompletionOptions.HiddenDefaultCmd = true    // keep it but hide from help\n```\n\nFile v1.0.0:references/flags.md\n\n# Cobra Flags Reference\n\nCobra delegates all flag parsing to `github.com/spf13/pflag`. `cobra.Command` exposes two `*pflag.FlagSet`s:\n\n- `cmd.Flags()` — local flags, only available on this command.\n- `cmd.PersistentFlags()` — inherited by all subcommands.\n\n## Common flag types\n\n```go\n// String\ncmd.Flags().String(\"name\", \"default\", \"description\")\ncmd.Flags().StringP(\"name\", \"n\", \"default\", \"description\")  // with shorthand\n\n// With pointer binding (no Lookup needed later)\nvar name string\ncmd.Flags().StringVar(&name, \"name\", \"default\", \"description\")\ncmd.Flags().StringVarP(&name, \"name\", \"n\", \"default\", \"description\")\n\n// Other types follow the same pattern:\ncmd.Flags().Int / IntVar / IntVarP\ncmd.Flags().Bool / BoolVar / BoolVarP\ncmd.Flags().Float64 / Float64Var\ncmd.Flags().Duration / DurationVar       // parses \"1h30m\", \"500ms\"\ncmd.Flags().StringSlice / StringSliceVar // comma-separated or repeated flags\ncmd.Flags().StringArray / StringArrayVar // repeated flags only (no comma splitting)\ncmd.Flags().IntSlice / IntSliceVar\ncmd.Flags().StringToString                // --label key=value --label k2=v2\n```\n\n## StringSlice vs StringArray\n\n| Flag type     | Input                 | Result                            |\n| ------------- | --------------------- | --------------------------------- |\n| `StringSlice` | `--tags a,b --tags c` | `[\"a\", \"b\", \"c\"]` — commas split  |\n| `StringArray` | `--tags a,b --tags c` | `[\"a,b\", \"c\"]` — commas NOT split |\n\nUse `StringArray` when values may legitimately contain commas.\n\n## Flag constraints\n\n```go\n// Fail if flag not provided\ncmd.MarkFlagRequired(\"output\")\n\n// Fail if both provided\ncmd.MarkFlagsMutuallyExclusive(\"json\", \"yaml\", \"table\")\n\n// Fail if none provided\ncmd.MarkFlagsOneRequired(\"file\", \"stdin\")\n\n// Require flag only if another flag is set\ncmd.MarkFlagsMutuallyExclusive(\"tls\", \"no-tls\")\n```\n\n## Persistent flag patterns\n\n```go\nfunc init() {\n    // global flags on root\n    rootCmd.PersistentFlags().StringVar(&cfgFile, \"config\", \"\", \"config file (default: $HOME/.myapp.yaml)\")\n    rootCmd.PersistentFlags().StringVar(&logLevel, \"log-level\", \"info\", \"log level (debug, info, warn, error)\")\n\n    // bind to viper immediately after defining\n    viper.BindPFlag(\"config\", rootCmd.PersistentFlags().Lookup(\"config\"))\n    viper.BindPFlag(\"log-level\", rootCmd.PersistentFlags().Lookup(\"log-level\"))\n}\n```\n\n## Custom flag value types\n\nImplement `pflag.Value` to parse arbitrary types:\n\n```go\ntype enumValue struct {\n    val     string\n    allowed []string\n}\n\nfunc (e *enumValue) String() string { return e.val }\nfunc (e *enumValue) Type() string   { return \"enum\" }\nfunc (e *enumValue) Set(s string) error {\n    for _, a := range e.allowed {\n        if s == a {\n            e.val = s\n            return nil\n        }\n    }\n    return fmt.Errorf(\"must be one of %v\", e.allowed)\n}\n\nvar outputFmt = &enumValue{val: \"table\", allowed: []string{\"table\", \"json\", \"yaml\"}}\ncmd.Flags().Var(outputFmt, \"output\", \"output format (table, json, yaml)\")\n```\n\n## Flag groups (required together)\n\nMark a set of flags that must all be provided if any one of them is provided:\n\n```go\ncmd.Flags().String(\"tls-cert\", \"\", \"TLS certificate file\")\ncmd.Flags().String(\"tls-key\", \"\", \"TLS key file\")\ncmd.MarkFlagsRequiredTogether(\"tls-cert\", \"tls-key\")\n```\n\n## Accessing flag values\n\nPrefer pointer binding (`StringVar`, `IntVar`, etc.) for type-safe access. When you need the flag post-parse:\n\n```go\nport, err := cmd.Flags().GetInt(\"port\")\nname, err := cmd.Flags().GetString(\"name\")\ntags, err := cmd.Flags().GetStringSlice(\"tags\")\n```\n\n## Flag changed vs default\n\n```go\nif cmd.Flags().Changed(\"port\") {\n    // user explicitly provided --port\n    // useful when distinguishing \"user set 0\" from \"flag not provided\"\n}\n```\n\n`Changed()` is also how viper knows which flags are explicit overrides — it only promotes a flag to the highest precedence layer if `Changed()` is true.\n\nFile v1.0.0:references/generators.md\n\n# Cobra Documentation and Scaffolding Generators\n\n## Doc generation\n\nCobra can generate documentation from your command tree in multiple formats. Import the `cobra/doc` sub-package:\n\n```bash\ngo get github.com/spf13/cobra/doc\n```\n\n### Markdown\n\n```go\nimport \"github.com/spf13/cobra/doc\"\n\nerr := doc.GenMarkdownTree(rootCmd, \"/tmp/docs/\")\n// generates /tmp/docs/myapp.md, /tmp/docs/myapp_serve.md, etc.\n\n// Single command\nvar buf bytes.Buffer\ndoc.GenMarkdown(rootCmd, &buf)\n```\n\n### Man pages\n\n```go\nheader := &doc.GenManHeader{\n    Title:   \"MYAPP\",\n    Section: \"1\",\n    Date:    &time.Time{},\n    Source:  \"myapp v1.0.0\",\n    Manual:  \"User Commands\",\n}\nerr := doc.GenManTree(rootCmd, header, \"/usr/local/share/man/man1/\")\n```\n\n### YAML\n\n```go\nerr := doc.GenYamlTree(rootCmd, \"/tmp/docs/\")\n```\n\n### RST (reStructuredText)\n\n```go\nerr := doc.GenReSTTree(rootCmd, \"/tmp/docs/\")\n```\n\n## cobra-cli scaffolder\n\n`cobra-cli` generates command files and wires them into your project:\n\n```bash\ngo install github.com/spf13/cobra-cli@latest\n\n# Initialize a new cobra project\ncobra-cli init myapp\n\n# Add a subcommand\ncobra-cli add serve\ncobra-cli add migrate\n\n# Add with a parent other than root\ncobra-cli add list --parent serve\n```\n\nGenerated files follow the standard pattern:\n\n```go\n// cmd/serve.go\nvar serveCmd = &cobra.Command{\n    Use:   \"serve\",\n    Short: \"A brief description of your command\",\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return nil\n    },\n}\n\nfunc init() {\n    rootCmd.AddCommand(serveCmd)\n}\n```\n\n`cobra-cli` is optional — many teams write command files by hand following the same pattern.\n\n## Help and usage template customization\n\nOverride the default help template:\n\n```go\nrootCmd.SetHelpTemplate(`\nUsage:  {{.UseLine}}\n{{if .HasAvailableSubCommands}}\nCommands:\n{{range .Commands}}{{if .IsAvailableCommand}}  {{rpad .Name .NamePadding }} {{.Short}}\n{{end}}{{end}}{{end}}\nFlags:\n{{.LocalFlags.FlagUsages | trimRightSpace}}\n`)\n```\n\nOverride the usage function entirely:\n\n```go\nrootCmd.SetUsageFunc(func(cmd *cobra.Command) error {\n    fmt.Fprintf(cmd.OutOrStdout(), \"Custom usage for %s\\n\", cmd.Name())\n    return nil\n})\n```\n\nCommon template functions available: `rpad`, `trimRightSpace`, `gt`, `eq`.\n\nFile v1.0.0:references/testing.md\n\n# Testing Cobra Commands\n\n## Basic test pattern\n\n```go\nfunc TestServeCmd(t *testing.T) {\n    stdout := new(bytes.Buffer)\n    stderr := new(bytes.Buffer)\n\n    rootCmd.SetOut(stdout)\n    rootCmd.SetErr(stderr)\n    rootCmd.SetArgs([]string{\"serve\", \"--port\", \"9090\", \"--dry-run\"})\n\n    err := rootCmd.Execute()\n    require.NoError(t, err)\n    assert.Contains(t, stdout.String(), \"listening on :9090\")\n    assert.Empty(t, stderr.String())\n}\n```\n\n## Isolation between tests\n\nCobra accumulates flag state across `Execute()` calls on the same command instance. Tests must be isolated.\n\n### Option 1: Re-create the command tree per test (recommended for unit tests)\n\n```go\nfunc newRootCmd() *cobra.Command {\n    root := &cobra.Command{Use: \"myapp\", SilenceUsage: true, SilenceErrors: true}\n    root.AddCommand(newServeCmd())\n    return root\n}\n\nfunc TestServeCmd(t *testing.T) {\n    root := newRootCmd()\n    root.SetArgs([]string{\"serve\", \"--port\", \"9090\"})\n    err := root.Execute()\n    require.NoError(t, err)\n}\n```\n\n### Option 2: Reset flags between tests\n\n```go\nfunc TestWithReset(t *testing.T) {\n    t.Cleanup(func() {\n        rootCmd.ResetFlags()\n        // re-define flags if needed\n    })\n}\n```\n\nRe-creating is safer — `ResetFlags` only clears the flag set, not subcommand state.\n\n## Testing commands that write output\n\nCommands must use `cmd.OutOrStdout()` / `cmd.ErrOrStderr()` instead of `os.Stdout` / `os.Stderr` for this to work.\n\n```go\n// In command handler:\nfunc runServe(cmd *cobra.Command, args []string) error {\n    fmt.Fprintln(cmd.OutOrStdout(), \"Server started\")\n    fmt.Fprintln(cmd.ErrOrStderr(), \"Debug: listening on port 8080\")\n    return nil\n}\n\n// In test:\nbuf := new(bytes.Buffer)\nrootCmd.SetOut(buf)\nrootCmd.Execute()\nassert.Contains(t, buf.String(), \"Server started\")\n```\n\n## Golden file tests\n\nFor commands with structured or lengthy output, use golden files:\n\n```go\nfunc TestOutputFormat(t *testing.T) {\n    buf := new(bytes.Buffer)\n    rootCmd.SetOut(buf)\n    rootCmd.SetArgs([]string{\"list\", \"--output\", \"json\"})\n    require.NoError(t, rootCmd.Execute())\n\n    golden := \"testdata/list-json.golden\"\n    if *update {  // -update flag\n        os.WriteFile(golden, buf.Bytes(), 0644)\n    }\n    want, _ := os.ReadFile(golden)\n    assert.Equal(t, string(want), buf.String())\n}\n```\n\nRun with `-update` to regenerate golden files after intentional output changes.\n\n## Testing error paths\n\n```go\nfunc TestInvalidArgs(t *testing.T) {\n    stderr := new(bytes.Buffer)\n    rootCmd.SetErr(stderr)\n    rootCmd.SetArgs([]string{\"delete\"})  // missing required arg\n\n    err := rootCmd.Execute()\n    assert.Error(t, err)\n    assert.Contains(t, err.Error(), \"accepts 1 arg\")\n}\n```\n\n## Table-driven command tests\n\n```go\ntests := []struct {\n    name    string\n    args    []string\n    wantOut string\n    wantErr bool\n}{\n    {\"no flags\", []string{\"serve\"}, \"listening on :8080\", false},\n    {\"custom port\", []string{\"serve\", \"--port\", \"9090\"}, \"listening on :9090\", false},\n    {\"invalid port\", []string{\"serve\", \"--port\", \"abc\"}, \"\", true},\n}\n\nfor _, tt := range tests {\n    t.Run(tt.name, func(t *testing.T) {\n        root := newRootCmd()  // fresh command tree per test\n        buf := new(bytes.Buffer)\n        root.SetOut(buf)\n        root.SetArgs(tt.args)\n        err := root.Execute()\n        if tt.wantErr {\n            assert.Error(t, err)\n        } else {\n            require.NoError(t, err)\n            assert.Contains(t, buf.String(), tt.wantOut)\n        }\n    })\n}\n```\n\n## Testing completions\n\n```go\nfunc TestCompletion(t *testing.T) {\n    root := newRootCmd()\n    buf := new(bytes.Buffer)\n    root.SetOut(buf)\n    root.SetArgs([]string{\"__complete\", \"delete\", \"\"})\n    root.Execute()\n\n    assert.Contains(t, buf.String(), \"pod\")\n    assert.Contains(t, buf.String(), \"service\")\n}\n```\n\nFile v1.0.0:evals/evals.json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"rune-vs-run-error-propagation\",\n    \"description\": \"Tests use of RunE instead of Run for error propagation\",\n    \"prompt\": \"I'm writing a cobra subcommand in Go that calls an external API. If the API returns an error, the command should exit non-zero. Should I use Run or RunE?\",\n    \"trap\": \"Without the skill, the model may say both work, suggest using Run with os.Exit(1), or not explain why Run is problematic. The correct answer is always RunE — it propagates the error through cobra's error handling chain.\",\n    \"assertions\": [\n      { \"id\": \"1.1\", \"text\": \"Recommends RunE, not Run\" },\n      {\n        \"id\": \"1.2\",\n        \"text\": \"Explains that Run cannot return an error — you'd need os.Exit or panic\"\n      },\n      {\n        \"id\": \"1.3\",\n        \"text\": \"Shows RunE returning the error from the handler\"\n      },\n      { \"id\": \"1.4\", \"text\": \"Does NOT suggest using os.Exit inside RunE\" },\n      {\n        \"id\": \"1.5\",\n        \"text\": \"Mentions that returning error from RunE causes cobra to exit non-zero\"\n      }\n    ]\n  },\n  {\n    \"id\": 2,\n    \"name\": \"args-validator-not-manual-check\",\n    \"description\": \"Tests use of cobra Args validators instead of manual len(args) checks in RunE\",\n    \"prompt\": \"I'm writing a Go CLI with cobra. My 'delete' command requires exactly one positional argument (the resource name). How should I validate this?\",\n    \"trap\": \"Without the skill, the model writes len(args) != 1 check inside RunE. The correct approach is Args: cobra.ExactArgs(1) on the command definition, which validates before RunE runs and gives a standard error message.\",\n    \"assertions\": [\n      {\n        \"id\": \"2.1\",\n        \"text\": \"Sets Args: cobra.ExactArgs(1) on the command struct\"\n      },\n      { \"id\": \"2.2\", \"text\": \"Does NOT write len(args) check inside RunE\" },\n      {\n        \"id\": \"2.3\",\n        \"text\": \"Mentions that cobra prints a standard error message when validation fails\"\n      },\n      {\n        \"id\": \"2.4\",\n        \"text\": \"RunE body accesses args[0] directly without re-validating length\"\n      }\n    ]\n  },\n  {\n    \"id\": 3,\n    \"name\": \"outOrStdout-not-os-stdout\",\n    \"description\": \"Tests use of cmd.OutOrStdout() instead of os.Stdout for testable output\",\n    \"prompt\": \"I'm writing a cobra command in Go that prints a table of results to the terminal. How should I write to stdout from inside RunE?\",\n    \"trap\": \"Without the skill, the model uses fmt.Println or os.Stdout directly. The correct approach is fmt.Fprintln(cmd.OutOrStdout(), ...) which can be redirected to a buffer in tests.\",\n    \"assertions\": [\n      { \"id\": \"3.1\", \"text\": \"Uses cmd.OutOrStdout() as the io.Writer target\" },\n      { \"id\": \"3.2\", \"text\": \"Does NOT use os.Stdout directly\" },\n      {\n        \"id\": \"3.3\",\n        \"text\": \"Does NOT use fmt.Println (which hardcodes os.Stdout)\"\n      },\n      {\n        \"id\": \"3.4\",\n        \"text\": \"Mentions testability as the reason — SetOut can redirect the writer in tests\"\n      }\n    ]\n  },\n  {\n    \"id\": 4,\n    \"name\": \"persistent-prerunE-hook-chain\",\n    \"description\": \"Tests PersistentPreRunE on root for global config init and the child override trap\",\n    \"prompt\": \"In my Go CLI with cobra, I want to initialize viper config before any subcommand runs. I also have one subcommand that needs its own PersistentPreRunE for extra setup. How do I make sure both run?\",\n    \"trap\": \"Without the skill, the model defines PersistentPreRunE on both root and child without noting that the child's hook replaces the parent's — so root's config init never runs for that subcommand.\",\n    \"assertions\": [\n      {\n        \"id\": \"4.1\",\n        \"text\": \"Explains that a child's PersistentPreRunE replaces (not chains) the parent's\"\n      },\n      {\n        \"id\": \"4.2\",\n        \"text\": \"Shows explicitly calling the parent's PersistentPreRunE from inside the child's hook\"\n      },\n      { \"id\": \"4.3\", \"text\": \"Does NOT claim both hooks run automatically\" },\n      {\n        \"id\": \"4.4\",\n        \"text\": \"Uses PersistentPreRunE (the *E variant) not PersistentPreRun\"\n      }\n    ]\n  },\n  {\n    \"id\": 5,\n    \"name\": \"silence-usage-and-errors\",\n    \"description\": \"Tests SilenceUsage and SilenceErrors on root command\",\n    \"prompt\": \"When my Go cobra CLI returns an error from RunE, the terminal shows the full usage/help text followed by the error. I only want to see the error message, not the usage. How do I fix this?\",\n    \"trap\": \"Without the skill, the model may suggest overriding SetUsageTemplate or wrapping the error. The correct fix is SilenceUsage: true on the root command.\",\n    \"assertions\": [\n      {\n        \"id\": \"5.1\",\n        \"text\": \"Sets SilenceUsage: true on the root cobra.Command\"\n      },\n      {\n        \"id\": \"5.2\",\n        \"text\": \"Optionally mentions SilenceErrors: true (for custom error formatting)\"\n      },\n      {\n        \"id\": \"5.3\",\n        \"text\": \"Does NOT suggest removing or wrapping the error in RunE\"\n      },\n      {\n        \"id\": \"5.4\",\n        \"text\": \"Explains that SilenceUsage only suppresses usage on error, not on --help\"\n      }\n    ]\n  },\n  {\n    \"id\": 6,\n    \"name\": \"command-group-registration-order\",\n    \"description\": \"Tests that AddGroup must be called before AddCommand that references it\",\n    \"prompt\": \"I want to group my cobra subcommands in the help output under labels like 'Core Commands:' and 'Management Commands:'. How do I set this up?\",\n    \"trap\": \"Without the skill, the model calls AddCommand first and AddGroup after, which doesn't work — groups must be registered before the commands that reference them.\",\n    \"assertions\": [\n      {\n        \"id\": \"6.1\",\n        \"text\": \"Calls AddGroup before AddCommand for commands that use that group\"\n      },\n      {\n        \"id\": \"6.2\",\n        \"text\": \"Sets GroupID on the subcommand matching the Group's ID field\"\n      },\n      { \"id\": \"6.3\", \"text\": \"Shows cobra.Group{ID: ..., Title: ...} struct\" },\n      {\n        \"id\": \"6.4\",\n        \"text\": \"Does NOT call AddCommand before AddGroup for the same group\"\n      }\n    ]\n  },\n  {\n    \"id\": 7,\n    \"name\": \"valid-args-function-dynamic-completion\",\n    \"description\": \"Tests ValidArgsFunction for dynamic shell completion instead of static ValidArgs\",\n    \"prompt\": \"My Go cobra 'get pod' command should complete pod names dynamically by querying the API server. ValidArgs only accepts a static list. How do I provide dynamic completions?\",\n    \"trap\": \"Without the skill, the model tries to populate ValidArgs at startup (querying the API at init time) or doesn't know about ValidArgsFunction.\",\n    \"assertions\": [\n      {\n        \"id\": \"7.1\",\n        \"text\": \"Uses ValidArgsFunction (not ValidArgs) for dynamic completions\"\n      },\n      {\n        \"id\": \"7.2\",\n        \"text\": \"Function signature returns ([]string, cobra.ShellCompDirective)\"\n      },\n      {\n        \"id\": \"7.3\",\n        \"text\": \"Returns cobra.ShellCompDirectiveNoFileComp to prevent file fallback\"\n      },\n      {\n        \"id\": \"7.4\",\n        \"text\": \"Does NOT query the API at init() or in ValidArgs (static list)\"\n      },\n      {\n        \"id\": \"7.5\",\n        \"text\": \"Handles errors by returning cobra.ShellCompDirectiveError\"\n      }\n    ]\n  },\n  {\n    \"id\": 8,\n    \"name\": \"register-flag-completion-func\",\n    \"description\": \"Tests RegisterFlagCompletionFunc for flag value completion\",\n    \"prompt\": \"My Go cobra command has an --output flag that accepts 'json', 'yaml', or 'table'. How do I make the shell complete valid values when the user types --output <TAB>?\",\n    \"trap\": \"Without the skill, the model does not know about RegisterFlagCompletionFunc and instead documents the valid values only in the flag description string.\",\n    \"assertions\": [\n      {\n        \"id\": \"8.1\",\n        \"text\": \"Calls cmd.RegisterFlagCompletionFunc(\\\"output\\\", func(...) ...)\"\n      },\n      {\n        \"id\": \"8.2\",\n        \"text\": \"The completion function returns []string{\\\"json\\\", \\\"yaml\\\", \\\"table\\\"} (or similar)\"\n      },\n      { \"id\": \"8.3\", \"text\": \"Returns cobra.ShellCompDirectiveNoFileComp\" },\n      {\n        \"id\": \"8.4\",\n        \"text\": \"Does NOT rely only on the flag usa","readmeExcerpt":"Skill: golang-spf13-cobra Owner: samber Summary: 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 SetArg","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"go get github.com/spf13/cobra@latest"},{"language":"go","snippet":"var rootCmd = &cobra.Command{\n    Use:          \"myapp\",\n    Short:        \"One-line summary\",\n    SilenceUsage: true,  // ✓ prevents usage wall on every error\n    SilenceErrors: true, // ✓ lets you control error output format\n}"},{"language":"text","snippet":"PersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE"},{"language":"go","snippet":"rootCmd.PersistentFlags().StringVar(&cfgFile, \"config\", \"\", \"config file path\") // inherited by all subcommands\nserveCmd.Flags().IntVar(&port, \"port\", 8080, \"listen port\")                     // local to serveCmd only\nserveCmd.MarkFlagRequired(\"port\")\nserveCmd.MarkFlagsMutuallyExclusive(\"json\", \"yaml\")"},{"language":"go","snippet":"func TestServeCmd(t *testing.T) {\n    buf := new(bytes.Buffer)\n    rootCmd.SetOut(buf)\n    rootCmd.SetArgs([]string{\"serve\", \"--port\", \"9090\"})\n    require.NoError(t, rootCmd.Execute())\n    assert.Contains(t, buf.String(), \"listening on :9090\")\n}"},{"language":"text","snippet":"PersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: golang-spf13-cobra\ndescription: \"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 configuration layering alongside cobra, see the `samber/cc-skills-golang@golang-spf13-viper` skill. For general CLI architecture (project layout, exit codes, signal handling, I/O patterns), see `samber/cc-skills-golang@golang-cli`.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.1.0\"\n  openclaw:\n    emoji: \"🐍\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n    install: []\n    skill-library-version: \"1.10.2\"\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs Bash(godig:*) Bash(gopls:*) LSP mcp__gopls__*\npaths:\n  - \"**/*.go\"\n---\n\n**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.\n\n**Modes:**\n\n- **Build** — creating a new CLI from scratch: follow command tree setup, hook wiring, and flag sections sequentially.\n- **Extend** — adding subcommands, flags, or completions to an existing CLI: read the current command tree first, then apply changes consistent with the existing structure.\n- **Review** — auditing an existing CLI: check the Common Mistakes table, verify `RunE` usage, `OutOrStdout()`, hook chain ordering, and args validation.\n\n# Using spf13/cobra for CLI command trees in Go\n\nCobra 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.\n\n**Official Resources:**\n\n- [pkg.go.dev/github.com/spf13/cobra](https://pkg.go.dev/github.com/spf13/cobra)\n- [github.com/spf13/cobra](https://github.com/spf13/cobra)\n- [cobra.dev](https://cobra.dev)\n\nThis 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 n"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-spf13-cobra\",\n  \"version\": \"1.1.0\",\n  \"publishedAt\": 1787448813168\n}"},{"path":"references/commands-and-args.md","content":"# Cobra Commands, Hooks, and Args Validators\n\n## The Run\\* lifecycle\n\nCobra commands have five run hooks. Cobra executes them in this fixed order:\n\n```\nPersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE\n```\n\nEach `*E` hook returns `error`. The non-`*E` variants (`PersistentPreRun`, `PreRun`, `Run`, `PostRun`, `PersistentPostRun`) have signature `func(cmd *cobra.Command, args []string)` — they cannot signal failure without `os.Exit` or panic. **Always use the `*E` variants.**\n\n### Which hook to use\n\n| Hook | Scope | When to use |\n| --- | --- | --- |\n| `PersistentPreRunE` | Parent + all descendants | Config init, auth check, telemetry setup — must run before every subcommand |\n| `PreRunE` | This command only | Validation that runs only for this command before `RunE` |\n| `RunE` | This command only | Main handler — the primary business logic |\n| `PostRunE` | This command only | Cleanup that runs only if `RunE` succeeded |\n| `PersistentPostRunE` | Parent + all descendants | Global cleanup (close connections, flush buffers) |\n\n### Inheritance rules\n\n`PersistentPreRunE` defined on the root command runs before every subcommand. But if a child command defines **its own** `PersistentPreRunE`, it **replaces** (does not chain) the parent's hook. Call the parent explicitly if you need both:\n\n```go\nvar childCmd = &cobra.Command{\n    PersistentPreRunE: func(cmd *cobra.Command, args []string) error {\n        // call parent's hook first\n        if err := rootCmd.PersistentPreRunE(cmd, args); err != nil {\n            return err\n        }\n        // child-specific logic\n        return nil\n    },\n}\n```\n\n### Execution stops on first error\n\nIf `PersistentPreRunE` returns an error, cobra stops — `RunE` and later hooks never run. Use this for fail-fast auth checks.\n\n## Args validators\n\nArgs validators run before `RunE`. Cobra prints a clear error message and exits without calling `RunE` when validation fails.\n\n### Built-in validators\n\n```go\ncobra.NoArgs                        // fails if any positional args provided\ncobra.ArbitraryArgs                 // accepts any number of args (default)\ncobra.ExactArgs(n int)              // requires exactly n args\ncobra.MinimumNArgs(n int)           // requires at least n args\ncobra.MaximumNArgs(n int)           // requires at most n args\ncobra.RangeArgs(min, max int)       // requires between min and max args\ncobra.OnlyValidArgs                 // all args must be in ValidArgs list\ncobra.ExactValidArgs(n int)         // exactly n args, all in ValidArgs\n```\n\n### Composing validators with MatchAll\n\n```go\nvar deleteCmd = &cobra.Command{\n    Use:       \"delete <resource>\",\n    Args:      cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),\n    ValidArgs: []string{\"pod\", \"service\", \"deployment\"},\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return doDelete(args[0])\n    },\n}\n```\n\n### Custom validators\n\nSignature: `func(cmd *cobra.Command, args []string) error`\n\n```go\nfunc validatePositiveInt(cmd "},{"path":"references/completions.md","content":"# Cobra Shell Completions Reference\n\nCobra generates shell completion scripts for bash, zsh, fish, and PowerShell automatically. Subcommand names and flag names are completed for free. You add completions for flag values and positional arguments.\n\n## Built-in completion command\n\nCobra registers a `completion` subcommand automatically:\n\n```bash\nmyapp completion bash   # generate bash script\nmyapp completion zsh    # generate zsh script\nmyapp completion fish   # generate fish script\nmyapp completion powershell\n\n# Install (example for zsh):\nmyapp completion zsh > \"${fpath[1]}/_myapp\"\n```\n\n## ShellCompDirective\n\nThe `ShellCompDirective` controls shell behavior after your completion function returns:\n\n| Directive | Meaning |\n| --- | --- |\n| `ShellCompDirectiveDefault` | Fall back to file completion after your results |\n| `ShellCompDirectiveNoFileComp` | Disable file completion fallback |\n| `ShellCompDirectiveNoSpace` | Don't add a space after the completion |\n| `ShellCompDirectiveFilterFileExt(exts)` | Only show files with given extensions |\n| `ShellCompDirectiveFilterDirs(dirs)` | Only show directories |\n| `ShellCompDirectiveError` | Signal an error (show no completions) |\n\nCombine with bitwise OR: `cobra.ShellCompDirectiveNoFileComp | cobra.ShellCompDirectiveNoSpace`.\n\nUse `ShellCompDirectiveNoFileComp` whenever your list is exhaustive — it prevents the shell from appending irrelevant files.\n\n## Static arg completions\n\n```go\nvar getCmd = &cobra.Command{\n    Use:       \"get <resource>\",\n    ValidArgs: []string{\"pod\", \"service\", \"deployment\", \"configmap\"},\n    Args:      cobra.OnlyValidArgs,\n    RunE: func(cmd *cobra.Command, args []string) error { /* ... */ },\n}\n```\n\n## Dynamic arg completions\n\n```go\nvar getCmd = &cobra.Command{\n    ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        if len(args) > 0 {\n            // first arg already provided — no more completions\n            return nil, cobra.ShellCompDirectiveNoFileComp\n        }\n        resources, err := listResources(toComplete)\n        if err != nil {\n            return nil, cobra.ShellCompDirectiveError\n        }\n        return resources, cobra.ShellCompDirectiveNoFileComp\n    },\n}\n```\n\n`toComplete` is the prefix the user has typed so far — filter your results by it for responsive completions.\n\n## Flag value completions\n\n```go\nfunc init() {\n    rootCmd.RegisterFlagCompletionFunc(\"output\", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        return []string{\"json\\tJSON output\", \"yaml\\tYAML output\", \"table\\tTable output\"}, cobra.ShellCompDirectiveNoFileComp\n    })\n\n    rootCmd.RegisterFlagCompletionFunc(\"namespace\", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        ns, err := listNamespaces()\n        if err != nil {\n            return nil, cobra.ShellCompDirectiveError\n        }\n        return ns, cobra.ShellCompDire"},{"path":"references/flags.md","content":"# Cobra Flags Reference\n\nCobra delegates all flag parsing to `github.com/spf13/pflag`. `cobra.Command` exposes two `*pflag.FlagSet`s:\n\n- `cmd.Flags()` — local flags, only available on this command.\n- `cmd.PersistentFlags()` — inherited by all subcommands.\n\n## Common flag types\n\n```go\n// String\ncmd.Flags().String(\"name\", \"default\", \"description\")\ncmd.Flags().StringP(\"name\", \"n\", \"default\", \"description\")  // with shorthand\n\n// With pointer binding (no Lookup needed later)\nvar name string\ncmd.Flags().StringVar(&name, \"name\", \"default\", \"description\")\ncmd.Flags().StringVarP(&name, \"name\", \"n\", \"default\", \"description\")\n\n// Other types follow the same pattern:\ncmd.Flags().Int / IntVar / IntVarP\ncmd.Flags().Bool / BoolVar / BoolVarP\ncmd.Flags().Float64 / Float64Var\ncmd.Flags().Duration / DurationVar       // parses \"1h30m\", \"500ms\"\ncmd.Flags().StringSlice / StringSliceVar // comma-separated or repeated flags\ncmd.Flags().StringArray / StringArrayVar // repeated flags only (no comma splitting)\ncmd.Flags().IntSlice / IntSliceVar\ncmd.Flags().StringToString                // --label key=value --label k2=v2\n```\n\n## StringSlice vs StringArray\n\n| Flag type     | Input                 | Result                            |\n| ------------- | --------------------- | --------------------------------- |\n| `StringSlice` | `--tags a,b --tags c` | `[\"a\", \"b\", \"c\"]` — commas split  |\n| `StringArray` | `--tags a,b --tags c` | `[\"a,b\", \"c\"]` — commas NOT split |\n\nUse `StringArray` when values may legitimately contain commas.\n\n## Flag constraints\n\n```go\n// Fail if flag not provided\ncmd.MarkFlagRequired(\"output\")\n\n// Fail if both provided\ncmd.MarkFlagsMutuallyExclusive(\"json\", \"yaml\", \"table\")\n\n// Fail if none provided\ncmd.MarkFlagsOneRequired(\"file\", \"stdin\")\n\n// Require flag only if another flag is set\ncmd.MarkFlagsMutuallyExclusive(\"tls\", \"no-tls\")\n```\n\n## Persistent flag patterns\n\n```go\nfunc init() {\n    // global flags on root\n    rootCmd.PersistentFlags().StringVar(&cfgFile, \"config\", \"\", \"config file (default: $HOME/.myapp.yaml)\")\n    rootCmd.PersistentFlags().StringVar(&logLevel, \"log-level\", \"info\", \"log level (debug, info, warn, error)\")\n\n    // bind to viper immediately after defining\n    viper.BindPFlag(\"config\", rootCmd.PersistentFlags().Lookup(\"config\"))\n    viper.BindPFlag(\"log-level\", rootCmd.PersistentFlags().Lookup(\"log-level\"))\n}\n```\n\n## Custom flag value types\n\nImplement `pflag.Value` to parse arbitrary types:\n\n```go\ntype enumValue struct {\n    val     string\n    allowed []string\n}\n\nfunc (e *enumValue) String() string { return e.val }\nfunc (e *enumValue) Type() string   { return \"enum\" }\nfunc (e *enumValue) Set(s string) error {\n    for _, a := range e.allowed {\n        if s == a {\n            e.val = s\n            return nil\n        }\n    }\n    return fmt.Errorf(\"must be one of %v\", e.allowed)\n}\n\nvar outputFmt = &enumValue{val: \"table\", allowed: []string{\"table\", \"json\", \"yaml\"}}\ncmd.Flags().Var(outputFmt, \"output\", \"output format (table, json, yaml)\")"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1558,"uniquenessScore":44,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T14:31:24.676Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T14:31:24.676Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:46:31.044Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}