cmd

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: May 22, 2026 License: MIT Imports: 22 Imported by: 0

README

cmd

English | 简体中文

cmd is a modern command-line library for Go. It keeps a small API surface, but adds the capabilities usually needed by production-grade CLIs:

  • Recursive command trees
  • Global flags and command-local flags
  • Positional argument schema
  • Multi-source binding with env / config / CLI / default
  • Shell completion
  • REPL and cursor-aware line completion APIs
  • Machine-readable spec
  • Markdown and man page generation
  • Hooks, middleware, and observers
  • Unified CLI errors and exit codes

This document is organized from quick start to platform-style integration.

Table of Contents

  1. Installation
  2. Quick Start
  3. CLI + REPL Tutorial
  4. Architecture Overview
  5. Two Usage Modes
  6. Command Model
  7. Flag Model
  8. Parsing Rules
  9. Help and Built-in Commands
  10. Config, Environment Variables, and Precedence
  11. Positional Arguments
  12. Completion
  13. REPL and Line Execution
  14. Machine-readable Spec
  15. Docs Generation
  16. Lifecycle Hooks
  17. Middleware
  18. Observers and Telemetry
  19. Unified Errors and Exit Codes
  20. Custom Extension Metadata
  21. Common Patterns
  22. API Quick Reference

Installation

Import the package using your actual module path. In this repository, the package path is:

import "pkg.gostartkit.com/cmd"

Quick Start

This minimal example includes:

  • A global flag --verbose
  • A version command
  • A hello command
  • Command-local flags, positional arguments, and env binding
package main

import (
	"context"
	"fmt"

	"pkg.gostartkit.com/cmd"
)

var (
	verbose bool
	name    string
	version = "v1.0.0"
)

func main() {
	cmd.SetFlags(func(f *cmd.FlagSet) {
		f.BoolVar(&verbose, "verbose", false, "enable verbose output", "v")
		f.SetCategory("verbose", "Global")
	})

	cmd.AddCommands(
		&cmd.Command{
			Name:      "version",
			UsageLine: "app version",
			Short:     "print version",
			Run: func(ctx context.Context, c *cmd.Command, args []string) error {
				fmt.Println(version)
				return nil
			},
		},
		&cmd.Command{
			Name:      "hello",
			UsageLine: "app hello [flags] <target>",
			Short:     "print greeting",
			Examples: []string{
				"app hello team --name sam",
				"APP_NAME=sam app hello user",
			},
			Positionals: []cmd.PositionalArg{
				{Name: "target", Usage: "greeting target", Required: true, Enum: []string{"team", "user"}},
			},
			SetFlags: func(f *cmd.FlagSet) {
				f.StringVar(&name, "name", "", "name to greet", "n")
				f.BindEnv("name", "APP_NAME")
				f.MarkRequired("name")
				f.SetEnum("name", "sam", "sara", "tom")
			},
			Run: func(ctx context.Context, c *cmd.Command, args []string) error {
				if verbose {
					fmt.Printf("[verbose] target=%s name=%s\n", args[0], name)
				}
				fmt.Printf("hello %s (%s)\n", name, args[0])
				return nil
			},
		},
	)

	cmd.Execute()
}

Example invocations:

app version
app --verbose hello team --name sam
APP_NAME=sara app hello user
app hello team -n tom

CLI + REPL Tutorial

If your goal is "define one command tree and support both a regular CLI and a REPL with smart hints and completion", the workflow below is the recommended setup.

1. Define one shared command tree

Using an explicit App instance keeps CLI, REPL, tests, and embedded runtimes on the same model:

package main

import (
	"context"
	"fmt"

	"pkg.gostartkit.com/cmd"
)

func buildApp() *cmd.App {
	app := cmd.NewApp("ops")
	app.Short = "Operations console"

	var verbose bool
	app.ConfigureFlags(func(f *cmd.FlagSet) {
		f.BoolVar(&verbose, "verbose", false, "verbose output", "v")
	})

	app.AddCommands(
		&cmd.Command{
			Name:      "deploy",
			UsageLine: "ops deploy [flags] <env>",
			Short:     "deploy service",
			Positionals: []cmd.PositionalArg{
				{
					Name:       "env",
					Required:   true,
					Enum:       []string{"dev", "staging", "prod"},
					Completion: func(ctx cmd.CompletionContext) []string { return []string{"dev", "staging", "prod"} },
				},
			},
			SetFlags: func(f *cmd.FlagSet) {
				var region string
				f.StringVar(&region, "region", "", "target region", "r")
				f.SetCompletion("region", func(ctx cmd.CompletionContext) []string {
					return []string{"cn", "us", "eu"}
				})
			},
			Run: func(ctx context.Context, c *cmd.Command, args []string) error {
				if verbose {
					fmt.Printf("[verbose] deploy to %s\n", args[0])
				}
				fmt.Printf("deploy %s\n", args[0])
				return nil
			},
		},
	)

	return app
}

The important part is:

  • commands, flags, and positionals are defined once
  • completion metadata such as Enum, SetCompletion(...), and PositionalArg.Completion lives on the same command tree
  • CLI and REPL both reuse the same completion engine
2. Enable the built-in REPL entry

If you want users to enter interactive mode through app repl, enable the built-in REPL command:

app.EnableREPL()

You can also configure the prompt and welcome text:

app.ConfigureREPL(func(cfg *cmd.REPLConfig) {
	cfg.Prompt = "ops> "
	cfg.Welcome = "type .help or press Tab"
})
3. Start through the unified entrypoint

The lowest-boilerplate main function looks like this:

func main() {
	app := buildApp()
	app.EnableREPL()
	cmd.Main(app)
}

With that setup:

  • ops deploy prod runs as a normal CLI
  • ops repl enters REPL mode

If you want to choose the runtime explicitly in code, you still can:

err := app.RunWith(ctx, cmd.CLIRuntime{Args: []string{"deploy", "prod"}})
err = app.RunWith(ctx, cmd.REPLRuntime{In: os.Stdin, Out: os.Stdout})
4. Use it as a CLI

The regular CLI usage stays unchanged:

ops deploy prod
ops deploy prod --region us
ops --verbose deploy dev
5. Use it in REPL mode

Enter REPL mode with:

ops repl

In a TTY terminal, the default REPL driver automatically supports:

  • Tab: complete commands, flags, positionals, and values
  • repeated Tab: page through longer candidate lists
  • real-time hints while typing
  • inline ghost text for the current best completion
  • Up / Down: command history
  • Left / Right: cursor movement
  • Backspace / Delete: character editing

For example:

ops> dep
hint: deploy - deploy service

ops> deploy --r
hint: --region - target region

ops> deploy p
hint: prod
6. What automatically carries over into REPL

Anything defined on the command tree is automatically reused by REPL, including:

  • command names and aliases
  • global flags and command-local flags
  • flag usage text
  • positional argument schemas
  • Enum
  • SetCompletion(...)
  • PositionalArg.Completion
  • command Short descriptions

That is why the recommended pattern is to keep completion rules on Command, FlagSet, and PositionalArg, instead of building a separate REPL-only layer.

For most apps, this is the minimal recommended stack:

  1. Keep one shared buildApp()
  2. Put value completion rules on the command model with Enum and SetCompletion(...)
  3. Call app.EnableREPL()
  4. Start with cmd.Main(app)

That usually gives you all of the following at once:

  • regular CLI execution
  • shell completion
  • REPL mode
  • REPL smart hints
  • REPL command and argument completion
  • REPL history and inline editing

Architecture Overview

The public API stays intentionally small, but internally the library follows a clear pipeline. Understanding that pipeline helps when you need to embed the package, override behavior, or generate tooling from the same command tree.

1. Effective root and shared command tree
  • App.Root is optional. If you do not set it, the library synthesizes a root command from App.Name, App.Short, App.Long, and App.Commands.
  • If both App.Root.SubCommands and App.Commands are present, they are merged into one effective root. Names already present on App.Root.SubCommands win; duplicate names from App.Commands are skipped.
  • Root-visible flags are also merged into one layer. The effective global flag set is built from the config flag (when enabled), App.SetFlags, and App.Root.SetFlags.

This is why CLI, help, completion, REPL, spec, and docs all see the same command tree instead of parallel models.

2. Registry, resolver, and dispatcher

Execution is split into three focused stages:

  • Registry: indexes command paths, aliases, and visible built-ins from the effective root.
  • Resolver: parses argv or REPL tokens into an Invocation, selects the target command, applies config/env/global flags, parses command-local flags, and validates positional arguments.
  • Dispatcher: handles the resolved invocation kind (usage, help, built-in, or command), then runs hooks, middleware, observers, and error normalization.

The built-ins help, completion, spec, and docs are registered only when the command tree does not already define those names. repl is added only after app.EnableREPL(), and it can also be shadowed by a user command.

3. Runtime selection

The runtime layer is explicit:

  • CLIRuntime always runs CLI parsing and dispatch.
  • REPLRuntime always starts REPL with the provided streams, prompt overrides, driver, and history hooks.
  • AutoRuntime prefers CLI whenever args are present. With no args, it enters REPL only if REPL is enabled and stdin/stdout are TTYs; otherwise it falls back to CLI usage/root execution.

That behavior is what makes cmd.Main(app) safe for both interactive terminals and non-interactive environments such as tests, pipes, or process supervisors.

4. State isolation and cached flag definitions

For performance, flag definitions are cached and reused as immutable templates. Each invocation still gets fresh runtime state:

  • repeated CLI runs do not leak previous flag values
  • REPL lines do not inherit mutable state from earlier commands
  • metadata returned by Lookup, Spec(), docs generation, and completion stays isolated from accidental mutation at runtime

In practice, one command model drives human-facing help, shell completion, REPL hints, and machine-facing exports without requiring separate synchronization code.

Two Usage Modes

The library supports two styles.

1. Global default instance: DefaultApp

This is the simplest approach for a single binary:

cmd.SetFlags(...)
cmd.AddCommands(...)
cmd.Execute()

Global entry points:

  • SetFlags
  • AddCommands
  • SetUsageTemplate
  • Execute

These helpers are only thin wrappers around the shared DefaultApp instance. The real execution model is still App + Root Command.

2. Explicit instance: App

Use this when you need:

  • Multiple CLI instances
  • Tests
  • Embedded execution
  • Framework or platform wrappers
app := cmd.NewApp("myapp")
app.SetFlags = func(f *cmd.FlagSet) { ... }
app.Commands = []*cmd.Command{...}

err := app.Run(context.Background(), []string{"hello", "team"})
if err != nil {
	// handle
}

If you want to stay on instance-style APIs without mutating fields directly, the app also provides thin helpers:

app := cmd.NewApp("myapp")
app.ConfigureFlags(func(f *cmd.FlagSet) { ... })
app.SetRootCommand(&cmd.Command{ ... })
app.AddCommands(...)

err := app.Execute([]string{"hello", "team"})

Command Model

The core types are App and Command.

App

App represents the entire CLI application. Common fields:

  • Name: application name
  • Short: short description
  • Long: long description
  • Root: optional root command
  • Commands: top-level commands
  • SetFlags: register global flags
  • BeforeRun / AfterRun / OnError: lifecycle hooks
  • Middlewares: middleware chain
  • Observers: event observers
  • Extensions: custom metadata
Root Command

App can also own a real root command through App.Root.

  • App.SetFlags remains the app-level global flag entry point.
  • App.Commands remains compatible and is treated as root subcommands.
  • App.Root.SetFlags is merged into the root/global flag set and is also visible to subcommands.
  • If the root command has Run, invoking only the binary runs the root command.
  • If the root command has no Run but has subcommands, invoking only the binary shows usage.
app := cmd.NewApp("myapp")

var (
	verbose bool
	profile string
)

app.SetFlags = func(f *cmd.FlagSet) {
	f.BoolVar(&verbose, "verbose", false, "enable verbose output", "v")
}

app.Root = &cmd.Command{
	UsageLine: "myapp [flags] [target]",
	Short:     "root entrypoint",
	Examples:  []string{"myapp team", "myapp version"},
	Positionals: []cmd.PositionalArg{
		{Name: "target", Usage: "target name"},
	},
	SetFlags: func(f *cmd.FlagSet) {
		f.StringVar(&profile, "profile", "", "profile name", "p")
	},
	Run: func(ctx context.Context, c *cmd.Command, args []string) error {
		fmt.Printf("root args=%v verbose=%v profile=%s\n", args, verbose, profile)
		return nil
	},
	SubCommands: []*cmd.Command{
		{
			Name:      "version",
			UsageLine: "myapp version",
			Short:     "print version",
			Run: func(ctx context.Context, c *cmd.Command, args []string) error {
				fmt.Println("v1.0.0")
				return nil
			},
		},
	},
}
Command

Command represents a node in the command tree. Common fields:

  • Name
  • Aliases
  • UsageLine
  • Short
  • Long
  • Examples
  • Positionals
  • SetFlags
  • Run
  • SubCommands
  • Deprecated
  • Hidden
  • BeforeRun / AfterRun / OnError
  • Middlewares
  • Observers
  • Extensions
Defining Subcommands
cmdAdmin := &cmd.Command{
	Name:      "admin",
	UsageLine: "app admin",
	Short:     "admin operations",
	SubCommands: []*cmd.Command{
		{
			Name:      "users",
			UsageLine: "app admin users",
			Short:     "manage users",
			Run: func(ctx context.Context, c *cmd.Command, args []string) error {
				return nil
			},
		},
	},
}

Flag Model

Flags are managed through FlagSet. The library supports:

  • Global flags
  • Command-local flags
  • Positional arguments
Defining Flags
var (
	force  bool
	count  int
	format string
)

f.BoolVar(&force, "force", false, "force operation", "f")
f.IntVar(&count, "count", 1, "retry count", "c")
f.StringVar(&format, "format", "text", "output format", "")

Supported value types include:

  • BoolVar
  • IntVar
  • Int64Var
  • UintVar
  • Uint64Var
  • StringVar
  • Float64Var
  • DurationVar
  • TextVar
  • Func
  • BoolFunc

There are also global versions of the same helpers operating on the default CommandLine.

Flag Metadata

After defining a flag, you can attach metadata:

f.StringVar(&format, "format", "text", "output format", "")
f.BindEnv("format", "APP_FORMAT")
f.BindConfig("format", "output.format")
f.SetEnum("format", "json", "yaml", "text")
f.MarkRequired("format")
f.MarkHidden("format")
f.MarkDeprecated("format", "use --output instead")
f.SetCategory("format", "Output")
f.SetExample("format", "json")

These metadata fields affect:

  • Parsing and validation
  • Help output
  • Completion
  • spec
  • docs

Parsing Rules

The parsing behavior is one of the main features of the library.

1. Global flags are allowed before the command
app --verbose version
app --config app.json hello
2. Command flags and positional arguments may be interspersed
app hello team -n sam
app hello team --name sam
app hello team extra --name sam

In other words, command flags do not need to appear before all positional arguments.

3. -- stops flag parsing
app hello -- --name-not-a-flag
4. help routes according to command context
app help hello
app --verbose help hello
app hello --help
5. Typos get suggestions

The library suggests close matches for unknown commands and flags:

  • statu -> status
  • --verboes -> --verbose

Help and Built-in Commands

Built-ins:

  • help
  • completion
  • spec
  • docs

If you define a user command with the same name, the user command wins and the built-in is skipped.

If you call app.EnableREPL(), the registry also exposes a built-in repl entry unless your own command tree already defines repl.

Custom Usage Template

If you use the default global instance, you can replace the default usage template:

cmd.SetUsageTemplate(`
{{.Name}} - {{.Short}}

Usage:
  {{.Name}} [flags] <command>
`)

For performance, usage rendering uses a small built-in replacement engine instead of text/template. Custom templates support literal text plus simple fields such as {{.Name}}, {{.Short}}, {{.Long}}, and {{.UsageLine}}.

Config, Environment Variables, and Precedence

Enable JSON Config Support
app := cmd.NewApp("app")
app.EnableConfigSupport()

Once enabled, the library injects a built-in global flag:

app --config app.json hello

The default loader expects JSON:

{
  "name": "from-config",
  "output": {
    "format": "json"
  }
}
Bind an env var
f.StringVar(&name, "name", "", "target name", "n")
f.BindEnv("name", "APP_NAME", "LEGACY_NAME")
Bind a config key
f.StringVar(&format, "format", "", "output format", "")
f.BindConfig("format", "output.format")
Precedence

The precedence is fixed:

CLI flag > env > config > default

Examples:

app --config app.json hello
APP_NAME=sam app --config app.json hello
app --config app.json hello --name cli
Custom Config Entry Points

You can also override:

  • ConfigLoader
  • ConfigFlag

For example, to plug in your own config loader.

Positional Arguments

Positional arguments are described through Command.Positionals.

Basic Usage
cmdDeploy := &cmd.Command{
	Name:      "deploy",
	UsageLine: "app deploy <env> [service]",
	Positionals: []cmd.PositionalArg{
		{Name: "env", Usage: "target environment", Required: true, Enum: []string{"dev", "staging", "prod"}},
		{Name: "service", Usage: "service name"},
	},
	Run: func(ctx context.Context, c *cmd.Command, args []string) error {
		env := args[0]
		service := ""
		if len(args) > 1 {
			service = args[1]
		}
		_ = env
		_ = service
		return nil
	},
}
Variadic positional arguments
Positionals: []cmd.PositionalArg{
	{Name: "files", Variadic: true, Usage: "input files"},
}
Completion

Positional arguments also support:

  • Enum
  • Completion
  • Extensions
Positionals: []cmd.PositionalArg{
	{
		Name: "service",
		Completion: func(ctx cmd.CompletionContext) []string {
			return []string{"api", "worker", "web"}
		},
	},
}
Validation

The library automatically handles:

  • Missing required positional arguments
  • Extra arguments for non-variadic commands
  • Enum validation

Completion

Generate shell scripts
app completion bash > /etc/bash_completion.d/app
app completion zsh > "${fpath[1]}/_app"
app completion fish > ~/.config/fish/completions/app.fish
app completion powershell > app.ps1
What completion supports
  • Command names
  • Command aliases
  • Global flags
  • Command-local flags
  • Flag enum values
  • Flag dynamic completion
  • Positional enum values
  • Positional dynamic completion
  • Built-in commands and their arguments

Example:

f.StringVar(&format, "format", "", "output format", "f")
f.SetEnum("format", "json", "yaml", "text")

f.StringVar(&name, "name", "", "target name", "n")
f.SetCompletion("name", func(ctx cmd.CompletionContext) []string {
	return []string{"sam", "sara", "tom"}
})

Built-ins also have completion:

  • app completion <shell>
  • app spec json
  • app docs markdown
  • app docs man
Programmatic completion

For readline, TUI, editor, or agent integrations, use the line completion APIs. They reuse the same command tree and completion engine as shell completion.

plain := app.CompleteLine("deploy --e", len("deploy --e"))
detailed := app.CompleteLineDetailed("deploy --e", len("deploy --e"))

CompleteLine returns plain suggestion strings and stays compatible with existing integrations. CompleteLineDetailed returns metadata for richer UIs:

type CompletionResult struct {
	Value       string
	Description string
	Kind        string
}

Current Kind values are:

  • command
  • flag
  • value
  • positional
  • builtin

Shell completion remains plain text through __complete; it does not emit structured metadata.

REPL and Line Execution

The REPL APIs let embedded programs reuse the existing App, command tree, flags, positionals, and completion logic without rebuilding dispatch.

err := app.RunLine(ctx, `deploy "hello world" --env prod`)

RunLine trims empty lines, splits shell-like input, then calls App.Run(ctx, args). The splitter supports whitespace, single quotes, double quotes, and backslash escaping.

For an interactive loop:

err := app.RunREPL(ctx, os.Stdin, os.Stdout)

If you want to choose the runtime explicitly, use the shared runtime interface:

err := app.RunWith(ctx, cmd.CLIRuntime{Args: os.Args[1:]})
err = app.RunWith(ctx, cmd.REPLRuntime{In: os.Stdin, Out: os.Stdout})
err = app.RunDefault(ctx, os.Args[1:])

For application entrypoints, you can also use the main-style helpers:

app.RunAuto(ctx, os.Args[1:])
app.MustRunDefault(ctx, os.Args[1:])
cmd.Main(app)

If you want the same binary to expose REPL mode without adding your own command, enable the built-in REPL entry:

app.EnableREPL()

Then users can enter REPL mode with:

app repl

Or configure the runtime directly:

repl := &cmd.REPL{
	App:    app,
	Prompt: "app> ",
	In:     in,
	Out:    out,
	Err:    errOut,
}
err := repl.Run(ctx)

If you need a dynamic prompt, provide PromptFunc. It is evaluated before each render:

app.ConfigureREPL(func(cfg *cmd.REPLConfig) {
	cfg.Prompt = "app> "
	cfg.PromptFunc = func(ctx context.Context, repl *cmd.REPL) string {
		if repl.App == nil {
			return ""
		}
		return repl.App.Name + "> "
	}
})

If PromptFunc returns an empty string, REPL falls back to Prompt, then to the default prompt "> ".

You can also load and persist history through hooks:

app.ConfigureREPL(func(cfg *cmd.REPLConfig) {
	cfg.History = &cmd.REPLHistoryHooks{
		Load: func(ctx context.Context) ([]string, error) {
			return []string{"deploy prod", "status"}, nil
		},
		Append: func(ctx context.Context, line string) error {
			fmt.Println("persist history:", line)
			return nil
		},
	}
})

Load runs when REPL starts. Append runs when a non-empty line is accepted for execution. In-memory history is still used for the current session, while hooks let you inject persistence.

Built-in REPL commands are:

  • exit
  • quit
  • .exit
  • .quit
  • .help

When stdin/stdout is a TTY, the default REPL driver also enables inline editing, history navigation, real-time context-aware hints, inline ghost text for the best completion, and Tab completion powered by the same command tree and value completion hooks used by CLI completion. Candidate lists are labeled by kind, so commands, flags, values, and positional arguments stay easy to distinguish, and repeated Tab presses page through longer candidate lists.

During line editing, terminal REPL keeps stdin in raw mode. After you press Enter to submit a command, the driver temporarily restores normal terminal mode before executing the command, then re-enters raw mode when REPL resumes. This allows command handlers to read from stdin, ask for confirmation, prompt for passwords, or perform their own terminal interaction without fighting the REPL line editor.

Command errors are printed and the REPL keeps running. context.Canceled or input EOF exits the loop.

Machine-readable Spec

Output
app spec
app spec json
What spec includes

spec is a versioned contract for the current command tree. It is suitable for:

  • Static site generation
  • IDE integration
  • Console UIs
  • Agent and AI pipelines
  • Automated tests

Current output includes:

  • schema_version
  • surface
  • available_surfaces
  • builtins
  • capabilities
  • config
  • App and command hooks
  • Middleware and observer markers
  • Global flags
  • The command tree
  • Stable command IDs and handler IDs
  • Positionals
  • Flags
  • extensions
Surface-aware export

Spec() keeps the default/base contract. If you need a REPL/runtime-facing contract from the same command tree, export a specific surface:

cliSpec := app.Spec()
replSpec := app.SpecFor(cmd.SurfaceREPL)

This is useful when CLI and REPL differ in usage lines or positional requirements, but still share the same base command definition.

Important fields in CommandSpec, FlagSpec, and PositionalSpec
  • id
  • handler_id
  • path
  • kind
  • enum
  • required
  • repeatable
  • deprecated
  • completion_key
  • supports_completion
  • source_order
  • extensions
Example
app spec json > spec.json

Example fields:

{
  "schema_version": "v2",
  "name": "app",
  "surface": "repl",
  "builtins": ["help", "completion", "spec", "docs"],
  "capabilities": {
    "completion_keys": true,
    "docs_export": true,
    "middleware": true,
    "observers": true,
    "surface_overrides": true,
    "stable_ids": true
  }
}

Docs Generation

docs is generated from Spec(), so it shares the default command contract used by spec, completion, and help output. If you need a REPL/runtime-specific schema, export it separately with SpecFor(surface).

Single-page output
app docs markdown
app docs man
Multi-file export
app docs markdown ./docs
app docs man ./manpages
Export layout
Markdown bundle
  • README.md
  • commands/<command>.md
  • commands/<command>/<subcommand>.md
Man bundle
  • <app>.1
  • <app>-<command>.1
  • <app>-<command>-<subcommand>.1
Markdown frontmatter

Markdown docs include frontmatter automatically, which is useful for:

  • Hugo, Docusaurus, Astro, MkDocs, and similar site generators
  • Search indexers
  • Content pipelines

Frontmatter includes:

  • kind
  • title
  • summary
  • command_name
  • command_path
  • extensions

Lifecycle Hooks

Hooks are best for execution lifecycle behavior, not wrapping-style cross-cutting control.

App-level hooks
app.BeforeRun = func(ctx cmd.HookContext) error {
	return nil
}

app.AfterRun = func(ctx cmd.HookContext) {
	if ctx.Err != nil {
		log.Printf("command failed: %v", ctx.Err)
	}
}

app.OnError = func(ctx cmd.HookContext) {
	var cliErr *cmd.CLIError
	if errors.As(ctx.Err, &cliErr) {
		log.Printf("kind=%s exit=%d command=%s", cliErr.Kind, cliErr.ExitCode, cliErr.Command)
	}
}
Command-level hooks
cmdDeploy := &cmd.Command{
	Name: "deploy",
	BeforeRun: func(ctx cmd.HookContext) error {
		return nil
	},
	AfterRun: func(ctx cmd.HookContext) {},
	OnError:  func(ctx cmd.HookContext) {},
	Run:      runDeploy,
}
Invocation order

On success:

  1. App BeforeRun
  2. Command BeforeRun
  3. Run
  4. Command AfterRun
  5. App AfterRun

On failure:

  1. App BeforeRun
  2. Command BeforeRun
  3. Run or a hook returns an error
  4. Command OnError
  5. App OnError
  6. Command AfterRun
  7. App AfterRun

Middleware

Middleware is for cross-cutting behavior such as:

  • Authentication
  • Tracing
  • Rate limiting
  • Auditing
  • Unified logging
App-level middleware
app.Use(func(ctx cmd.MiddlewareContext, next cmd.NextFunc) error {
	start := time.Now()
	err := next(ctx.Context)
	log.Printf("command=%s duration=%s err=%v", ctx.Command.Name, time.Since(start), err)
	return err
})
Command-level middleware
cmdDeploy := &cmd.Command{
	Name: "deploy",
	Middlewares: []cmd.Middleware{
		func(ctx cmd.MiddlewareContext, next cmd.NextFunc) error {
			if len(ctx.Args) == 0 {
				return errors.New("missing target")
			}
			return next(ctx.Context)
		},
	},
	Run: runDeploy,
}
Wrapping order

Execution order is:

app middleware -> command middleware -> Command.Run

Observers and Telemetry

Observers provide a stable event stream for:

  • Metrics
  • Tracing adapters
  • Event logs
  • Analytics
Register an observer
app.AddObserver(cmd.ObserverFunc(func(event cmd.Event) {
	log.Printf(
		"type=%s command=%s exit=%d duration=%s",
		event.Type,
		event.Command.Name,
		event.ExitCode,
		event.Duration,
	)
}))

Commands can also register their own Observers.

Current event types
  • command_started
  • command_finished
  • command_failed
Event fields

Event includes:

  • Type
  • App
  • Command
  • Args
  • Err
  • StartTime
  • EndTime
  • Duration
  • ExitCode

Unified Errors and Exit Codes

Library-generated normalized errors are returned as *CLIError.

Error kinds

Current Kind values:

  • invalid_arguments
  • not_found
  • canceled
  • internal
  • runtime
Exit codes
  • Invalid arguments: 2
  • Unknown command: 2
  • context.Canceled: 130
  • context.DeadlineExceeded: 124
  • Runtime failure: 1
Example
err := app.Run(ctx, os.Args[1:])
if err != nil {
	var cliErr *cmd.CLIError
	if errors.As(err, &cliErr) {
		fmt.Println(cliErr.Kind, cliErr.ExitCode, cliErr.Command)
	}
}

Execute() automatically exits using ExitStatus() on the default instance.

Custom Extension Metadata

If you need to attach custom metadata to the command tree, for example:

  • Site categorization
  • Console UI hints
  • Internal ownership
  • Feature flags
  • OpenAPI or agent-specific extension fields

use extensions.

App-level
app.SetExtension("x-site-section", "cli")
Command-level
cmdDeploy.SetExtension("x-owner", "platform")
Positional-level
cmdDeploy.Positionals[0].SetExtension("x-label", "Environment")
Flag-level
cmdDeploy.SetFlags = func(f *cmd.FlagSet) {
	f.StringVar(&format, "format", "", "output format", "")
	_ = f.SetExtension("format", "x-ui-control", "select")
}
Surface-level overrides

If one command definition needs different exported shapes for CLI and REPL/runtime schema, keep one base command and attach per-surface overrides:

requiredFalse := false

cmdCreateUser := &cmd.Command{
	Name:      "user",
	UsageLine: "app create user <name> [flags]",
	Positionals: []cmd.PositionalArg{{
		Name:          "name",
		Usage:         "user name",
		Required:      true,
		Kind:          "user",
		CompletionKey: "user",
		Surfaces: map[cmd.Surface]cmd.PositionalSurface{
			cmd.SurfaceREPL: {Required: &requiredFalse},
		},
	}},
	Surfaces: map[cmd.Surface]cmd.CommandSurface{
		cmd.SurfaceREPL: {UsageLine: "app create user [name] [flags]"},
	},
}

These metadata fields are exported into:

  • spec
  • Markdown frontmatter

Extension maps are cloned when metadata is copied into specs, docs, and runtime flag views. Map and slice-shaped values are cloned recursively, but opaque pointer or custom object payloads are shared by reference. If you need full isolation, store immutable values or clone the payload before attaching it.

Common Patterns

1. Global config plus command-local flags
app := cmd.NewApp("app")
app.EnableConfigSupport()

app.SetFlags = func(f *cmd.FlagSet) {
	f.BoolVar(&verbose, "verbose", false, "verbose output", "v")
}

app.Commands = []*cmd.Command{
	{
		Name: "sync",
		SetFlags: func(f *cmd.FlagSet) {
			f.StringVar(&endpoint, "endpoint", "", "api endpoint", "")
			f.BindEnv("endpoint", "APP_ENDPOINT")
			f.BindConfig("endpoint", "api.endpoint")
			f.MarkRequired("endpoint")
		},
		Run: runSync,
	},
}
2. Use enums for both validation and completion
f.StringVar(&env, "env", "", "target environment", "")
f.SetEnum("env", "dev", "staging", "prod")
3. Use observers for metrics
app.AddObserver(cmd.ObserverFunc(func(event cmd.Event) {
	switch event.Type {
	case cmd.EventCommandFinished:
		metrics.RecordSuccess(event.Command.Name, event.Duration)
	case cmd.EventCommandFailed:
		metrics.RecordFailure(event.Command.Name, event.Duration)
	}
}))
4. Use docs and spec to drive docs sites and consoles
app spec json > site/spec.json
app docs markdown ./site/docs

API Quick Reference

Application and commands
  • NewApp(name string) *App
  • (*App).Run(ctx, args)
  • (*App).RunWith(ctx, runtime)
  • (*App).RunAuto(ctx, args)
  • (*App).RunDefault(ctx, args)
  • (*App).RunLine(ctx, line)
  • (*App).RunREPL(ctx, in, out)
  • (*App).Main(ctx, runtime)
  • (*App).MainAuto(ctx, args)
  • (*App).MainDefault(ctx, args)
  • (*App).MustRun(ctx, runtime)
  • (*App).MustRunAuto(ctx, args)
  • (*App).MustRunDefault(ctx, args)
  • (*App).DefaultRuntime(args)
  • (*App).CompleteLine(line, cursor)
  • (*App).CompleteLineDetailed(line, cursor)
  • (*App).EnableREPL()
  • (*App).ConfigureREPL(fn)
  • (*App).EnableConfigSupport()
  • (*App).Use(...)
  • (*App).AddObserver(...)
  • (*App).SetExtension(key, value)
  • (*App).Spec()
  • (*App).SpecFor(surface)
  • (*App).AvailableSurfaces()
Default instance
  • SetFlags(...)
  • AddCommands(...)
  • SetUsageTemplate(...)
  • Execute()
  • Main(app)
  • MainWithContext(ctx, app)
FlagSet metadata helpers
  • BindEnv
  • BindConfig
  • SetID
  • SetKind
  • SetEnum
  • SetCompletionKey
  • SetCompletion
  • MarkRepeatable
  • MarkRequired
  • MarkHidden
  • MarkDeprecated
  • SetCategory
  • SetExample
  • SetExtension
  • SetSurface
Shared error and suggestion helpers
  • SuggestCommands
  • UnknownCommandError
  • UnknownSubcommandError
  • UsageError
Important types
  • App
  • Command
  • REPL
  • REPLConfig
  • Runtime
  • DefaultRuntime
  • CLIRuntime
  • REPLRuntime
  • AutoRuntime
  • Surface
  • CommandSurface
  • PositionalSurface
  • FlagSurface
  • FlagSet
  • Flag
  • PositionalArg
  • CompletionContext
  • CompletionResult
  • LineCompleter
  • DetailedLineCompleter
  • REPL
  • HookContext
  • MiddlewareContext
  • Event
  • CLIError
  • AppSpec

Summary

If you only need a small CLI, these are enough:

  • SetFlags
  • AddCommands
  • Execute

If you want a CLI that can grow into a platform, organize around this model:

  • Command / Flag / Positional as the single command model
  • env / config / CLI as the single source-of-truth for configuration resolution
  • hooks / middleware / observer as the runtime extension layer
  • spec / docs as the external contract
  • surface overrides + rich spec metadata as the bridge to REPL, parser, schema, and agent consumers

That is the direction this library is best suited for today.

Documentation

Overview

Package cmd provides a modern command-line library for Go.

The package is centered around App and Command. It supports recursive subcommands, global and command-local flags, positional argument schemas, environment and config binding, shell completion, machine-readable specs, generated documentation, lifecycle hooks, middleware, observer events, normalized CLI errors, and a built-in REPL that reuses the same command tree.

The simplest usage relies on the default application instance:

cmd.SetFlags(func(f *cmd.FlagSet) {
	f.BoolVar(&verbose, "verbose", false, "enable verbose output", "v")
})

cmd.AddCommands(&cmd.Command{
	Name:      "version",
	UsageLine: "app version",
	Short:     "print version",
	Run: func(ctx context.Context, c *cmd.Command, args []string) error {
		fmt.Println(version)
		return nil
	},
})

cmd.Execute()

For larger applications, create an explicit App with NewApp, attach commands, configure flags and config support, and call Run directly.

When an application needs both CLI and interactive usage, define the command tree once and enable the built-in REPL on the same App. CLI execution, REPL execution, completion, and inline REPL hints all share the same parser and command model. Terminal REPL sessions support editable input, history navigation, completion, dynamic prompts, and optional history load/append hooks.

Runtime helpers are also available so applications can choose explicit CLI or REPL entrypoints, or let the library automatically select an appropriate runtime for the current invocation.

Internally, both CLI args and REPL lines flow through the same Registry, Resolver, and Dispatcher pipeline. That shared pipeline keeps help, completion, spec export, docs generation, and command execution aligned on the same effective command tree while still isolating runtime flag state for each invocation.

See README.md for the full usage guide, including config precedence, completion, REPL configuration, runtime helpers, spec export, documentation generation, hooks, middleware, observers, and custom extensions.

Index

Constants

View Source
const (
	ErrorKindInvalidArguments = "invalid_arguments"
	ErrorKindNotFound         = "not_found"
	ErrorKindCanceled         = "canceled"
	ErrorKindInternal         = "internal"
	ErrorKindRuntime          = "runtime"
)

Variables

View Source
var (
	ErrNotFound = errors.New("not found")

	DefaultApp = NewApp(filepath.Base(os.Args[0]))
)
View Source
var ErrHelp = errors.New("flag: help requested")

ErrHelp is the error returned if the -help or -h flag is invoked but no such flag is defined.

View Source
var Usage = func() {
	fmt.Fprintf(CommandLine.Output(), "Usage of %s:\n", os.Args[0])
	PrintDefaults()
}

Usage prints a usage message documenting all defined command-line flags to CommandLine's output, which by default is os.Stderr. It is called when an error occurs while parsing flags. The function is a variable that may be changed to point to a custom function. By default it prints a simple header and calls PrintDefaults; for details about the format of the output and how to control it, see the documentation for PrintDefaults. Custom usage functions may choose to exit the program; by default exiting happens anyway as the command line's error handling strategy is set to ExitOnError.

Functions

func AddCommands

func AddCommands(cmds ...*Command)

AddCommands Add Command.

func Arg added in v0.1.7

func Arg(i int) string

Arg returns the i'th command-line argument. Arg(0) is the first remaining argument after flags have been processed. Arg returns an empty string if the requested element does not exist.

func Args added in v0.1.7

func Args() []string

Args returns the non-flag command-line arguments.

func BindConfig added in v0.1.8

func BindConfig(name string, configKeys ...string)

func BindEnv added in v0.1.8

func BindEnv(name string, envVars ...string)

func Bool added in v0.1.7

func Bool(name string, value bool, usage string, shorthand string) *bool

Bool defines a bool flag with specified name, default value, and usage string. The return value is the address of a bool variable that stores the value of the flag.

func BoolFunc added in v0.1.7

func BoolFunc(name, usage string, fn func(string) error, shorthand string)

BoolFunc defines a flag with the specified name and usage string without requiring values. Each time the flag is seen, fn is called with the value of the flag. If fn returns a non-nil error, it will be treated as a flag value parsing error.

func BoolVar added in v0.1.7

func BoolVar(p *bool, name string, value bool, usage string, shorthand string)

BoolVar defines a bool flag with specified name, default value, and usage string. The argument p points to a bool variable in which to store the value of the flag.

func Duration added in v0.1.7

func Duration(name string, value time.Duration, usage string, shorthand string) *time.Duration

Duration defines a time.Duration flag with specified name, default value, and usage string. The return value is the address of a time.Duration variable that stores the value of the flag. The flag accepts a value acceptable to time.ParseDuration.

func DurationVar added in v0.1.7

func DurationVar(p *time.Duration, name string, value time.Duration, usage string, shorthand string)

DurationVar defines a time.Duration flag with specified name, default value, and usage string. The argument p points to a time.Duration variable in which to store the value of the flag. The flag accepts a value acceptable to time.ParseDuration.

func Execute

func Execute()

Execute func

func Float64 added in v0.1.7

func Float64(name string, value float64, usage string, shorthand string) *float64

Float64 defines a float64 flag with specified name, default value, and usage string. The return value is the address of a float64 variable that stores the value of the flag.

func Float64Var added in v0.1.7

func Float64Var(p *float64, name string, value float64, usage string, shorthand string)

Float64Var defines a float64 flag with specified name, default value, and usage string. The argument p points to a float64 variable in which to store the value of the flag.

func Func added in v0.1.7

func Func(name, usage string, fn func(string) error, shorthand string)

Func defines a flag with the specified name and usage string. Each time the flag is seen, fn is called with the value of the flag. If fn returns a non-nil error, it will be treated as a flag value parsing error.

func Int added in v0.1.7

func Int(name string, value int, usage string, shorthand string) *int

Int defines an int flag with specified name, default value, and usage string. The return value is the address of an int variable that stores the value of the flag.

func Int64 added in v0.1.7

func Int64(name string, value int64, usage string, shorthand string) *int64

Int64 defines an int64 flag with specified name, default value, and usage string. The return value is the address of an int64 variable that stores the value of the flag.

func Int64Var added in v0.1.7

func Int64Var(p *int64, name string, value int64, usage string, shorthand string)

Int64Var defines an int64 flag with specified name, default value, and usage string. The argument p points to an int64 variable in which to store the value of the flag.

func IntVar added in v0.1.7

func IntVar(p *int, name string, value int, usage string, shorthand string)

IntVar defines an int flag with specified name, default value, and usage string. The argument p points to an int variable in which to store the value of the flag.

func LexLine added in v0.2.0

func LexLine(line string) ([]string, error)

LexLine converts a REPL input line into argv-style tokens.

func LexLineForCompletion added in v0.2.0

func LexLineForCompletion(line string) ([]string, string, error)

LexLineForCompletion tokenizes a partial REPL line for cursor-aware completion.

func LoadJSONConfig added in v0.1.8

func LoadJSONConfig(path string) (map[string]any, error)

func Main added in v0.2.0

func Main(app *App)

func MainWithContext added in v0.2.0

func MainWithContext(ctx context.Context, app *App)

func MarkDeprecated added in v0.1.8

func MarkDeprecated(name, message string)

func MarkHidden added in v0.1.8

func MarkHidden(name string)

func MarkRepeatable added in v0.2.0

func MarkRepeatable(name string)

func MarkRequired added in v0.1.8

func MarkRequired(name string)

func NArg added in v0.1.7

func NArg() int

NArg is the number of arguments remaining after flags have been processed.

func NFlag added in v0.1.7

func NFlag() int

NFlag returns the number of command-line flags that have been set.

func Parse added in v0.1.7

func Parse()

Parse parses the command-line flags from os.Args[1:]. Must be called after all flags are defined and before flags are accessed by the program.

func Parsed added in v0.1.7

func Parsed() bool

Parsed reports whether the command-line flags have been parsed.

func PrintDefaults added in v0.1.7

func PrintDefaults()

PrintDefaults prints, to standard error unless configured otherwise, a usage message showing the default settings of all defined command-line flags. For an integer valued flag x, the default output has the form

-x int
	usage-message-for-x (default 7)

The usage message will appear on a separate line for anything but a bool flag with a one-byte name. For bool flags, the type is omitted and if the flag name is one byte the usage message appears on the same line. The parenthetical default is omitted if the default is the zero value for the type. The listed type, here int, can be changed by placing a back-quoted name in the flag's usage string; the first such item in the message is taken to be a parameter name to show in the message and the back quotes are stripped from the message when displayed. For instance, given

flag.String("I", "", "search `directory` for include files")

the output will be

-I directory
	search directory for include files.

To change the destination for flag messages, call CommandLine.SetOutput.

func Set added in v0.1.7

func Set(name, value string) error

Set sets the value of the named command-line flag.

func SetCategory added in v0.1.8

func SetCategory(name, category string)

func SetCompletion added in v0.1.8

func SetCompletion(name string, fn CompletionFunc)

func SetCompletionKey added in v0.2.0

func SetCompletionKey(name, key string)

func SetEnum added in v0.1.8

func SetEnum(name string, values ...string)

func SetExample added in v0.1.8

func SetExample(name, example string)

func SetFlags

func SetFlags(f func(f *FlagSet))

SetFlags set flags to all commands

func SetID added in v0.2.0

func SetID(name, id string)

func SetKind added in v0.2.0

func SetKind(name, kind string)

func SetSurface added in v0.2.0

func SetSurface(name string, surface Surface, override FlagSurface)

func SetUsageTemplate

func SetUsageTemplate(usageTemplate string)

SetUsageTemplate set value to usageTemplate

func SplitLine added in v0.1.10

func SplitLine(line string) ([]string, error)

SplitLine splits a REPL input line into argv-style tokens.

func SplitLineForCompletion added in v0.1.10

func SplitLineForCompletion(line string) (args []string, current string, err error)

SplitLineForCompletion splits a partial REPL line into completed args and the current token.

func String added in v0.1.7

func String(name string, value string, usage string, shorthand string) *string

String defines a string flag with specified name, default value, and usage string. The return value is the address of a string variable that stores the value of the flag.

func StringVar added in v0.1.7

func StringVar(p *string, name string, value string, usage string, shorthand string)

StringVar defines a string flag with specified name, default value, and usage string. The argument p points to a string variable in which to store the value of the flag.

func SuggestCommands added in v0.2.0

func SuggestCommands(name string, commands Commands) []string

func TextVar added in v0.1.7

func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string, shorthand string)

TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.

func Uint added in v0.1.7

func Uint(name string, value uint, usage string, shorthand string) *uint

Uint defines a uint flag with specified name, default value, and usage string. The return value is the address of a uint variable that stores the value of the flag.

func Uint64 added in v0.1.7

func Uint64(name string, value uint64, usage string, shorthand string) *uint64

Uint64 defines a uint64 flag with specified name, default value, and usage string. The return value is the address of a uint64 variable that stores the value of the flag.

func Uint64Var added in v0.1.7

func Uint64Var(p *uint64, name string, value uint64, usage string, shorthand string)

Uint64Var defines a uint64 flag with specified name, default value, and usage string. The argument p points to a uint64 variable in which to store the value of the flag.

func UintVar added in v0.1.7

func UintVar(p *uint, name string, value uint, usage string, shorthand string)

UintVar defines a uint flag with specified name, default value, and usage string. The argument p points to a uint variable in which to store the value of the flag.

func UnknownCommandError added in v0.2.0

func UnknownCommandError(name string, commands Commands) error

func UnknownSubcommandError added in v0.2.0

func UnknownSubcommandError(command string, target string, subcommands Commands) error

func UnquoteUsage added in v0.1.7

func UnquoteUsage(flag *Flag) (name string, usage string)

UnquoteUsage extracts a back-quoted name from the usage string for a flag and returns it and the un-quoted usage. Given "a `name` to show" it returns ("name", "a name to show"). If there are no back quotes, the name is an educated guess of the type of the flag's value, or the empty string if the flag is boolean.

func UsageError added in v0.2.0

func UsageError(usageLine string) error

func Var added in v0.1.7

func Var(value Value, name string, usage string, shorthand string)

Var defines a flag with the specified name and usage string. The type and value of the flag are represented by the first argument, of type Value, which typically holds a user-defined implementation of Value. For instance, the caller could create a flag that turns a comma-separated string into a slice of strings by giving the slice the methods of Value; in particular, Set would decompose the comma-separated string into the slice.

func VisibleCommandNames added in v0.2.0

func VisibleCommandNames(commands Commands) []string

func Visit added in v0.1.7

func Visit(fn func(*Flag))

Visit visits the command-line flags in lexicographical order, calling fn for each. It visits only those flags that have been set.

func VisitAll added in v0.1.7

func VisitAll(fn func(*Flag))

VisitAll visits the command-line flags in lexicographical order, calling fn for each. It visits all flags, even those not set.

Types

type AfterHook added in v0.1.8

type AfterHook func(ctx HookContext)

type App added in v0.1.8

type App struct {
	Name          string
	Short         string
	Long          string
	Root          *Command
	Commands      Commands
	REPL          REPLConfig
	UsageTemplate string
	Out           io.Writer
	Err           io.Writer
	SetFlags      func(f *FlagSet)
	ConfigEnabled bool
	ConfigLoader  ConfigLoader
	ConfigFlag    ConfigFlagOptions
	BeforeRun     BeforeHook
	AfterRun      AfterHook
	OnError       ErrorHook
	Middlewares   []Middleware
	Observers     []Observer
	// Extensions carries custom metadata for integrations and tooling.
	// Slice and map values are cloned when the library copies metadata, but
	// opaque pointer or custom object payloads are shared by reference. Callers
	// that need full isolation should store immutable values or clone payloads
	// themselves before attaching them here.
	Extensions map[string]any
	// contains filtered or unexported fields
}

App is the main application container

func NewApp added in v0.1.8

func NewApp(name string) *App

NewApp creates a new App instance

func (*App) AddCommands added in v0.1.10

func (a *App) AddCommands(cmds ...*Command)

AddCommands appends top-level commands to the app.

func (*App) AddObserver added in v0.1.8

func (a *App) AddObserver(observers ...Observer)

func (*App) AvailableSurfaces added in v0.2.0

func (a *App) AvailableSurfaces() []Surface

func (*App) CompleteLine added in v0.1.10

func (a *App) CompleteLine(line string, cursor int) []string

func (*App) CompleteLineDetailed added in v0.1.10

func (a *App) CompleteLineDetailed(line string, cursor int) []CompletionResult

func (*App) ConfigureFlags added in v0.1.10

func (a *App) ConfigureFlags(f func(f *FlagSet))

ConfigureFlags sets the app-level global flag registration function.

func (*App) ConfigureREPL added in v0.2.0

func (a *App) ConfigureREPL(fn func(cfg *REPLConfig))

func (*App) DefaultRuntime added in v0.2.0

func (a *App) DefaultRuntime(args []string) Runtime

func (*App) EnableConfigSupport added in v0.1.8

func (a *App) EnableConfigSupport()

func (*App) EnableREPL added in v0.2.0

func (a *App) EnableREPL()

func (*App) Execute added in v0.1.10

func (a *App) Execute(args []string) error

Execute runs the app with the provided args.

func (*App) ExitStatus added in v0.1.8

func (a *App) ExitStatus() int

func (*App) Main added in v0.2.0

func (a *App) Main(ctx context.Context, runtime Runtime) int

func (*App) MainAuto added in v0.2.0

func (a *App) MainAuto(ctx context.Context, args []string) int

func (*App) MainDefault added in v0.2.0

func (a *App) MainDefault(ctx context.Context, args []string) int

func (*App) MustRun added in v0.2.0

func (a *App) MustRun(ctx context.Context, runtime Runtime)

func (*App) MustRunAuto added in v0.2.0

func (a *App) MustRunAuto(ctx context.Context, args []string)

func (*App) MustRunDefault added in v0.2.0

func (a *App) MustRunDefault(ctx context.Context, args []string)

func (*App) Run added in v0.1.8

func (a *App) Run(ctx context.Context, args []string) error

Run executes the application

func (*App) RunAuto added in v0.2.0

func (a *App) RunAuto(ctx context.Context, args []string) error

func (*App) RunDefault added in v0.2.0

func (a *App) RunDefault(ctx context.Context, args []string) error

func (*App) RunLine added in v0.1.10

func (a *App) RunLine(ctx context.Context, line string) error

func (*App) RunREPL added in v0.1.10

func (a *App) RunREPL(ctx context.Context, in io.Reader, out io.Writer) error

func (*App) RunWith added in v0.2.0

func (a *App) RunWith(ctx context.Context, runtime Runtime) error

func (*App) SetExtension added in v0.1.8

func (a *App) SetExtension(key string, value any)

func (*App) SetRootCommand added in v0.1.10

func (a *App) SetRootCommand(root *Command)

SetRootCommand assigns the app root command.

func (*App) Spec added in v0.1.8

func (a *App) Spec() AppSpec

func (*App) SpecFor added in v0.2.0

func (a *App) SpecFor(surface Surface) AppSpec

func (*App) Usage added in v0.1.8

func (a *App) Usage()

func (*App) Use added in v0.1.8

func (a *App) Use(middlewares ...Middleware)

func (*App) UseUsageTemplate added in v0.1.10

func (a *App) UseUsageTemplate(usageTemplate string)

UseUsageTemplate replaces the app usage template.

type AppSpec added in v0.1.8

type AppSpec struct {
	SchemaVersion     string            `json:"schema_version"`
	Name              string            `json:"name"`
	Short             string            `json:"short"`
	Surface           string            `json:"surface,omitempty"`
	AvailableSurfaces []string          `json:"available_surfaces,omitempty"`
	Builtins          []string          `json:"builtins,omitempty"`
	Capabilities      CapabilitySpec    `json:"capabilities"`
	Config            ConfigRuntimeSpec `json:"config"`
	Hooks             HookSpec          `json:"hooks,omitempty"`
	HasMiddleware     bool              `json:"has_middleware,omitempty"`
	HasObservers      bool              `json:"has_observers,omitempty"`
	Extensions        map[string]any    `json:"extensions,omitempty"`
	Root              *CommandSpec      `json:"root,omitempty"`
	GlobalFlags       []FlagSpec        `json:"global_flags,omitempty"`
	Commands          []CommandSpec     `json:"commands"`
}

type AutoRuntime added in v0.2.0

type AutoRuntime struct {
	Args []string
	In   io.Reader
	Out  io.Writer
	Err  io.Writer
}

func (AutoRuntime) Run added in v0.2.0

func (r AutoRuntime) Run(ctx context.Context, app *App) error

type BasicREPLDriver added in v0.2.0

type BasicREPLDriver struct{}

func (BasicREPLDriver) Run added in v0.2.0

func (d BasicREPLDriver) Run(ctx context.Context, r *REPL) error

type BeforeHook added in v0.1.8

type BeforeHook func(ctx HookContext) error

type BuiltinHandler added in v0.2.0

type BuiltinHandler func(ctx context.Context, app *App, args []string) error

type CLIError added in v0.1.8

type CLIError struct {
	Kind     string
	Message  string
	Command  string
	ExitCode int
	Err      error
}

func (*CLIError) Error added in v0.1.8

func (e *CLIError) Error() string

func (*CLIError) Unwrap added in v0.1.8

func (e *CLIError) Unwrap() error

type CLIRuntime added in v0.2.0

type CLIRuntime struct {
	Args []string
}

func (CLIRuntime) Run added in v0.2.0

func (r CLIRuntime) Run(ctx context.Context, app *App) error

type CapabilitySpec added in v0.1.8

type CapabilitySpec struct {
	GlobalFlags        bool `json:"global_flags"`
	InterspersedFlags  bool `json:"interspersed_flags"`
	EnvBinding         bool `json:"env_binding"`
	ConfigBinding      bool `json:"config_binding"`
	ShellCompletion    bool `json:"shell_completion"`
	SpecExport         bool `json:"spec_export"`
	DocsExport         bool `json:"docs_export"`
	ValueCompletion    bool `json:"value_completion"`
	Positionals        bool `json:"positionals"`
	SurfaceOverrides   bool `json:"surface_overrides"`
	StableIDs          bool `json:"stable_ids"`
	SemanticKinds      bool `json:"semantic_kinds"`
	RepeatableFlags    bool `json:"repeatable_flags"`
	CompletionKeys     bool `json:"completion_keys"`
	LifecycleHooks     bool `json:"lifecycle_hooks"`
	Middleware         bool `json:"middleware"`
	Observers          bool `json:"observers"`
	ErrorNormalization bool `json:"error_normalization"`
}

type Command

type Command struct {
	Name        string
	ID          string
	HandlerID   string
	Aliases     []string
	UsageLine   string
	Short       string
	Long        string
	Group       string
	Examples    []string
	Positionals []PositionalArg
	Deprecated  string
	Hidden      bool
	BeforeRun   BeforeHook
	AfterRun    AfterHook
	OnError     ErrorHook
	Middlewares []Middleware
	Observers   []Observer
	// Extensions carries custom metadata for integrations and tooling.
	// Slice and map values are cloned when the library copies metadata, but
	// opaque pointer or custom object payloads are shared by reference. Callers
	// that need full isolation should store immutable values or clone payloads
	// themselves before attaching them here.
	Extensions  map[string]any
	Surfaces    map[Surface]CommandSurface
	Run         func(ctx context.Context, cmd *Command, args []string) error
	SetFlags    func(f *FlagSet)
	SubCommands Commands
	// contains filtered or unexported fields
}

Command struct

func (*Command) AddObserver added in v0.1.8

func (c *Command) AddObserver(observers ...Observer)

func (*Command) GetAlias added in v0.1.8

func (c *Command) GetAlias() string

GetAlias get alias

func (*Command) Runnable

func (c *Command) Runnable() bool

Runnable bool

func (*Command) SetExtension added in v0.1.8

func (c *Command) SetExtension(key string, value any)

func (*Command) SetSurface added in v0.2.0

func (c *Command) SetSurface(surface Surface, override CommandSurface)

func (*Command) Usage

func (c *Command) Usage()

Usage u

func (*Command) Use added in v0.1.8

func (c *Command) Use(middlewares ...Middleware)

type CommandSpec added in v0.1.8

type CommandSpec struct {
	ID            string           `json:"id,omitempty"`
	HandlerID     string           `json:"handler_id,omitempty"`
	Path          []string         `json:"path,omitempty"`
	Name          string           `json:"name"`
	Aliases       []string         `json:"aliases,omitempty"`
	UsageLine     string           `json:"usage_line,omitempty"`
	Short         string           `json:"short,omitempty"`
	Long          string           `json:"long,omitempty"`
	Group         string           `json:"group,omitempty"`
	Deprecated    string           `json:"deprecated,omitempty"`
	Hidden        bool             `json:"hidden,omitempty"`
	Runnable      bool             `json:"runnable,omitempty"`
	Examples      []string         `json:"examples,omitempty"`
	Hooks         HookSpec         `json:"hooks,omitempty"`
	HasMiddleware bool             `json:"has_middleware,omitempty"`
	HasObservers  bool             `json:"has_observers,omitempty"`
	Extensions    map[string]any   `json:"extensions,omitempty"`
	Positionals   []PositionalSpec `json:"positionals,omitempty"`
	Flags         []FlagSpec       `json:"flags,omitempty"`
	SubCommands   []CommandSpec    `json:"subcommands,omitempty"`
}

type CommandSurface added in v0.2.0

type CommandSurface struct {
	UsageLine          string
	Short              string
	Long               string
	Group              string
	Deprecated         string
	Aliases            []string
	Examples           []string
	Hidden             *bool
	ReplacePositionals bool
	Positionals        []PositionalArg
	Extensions         map[string]any
}

type Commands

type Commands []*Command

func (*Commands) Search

func (c *Commands) Search(name string) *Command

Search use binary search to find and return the smallest index *Command

type CompletionContext added in v0.1.8

type CompletionContext struct {
	App        *App
	Command    *Command
	Flag       *Flag
	Positional *PositionalArg
	Args       []string
	Current    string
}

type CompletionFunc added in v0.1.8

type CompletionFunc func(ctx CompletionContext) []string

type CompletionResult added in v0.1.10

type CompletionResult struct {
	Value       string
	Description string
	Kind        string
}

type ConfigFlagOptions added in v0.1.8

type ConfigFlagOptions struct {
	Name      string
	Shorthand string
	Usage     string
	EnvVars   []string
	Example   string
}

type ConfigLoader added in v0.1.8

type ConfigLoader func(path string) (map[string]any, error)

type ConfigRuntimeSpec added in v0.1.8

type ConfigRuntimeSpec struct {
	Enabled   bool     `json:"enabled"`
	FlagName  string   `json:"flag_name,omitempty"`
	Shorthand string   `json:"shorthand,omitempty"`
	EnvVars   []string `json:"env_vars,omitempty"`
}

type DetailedLineCompleter added in v0.1.10

type DetailedLineCompleter interface {
	CompleteLineDetailed(line string, cursor int) []CompletionResult
}

type Dispatcher added in v0.2.0

type Dispatcher struct {
	App *App
}

func (*Dispatcher) Dispatch added in v0.2.0

func (d *Dispatcher) Dispatch(ctx context.Context, invocation *Invocation) error

type ErrorHandling added in v0.1.7

type ErrorHandling int

ErrorHandling defines how FlagSet.Parse behaves if the parse fails.

const (
	ContinueOnError ErrorHandling = iota // Return a descriptive error.
	ExitOnError                          // Call os.Exit(2) or for -h/-help Exit(0).
	PanicOnError                         // Call panic with a descriptive error.
)

These constants cause FlagSet.Parse to behave as described if the parse fails.

type ErrorHook added in v0.1.8

type ErrorHook func(ctx HookContext)

type Event added in v0.1.8

type Event struct {
	Type      EventType
	App       *App
	Command   *Command
	Args      []string
	Err       error
	StartTime time.Time
	EndTime   time.Time
	Duration  time.Duration
	ExitCode  int
}

type EventType added in v0.1.8

type EventType string
const (
	EventCommandStarted  EventType = "command_started"
	EventCommandFinished EventType = "command_finished"
	EventCommandFailed   EventType = "command_failed"
)

type Flag added in v0.1.7

type Flag struct {
	Name          string // name as it appears on command line
	Shorthand     string // single-letter shorthand name
	Usage         string // help message
	Value         Value  // value as set
	DefValue      string // default value (as text); for usage message
	ID            string
	Kind          string
	Category      string // logical help group
	EnvVars       []string
	ConfigKeys    []string
	Enum          []string
	Required      bool
	Repeatable    bool
	Hidden        bool
	Deprecated    string
	Example       string
	CompletionKey string
	Completion    CompletionFunc
	// Extensions carries custom metadata for integrations and tooling.
	// Slice and map values are cloned when the library copies metadata, but
	// opaque pointer or custom object payloads are shared by reference. Callers
	// that need full isolation should store immutable values or clone payloads
	// themselves before attaching them here.
	Extensions map[string]any
	Surfaces   map[Surface]FlagSurface
	// contains filtered or unexported fields
}

A Flag represents the state of a flag.

func Lookup added in v0.1.7

func Lookup(name string) *Flag

Lookup returns the Flag structure of the named command-line flag, returning nil if none exists.

func LookupShort added in v0.1.7

func LookupShort(name string) *Flag

LookupShort returns the Flag structure of the named shorthand command-line flag, returning nil if none exists.

type FlagSet added in v0.1.7

type FlagSet struct {
	// Usage is the function called when an error occurs while parsing flags.
	// The field is a function (not a method) that may be changed to point to
	// a custom error handler. What happens after Usage is called depends
	// on the ErrorHandling setting; for the command line, this defaults
	// to ExitOnError, which exits the program after calling Usage.
	Usage func()
	// contains filtered or unexported fields
}

A FlagSet represents a set of defined flags. The zero value of a FlagSet has no name and has ContinueOnError error handling.

Flag names must be unique within a FlagSet. An attempt to define a flag whose name is already in use will cause a panic.

var CommandLine *FlagSet

CommandLine is the default set of command-line flags, parsed from os.Args. The top-level functions such as BoolVar, Arg, and so on are wrappers for the methods of CommandLine.

func NewFlagSet added in v0.1.7

func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet

NewFlagSet returns a new, empty flag set with the specified name and error handling property. If the name is not empty, it will be printed in the default usage message and in error messages.

func (*FlagSet) ApplyConfig added in v0.1.8

func (f *FlagSet) ApplyConfig(data map[string]any) error

func (*FlagSet) ApplyEnv added in v0.1.8

func (f *FlagSet) ApplyEnv() error

func (*FlagSet) Arg added in v0.1.7

func (f *FlagSet) Arg(i int) string

Arg returns the i'th argument. Arg(0) is the first remaining argument after flags have been processed. Arg returns an empty string if the requested element does not exist.

func (*FlagSet) Args added in v0.1.7

func (f *FlagSet) Args() []string

Args returns the non-flag arguments.

func (*FlagSet) BindConfig added in v0.1.8

func (f *FlagSet) BindConfig(name string, configKeys ...string)

func (*FlagSet) BindEnv added in v0.1.8

func (f *FlagSet) BindEnv(name string, envVars ...string)

func (*FlagSet) Bool added in v0.1.7

func (f *FlagSet) Bool(name string, value bool, usage string, shorthand string) *bool

Bool defines a bool flag with specified name, default value, and usage string. The return value is the address of a bool variable that stores the value of the flag.

func (*FlagSet) BoolFunc added in v0.1.7

func (f *FlagSet) BoolFunc(name, usage string, fn func(string) error, shorthand string)

BoolFunc defines a flag with the specified name and usage string without requiring values. Each time the flag is seen, fn is called with the value of the flag. If fn returns a non-nil error, it will be treated as a flag value parsing error.

func (*FlagSet) BoolVar added in v0.1.7

func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string, shorthand string)

BoolVar defines a bool flag with specified name, default value, and usage string. The argument p points to a bool variable in which to store the value of the flag.

func (*FlagSet) Duration added in v0.1.7

func (f *FlagSet) Duration(name string, value time.Duration, usage string, shorthand string) *time.Duration

Duration defines a time.Duration flag with specified name, default value, and usage string. The return value is the address of a time.Duration variable that stores the value of the flag. The flag accepts a value acceptable to time.ParseDuration.

func (*FlagSet) DurationVar added in v0.1.7

func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string, shorthand string)

DurationVar defines a time.Duration flag with specified name, default value, and usage string. The argument p points to a time.Duration variable in which to store the value of the flag. The flag accepts a value acceptable to time.ParseDuration.

func (*FlagSet) ErrorHandling added in v0.1.7

func (f *FlagSet) ErrorHandling() ErrorHandling

ErrorHandling returns the error handling behavior of the flag set.

func (*FlagSet) Float64 added in v0.1.7

func (f *FlagSet) Float64(name string, value float64, usage string, shorthand string) *float64

Float64 defines a float64 flag with specified name, default value, and usage string. The return value is the address of a float64 variable that stores the value of the flag.

func (*FlagSet) Float64Var added in v0.1.7

func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string, shorthand string)

Float64Var defines a float64 flag with specified name, default value, and usage string. The argument p points to a float64 variable in which to store the value of the flag.

func (*FlagSet) Func added in v0.1.7

func (f *FlagSet) Func(name, usage string, fn func(string) error, shorthand string)

Func defines a flag with the specified name and usage string. Each time the flag is seen, fn is called with the value of the flag. If fn returns a non-nil error, it will be treated as a flag value parsing error.

func (*FlagSet) Init added in v0.1.7

func (f *FlagSet) Init(name string, errorHandling ErrorHandling)

Init sets the name and error handling property for a flag set. By default, the zero FlagSet uses an empty name and the ContinueOnError error handling policy.

func (*FlagSet) Int added in v0.1.7

func (f *FlagSet) Int(name string, value int, usage string, shorthand string) *int

Int defines an int flag with specified name, default value, and usage string. The return value is the address of an int variable that stores the value of the flag.

func (*FlagSet) Int64 added in v0.1.7

func (f *FlagSet) Int64(name string, value int64, usage string, shorthand string) *int64

Int64 defines an int64 flag with specified name, default value, and usage string. The return value is the address of an int64 variable that stores the value of the flag.

func (*FlagSet) Int64Var added in v0.1.7

func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string, shorthand string)

Int64Var defines an int64 flag with specified name, default value, and usage string. The argument p points to an int64 variable in which to store the value of the flag.

func (*FlagSet) IntVar added in v0.1.7

func (f *FlagSet) IntVar(p *int, name string, value int, usage string, shorthand string)

IntVar defines an int flag with specified name, default value, and usage string. The argument p points to an int variable in which to store the value of the flag.

func (*FlagSet) IsSet added in v0.1.8

func (f *FlagSet) IsSet(name string) bool

func (*FlagSet) Lookup added in v0.1.7

func (f *FlagSet) Lookup(name string) (*Flag, bool)

searchFlagsName searches for a flag by name.

func (*FlagSet) LookupShort added in v0.1.7

func (f *FlagSet) LookupShort(shorthand string) (*Flag, bool)

LookupShort returns the Flag structure of the named shorthand flag, returning nil if none exists.

func (*FlagSet) MarkDeprecated added in v0.1.8

func (f *FlagSet) MarkDeprecated(name, message string)

func (*FlagSet) MarkHidden added in v0.1.8

func (f *FlagSet) MarkHidden(name string)

func (*FlagSet) MarkRepeatable added in v0.2.0

func (f *FlagSet) MarkRepeatable(name string)

func (*FlagSet) MarkRequired added in v0.1.8

func (f *FlagSet) MarkRequired(name string)

func (*FlagSet) NArg added in v0.1.7

func (f *FlagSet) NArg() int

NArg is the number of arguments remaining after flags have been processed.

func (*FlagSet) NFlag added in v0.1.7

func (f *FlagSet) NFlag() int

NFlag returns the number of flags that have been set.

func (*FlagSet) Name added in v0.1.7

func (f *FlagSet) Name() string

Name returns the name of the flag set.

func (*FlagSet) Output added in v0.1.7

func (f *FlagSet) Output() io.Writer

Output returns the destination for usage and error messages. os.Stderr is returned if output was not set or was set to nil.

func (*FlagSet) Parse added in v0.1.7

func (f *FlagSet) Parse(arguments []string) error

Parse parses flag definitions from the argument list, which should not include the command name. Must be called after all flags in the FlagSet are defined and before flags are accessed by the program. The return value will be ErrHelp if -help or -h were set but not defined.

func (*FlagSet) Parsed added in v0.1.7

func (f *FlagSet) Parsed() bool

Parsed reports whether f.Parse has been called.

func (*FlagSet) PrintDefaults added in v0.1.7

func (f *FlagSet) PrintDefaults()

PrintDefaults prints, to standard error unless configured otherwise, the default values of all defined command-line flags in the set. See the documentation for the global function PrintDefaults for more information.

func (*FlagSet) Set added in v0.1.7

func (f *FlagSet) Set(name, value string) error

Set sets the value of the named flag.

func (*FlagSet) SetCategory added in v0.1.8

func (f *FlagSet) SetCategory(name, category string)

func (*FlagSet) SetCompletion added in v0.1.8

func (f *FlagSet) SetCompletion(name string, fn CompletionFunc)

func (*FlagSet) SetCompletionKey added in v0.2.0

func (f *FlagSet) SetCompletionKey(name, key string)

func (*FlagSet) SetEnum added in v0.1.8

func (f *FlagSet) SetEnum(name string, values ...string)

func (*FlagSet) SetExample added in v0.1.8

func (f *FlagSet) SetExample(name, example string)

func (*FlagSet) SetExtension added in v0.1.8

func (f *FlagSet) SetExtension(name, key string, value any) error

func (*FlagSet) SetID added in v0.2.0

func (f *FlagSet) SetID(name, id string)

func (*FlagSet) SetKind added in v0.2.0

func (f *FlagSet) SetKind(name, kind string)

func (*FlagSet) SetOutput added in v0.1.7

func (f *FlagSet) SetOutput(output io.Writer)

SetOutput sets the destination for usage and error messages. If output is nil, os.Stderr is used.

func (*FlagSet) SetSurface added in v0.2.0

func (f *FlagSet) SetSurface(name string, surface Surface, override FlagSurface)

func (*FlagSet) String added in v0.1.7

func (f *FlagSet) String(name string, value string, usage string, shorthand string) *string

String defines a string flag with specified name, default value, and usage string. The return value is the address of a string variable that stores the value of the flag.

func (*FlagSet) StringVar added in v0.1.7

func (f *FlagSet) StringVar(p *string, name string, value string, usage string, shorthand string)

StringVar defines a string flag with specified name, default value, and usage string. The argument p points to a string variable in which to store the value of the flag.

func (*FlagSet) TextVar added in v0.1.7

func (f *FlagSet) TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string, shorthand string)

TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.

func (*FlagSet) Uint added in v0.1.7

func (f *FlagSet) Uint(name string, value uint, usage string, shorthand string) *uint

Uint defines a uint flag with specified name, default value, and usage string. The return value is the address of a uint variable that stores the value of the flag.

func (*FlagSet) Uint64 added in v0.1.7

func (f *FlagSet) Uint64(name string, value uint64, usage string, shorthand string) *uint64

Uint64 defines a uint64 flag with specified name, default value, and usage string. The return value is the address of a uint64 variable that stores the value of the flag.

func (*FlagSet) Uint64Var added in v0.1.7

func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string, shorthand string)

Uint64Var defines a uint64 flag with specified name, default value, and usage string. The argument p points to a uint64 variable in which to store the value of the flag.

func (*FlagSet) UintVar added in v0.1.7

func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string, shorthand string)

UintVar defines a uint flag with specified name, default value, and usage string. The argument p points to a uint variable in which to store the value of the flag.

func (*FlagSet) Validate added in v0.1.8

func (f *FlagSet) Validate() error

func (*FlagSet) Var added in v0.1.7

func (f *FlagSet) Var(value Value, name string, usage string, shorthand string)

Var defines a flag with the specified name and usage string. The type and value of the flag are represented by the first argument, of type Value, which typically holds a user-defined implementation of Value. For instance, the caller could create a flag that turns a comma-separated string into a slice of strings by giving the slice the methods of Value; in particular, Set would decompose the comma-separated string into the slice.

func (*FlagSet) Visit added in v0.1.7

func (f *FlagSet) Visit(fn func(*Flag))

Visit visits the flags in lexicographical order, calling fn for each. It visits only those flags that have been set.

func (*FlagSet) VisitAll added in v0.1.7

func (f *FlagSet) VisitAll(fn func(*Flag))

VisitAll visits the flags in lexicographical order, calling fn for each. It visits all flags, even those not set.

func (*FlagSet) WarnDeprecated added in v0.1.8

func (f *FlagSet) WarnDeprecated()

type FlagSpec added in v0.1.8

type FlagSpec struct {
	ID                 string         `json:"id,omitempty"`
	Name               string         `json:"name"`
	Shorthand          string         `json:"shorthand,omitempty"`
	Type               string         `json:"type,omitempty"`
	Kind               string         `json:"kind,omitempty"`
	Usage              string         `json:"usage,omitempty"`
	Default            string         `json:"default,omitempty"`
	Category           string         `json:"category,omitempty"`
	EnvVars            []string       `json:"env_vars,omitempty"`
	ConfigKeys         []string       `json:"config_keys,omitempty"`
	SourceOrder        []string       `json:"source_order,omitempty"`
	Enum               []string       `json:"enum,omitempty"`
	Required           bool           `json:"required,omitempty"`
	Repeatable         bool           `json:"repeatable,omitempty"`
	Hidden             bool           `json:"hidden,omitempty"`
	Deprecated         string         `json:"deprecated,omitempty"`
	Example            string         `json:"example,omitempty"`
	CompletionKey      string         `json:"completion_key,omitempty"`
	SupportsCompletion bool           `json:"supports_completion,omitempty"`
	Extensions         map[string]any `json:"extensions,omitempty"`
}

type FlagSurface added in v0.2.0

type FlagSurface struct {
	Usage         string
	Default       string
	Category      string
	Enum          []string
	Required      *bool
	Hidden        *bool
	Deprecated    string
	Example       string
	Kind          string
	Repeatable    *bool
	CompletionKey string
	Extensions    map[string]any
}

type Getter added in v0.1.7

type Getter interface {
	Value
	Get() any
}

Getter is an interface that allows the contents of a Value to be retrieved. It wraps the Value interface, rather than being part of it, because it appeared after Go 1 and its compatibility rules. All Value types provided by this package satisfy the Getter interface, except the type used by Func.

type HookContext added in v0.1.8

type HookContext struct {
	Context   context.Context
	App       *App
	Command   *Command
	Args      []string
	Err       error
	StartTime time.Time
}

type HookSpec added in v0.1.8

type HookSpec struct {
	BeforeRun bool `json:"before_run,omitempty"`
	AfterRun  bool `json:"after_run,omitempty"`
	OnError   bool `json:"on_error,omitempty"`
}

type Invocation added in v0.2.0

type Invocation struct {
	App            *App
	Registry       *Registry
	Root           *Command
	CommandPath    []*Command
	Command        *Command
	RawArgs        []string
	Args           []string
	FlagSet        *FlagSet
	Positionals    []string
	InheritedFlags []parsedFlagValue
	Builtin        string
	IsREPL         bool
	Kind           InvocationKind
}

Invocation is the shared intermediate representation between CLI/REPL input and execution.

type InvocationKind added in v0.2.0

type InvocationKind string
const (
	InvocationNoop    InvocationKind = "noop"
	InvocationUsage   InvocationKind = "usage"
	InvocationHelp    InvocationKind = "help"
	InvocationBuiltin InvocationKind = "builtin"
	InvocationCommand InvocationKind = "command"
)

type LineCompleter added in v0.1.10

type LineCompleter interface {
	CompleteLine(line string, cursor int) []string
}

type Middleware added in v0.1.8

type Middleware func(ctx MiddlewareContext, next NextFunc) error

type MiddlewareContext added in v0.1.8

type MiddlewareContext struct {
	Context   context.Context
	App       *App
	Command   *Command
	Args      []string
	StartTime time.Time
}

type NextFunc added in v0.1.8

type NextFunc func(ctx context.Context) error

type Observer added in v0.1.8

type Observer interface {
	HandleEvent(event Event)
}

type ObserverFunc added in v0.1.8

type ObserverFunc func(event Event)

func (ObserverFunc) HandleEvent added in v0.1.8

func (f ObserverFunc) HandleEvent(event Event)

type PositionalArg added in v0.1.8

type PositionalArg struct {
	Name          string
	Usage         string
	Required      bool
	Variadic      bool
	Enum          []string
	Example       string
	ID            string
	Kind          string
	CompletionKey string
	Completion    CompletionFunc
	// Extensions carries custom metadata for integrations and tooling.
	// Slice and map values are cloned when the library copies metadata, but
	// opaque pointer or custom object payloads are shared by reference. Callers
	// that need full isolation should store immutable values or clone payloads
	// themselves before attaching them here.
	Extensions map[string]any
	Surfaces   map[Surface]PositionalSurface
}

func (*PositionalArg) SetExtension added in v0.1.8

func (p *PositionalArg) SetExtension(key string, value any)

func (*PositionalArg) SetSurface added in v0.2.0

func (p *PositionalArg) SetSurface(surface Surface, override PositionalSurface)

type PositionalSpec added in v0.1.8

type PositionalSpec struct {
	ID                 string         `json:"id,omitempty"`
	Name               string         `json:"name"`
	Usage              string         `json:"usage,omitempty"`
	Required           bool           `json:"required,omitempty"`
	Variadic           bool           `json:"variadic,omitempty"`
	Kind               string         `json:"kind,omitempty"`
	Enum               []string       `json:"enum,omitempty"`
	Example            string         `json:"example,omitempty"`
	CompletionKey      string         `json:"completion_key,omitempty"`
	SupportsCompletion bool           `json:"supports_completion,omitempty"`
	Extensions         map[string]any `json:"extensions,omitempty"`
}

type PositionalSurface added in v0.2.0

type PositionalSurface struct {
	Name          string
	Usage         string
	Required      *bool
	Variadic      *bool
	Enum          []string
	Example       string
	Kind          string
	CompletionKey string
	Extensions    map[string]any
}

type REPL added in v0.1.10

type REPL struct {
	App        *App
	Prompt     string
	PromptFunc func(ctx context.Context, repl *REPL) string
	In         io.Reader
	Out        io.Writer
	Err        io.Writer
	Welcome    string
	Driver     REPLDriver
	History    *REPLHistoryHooks
	// contains filtered or unexported fields
}

func (*REPL) Run added in v0.1.10

func (r *REPL) Run(ctx context.Context) error

type REPLConfig added in v0.2.0

type REPLConfig struct {
	Enabled    bool
	Prompt     string
	PromptFunc func(ctx context.Context, repl *REPL) string
	Welcome    string
	Driver     REPLDriver
	History    *REPLHistoryHooks
}

type REPLDriver added in v0.2.0

type REPLDriver interface {
	Run(ctx context.Context, repl *REPL) error
}

type REPLHistoryHooks added in v0.2.1

type REPLHistoryHooks struct {
	Load   func(ctx context.Context) ([]string, error)
	Append func(ctx context.Context, line string) error
}

type REPLRuntime added in v0.2.0

type REPLRuntime struct {
	In         io.Reader
	Out        io.Writer
	Err        io.Writer
	Prompt     string
	PromptFunc func(ctx context.Context, repl *REPL) string
	Welcome    string
	Driver     REPLDriver
	History    *REPLHistoryHooks
}

func (REPLRuntime) Run added in v0.2.0

func (r REPLRuntime) Run(ctx context.Context, app *App) error

type Registry added in v0.2.0

type Registry struct {
	App      *App
	Root     *Command
	ByPath   map[string]*Command
	Aliases  map[string]*Command
	Builtins map[string]BuiltinHandler
	// contains filtered or unexported fields
}

Registry is a read-only index over the shared command tree.

func (*Registry) Builtin added in v0.2.0

func (r *Registry) Builtin(name string) (BuiltinHandler, bool)

func (*Registry) Lookup added in v0.2.0

func (r *Registry) Lookup(parent *Command, name string) *Command

func (*Registry) ResolveCommand added in v0.2.0

func (r *Registry) ResolveCommand(args []string) ([]*Command, *Command, []string, error)

func (*Registry) VisibleBuiltins added in v0.2.0

func (r *Registry) VisibleBuiltins() []string

type Resolver added in v0.2.0

type Resolver struct {
	App      *App
	Registry *Registry
}

func (*Resolver) Resolve added in v0.2.0

func (r *Resolver) Resolve(ctx context.Context, args []string, opts resolveOptions) (*Invocation, error)

func (*Resolver) ResolveCompletion added in v0.2.0

func (r *Resolver) ResolveCompletion(args []string) completionState

type Runtime added in v0.2.0

type Runtime interface {
	Run(ctx context.Context, app *App) error
}

func DefaultRuntime added in v0.2.0

func DefaultRuntime(args []string) Runtime

type Surface added in v0.2.0

type Surface string
const (
	SurfaceCLI  Surface = "cli"
	SurfaceREPL Surface = "repl"
)

type TerminalREPLDriver added in v0.2.0

type TerminalREPLDriver struct{}

func (TerminalREPLDriver) Run added in v0.2.0

func (d TerminalREPLDriver) Run(ctx context.Context, repl *REPL) error

type Value added in v0.1.7

type Value interface {
	String() string
	Set(string) error
}

Value is the interface to the dynamic value stored in a flag. (The default value is represented as a string.)

If a Value has an IsBoolFlag() bool method returning true, the command-line parser makes -name equivalent to -name=true rather than using the next command-line argument.

Set is called once, in command line order, for each flag present. The flag package may call the String method with a zero-valued receiver, such as a nil pointer.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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