cli

package
v2.679.0 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 2026 License: MIT Imports: 14 Imported by: 13

Documentation

Overview

Package cli provides helpers for building command-line applications with go-service.

This package wraps the command framework used by this module (github.com/cristalhq/acmd) and provides a small layer of conveniences for wiring subcommands using go-service DI (Fx/Dig via the `di` package).

In typical service applications, this package is used together with `go-service-template` and the high-level module bundles from the `module` package.

Entry points

Start with NewApplication to construct an Application and register subcommands via a RegisterFunc. Most applications then call either:

Application.RunCode returns os.ExitCodeSuccess on success, returns the requested non-zero shutdown exit code when the DI application shuts down with one, and returns os.ExitCodeFailure for other errors.

Application.Run reads the go-service os.Args variable, sanitizes injected Go test harness flags such as `-test.v` and `-test.run=...`, and then passes the remaining arguments to the command runner.

Subcommands and DI wiring

Subcommands are added via Commander methods:

  • Application.AddServer creates a long-running server-style command. It starts the DI app and then blocks until the DI app signals completion, stopping it afterwards.
  • Application.AddClient creates a short-lived client-style command. It starts the DI app, then stops it immediately after startup completes.

Each added subcommand returns a *Command, which embeds a `*flag.FlagSet`. Define command-specific flags on that `FlagSet` before execution. The command implementation parses it and wires the parsed flag set into DI so constructors can read parsed values. Command names must be unique across the application.

Environment-derived metadata

The CLI name and version are derived from environment helpers in `env` and exposed via package variables (Name and Version) so they can be reused consistently.

Index

Constants

This section is empty.

Variables

View Source
var ErrCommandRegistered = errors.New("command already registered")

ErrCommandRegistered indicates a subcommand name has already been registered on an Application.

View Source
var FS = os.NewFS()

FS is the filesystem used by CLI helpers for configuration lookup and reading sources.

It defaults to an *os.FS rooted in the host filesystem (see os.NewFS). Tests may override this variable to control filesystem reads performed during CLI setup.

View Source
var Name = env.NewName(FS)

Name is the CLI application name derived from the environment.

The name is resolved via `env.NewName(FS)` and is used by Application.Run to populate the command runner's app metadata (for example help text and descriptions). It is resolved at package initialization; tests or embedders that need to change it after init should assign this variable directly.

View Source
var Version = env.NewVersion()

Version is the CLI application version derived from the environment.

The version is resolved via `env.NewVersion()` and is used by Application.Run to populate the command runner's version information. It is resolved at package initialization; tests or embedders that need to change it after init should assign this variable directly.

Functions

This section is empty.

Types

type Application

type Application struct {
	// contains filtered or unexported fields
}

Application is a command-line application composed of subcommands.

An Application maintains a set of commands and delegates parsing/execution to the underlying command framework (github.com/cristalhq/acmd).

func NewApplication

func NewApplication(register RegisterFunc) *Application

NewApplication constructs an Application and invokes register to add subcommands.

The returned Application is pre-populated with the current module-level Name and Version values. Those variables are initialized from the environment at package init time and can be assigned directly by tests or embedders that need post-init overrides.

func (*Application) AddClient

func (a *Application) AddClient(name, description string, opts ...Option) *Command

AddClient adds a short-lived client subcommand with DI lifecycle wiring.

The returned *Command embeds a *flag.FlagSet. The flag set is parsed before DI startup and is then provided into the DI container so constructors can consume parsed flag values. Command names must be unique across the application. Duplicate command names panic with an error that wraps ErrCommandRegistered.

Execution semantics:

  • parse the command args into the command's FlagSet
  • build a DI application with panic recovery, a fresh copy of the provided options, plus the command's module
  • start the DI application
  • stop the DI application immediately after startup completes

Client commands should perform their main action from an invoked constructor or a lifecycle OnStart hook so the work completes before startup returns and the graph is stopped.

Any start/stop error is wrapped with the subcommand name for easier attribution.

func (*Application) AddServer

func (a *Application) AddServer(name, description string, opts ...Option) *Command

AddServer adds a long-running server subcommand with DI lifecycle wiring.

The returned *Command embeds a *flag.FlagSet. The flag set is parsed before DI startup and is then provided into the DI container so constructors can consume parsed flag values. Command names must be unique across the application. Duplicate command names panic with an error that wraps ErrCommandRegistered.

Execution semantics:

  • parse the command args into the command's FlagSet
  • build a DI application with panic recovery, a fresh copy of the provided options, plus the command's module and runtime.Module
  • start the DI application
  • block until the DI application shuts down or ctx is canceled
  • stop the DI application

Any start/stop error or non-zero shutdown request is wrapped with the subcommand name for easier attribution.

func (*Application) Run

func (a *Application) Run(ctx context.Context) error

Run executes the application using the configured command set.

Run configures the underlying command runner with:

  • app name/description derived from a.name
  • version derived from a.version
  • sanitized process arguments from the go-service os.Args variable, with Go test harness flags such as "-test.v" removed (see os.SanitizeArgs)
  • the provided context

It returns any execution error from the underlying runner or command ExecFunc.

func (*Application) RunCode added in v2.372.0

func (a *Application) RunCode(ctx context.Context) int

RunCode executes the application and returns the process exit code that represents the result.

RunCode returns os.ExitCodeSuccess when Run succeeds. When Run returns an error, RunCode logs the error and returns either the non-zero shutdown exit code carried by the error or os.ExitCodeFailure.

type Command

type Command struct {
	*flag.FlagSet
}

Command wraps a *flag.FlagSet and provides DI wiring for CLI subcommands.

The embedded FlagSet is intended to be configured with flags by the caller, then parsed by the subcommand execution path. The `module` method exposes providers for the filesystem/name/version metadata and the command's FlagSet, and enables DI panic recovery.

func NewCommand added in v2.66.0

func NewCommand(name string) *Command

NewCommand creates a new CLI Command with the given name.

The returned Command embeds a *flag.FlagSet that you can use to define CLI flags. Application subcommands call flag.FlagSet.Parse before starting DI, and the Command's `module` wires the parsed FlagSet into the DI container so constructors can read flag values.

type Commander

type Commander interface {
	// AddServer registers a long-running server-style subcommand.
	//
	// Command names must be unique across the entire application.
	//
	// The subcommand:
	//   - parses command args into the returned `*Command`'s FlagSet,
	//   - starts a DI application built from opts plus server-specific wiring,
	//   - blocks until the DI application signals completion,
	//   - then stops the DI application.
	AddServer(name, description string, opts ...Option) *Command

	// AddClient registers a short-lived client-style subcommand.
	//
	// Command names must be unique across the entire application.
	//
	// The subcommand:
	//   - parses command args into the returned `*Command`'s FlagSet,
	//   - starts a DI application built from opts plus client-specific wiring,
	//   - then stops the DI application immediately after startup completes.
	//
	// Run the command's main action from an invoked constructor or a lifecycle
	// OnStart hook so it completes before startup returns.
	AddClient(name, description string, opts ...Option) *Command
}

Commander registers CLI subcommands on an application.

Implementations typically add subcommands that build and run a DI application using go-service's `di` package. The returned *Command embeds a `*flag.FlagSet` so you can define command-specific flags before execution.

type Option

type Option = di.Option

Option is an alias for di.Option.

type RegisterFunc

type RegisterFunc = func(commander Commander)

RegisterFunc registers subcommands on a Commander.

A RegisterFunc is invoked by NewApplication to populate the application's command set. Implementations typically call commander.AddServer and/or commander.AddClient.

Jump to

Keyboard shortcuts

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