Attach the commands to a CLI¶
This guide shows how a host binary wires the sign and keys command builders
onto its root command: first for a plain Cobra
CLI, then for a go-tool-base tool.
Both paths are real and compilable.
Every constructor returns a plain *cobra.Command and takes one
signingcli.Logger. You do not need an adapter:
a *slog.Logger and go-tool-base's logger.Logger both satisfy the interface
structurally.
Attaching the commands does not compile in any signing backend. That is a separate, deliberate step; see Compile in signing backends.
Plain Cobra root (e.g. sigillum)¶
Add the module and attach the two top-level builders directly. NewCmdKeys
returns the keys parent with all five subcommands (mint, generate, wkd,
minisign and publish) already attached, so one AddCommand brings the whole
group.
package main
import (
"log/slog"
"os"
"github.com/spf13/cobra"
signingcli "gitlab.com/phpboyscout/go/signing-cli"
// Compile in the backends this binary should offer (see the
// companion how-to). Without at least one, `--backend` has no
// valid value.
_ "gitlab.com/phpboyscout/go/signing-aws-kms" // registers "aws-kms"
_ "gitlab.com/phpboyscout/go/signing/local" // registers "local"
)
func main() {
log := slog.New(slog.NewTextHandler(os.Stderr, nil))
root := &cobra.Command{Use: "sigillum"}
root.AddCommand(
signingcli.NewCmdSign(log), // sign <input-file>
signingcli.NewCmdKeys(log), // keys (mint | generate | wkd | minisign | publish)
)
if err := root.Execute(); err != nil {
os.Exit(1)
}
}
That is the entire integration. sigillum sign … and all five keys
subcommands work.
Attaching a single subcommand¶
If you want only part of the group, say keys mint under your own parent, the
subcommand builders are exported too:
myKeys := &cobra.Command{Use: "keys"}
myKeys.AddCommand(
signingcli.NewCmdKeysMint(log),
signingcli.NewCmdKeysGenerate(log),
signingcli.NewCmdKeysWKD(log),
signingcli.NewCmdKeysMinisign(log),
signingcli.NewCmdKeysPublish(log),
)
root.AddCommand(myKeys)
NewCmdKeys(log) is the convenience that does exactly this, plus one thing a
hand-built parent will not do unless you add it: it answers an unknown
subcommand (keys bogus) with an error instead of printing help and exiting 0.
go-tool-base root (gtb and scaffolded tools)¶
go-tool-base registers subcommands through setup.Wrap, which pairs a command
with the GTB feature it belongs to (an empty feature string means "always on,
not gated by a feature flag"). Pass the framework logger straight in via
p.GetLogger():
import (
"gitlab.com/phpboyscout/go-tool-base/pkg/cmd/root"
"gitlab.com/phpboyscout/go-tool-base/pkg/setup"
signingcli "gitlab.com/phpboyscout/go/signing-cli"
)
rootCmd := root.NewCmdRoot(p,
// … other subcommands …
setup.Wrap("", signingcli.NewCmdKeys(p.GetLogger())),
setup.Wrap("", signingcli.NewCmdSign(p.GetLogger())),
)
p is the GTB *props.Props; p.GetLogger() returns a logger.Logger, which
satisfies signingcli.Logger directly. This is how the shipped gtb binary
wires the commands, in cli/pkg/cmd/root/root.go in the go-tool-base
repository.
As with the plain-Cobra path, the backends must still be blank-imported in the
binary's main package. In gtb those live in a single on/off file,
cli/cmd/gtb/signing.go; see Compile in signing backends.
Verify the wiring¶
your-tool sign --help # shows --backend, --key-id, --public-key, …
your-tool keys --help # lists mint, generate, wkd, minisign, publish
your-tool keys mint --help # --backend's help lists the compiled-in backend types
If --backend lists no backends, you have attached the commands but not
compiled any backend in.
See also¶
- Compile in signing backends, to make
--backend aws-kmsand--backend localactually resolve. - The Logger seam: why
p.GetLogger()andslog.New(...)both work without an adapter. signandkeys: the flag reference for each command.- Add signing to your CLI and sign your first release: the same wiring built from an empty directory, then used to sign something.
- What signing-cli does not do: the boundaries to know about before you build on the commands.