warg is an opinionated CLI (Command Line Interface) framework for Go. It provides a declarative approach to building CLI applications with nested commands, detailed help output, and flexible flag configuration from multiple sources.
warg applications are built from four structural types:
- App (app.go) - The top-level application container
- Section (section.go) - "Folders" for organizing commands (noun names)
- Cmd (command.go) - Executable commands (verb names like
add,edit,run) - Flag (flag.go) - Configuration options for commands
- Subcommands required: Apps must have at least one subcommand.
<appname> --flag <value>alone won't work; use<appname> <command> --flag <value> - No positional arguments: Use required flags instead (e.g.,
git clone --url <url>instead ofgit clone <url>) - Flag resolution order:
os.Args→ config files → environment variables → app defaults
warg/
├── app.go # App type, New(), MustRun(), Parse()
├── app_parse.go # Parsing logic, ParseState, ValueMap
├── command.go # Cmd type, CmdContext, Action
├── flag.go # Flag type and options
├── section.go # Section type for organizing commands
├── help_*.go # Help output formatters (detailed, outline, allcommands)
├── testing.go # GoldenTest for snapshot testing
├── completion/ # Shell completion (zsh)
├── config/ # Config file readers (YAML, JSON)
├── value/ # Flag value types
│ ├── scalar/ # Single values (String, Int, Bool, Path, etc.)
│ ├── slice/ # List values
│ └── contained/ # Type definitions
├── examples/ # Example applications
│ ├── butler/ # Simple example
│ ├── fling/ # Link/unlink utility
│ ├── grabbit/ # Reddit image downloader
│ └── starghaze/ # GitHub stars manager
└── metadata/ # Key/value parse metadata
app := warg.New(
"appname",
"v1.0.0",
warg.NewSection(
"Section help text",
warg.NewSubCmd(
"command",
"Command help",
actionFunc,
warg.NewCmdFlag(
"--flag",
"Flag help",
scalar.String(),
),
),
),
)| Type | Purpose | File |
|---|---|---|
App |
Application container | app.go |
Section |
Command grouping | section.go |
Cmd |
Executable command | command.go |
CmdContext |
Context passed to actions | command.go |
Action |
Command handler function func(CmdContext) error |
command.go |
Flag |
Command flag definition | flag.go |
ParseResult |
Result of parsing | app_parse.go |
ParseState |
Current parsing state | app_parse.go |
warg.GlobalFlag()/warg.NewGlobalFlag()- Add global flagswarg.ConfigFlag()- Enable config file supportwarg.HelpFlag()- Customize helpwarg.SkipAll()- Skip all auto-added features (for tests)warg.SkipCompletionCmds()- Skip completion commandswarg.SkipGlobalColorFlag()- Skip--colorflagwarg.SkipGlobalTermWidthFlag()- Skip--term-widthflagwarg.SkipVersionCmd()- Skipversioncommandwarg.SkipValidation()- Skip startup validation
warg.Alias()- Short alias (e.g.,-n)warg.EnvVars()- Environment variable nameswarg.Required()- Mark as requiredwarg.ConfigPath()- Path in config filewarg.FlagCompletions()- Tab completion function
go test ./..../scripts/test_update_golden.shUse warg.GoldenTest for snapshot testing:
warg.GoldenTest(
t,
warg.GoldenTestArgs{
App: app(),
UpdateGolden: updateGolden,
ExpectActionErr: false,
},
warg.ParseWithArgs([]string{"app", "cmd", "--flag", "value"}),
warg.ParseWithLookupEnv(warg.LookupMap(nil)),
)- Package imports: Most warg types are in the main
wargpackage. Value types are invalue/scalarandvalue/slice - Error handling: Commands return errors;
MustRun()exits on error - Naming conventions:
- Commands use verb names (
add,edit,delete) - Sections use noun names (
config,comments) - Flags start with
--and optionally have-aliases
- Commands use verb names (
- Linting:
.golangci.ymlconfigures golangci-lint - Git hooks:
lefthook.ymlfor pre-commit hooks - YAML linting:
.yamllint.yml
See Go Project Notes for additional tooling documentation.
warg.ConfigFlag(
yamlreader.New,
warg.FlagMap{
"--config": warg.NewFlag(
"Path to config file",
scalar.Path(),
),
},
)For commands that wrap other tools:
warg.NewSubCmd(
"exec",
"Execute with environment",
execAction,
warg.AllowForwardedArgs(),
)
// Usage: app exec --env prod -- go run .warg.FlagCompletions(warg.CompletionsValues([]string{"option1", "option2"}))
warg.FlagCompletions(warg.CompletionsDirectories())
warg.FlagCompletions(warg.CompletionsDirectoriesFiles())