{"id":"98d8b4b5-cb78-45d3-9784-110c833b01a6","shortId":"3RzJmG","kind":"skill","title":"golang-spf13-cobra","tagline":"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","description":"**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>.","tags":["golang","spf13","cobra","skills","samber","agent","agent-skills","antigravity","claude","claude-code","code","codex"],"capabilities":["skill","source-samber","skill-golang-spf13-cobra","topic-agent","topic-agent-skills","topic-antigravity","topic-claude","topic-claude-code","topic-code","topic-codex","topic-coding","topic-copilot","topic-cursor","topic-gemini","topic-gemini-cli-extension"],"categories":["cc-skills-golang"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/samber/cc-skills-golang/golang-spf13-cobra","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add samber/cc-skills-golang","source_repo":"https://github.com/samber/cc-skills-golang","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 1725 github stars · SKILL.md body (8,616 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:53:02.860Z","embedding":null,"createdAt":"2026-05-01T12:52:37.078Z","updatedAt":"2026-05-18T18:53:02.860Z","lastSeenAt":"2026-05-18T18:53:02.860Z","tsv":"'/github.com/spf13/cobra](https://pkg.go.dev/github.com/spf13/cobra)':179 '/postrun':997 '/spf13/cobra/issues':1117 '/spf13/cobra@latest':213 '/spf13/cobra](https://github.com/spf13/cobra)':182 '1':768,909,916 '2':788,912 '3':808 '4':827 '5':842 '8080':621 '9090':731,740 'accept':908 'accumul':742,852,974 'across':745,855,971 'ad':86 'addcommand':374,422 'addgroup':411 'alon':296,314 'alongsid':1083 'alway':450,769 'annot':687,1021 'annotation-bas':1020 'appli':102,599 'applic':146 'architectur':1064 'arg':19,127,156,235,303,511,523,535,564,661,667,811,813,817,898,910,914,961,1000 'argument':516 'assert.contains':735 'assign':431 'audit':110 'auth':477,806 'automat':653 'base':1022 'bash':208 'behavior':62,1108 'best':766 'binari':299,381 'bind':338,643,804,1015 'bindpflag':283 'buf':722,726 'buf.string':737 'bug':1105 'build':42,68,748,984 'built':539 'built-in':538 'bypass':528,786,884,902 'bytes.buffer':724 'call':423,487,747,857,958 'cannot':458,775,837,874,925 'captur':839,926 'cfgfile':608 'chain':18,124,949,998 'chang':103 'check':114,478,524,807,899 'child':480,940,951,964 'cli':6,40,72,94,113,132,145,261,330,362,1037,1059,1063 'cmd':562,666,960 'cmd.errorstderr':711,830,939 'cmd.outorstdout':710,829,938 'cobra':4,137,214,229,266,286,295,361,427,436,513,529,582,649,741,819,851,892,903,946,973,1036,1084 'cobra-c':1035 'cobra.command':12,386,563 'cobra.dev':183,184 'cobra.exactargs':915 'code':196,1068 'command':7,29,43,76,98,133,232,344,358,366,377,437,604,694,696,707,751,847,919,970,987,1050 'command/subcommand':150 'commands-and-args.md':509,578,993 'common':116,862 'complet':90,159,237,647,652,662,683,762,1023,1025,1046 'completions.md':691,1016 'compos':554,825 'concern':228 'config':307,324,474,609,610,790 'configur':168,238,1081 'consist':104 'context7':201 'control':406 'count':536 'creat':69,845 'cross':1053 'cross-refer':1052 'current':97 'custom':24,559,636,1011 'daemon':269 'de':140 'declar':603,913 'default':1088 'defer':787,885 'deleg':583 'design':53 'differ':221 'direct':705,834,923 'discover':206 'doc':1033 'document':162,194 'driven':1049 'drop':943 'dynam':664 'e':452,456 'encount':1103 'engin':41 'entir':486,957 'env':272,310,327,1086 'error':401,407,460,532,566,778,822,877,890,906 'escap':781,879 'everi':360,400,469,797,999 'exactarg':22,542 'exactvalidarg':552 'exampl':197,573 'execut':442,698,746,856,978 'exhaust':189 'exist':93,107,112 'exit':895,1067 'explicit':490 'extend':85,654 'face':57,243 'facto':141 'fail':867 'fallback':677 'famili':435 'feel':46 'file':308,611,676,759,931,1044,1087 'first':59,100,983 'five':439 'fix':868 'flag':28,82,88,152,234,246,263,287,301,580,584,589,597,598,637,639,681,743,853,975,980,1085 'flags.md':645,1005 'fn':680 'follow':75 'form':457 'format':409 'fresh':750,986 'full':503,569,995 'func':561,665,718 'fundament':220 'general':1062,1097 'generat':160,163,650,1034 'generators.md':1026 'get':210 'github.com':181,212,1116 'github.com/spf13/cobra/issues':1115 'github.com/spf13/cobra@latest':211 'github.com/spf13/cobra](https://github.com/spf13/cobra)':180 'give':818 'go':39,136,144,209,383,605,717,1098 'golang':2,5,348,1058,1076,1093 'golang-c':1057 'golang-spf13-cobra':1 'golang-spf13-viper':347,1075 'golang-test':1092 'golden':758,1043 'group':30,419,432,640,1010 'hand':278 'handl':167,893,932,1070 'handler':708 'help':203,247,416 'highest':291 'highest-preced':290 'hook':17,66,79,123,441,956,966 'i/o':1071 'in':540 'independ':227 'inform':200 'inherit':506,592,613,1003 'init':475 'initi':791 'insid':525,815 'instanc':861 'instead':871 'integr':276,357 'intvar':618 'isol':756,1041 'issu':1113 'job':174 'json':631 'key':253,461 'key-valu':252 'label':413 'layer':169,293,1082 'layout':1066 'len':522,897 'let':404,891 'level':930 'librari':9,193,218 'lifecycl':504 'line':392 'listen':622,738 'local':27,596,624 'long':320 'long-run':319 'man':1028 'markdown':1030 'matchal':23,556,575,824 'max':550 'maximumnarg':546 'messag':533,823,907 'min':549 'minimumnarg':544 'mistak':117,863,864 'mode':67 'myapp':388 'n':543,545,547,553 'name':378,382,679 'nativ':47 'need':265,273,305,336,493 'never':520,701,772 'new':71,723 'noarg':21,541 'non':455 'offici':175 'one':391 'one-lin':390 'onlyvalidarg':551 'open':1111 'order':125,444 'os':929 'os-level':928 'os.exit':783,881 'os.stderr':704 'os.stdout':703,835,922 'outorstdout':122 'output':408,417,716,833,927 'own':231 'page':1029 'panic':785,883 'parent':484,489,944,954 'parent.persistentprerune':959 'pars':153,585 'path':612 'pattern':576,757,1042,1072,1100 'per':753,849,989 'persist':25,588 'persistentflag':590 'persistentpostrun':449 'persistentprerun':16,340,445,463,481,793,941,1002 'persona':35 'pflag':155,587,634,1007 'pflag.flag':279 'pkg.go.dev':178 'pkg.go.dev/github.com/spf13/cobra](https://pkg.go.dev/github.com/spf13/cobra)':177 'place':801 'platform':207 'pleas':190 'plus':367 'port':619,620,623,629,730 'posit':515,660,810 'postrun':448,495 'practic':767 'preced':292,1089 'prerun':446,996 'prevent':396 'primer':581,648 'programmat':700 'project':1065 'provid':148 'pure':250 'put':789 'rangearg':548 're':844 're-creat':843 'read':95,270,323,992 'receiv':911 'redirect':715,936 'refer':191,425,1054 'references/commands-and-args.md':510,579,994 'references/completions.md':692,1017 'references/flags.md':646,1006 'references/generators.md':1027 'references/testing.md':765,1040 'regist':372,418 'registerflagcompletionfunc':32,678 'replac':482,952 'require.noerror':732 'required/exclusive/onerequired':1009 'resolut':240,311 'resolv':255 'resourc':176 'retroact':430 'return':459,672,776,875,888 'reus':967 'review':109 'right':65,800 'root':343,365,376,466,969 'rootcmd':385 'rootcmd.execute':734 'rootcmd.persistentflags':606 'rootcmd.setargs':727 'rootcmd.setout':725 'rst':1032 'rule':462,507,1004 'run':15,321,434,440,467,496,519,773,774,795,870 'rune':13,120,447,499,518,526,771,816,873,887,901 'samber/cc-skills-golang':346,1056,1074,1091 'scaffold':1038 'scratch':74 'seam':277 'second':977 'section':83 'see':345,508,577,644,690,763,979,1055,1073,1090 'sequenti':84 'serv':729 'servecmd':626 'servecmd.flags':617 'servecmd.markflagrequired':628 'servecmd.markflagsmutuallyexclusive':630 'servic':322 'set':571,1019 'setup':78 'shell':51,158,651 'shellcompdirect':33,671,685,1018 'shellcompdirectivenofilecomp':673 'short':389 'side':354 'signal':1069 'silenceerror':402 'silenceusag':394 'silent':942 'skill':186,1060,1079,1095 'skill-golang-spf13-cobra' 'source-samber' 'spf13':3,349,1077 'spf13/cobra':11,130,1110 'standard':142,531,821,905 'state':744,854,976 'static':659 'string':565,658,669,670,728 'stringvar':607 'structur':108 'subcommand':87,245,331,371,414,470,595,616,798 'succeed':500 'summari':393 'suppress':675 'surfac':58 'tabl':118,1048 'table-driven':1047 'take':300 'test':689,693,695,713,754,761,841,850,924,972,990,1024,1045,1051,1094,1099 'testing.md':764,1039 'testing.t':721 'testservecmd':719 'text':248 'thing':222 'tocomplet':668 'topic-agent' 'topic-agent-skills' 'topic-antigravity' 'topic-claude' 'topic-claude-code' 'topic-code' 'topic-codex' 'topic-coding' 'topic-copilot' 'topic-cursor' 'topic-gemini' 'topic-gemini-cli-extension' 'track':537 'treat':284 'tree':8,44,77,99,134,151,233,359,752,848,988 'true':395,403 'type':635,1008,1013 'unexpect':1107 'unix':50 'usag':34,121,397 'use':10,129,226,294,312,332,387,410,451,471,702,709,770,828,869,886,937 'user':56,242 'user-fac':55,241 'v1':557 'v2':558 'valid':20,128,157,236,512,514,560,570,809,826,1001 'validarg':657 'validargsfunct':31,663 'valu':239,254,638,682,686,1012 'var':384 'variant':453 'verifi':119 'via':154,282 'viper':172,216,230,275,281,313,350,353,642,803,1014,1078 'vs':14,26,215 'wall':398 'wire':61,80 'without':256 'write':521,836,896,920 'yaml':271,326,632,1031 'yes':244,259,267 'zero':368","prices":[{"id":"cbc9faac-1827-4a17-8247-a47690d313ca","listingId":"98d8b4b5-cb78-45d3-9784-110c833b01a6","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"samber","category":"cc-skills-golang","install_from":"skills.sh"},"createdAt":"2026-05-01T12:52:37.078Z"}],"sources":[{"listingId":"98d8b4b5-cb78-45d3-9784-110c833b01a6","source":"github","sourceId":"samber/cc-skills-golang/golang-spf13-cobra","sourceUrl":"https://github.com/samber/cc-skills-golang/tree/main/skills/golang-spf13-cobra","isPrimary":false,"firstSeenAt":"2026-05-01T12:52:37.078Z","lastSeenAt":"2026-05-18T18:53:02.860Z"},{"listingId":"98d8b4b5-cb78-45d3-9784-110c833b01a6","source":"skills_sh","sourceId":"samber/cc-skills-golang/golang-spf13-cobra","sourceUrl":"https://skills.sh/samber/cc-skills-golang/golang-spf13-cobra","isPrimary":true,"firstSeenAt":"2026-05-07T20:42:04.131Z","lastSeenAt":"2026-05-07T22:41:22.843Z"}],"details":{"listingId":"98d8b4b5-cb78-45d3-9784-110c833b01a6","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"samber","slug":"golang-spf13-cobra","github":{"repo":"samber/cc-skills-golang","stars":1725,"topics":["agent","agent-skills","ai","antigravity","claude","claude-code","code","codex","coding","copilot","cursor","gemini","gemini-cli-extension","openclaw","opencode","plugin","skills","skillsmp","vibe-coding"],"license":"mit","html_url":"https://github.com/samber/cc-skills-golang","pushed_at":"2026-05-18T17:36:00Z","description":"🧑‍🎨 A collection of Golang agentic skills that works","skill_md_sha":"543dde3b05a742092a57a3d02699200b8a337063","skill_md_path":"skills/golang-spf13-cobra/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/samber/cc-skills-golang/tree/main/skills/golang-spf13-cobra"},"layout":"multi","source":"github","category":"cc-skills-golang","frontmatter":{"name":"golang-spf13-cobra","license":"MIT","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`.","compatibility":"Designed for Claude Code or similar AI coding agents, and for projects using Golang."},"skills_sh_url":"https://skills.sh/samber/cc-skills-golang/golang-spf13-cobra"},"updatedAt":"2026-05-18T18:53:02.860Z"}}