feat: add Cobra (Go) integration for generating usage specs#498
Conversation
Summary of ChangesHello @jdx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a significant new integration for Go's Cobra CLI framework, allowing developers to automatically generate usage specifications. This capability streamlines the process of creating consistent and comprehensive documentation and completion scripts for command-line tools, reducing manual effort and improving the user experience for Cobra-based applications. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new integration for the Cobra Go CLI framework. The implementation is well-structured and includes a comprehensive set of features, tests, and documentation. The code converts a Cobra command tree into a usage spec in KDL or JSON format, enabling features like shell completions and documentation generation. I've found a couple of minor issues related to JSON serialization consistency and default value handling that could improve the robustness of the integration. Overall, this is a great addition.
integrations/cobra/spec.go
Outdated
| Bin string `json:"bin,omitempty"` | ||
| Version string `json:"version,omitempty"` | ||
| About string `json:"about,omitempty"` | ||
| Long string `json:"about_long,omitempty"` |
There was a problem hiding this comment.
The JSON tag for the Long field is json:"about_long,omitempty". For consistency with the KDL output which uses long_about, and with the SpecCommand.HelpLong field which uses json:"help_long,omitempty", this should be json:"long_about,omitempty".
| Long string `json:"about_long,omitempty"` | |
| Long string `json:"long_about,omitempty"` |
integrations/cobra/convert.go
Outdated
| if f.DefValue != "" && f.DefValue != "false" && f.DefValue != "0" && f.DefValue != "[]" { | ||
| sf.Default = []string{f.DefValue} | ||
| } |
There was a problem hiding this comment.
The logic to skip default values that are zero-values (e.g., "", 0, false) can be problematic. In some CLI tools, these zero values can be meaningful defaults (e.g., a port number of 0 might mean 'assign a random port', or an empty string "" could be a valid default path). By omitting them, the generated spec becomes inaccurate. It would be more robust to always include the default value as reported by Cobra/pflag. If the goal is to avoid clutter, this could be an option for the generator or handled by the consumer of the spec.
There was a problem hiding this comment.
Pull request overview
This PR adds a Go integration for the Cobra CLI framework that generates usage specs in KDL format. The integration enables Cobra-based CLIs to generate shell completions (bash, zsh, fish, PowerShell, nushell), markdown documentation, and man pages from their command definitions.
Changes:
- Adds
integrations/cobra/package with conversion logic from Cobra commands to usage specs - Implements KDL and JSON output formats with 4 public API functions
- Includes 15 comprehensive tests covering various Cobra features
- Provides a complete example CLI demonstrating the integration
- Updates integrations README to mark Cobra as completed
Reviewed changes
Copilot reviewed 10 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| integrations/cobra/spec.go | Defines type structures for representing CLI specs (Spec, SpecCommand, SpecFlag, SpecArg, SpecChoices) |
| integrations/cobra/kdl.go | Implements KDL rendering logic with string escaping and formatting |
| integrations/cobra/convert.go | Converts Cobra command trees into internal Spec structures |
| integrations/cobra/cobra_usage.go | Public API with Generate, GenerateJSON, GenerateToFile, and GenerateJSONToFile functions |
| integrations/cobra/cobra_usage_test.go | 15 tests covering simple commands, nested subcommands, flags, args, aliases, and more |
| integrations/cobra/example/main.go | Example deployment CLI demonstrating integration pattern |
| integrations/cobra/go.mod | Go module definition with Cobra v1.10.2 dependency |
| integrations/cobra/go.sum | Go module checksums |
| integrations/cobra/example/go.mod | Example module with local replace directive |
| integrations/cobra/example/go.sum | Example module checksums |
| integrations/cobra/README.md | Comprehensive documentation with installation, usage examples, API reference, and feature mapping |
| integrations/README.md | Updates to mark Cobra integration as complete |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| // kdlQuoteAlways always wraps the string in KDL double quotes with escaping. | ||
| func kdlQuoteAlways(s string) string { | ||
| s = strings.ReplaceAll(s, `\`, `\\`) |
There was a problem hiding this comment.
The kdlQuoteAlways function only escapes backslashes and double quotes, but it doesn't escape other special characters that should be escaped in KDL strings, such as newlines (\n), tabs (\t), and carriage returns (\r). This could cause issues when the CLI has help text or descriptions containing these characters. Consider adding escaping for these special characters: \n for newline, \t for tab, \r for carriage return.
| s = strings.ReplaceAll(s, `\`, `\\`) | |
| s = strings.ReplaceAll(s, `\`, `\\`) | |
| s = strings.ReplaceAll(s, "\n", `\n`) | |
| s = strings.ReplaceAll(s, "\t", `\t`) | |
| s = strings.ReplaceAll(s, "\r", `\r`) |
| usage = fmt.Sprintf("<%s>", arg.Name) | ||
| } else { | ||
| usage = fmt.Sprintf("[%s]", arg.Name) | ||
| } | ||
| if arg.Var { | ||
| usage += "\u2026" // unicode ellipsis … | ||
| } | ||
|
|
||
| // In KDL, [brackets] are type annotations and must be quoted. | ||
| // <angle_brackets> are fine as bare identifiers. | ||
| if strings.HasPrefix(usage, "[") { | ||
| fmt.Fprintf(&b, "%sarg %s", indent, kdlQuoteAlways(usage)) | ||
| } else { | ||
| fmt.Fprintf(&b, "%sarg %s", indent, usage) |
There was a problem hiding this comment.
The arg name inside angle brackets is not escaped or validated when rendering. If a Cobra command's Use field contains arg names with special characters (e.g., Use: "cmd <my file>"), this could produce invalid KDL output like arg <my file>. Consider either escaping the arg name or validating that it doesn't contain special characters. The same issue exists at line 190 where flag arg names are rendered.
| package cobra_usage | ||
|
|
||
| import ( | ||
| "strings" | ||
| "testing" | ||
|
|
||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| func TestSimpleCommand(t *testing.T) { | ||
| cmd := &cobra.Command{ | ||
| Use: "mycli", | ||
| Short: "A simple CLI", | ||
| Version: "1.0.0", | ||
| } | ||
| cmd.Flags().BoolP("verbose", "v", false, "Enable verbose output") | ||
| cmd.Flags().StringP("config", "c", "", "Config file path") | ||
|
|
||
| got := Generate(cmd) | ||
|
|
||
| assertContains(t, got, `name mycli`) | ||
| assertContains(t, got, `bin mycli`) | ||
| assertContains(t, got, `version "1.0.0"`) | ||
| assertContains(t, got, `about "A simple CLI"`) | ||
| assertContains(t, got, `flag "-v --verbose" help="Enable verbose output"`) | ||
| assertContains(t, got, `flag "-c --config" help="Config file path"`) | ||
| assertContains(t, got, `arg <CONFIG>`) | ||
| } | ||
|
|
||
| func TestNestedSubcommands(t *testing.T) { | ||
| root := &cobra.Command{Use: "app", Short: "An app"} | ||
| sub := &cobra.Command{Use: "sub", Short: "A subcommand"} | ||
| nested := &cobra.Command{Use: "nested", Short: "A nested command"} | ||
| sub.AddCommand(nested) | ||
| root.AddCommand(sub) | ||
|
|
||
| got := Generate(root) | ||
|
|
||
| assertContains(t, got, `cmd sub`) | ||
| assertContains(t, got, `help="A subcommand"`) | ||
| assertContains(t, got, `cmd nested help="A nested command"`) | ||
| } | ||
|
|
||
| func TestPersistentFlags(t *testing.T) { | ||
| root := &cobra.Command{Use: "app"} | ||
| root.PersistentFlags().BoolP("debug", "d", false, "Enable debug mode") | ||
|
|
||
| sub := &cobra.Command{Use: "run", Short: "Run something"} | ||
| root.AddCommand(sub) | ||
|
|
||
| got := Generate(root) | ||
|
|
||
| assertContains(t, got, `flag "-d --debug" help="Enable debug mode" global=#true`) | ||
| } | ||
|
|
||
| func TestRequiredFlags(t *testing.T) { | ||
| cmd := &cobra.Command{Use: "deploy"} | ||
| cmd.Flags().String("env", "", "Target environment") | ||
| cmd.MarkFlagRequired("env") | ||
|
|
||
| got := Generate(cmd) | ||
|
|
||
| assertContains(t, got, `flag --env help="Target environment" required=#true`) | ||
| } | ||
|
|
||
| func TestHiddenAndDeprecated(t *testing.T) { | ||
| root := &cobra.Command{Use: "app"} | ||
| hidden := &cobra.Command{Use: "internal", Short: "Internal command", Hidden: true} | ||
| deprecated := &cobra.Command{Use: "old", Short: "Old command", Deprecated: "use new instead"} | ||
| root.AddCommand(hidden, deprecated) | ||
|
|
||
| root.Flags().String("secret", "", "Secret flag") | ||
| root.Flags().MarkHidden("secret") | ||
|
|
||
| got := Generate(root) | ||
|
|
||
| assertContains(t, got, `cmd internal hide=#true help="Internal command"`) | ||
| assertContains(t, got, `cmd old help="Old command" deprecated="use new instead"`) | ||
| assertContains(t, got, `flag --secret help="Secret flag" hide=#true`) | ||
| } | ||
|
|
||
| func TestArgInference(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| use string | ||
| expected []string | ||
| }{ | ||
| { | ||
| name: "required arg", | ||
| use: "cmd <file>", | ||
| expected: []string{"arg <file>"}, | ||
| }, | ||
| { | ||
| name: "optional arg", | ||
| use: "cmd [name]", | ||
| expected: []string{`arg "[name]" required=#false`}, | ||
| }, | ||
| { | ||
| name: "variadic arg", | ||
| use: "cmd <files>...", | ||
| expected: []string{"arg <files>\u2026 var=#true"}, | ||
| }, | ||
| { | ||
| name: "mixed args", | ||
| use: "cmd <source> [dest]", | ||
| expected: []string{"arg <source>", `arg "[dest]" required=#false`}, | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| cmd := &cobra.Command{Use: tt.use} | ||
| got := Generate(cmd) | ||
| for _, exp := range tt.expected { | ||
| assertContains(t, got, exp) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestValidArgsChoices(t *testing.T) { | ||
| cmd := &cobra.Command{ | ||
| Use: "deploy <env>", | ||
| ValidArgs: []string{"dev", "staging", "prod"}, | ||
| } | ||
|
|
||
| got := Generate(cmd) | ||
|
|
||
| assertContains(t, got, `arg <env>`) | ||
| assertContains(t, got, `choices {`) | ||
| assertContains(t, got, `"dev"`) | ||
| assertContains(t, got, `"staging"`) | ||
| assertContains(t, got, `"prod"`) | ||
| } | ||
|
|
||
| func TestCountFlag(t *testing.T) { | ||
| cmd := &cobra.Command{Use: "app"} | ||
| cmd.Flags().CountP("verbose", "v", "Increase verbosity") | ||
|
|
||
| got := Generate(cmd) | ||
|
|
||
| assertContains(t, got, `flag "-v --verbose" help="Increase verbosity" var=#true count=#true`) | ||
| } | ||
|
|
||
| func TestDefaultValues(t *testing.T) { | ||
| cmd := &cobra.Command{Use: "app"} | ||
| cmd.Flags().String("output", "json", "Output format") | ||
| cmd.Flags().Int("retries", 3, "Number of retries") | ||
|
|
||
| got := Generate(cmd) | ||
|
|
||
| assertContains(t, got, `flag --output help="Output format" default=json`) | ||
| assertContains(t, got, `flag --retries help="Number of retries" default="3"`) | ||
| } | ||
|
|
||
| func TestBoolFlagNoArg(t *testing.T) { | ||
| cmd := &cobra.Command{Use: "app"} | ||
| cmd.Flags().Bool("force", false, "Force the operation") | ||
|
|
||
| got := Generate(cmd) | ||
|
|
||
| line := findLine(got, "flag --force") | ||
| if line == "" { | ||
| t.Fatal("expected flag --force in output") | ||
| } | ||
| if strings.Contains(line, "arg") { | ||
| t.Errorf("bool flag should not have arg child, got: %s", line) | ||
| } | ||
| } | ||
|
|
||
| func TestSkipsBuiltinCommands(t *testing.T) { | ||
| root := &cobra.Command{Use: "app", Version: "1.0.0"} | ||
| root.AddCommand(&cobra.Command{Use: "run", Short: "Run"}) | ||
| // Cobra auto-adds "help" and "completion" commands | ||
|
|
||
| got := Generate(root) | ||
|
|
||
| assertNotContains(t, got, `cmd help`) | ||
| assertNotContains(t, got, `cmd completion`) | ||
| assertContains(t, got, `cmd run`) | ||
| } | ||
|
|
||
| func TestSkipsBuiltinFlags(t *testing.T) { | ||
| cmd := &cobra.Command{Use: "app", Version: "1.0.0"} | ||
| cmd.Flags().String("custom", "", "A custom flag") | ||
|
|
||
| got := Generate(cmd) | ||
|
|
||
| assertNotContains(t, got, `flag --help`) | ||
| assertNotContains(t, got, `flag --version`) | ||
| assertContains(t, got, `flag --custom`) | ||
| } | ||
|
|
||
| func TestSubcommandRequired(t *testing.T) { | ||
| root := &cobra.Command{Use: "app"} | ||
| sub := &cobra.Command{Use: "config", Short: "Manage config"} | ||
| sub.AddCommand(&cobra.Command{Use: "get", Short: "Get a value"}) | ||
| sub.AddCommand(&cobra.Command{Use: "set", Short: "Set a value"}) | ||
| root.AddCommand(sub) | ||
|
|
||
| got := Generate(root) | ||
|
|
||
| assertContains(t, got, `subcommand_required=#true`) | ||
| } | ||
|
|
||
| func TestAliases(t *testing.T) { | ||
| root := &cobra.Command{Use: "app"} | ||
| sub := &cobra.Command{ | ||
| Use: "install", | ||
| Short: "Install packages", | ||
| Aliases: []string{"i", "add"}, | ||
| } | ||
| root.AddCommand(sub) | ||
|
|
||
| got := Generate(root) | ||
|
|
||
| assertContains(t, got, `alias i add`) | ||
| } | ||
|
|
||
| func TestGenerateJSON(t *testing.T) { | ||
| cmd := &cobra.Command{ | ||
| Use: "mycli", | ||
| Short: "A CLI tool", | ||
| Version: "2.0.0", | ||
| } | ||
|
|
||
| data, err := GenerateJSON(cmd) | ||
| if err != nil { | ||
| t.Fatalf("GenerateJSON failed: %v", err) | ||
| } | ||
|
|
||
| jsonStr := string(data) | ||
| assertContains(t, jsonStr, `"name": "mycli"`) | ||
| assertContains(t, jsonStr, `"version": "2.0.0"`) | ||
| assertContains(t, jsonStr, `"about": "A CLI tool"`) | ||
| } | ||
|
|
||
| func TestLongHelp(t *testing.T) { | ||
| root := &cobra.Command{ | ||
| Use: "app", | ||
| Short: "Short help", | ||
| Long: "This is a much longer description of the app.", | ||
| } | ||
|
|
||
| got := Generate(root) | ||
|
|
||
| assertContains(t, got, `about "Short help"`) | ||
| assertContains(t, got, `long_about "This is a much longer description of the app."`) | ||
| } | ||
|
|
||
| // --- helpers --- | ||
|
|
||
| func assertContains(t *testing.T, got, want string) { | ||
| t.Helper() | ||
| if !strings.Contains(got, want) { | ||
| t.Errorf("output does not contain %q\ngot:\n%s", want, got) | ||
| } | ||
| } | ||
|
|
||
| func assertNotContains(t *testing.T, got, unwanted string) { | ||
| t.Helper() | ||
| if strings.Contains(got, unwanted) { | ||
| t.Errorf("output should not contain %q\ngot:\n%s", unwanted, got) | ||
| } | ||
| } | ||
|
|
||
| func findLine(output, prefix string) string { | ||
| for _, line := range strings.Split(output, "\n") { | ||
| if strings.Contains(line, prefix) { | ||
| return line | ||
| } | ||
| } | ||
| return "" | ||
| } |
There was a problem hiding this comment.
Consider adding test coverage for edge cases such as: help text containing newlines or special characters, argument names with spaces or special characters, and flags/args with multiple default values. While these are uncommon scenarios, they would help ensure the KDL escaping and rendering logic handles all cases correctly.
Adds a Go package at integrations/cobra/ that converts Cobra command trees into usage specs in KDL format, enabling shell completions, docs, and man pages for any Cobra-based CLI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix JSON tag: `about_long` → `long_about` for consistency with KDL output - Use type-aware default suppression: only skip "false" for bool and "0" for count flags, preserving string defaults like "0" - Only set subcommand_required when command has no Run/RunE handler - Improve builtin detection: check Cobra annotations before falling back to name matching, so user-defined "help"/"completion" commands with custom Run handlers are preserved - Add Args validators to example commands to prevent panics - Add tests for runnable commands with subcommands and string "0" defaults Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7ac301a to
464f52d
Compare
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #498 +/- ##
=======================================
Coverage 77.81% 77.81%
=======================================
Files 47 47
Lines 6595 6595
Branches 6595 6595
=======================================
Hits 5132 5132
Misses 1105 1105
Partials 358 358 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- JSON output now matches usage-lib's schema: root "cmd" object, map-based subcommands, "choices" field (not "values"), flag short/long as arrays, usage strings on flags and args - Skip [command] and [subcommand] placeholders in parseArgsFromUse so they aren't treated as real positional arguments - Add tests for JSON schema shape, choices format, and placeholder skipping Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
### 🚀 Features - add Cobra (Go) integration for generating usage specs by [@jdx](https://github.com/jdx) in [#498](#498) - Add support for nushell by [@abusch](https://github.com/abusch) in [#485](#485) ### 🐛 Bug Fixes - **(docs)** align homepage feature button with integrations page by [@jdx](https://github.com/jdx) in [#496](#496) ### 📚 Documentation - add integrations directory with framework tracker by [@jdx](https://github.com/jdx) in [#497](#497) - add integrations directory with framework tracker by [@jdx](https://github.com/jdx) in [#499](#499) ### 🔍 Other Changes - mise up by [@muzimuzhi](https://github.com/muzimuzhi) in [#492](#492) ### 📦️ Dependency Updates - update actions/checkout digest to de0fac2 by [@renovate[bot]](https://github.com/renovate[bot]) in [#494](#494) - update taiki-e/upload-rust-binary-action digest to f391289 by [@renovate[bot]](https://github.com/renovate[bot]) in [#495](#495) - lock file maintenance by [@renovate[bot]](https://github.com/renovate[bot]) in [#500](#500) ### New Contributors - @abusch made their first contribution in [#485](#485)
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [usage](https://github.com/jdx/usage) | minor | `2.16.2` → `2.17.0` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>jdx/usage (usage)</summary> ### [`v2.17.0`](https://github.com/jdx/usage/blob/HEAD/CHANGELOG.md#2170---2026-02-16) [Compare Source](jdx/usage@v2.16.2...v2.17.0) ##### 🚀 Features - add Cobra (Go) integration for generating usage specs by [@​jdx](https://github.com/jdx) in [#​498](jdx/usage#498) - Add support for nushell by [@​abusch](https://github.com/abusch) in [#​485](jdx/usage#485) ##### 🐛 Bug Fixes - **(docs)** align homepage feature button with integrations page by [@​jdx](https://github.com/jdx) in [#​496](jdx/usage#496) ##### 📚 Documentation - add integrations directory with framework tracker by [@​jdx](https://github.com/jdx) in [#​497](jdx/usage#497) - add integrations directory with framework tracker by [@​jdx](https://github.com/jdx) in [#​499](jdx/usage#499) ##### 🔍 Other Changes - mise up by [@​muzimuzhi](https://github.com/muzimuzhi) in [#​492](jdx/usage#492) ##### 📦️ Dependency Updates - update actions/checkout digest to [`de0fac2`](jdx/usage@de0fac2) by [@​renovate\[bot\]](https://github.com/renovate\[bot]) in [#​494](jdx/usage#494) - update taiki-e/upload-rust-binary-action digest to [`f391289`](jdx/usage@f391289) by [@​renovate\[bot\]](https://github.com/renovate\[bot]) in [#​495](jdx/usage#495) - lock file maintenance by [@​renovate\[bot\]](https://github.com/renovate\[bot]) in [#​500](jdx/usage#500) ##### New Contributors - [@​abusch](https://github.com/abusch) made their first contribution in [#​485](jdx/usage#485) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNS4yIiwidXBkYXRlZEluVmVyIjoiNDMuMTUuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90IiwiYXV0b21hdGlvbjpib3QtYXV0aG9yZWQiLCJkZXBlbmRlbmN5LXR5cGU6Om1pbm9yIl19-->
Summary
integrations/cobra/that converts Cobra command trees into usage specs in KDL formatGenerate,GenerateJSON,GenerateToFile,GenerateJSONToFile), 15 tests, an example CLI, and documentationTest plan
cd integrations/cobra && go test ./...— all 15 tests passcd integrations/cobra/example && go run . --usage-spec— prints valid KDLusage generate mdto produce markdown docs🤖 Generated with Claude Code
Note
Medium Risk
Introduces a new standalone integration module with non-trivial conversion/serialization logic; risk is mainly correctness/compatibility of generated specs rather than impact on existing runtime behavior.
Overview
Adds a new Go integration,
integrations/cobra(cobra_usage), that convertsspf13/cobracommand trees into usage specs and renders them as KDL (forusage generate) or as JSON matching the usage-lib schema.The converter maps Cobra commands/flags/args (including aliases, hidden/deprecated, persistent vs local flags,
ValidArgschoices, required/count/bool/default handling, and skipping Cobra’s built-in help/completion commands and--help/--versionflags), and includes an example CLI plus comprehensive tests and integration documentation. Updatesintegrations/README.mdto mark Cobra as implemented.Written by Cursor Bugbot for commit 0ceaea1. This will update automatically on new commits. Configure here.