A minimal generic command-line framework for Go: a command tree with auto-generated help and typed flag parsing.
Zero runtime dependencies, deliberately small — no lifecycle, no middleware,
no configuration files. Commands are plain values, flags are specs, and
parsing is pure: Parse returns typed values without touching your
variables, and Dispatch reports everything through errors instead of
printing.
package main
import (
"errors"
"fmt"
"os"
"github.com/pulseaiclub/pli"
)
func main() {
root := &cli.Command{Name: "app", Desc: "example app", Flags: []cli.Flag{
cli.String("name", "n", "name to greet", "world"),
cli.Int("rounds", "", "how many times to greet", 1),
}}
root.Run = func(args []string, f cli.Flags) error {
for range f.Int("rounds") {
fmt.Printf("hello %s\n", f.String("name"))
}
return nil
}
if err := root.Dispatch(os.Args[1:]); err != nil {
var ue *cli.UsageError
if errors.As(err, &ue) {
fmt.Fprintf(os.Stderr, "%s\n\n%s", ue.Error(), ue.Help())
os.Exit(2)
}
var he *cli.HelpError
if errors.As(err, &he) {
fmt.Print(he.Help)
os.Exit(0)
}
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}Command— one node in a command tree; plain data. A command runs (Run func(args []string, flags Flags) error), groups subcommands (Sub), or both.Add— register subcommands (wires parent for usage paths).String,Int,Bool,Duration,Var[T]— flag specs (values, not bindings).Boolis a presence flag;--name=false/--name=trueare also accepted.Flags— the parsed value set; read with typed getters (f.String(name),f.Int(name),f.Bool(name),f.Duration(name)).Parse(args)→(Flags, []string, error)— pure; absent flags yield their declared default.Dispatch(args)— select a subcommand, parse flags, run. Never prints: help requests return*HelpError, usage mistakes*UsageError(message + rendered help), other run errors*RunError(with the failing command path).
Flags support --name value, --name=value, -n value, -n=value, --
end-of-flags, and -1s-style negative numbers as positionals. The names
help, -h, and --help are reserved for help.
Apache License 2.0 — see LICENSE.