Args and flags
Positional args, named flags, shorts, defaults, slices, repeats, and validation, all declared through field tags.
A command's inputs are its config struct fields, and the tags on each field decide how a value reaches it. This guide covers the whole tag vocabulary in use. The tags reference lists each tag in one place.
Positional arguments
arg with a zero-based index marks a positional argument. The first bare argument fills arg:"0", the second fills arg:"1", and so on. Flags in between do not count, so a positional lands in the right slot no matter how many flags precede it.
type CopyConfig struct {
Src string `arg:"0" help:"Source path" rules:"required"`
Dst string `arg:"1" help:"Destination path" rules:"required"`
}copy ./a.txt ./b.txt # Src = "./a.txt", Dst = "./b.txt"Named flags and shorts
arg with a name marks a named flag (--name), and short adds a single-character alias (-n). A bool field is set to true by its bare presence. Any other type takes the next token as its value, or the value after an =.
type BuildConfig struct {
Output string `arg:"output" short:"o" help:"Output path"`
Verbose bool `arg:"verbose" short:"V" help:"Verbose output"`
}build --output ./bin/app -V
build --output=./bin/app # = form
build -o ./bin/app # shortDefaults
default seeds a value when nothing else supplies one. It never overrides real input, so a flag, env var, or resolved config value still wins.
type ServeConfig struct {
Addr string `arg:"addr" default:":8080" help:"Listen address"`
}With no --addr and no ADDR in the environment, Addr is :8080.
Environment binding
env binds an environment variable to a field. The framework folds the process environment into the merge, so an env-tagged field picks up its variable with no extra wiring. A flag still beats it. See Config and environment for the full precedence.
type DBConfig struct {
DSN string `arg:"dsn" env:"DATABASE_DSN" help:"Database connection string"`
}DATABASE_DSN=postgres://localhost/app myapp migrateSlices and separators
A slice field ([]string, []int, ...) accepts a single string split into elements. The separator is a comma by default, or set your own with sep. Set sep:"" to turn splitting off and keep each value whole.
type RunConfig struct {
Tags []string `arg:"tag" short:"t" help:"Tags to apply"`
Ports []int `arg:"port" short:"p" sep:"," help:"Ports to bind"`
}run -p 8080,9090 # Ports => [8080, 9090]Repeatable flags
A flag bound to a slice field can be passed more than once, and every occurrence is kept. Repeats and the sep separator stack, so each occurrence is split first and the pieces are joined into one slice. A scalar (non-slice) field keeps only the last value.
run -t edge -t beta -t canary # Tags => ["edge", "beta", "canary"]
run -t edge,beta -t canary # Tags => ["edge", "beta", "canary"]
run -p 8080,9090 -p 3000 # Ports => [8080, 9090, 3000]Validation
rules declares validation rules, separated by spaces, with arguments after a colon. The merged value is checked before Run, so a value from config or a default satisfies required as a flag does. Two rules are built in.
requiredfails when a field has no input, no default, and a zero value.oneof:a,b,crestricts a field to one of the listed values.
type DeployConfig struct {
Env string `arg:"env" rules:"required oneof:dev,staging,prod" help:"Target environment"`
Region string `arg:"region" default:"eu" rules:"oneof:eu,us" help:"Region"`
}A failed rule stops the command before Run and prints the failure. Validation is powered by the structs module, which cli builds on.
Masking secrets
secret:"true" masks a field's resolved value in --help-values output, so a token sourced from the environment or a config file is not shown in full in help that gets pasted into logs or screenshots.
type APIConfig struct {
Token string `arg:"token" env:"API_TOKEN" secret:"true" help:"API token"`
}Embedded and nested config
Following Go's own field-promotion rules, an anonymous embedded struct has its fields promoted to plain top-level flags with no prefix, while a named nested struct groups under a dotted path.
type RepoFlags struct {
Repo string `arg:"repo" short:"r" help:"Repository"`
Branch string `arg:"branch" short:"b" default:"main" help:"Branch"`
}
type PushConfig struct {
RepoFlags // promoted: --repo, --branch
Remote Remote `arg:"remote"` // nested: --remote.url
}
type Remote struct {
URL string `arg:"url" help:"Remote URL"`
}Embed a shared RepoFlags to give several commands the same flags with no duplication. A nested field is reached by its dotted path, --remote.url.