Skip to content

Struct Tags Reference

Quick reference for all BOA struct tags.

Tag Reference

Tag Aliases Description Example
descr desc, description, help Help text descr:"User name"
name long Override flag name name:"server-host"
short Single-char flag short:"n"
env Environment variable env:"APP_HOST"
default Default value default:"8080"
required req Mark as required required:"true"
optional opt Mark as optional optional:"true"
positional pos Positional argument positional:"true"
alts alternatives Allowed values alts:"a,b,c"
strict-alts strict Validate alts strict:"true"
min Min value (numeric) or min length (string/slice) min:"1"
max Max value (numeric) or max length (string/slice) max:"65535"
pattern Regex pattern (strings only) pattern:"^[a-z]+$"
configfile Auto-load config file (root or substruct) configfile:"true"
boa Special directives boa:"ignore", boa:"configonly"

Special Field Types

Pointer Fields

Pointer types (*string, *int, *bool, etc.) are always optional by default, regardless of the global configuration. A nil value means the flag was not provided. Use required:"true" to override.

type Params struct {
    Name  *string `descr:"user name"`              // optional, nil if not set
    Count *int    `descr:"item count"`              // optional, nil if not set
    Force *bool   `required:"true" descr:"force"`   // required even though it's a pointer
}

The boa:"ignore" and boa:"configonly" Tags

Fields tagged boa:"ignore" (or its alias boa:"configonly") are skipped during CLI flag and environment variable registration. They do not appear in --help output and cannot be set via the command line or env vars.

However, these fields still receive values from config file loading, since config files are loaded via json.Unmarshal (or the configured unmarshal function) which writes directly to struct fields. This makes these tags useful for config-file-only fields:

type Params struct {
    ConfigFile string `configfile:"true" optional:"true" default:"config.json"`
    Host       string `descr:"server host"`
    Port       int    `descr:"server port"`
    InternalID string `boa:"ignore"`     // only loaded from config file
    Metadata   map[string]string `boa:"configonly"` // clearer intent: config-file-only
}

boa:"configonly" is functionally identical to boa:"ignore" but communicates intent more clearly.

Map Fields

Map types with string keys (map[string]string, map[string]int, map[string]int64) use key=val,key=val syntax on the CLI. Maps default to optional.

type Params struct {
    Labels map[string]string `descr:"key=value labels"`
    Limits map[string]int    `descr:"resource limits"`
}
// Usage: myapp --labels env=prod,team=backend --limits cpu=4,memory=8192

For complex map value types (e.g., map[string][]string), the CLI uses JSON syntax. See Advanced.

Complex Types (JSON Fallback)

Any field type without native pflag support (nested slices, complex maps, etc.) automatically falls back to JSON parsing on the CLI:

type Params struct {
    Matrix [][]int             `descr:"nested matrix" optional:"true"`
    Meta   map[string][]string `descr:"metadata" optional:"true"`
}
// Usage: --matrix '[[1,2],[3,4]]' --meta '{"tags":["a","b"]}'

Examples

Basic Flags

type Params struct {
    Host string `descr:"Server hostname" default:"localhost"`
    Port int    `descr:"Server port" short:"p" default:"8080"`
}

Environment Variables

type Params struct {
    APIKey   string `env:"API_KEY" descr:"API authentication key"`
    LogLevel string `env:"LOG_LEVEL" default:"info"`
}

Positional Arguments

type Params struct {
    Source string `positional:"true" descr:"Source file"`
    Dest   string `positional:"true" descr:"Destination file"`
}
// Usage: myapp <source> <dest>

Optional Positional Arguments

type Params struct {
    File   string `positional:"true" descr:"Input file"`
    Output string `positional:"true" optional:"true" default:"out.txt"`
}
// Usage: myapp <file> [output]

Enum Values

type Params struct {
    Format string `alts:"json,yaml,toml" default:"json"`
    Level  string `alts:"debug,info,warn,error" strict:"true"`
}

Min/Max Validation

For numeric types, min and max validate the value itself. For strings and slices, they validate the length:

type Params struct {
    Port    int      `descr:"port" min:"1" max:"65535"`
    Rate    float64  `descr:"rate" min:"0.0" max:"1.0"`
    Name    string   `descr:"name" min:"3" max:"20"`
    Retries int      `descr:"retries" max:"10"`
    Tags    []string `descr:"tags" min:"1" max:"5"`
    Files   []string `positional:"true" min:"2" max:"10"`
}

Optional (pointer) fields are only validated when a value is actually provided.

Pattern Validation

Use pattern to validate string fields against a regular expression:

type Params struct {
    Name string `descr:"name" pattern:"^[a-z][a-z0-9-]*$"`
    Tag  string `descr:"tag" pattern:"^v[0-9]+\\.[0-9]+\\.[0-9]+$"`
}

Optional (pointer) fields are only validated when a value is actually provided.

Config File

type Params struct {
    Config string `configfile:"true" optional:"true" default:"config.json" descr:"Path to config file"`
    Host   string `descr:"Server hostname"`
    Port   int    `descr:"Server port"`
}
// Usage: myapp --config myconfig.json
// Or just: myapp (loads config.json by default)

The tagged field must be a string. Only one configfile field per struct level. Nested structs can also have their own configfile:"true" field for substruct-level config files. See Advanced for details.

Combined Example

type Params struct {
    // Required flag with short form and env var
    Config string `short:"c" env:"APP_CONFIG" descr:"Config file path"`

    // Optional flag with default
    Port int `short:"p" optional:"true" default:"8080" descr:"Listen port"`

    // Positional argument
    Command string `positional:"true" descr:"Command to run"`

    // Boolean flag (defaults to false automatically)
    Verbose bool `short:"v" optional:"true" descr:"Verbose output"`

    // Enum with validation
    Mode string `alts:"dev,prod" default:"dev" descr:"Run mode"`
}

Auto-Generated Values

Without explicit tags, BOA derives flag names and short flags automatically. Environment variables are not auto-derived by default -- add ParamEnricherEnv to your enricher chain or use env struct tags.

The camelToKebabCase conversion handles acronyms correctly:

Field Flag Short Env Var
ServerHost --server-host -s (none by default)
DBHost --db-host -d (none by default)
HTTPPort --http-port -h (skipped, reserved) (none by default)
MaxRetries --max-retries -m (none by default)
FB --fb -f (none by default)

To auto-derive env vars, set ParamEnrich:

boa.CmdT[Params]{
    Use: "app",
    ParamEnrich: boa.ParamEnricherCombine(
        boa.ParamEnricherName,
        boa.ParamEnricherShort,
        boa.ParamEnricherEnv,   // adds SERVER_HOST, MAX_RETRIES, etc.
        boa.ParamEnricherBool,
    ),
}

See Enrichers to customize this behavior.

Named Struct Auto-Prefixing

Named (non-anonymous) struct fields auto-prefix their children's flag names and env var names. This prevents collisions when the same struct type is used in multiple fields.

type DBConfig struct {
    Host string `descr:"database host" default:"localhost"`
    Port int    `descr:"database port" default:"5432"`
}

type Params struct {
    Primary DBConfig  // named → --primary-host, --primary-port
    Replica DBConfig  // named → --replica-host, --replica-port
}

Rules

  • Embedded (anonymous) fields are not prefixed: CommonFlags--verbose
  • Named fields auto-prefix: DB DBConfig--db-host
  • Deep nesting chains: Infra.Primary.Host--infra-primary-host
  • Env vars also prefixed: DB.Host with ParamEnricherEnvDB_HOST
  • Explicit tags also prefixed: name:"host" inside named field API--api-host
  • Explicit env tags also prefixed: env:"HOST" inside named field APIAPI_HOST

Example with Env Vars

type ServerConfig struct {
    Host string `env:"SERVER_HOST" default:"localhost"`
    Port int    `env:"SERVER_PORT" default:"8080"`
}

type Params struct {
    API ServerConfig  // env vars become API_SERVER_HOST, API_SERVER_PORT
}

Beyond Struct Tags

Struct tags cover the most common use cases, but for dynamic behavior you'll need programmatic configuration via HookContext:

  • Dynamic defaults - Set defaults based on runtime values
  • Conditional requirements - Make fields required based on other fields
  • Dynamic completions - Shell completions from APIs, files, or computed at runtime
  • AlternativesFunc - Generate completion suggestions dynamically (e.g., list files, query databases)
  • Custom validation - Complex validation logic
boa.CmdT[Params]{
    Use: "app",
    InitFuncCtx: func(ctx *boa.HookContext, p *Params, cmd *cobra.Command) error {
        param := ctx.GetParam(&p.Region)
        param.SetAlternatives(fetchRegionsFromAPI())
        param.SetStrictAlts(true)
        return nil
    },
}

See Advanced for the full Param interface and examples.

See Also