Cobra command trees
Preserve the CLI's public contract: command paths, flags, arguments, output streams, help, completion, exit behavior, and compatibility.
Inspect before editing
Check go.mod, root-command construction, Execute/ExecuteContext, parent and child hooks, flags, argument validators, I/O, exit-code mapping, completions, generated docs, and tests. Prefer local command factories and helpers over introducing a parallel structure.
Command execution
- Use
RunEand*Ehooks when the handler can fail and the caller should receive the error.Runremains valid for genuinely infallible behavior. - Keep parsing and structural argument checks in Cobra's validation facilities when that improves help and diagnostics. Domain validation that requires loaded state can remain in the handler.
- Return errors from command code instead of calling
os.Exit; let the outermost executable choose rendering and exit status. Preserve any established typed-error or silence policy. - Pass
cmd.Context()into cancellable work. Do not replace it withcontext.Background()inside a command.
Do not assume every ancestor persistent hook runs. Child hooks and the selected traversal behavior affect inheritance. Inspect the pinned version and test the actual order before moving initialization into a parent hook.
Flags and configuration
Distinguish local and persistent flags and check for inherited-name collisions. Preserve shorthand, defaults, deprecation, requiredness, normalization, and help text as user-facing API.
Read values from the command's flag set or the project's injected configuration object. When integrating Viper, bind flags before any lookup or decode that depends on them; the correct location follows the construction and loading order.
For the concrete hook sequence, built-in validators, flag APIs, completion directives, and an isolated test fixture, read references/api-and-testing.md.
Change the public surface coherently
When adding or changing a command, update its Use, Short/Long, Example, argument validator, flags, completion, and tests as one contract. Keep aliases, hidden/deprecated status, command groups, and inherited flags stable unless the CLI change calls for them. Ensure the executable boundary renders a returned error once and maps it to the established exit status.
Review SilenceUsage and SilenceErrors together with that outer error-rendering policy; changing only one can duplicate output or hide useful usage.
I/O, help, and completion
Use cmd.OutOrStdout(), cmd.ErrOrStderr(), and cmd.InOrStdin() in handlers that should respect Cobra's configured streams. Keep diagnostic and machine-readable output on their documented channels.
Completion functions should be fast, cancellation-aware, and free of surprising mutations. Keep ordinary command output out of completion responses and preserve the selected shell directives.
If documentation or completion artifacts are generated, use the repository's existing generation command and review the diff for deterministic output.
Testing and verification
Prefer constructing a fresh command tree per test; Cobra command and flag objects retain parse state across executions. Set arguments, context, and in-memory streams explicitly, then assert returned errors and output separately. Avoid testing production behavior through process-global os.Args or os.Stdout unless the executable boundary itself is under test.
Cover parent/child hook order, cancellation, argument validation, flag precedence, output channels, completion, and exit mapping affected by the change. Run formatting and relevant tests, then manually inspect changed help text for public CLI changes.