clikit

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package clikit is the invocation and help contract shared by the ~/dev Go command-line tools. A tool declares its commands as native Kong structs (github.com/alecthomas/kong) and describes itself once, as an App; main and the tests run that same value.

One declaration drives both parsing and help: a command is a struct whose fields are flags and positional arguments, each with a help tag, and whose Run method does the work. Long prose belongs in a Help() string method on the same type, and titled blocks such as examples in a HelpSections method. Nothing about a command's syntax is written twice.

type CLI struct {
	Dir string `help:"Directory that holds the store." env:"TOOL_DIR" default:"~/.tool" type:"path"`
	Add AddCmd `cmd:"" help:"Register a repository."`
}

type AddCmd struct {
	Path string `arg:"" type:"existingdir" help:"Checkout to register."`
}

func (c *AddCmd) Run(ctx *kong.Context, s *Store) error { ... }

var app = clikit.App{
	Name:        "tool",
	Description: "tool keeps a registry of repositories.",
	New:         func() any { return &CLI{} },
	Options: []kong.Option{
		kong.BindToProvider(func(cli *CLI) (*Store, error) { return openStore(cli.Dir) }),
	},
	ExitCodes: map[int]string{3: "a repository is missing"},
}

func main() { os.Exit(app.Run(os.Args[1:])) }

Each invocation parses into a fresh grammar from New, so Options must not capture one. A Run method or provider that needs the parsed root or its flags takes the root type as a parameter (cli *CLI above); Kong binds it.

Run guarantees:

  • Help always works. --help prints the page to stdout and exits 0 before any command runs, any hook after BeforeReset fires, or any environment variable is read. Load configuration and credentials in Run methods or through kong.BindToProvider, which is called only when a Run method asks for the value, never in grammar hooks or mappers. No option can take this away.
  • Help is rendered from the model. The synopsis, arguments, flags, typed placeholders, defaults, enums, environment variables, flag-group constraints, passthrough and exit codes come from the same declaration that parses argv. Help() text and sections are printed verbatim, never reflowed.
  • A declaration whose help would be missing or untrue fails before parsing: anything visible without help, an empty Description, an enum default outside its values, an xor group with only some members required, a branching positional argument, or kong.NoDefaultHelp. The first test (or run) of the tool names each problem.
  • Outcomes are classified by origin. Invalid argv exits with App.UsageCode after an error line, the synopsis and a pointer to --help, all on stderr. A bad value from an environment variable, and anything else that fails, exits with App.FailureCode. A command chooses its own status with Exit, declared in App.ExitCodes, or reports a usage error it found itself with Usage.

Commands write through the bound *kong.Context (ctx.Stdout, ctx.Stderr), which are App.Stdout and App.Stderr themselves, and read input from a bound io.Reader parameter (App.Stdin). The clikittest package runs an App with captured output and pins every help page.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Exit

func Exit(code int) error

Exit makes a command end with status code without printing anything more: the command has already reported what happened. Declare the code in App.ExitCodes so help lists it. Exit(0) is nil.

func Usage

func Usage(err error) error

Usage marks err as a usage error the command found itself, such as a combination of flags its declaration cannot express. Run prints it with the command's synopsis and exits with App.UsageCode. It classifies the outcome only: return it before the command has changed anything.

Types

type App

type App struct {
	// Name is the program name in help and error lines. Empty means the base
	// name of os.Args[0].
	Name string

	// Description says what the tool is for; required.
	Description string

	// New returns a fresh grammar, a pointer to the root command struct. Every
	// invocation gets its own, since parsing writes into it.
	New func() any

	// Options are Kong options: kong.Bind, kong.BindToProvider, kong.Vars,
	// mappers and so on. They are shared by every invocation, so they must not
	// capture a grammar instance; a provider or Run method that needs the
	// parsed root takes it as a parameter (func(cli *CLI) (*Store, error)).
	Options []kong.Option

	// ExitCodes adds the statuses the tool's commands return through Exit,
	// with their meaning. 0, UsageCode and FailureCode are always listed; an
	// entry here rewords one of them.
	ExitCodes map[int]string

	// UsageCode is the exit status for invalid argv. Zero means 2.
	UsageCode int

	// FailureCode is the exit status for every other failure. Zero means 1.
	FailureCode int

	// Stdin is bound for Run methods as an io.Reader. Nil means os.Stdin.
	Stdin io.Reader

	// Stdout and Stderr become ctx.Stdout and ctx.Stderr of the bound
	// *kong.Context, unwrapped. Nil means os.Stdout and os.Stderr.
	Stdout, Stderr io.Writer
}

App is one tool's whole command line: main runs it and its tests run the same value, so nothing about the tool is assembled twice.

func (App) Run

func (a App) Run(args []string) (code int)

Run parses args (without the program name), runs the selected command and returns the process exit status. It never calls os.Exit.

type HelpSections

type HelpSections interface {
	HelpSections() []Section
}

HelpSections is implemented by a command struct (or the root struct) to add sections such as Examples or Output to its help page.

type Section

type Section struct {
	Title string
	Body  string

	// Shared prints the section on this command's page and on the page of
	// every command below it, such as a tool-wide overview on the root.
	Shared bool
}

Section is a titled block of help a command declares, printed verbatim after the generated parts of its page.

Directories

Path Synopsis
Package clikittest runs a clikit App in tests exactly as main does, and pins every help page against golden files.
Package clikittest runs a clikit App in tests exactly as main does, and pins every help page against golden files.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL