8.6 KiB
Consumer guide
CommandKit is distributed as three Go modules. Start with the core and add an
integration module only when the application uses that library. Each module
returns core commandkit.Command declarations, which the application installs
through commandkit.New or App.Register.
Module selection
| Import | Use when |
|---|---|
gitea.maximumdirect.net/eric/CommandKit |
The application needs typed command declarations and common CLI behavior. |
gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig |
The application wants ConfigKit-backed configuration scopes and reports. |
gitea.maximumdirect.net/eric/CommandKit/integrations/ckprompt |
The application wants PromptKit engine configuration/comparison, prompt/profile catalogs, named inspection, or requirements discovery. |
The two integrations are independent optional imports. ckprompt uses the
public scope and error contracts from ckconfig; importing it does not add the
config family. An application that wants both families passes both returned
declarations to core. The maintained examples show
core-only, ConfigKit-only, and composed applications.
Go compatibility
All three modules declare a consumer minimum of Go 1.26.0. The root module also selects ReleaseKit v0.4.0 as a Go tool, which makes that tool's module graph part of the root consumer module requirements even though production packages do not import ReleaseKit. The release policy defines the support assumption. Maintainers use Go 1.26.8 for validation and publication; see the release procedure.
Core commands
Declare typed flags and operands with CommandSpec[I], then capture them with
NewCommand. Bindings deliver Supplied[T], which distinguishes an omitted
default from an explicitly supplied empty, false, or zero value.
package example
import (
"fmt"
"strconv"
commandkit "gitea.maximumdirect.net/eric/CommandKit"
)
type GreetInput struct {
Count commandkit.Supplied[int]
}
func Greeting() commandkit.Command {
countDefault := 1
return commandkit.NewCommand(commandkit.CommandSpec[GreetInput]{
Name: "greet", Summary: "Write a greeting.",
Flags: []commandkit.Flag[GreetInput]{
commandkit.ValueFlag(
commandkit.FlagMeta{Name: "count", Usage: "Number of greetings."},
&countDefault, strconv.Atoi,
func(input *GreetInput, value commandkit.Supplied[int]) {
input.Count = value
},
),
},
Run: func(invocation commandkit.Invocation, input GreetInput) commandkit.Outcome {
_, _ = fmt.Fprintln(invocation.Streams.Out, input.Count.Value)
return commandkit.Success()
},
})
}
The application supplies context.Context, argv without the executable name,
and output streams to App.Execute; it decides how the returned status maps to
process exit. New installs generated help/version and caller declarations as
one batch. Register validates each call as a batch before changing that App.
Invalid declaration errors retain their wrapped identity for errors.Is and
errors.As.
Declarations copy their metadata and slice inputs when captured, retain callback
references, and can be reused across applications. Copies of a typed binding
preserve its identity; a separately constructed lookalike does not. Supplied
values convert before input construction. A command's NewInput creates input
only when execution reaches it; help does not construct caller input or run
provider callbacks.
ConfigKit scopes
For an application with one ordinary app configuration loader,
ckconfig.AppCommand supplies the state-free convenience declaration:
app, err := commandkit.New(
commandkit.Identity{Name: "Example", Version: "dev"},
ckconfig.AppCommand(loadAppConfig),
)
loadAppConfig has the signature
func(context.Context, ckconfig.Selection) (*configkit.Result[T], error).
Construction, installation, and help do not call it. Selection preserves
whether config and overlay paths were explicitly supplied, including empty
values.
Use ckconfig.Command(ckconfig.Suite[I, S]{...}) when the application needs
multiple named scopes, selector flags, scope-aware input checks, or shared
acquisition state or a custom comparison provider. A declared Diff capability
uses Scope.Compare; ckconfig.FromConfigKit and AppCommand provide the
ConfigKit-backed implementation. Each comparison side gets its own initialized
and checked input, while state is shared by the invocation. Factory results
remain caller-owned, so separate initialization calls do not guarantee distinct
objects. See
ckconfig.Suite's GoDoc for factory
timing, omitted-factory zero values (including nil pointers), and ownership.
The application owns the state type and what it caches. ckconfig.FromConfigKit
adapts a typed ConfigKit loader without calling it during construction.
The config family provides scope discovery, validation, native effective YAML,
source inventory, path explanation, and ConfigKit-backed comparison for the
capabilities declared by its scopes. The CLI reference
owns operator syntax and report details.
PromptKit configuration and definitions
ckprompt.ConfigScope(loadEngine) returns a ckconfig.Scope for the PromptKit
engine's captured configuration. Add that scope to a ckconfig.Suite to expose
it under config with validate/show/sources/explain and native diff operations;
it does not install PromptKit catalog, definition, or requirements commands.
ckprompt.FromEngine(loadEngine) supplies the prompt/profile catalog callbacks,
named inspection callbacks, and native requirements callback. Set its
NewInput, NewState, selectors, or validation when the application needs
them, then pass ckprompt.Command(suite) to core. All five callbacks are
independently optional; Command creates each operation group only when its
callbacks are present. Applications can use the requirements callback alone,
clear it while retaining other operations, wrap it, or replace it with their
own provider. For catalogs without named or requirements inspection, narrow the
suite before command capture:
definitions := ckprompt.FromEngine(loadEngine)
definitions.InspectPrompt = nil
definitions.InspectProfile = nil
definitions.InspectRequirements = nil
definitionCommand := ckprompt.Command(definitions)
Each selected inspection, requirements, or catalog operation prepares one input,
applies its captured selectors, checks that input, and initializes one state
value when those steps are reached. See
ckprompt.Suite's GoDoc for factory
timing, omitted-factory zero values, and caller-owned objects and effects.
The loader receives invocation context, explicitly supplied selection, input,
and state. The adapter uses PromptKit's public listing and inspection methods,
including Engine.InspectRequirements, and preserves acquisition diagnostics
and supported error identity.
CommandKit-owned listing and inspection code does not execute prompts, contact model providers, or resolve credential values; application loaders and direct callbacks retain their own effects. The CLI reference owns the command and report contracts.
The composed example
combines app and PromptKit config scopes, comparison and catalogs, named and
requirements inspection, and an application-owned session restore command.
Outcomes and ownership
Core classifies usage and operational failures while preserving application
domain outcomes and supported error identity. Report and diagnostic delivery
errors remain inspectable separately from the operation cause. The caller owns
process startup, signal handling, and exit mapping; Execute never exits the
process.
Go declarations and GoDoc own exact exported contracts. ConfigKit owns configuration decoding, validation, and provenance. PromptKit owns prompt formats, profile resolution, and inspection details. See the ConfigKit inspection API, PromptKit engine methods, configuration inspection, and inspection types.