Files
commandkit/docs/adr/0002-cobra-backend.md

5.2 KiB

ADR 0002: Use Cobra and pflag as the initial internal CLI backend

Status

Accepted.

Date

2026-10-06

Context

CommandKit's selected dispatcher model needs nested routing, flags and operands, generated help, usage diagnostics, and invocation execution. Reimplementing this generic infrastructure would add work beyond the suite-specific inspection and consistency behavior that motivates the library.

Cobra and urfave/cli v3 were the finalists. The latter's destination bindings and duplicate controls offered a close fit for the explicit-input model. The author strongly preferred Cobra because of its broader adoption. Familiarity and the availability of contributors who know the framework are useful maintenance considerations across several related applications.

The selection was based on documentation and API review. Ecosystem adoption is the selection rationale, not evidence that every backend default is an appropriate CommandKit contract.

Decision

Use Cobra with pflag as the sole initial CLI backend. CommandKit translates its registrations into backend command trees, flag bindings, and execution callbacks. Reuse their routing, option parsing, help, context, and stream mechanisms and add adaptation where selected CommandKit semantics require it.

CommandKit retains its own public registration API, typed inputs, standard families, and observable contracts. Applications do not construct Cobra commands or use pflag getters in handlers. ADR 0003 isolates the backend behind an internal adapter and root-owned public contracts.

Applications retain process lifecycle and domain execution. ConfigKit and PromptKit retain configuration and inspection semantics. Framework selection does not transfer those responsibilities to Cobra or CommandKit.

Build fresh backend command/flag state and input storage per invocation. A fresh command tree constructed from registered definitions is the initial approach. Tree construction must not load configuration or create application runtime.

Implement one concrete backend. There is no initial public backend selector or pluggable framework. A future replacement can change internal implementation while preserving the public API and selected behavioral contracts.

Alternatives considered

Alternative Advantages Reason not selected
urfave/cli v3 Destination bindings for flags and named operands, presence queries, and duplicate controls fit the chosen input model closely. Credible alternative; Cobra's broader adoption is the preferred maintenance tradeoff.
pflag alone Established parsing with a smaller integration surface. Leaves more routing, help integration, and command infrastructure to implement.
Kong Compact typed-struct and tag-driven declarations. Its main declaration model differs from the explicit-binding API; adaptation reduces its benefit.
Standard flag alone Familiar variable binding and custom value parsing. First-operand stopping requires adaptation for the intended syntax, with more custom command infrastructure.
Expose Cobra as the public API Less adapter code and the full framework surface. Couples consumers to backend structures and framework-specific configuration.
Interchangeable backends immediately Future integration flexibility. Adds abstraction and behavior surfaces without a current requirement.

Consequences

The framework supplies established generic CLI machinery. CommandKit still owns registration conflicts, reserved families, typed bindings and presence, standard help and diagnostics, provider integration, and selected reports and outcomes.

The adapter must accommodate explicit empty/false/zero values, fresh state, selected repetition and operand rules, and help without configuration. Backend features do not expand the standard automatically: for example, completion commands remain deferred unless deliberately selected.

Backend error handling must preserve application outcomes, avoid duplicate diagnostics, and return control to the application's entry point. Native YAML inspection and multi-document scope display remain integration work using the owning libraries. Choosing a framework introduces no JSON report requirement.

Exact dependency versions and attribution are selected when dependencies are incorporated. Meaningful integration evidence must exercise the real adapter against selected contracts. A dependency update or replacement can change CLI behavior even with unchanged Go signatures and is subject to compatibility policy.

The architecture policy owns normative boundaries; the backend roadmap owns implementation tasks and status. ADR 0001 records the dispatcher and input model. Remaining command and grammar proposals belong to the CLI roadmap.

Reviewed primary references from the selection: