A reusable Go library that plugs into existing CLI frameworks to add helpers, shell completions, and more polished help output.
| Package | Description |
|---|---|
cli/cobra |
Cobra framework adapters |
cli/kong |
Kong framework adapters |
cli/urfave |
urfave/cli framework adapters |
complete |
Shell completion generation (bash, zsh, fish, pwsh, elvish, nu) |
help |
Structured help rendering with themed output |
theme |
Configurable theme (via lipgloss) |
go get github.com/gechr/clib
Use the built-in light/dark pair, or build an explicit pair for your terminal backgrounds:
// Auto-detect the terminal background and select from clib's defaults.
th := theme.Auto()
// Or require an explicit light/dark pair.
themes := theme.MustPair(
theme.Light().With(
theme.WithRed(lipgloss.NewStyle().Foreground(lipgloss.Color("#a11d33"))),
theme.WithEntityColors([]color.Color{lipgloss.Color("#5d4037"), lipgloss.Color("#00695c")}),
),
theme.Dark().With(
theme.WithRed(lipgloss.NewStyle().Foreground(lipgloss.Color("9"))),
theme.WithEntityColors([]color.Color{lipgloss.Color("208"), lipgloss.Color("51")}),
),
)
th = themes.Auto()To let users pick themes via the environment, build the pair from <PREFIX>_THEME_LIGHT and <PREFIX>_THEME_DARK (both required):
// Reads CLIB_THEME_LIGHT and CLIB_THEME_DARK (override the prefix with SetEnvPrefix).
themes, err := theme.PairFromEnv()
if err != nil {
return err
}
th := themes.Auto()Setting the single <PREFIX>_THEME (e.g. CLIB_THEME=dracula) forces that theme regardless of the terminal background, taking precedence over the light/dark pair. Any Auto() call honors it, including the default theme.Auto() and help.NewRenderer(nil). An unknown name is ignored and detection proceeds as normal.
Build structured help output. Content blocks implement the help.Content
interface: FlagGroup, Args, Usage, Text, Examples, CommandGroup,
and nested *Section.
hr := help.NewRenderer(th)
sections := []help.Section{
{Title: "Flags", Content: []help.Content{
help.FlagGroup{
{Short: "q", Long: "query", Placeholder: "text", Desc: "Filter results by query"},
{
Short: "f",
Long: "format",
Placeholder: "format",
Desc: "Output format",
Enum: []string{"table", "json", "yaml"},
EnumDefault: "table",
},
},
}},
{Title: "Examples", Content: []help.Content{
help.Examples{
{Comment: "List items in JSON format", Command: "catalog list --format json"},
},
}},
}
if err := hr.Render(os.Stdout, sections); err != nil {
return err
}Flag fields use bare names - the renderer adds dashes (-/--) and angle
brackets (</>) automatically. Sections can be nested by including a
*help.Section as content.
Each adapter provides the same core capabilities for its framework:
Extend (or struct tags for Kong), FlagMeta, Sections/HelpFunc, NewCompletion,
and CSVFlag.
Annotate your CLI struct with Kong-style tags and a clib:"..." tag for
clib-specific metadata (grouping, descriptions, completions, placeholders):
type CLI struct {
clib.CompletionFlags
Query string `name:"query" short:"q" help:"Filter results by query" clib:"group='Filters',terse='Query',complete='predictor=query',order=keep"`
Fields clib.CSVFlag `name:"fields" help:"Fields to show" clib:"complete='predictor=field,comma'"`
Format string `name:"format" short:"f" help:"Output format" default:"table" enum:"table,json,yaml"`
}
flags := clib.Reflect(&CLI{})
gen := complete.NewGenerator("catalog").FromFlags(flags)
gen.Install("fish", false)Integrate with Kong's help system using HelpPrinter or HelpPrinterFunc:
r := help.NewRenderer(th)
k := konglib.Must(&cli,
konglib.Help(clib.HelpPrinterFunc(r, clib.NodeSectionsFunc())),
)Use Extend to attach clib metadata to pflag flags:
f := root.Flags()
f.StringP("query", "q", "", "Filter results by query")
f.StringP("format", "f", "table", "Output format")
cobraFields := &cobracli.CSVFlag{}
f.Var(cobraFields, "fields", "Fields to show")
cobracli.Extend(f.Lookup("query"), cobracli.FlagExtra{
Group: "Filters", Placeholder: "text", Complete: "predictor=query", Order: complete.OrderKeep,
})
cobracli.Extend(f.Lookup("format"), cobracli.FlagExtra{
Group: "Output", Placeholder: "format", Enum: []string{"table", "json", "yaml"}, EnumDefault: "table",
})
cobracli.Extend(f.Lookup("fields"), cobracli.FlagExtra{
Complete: "predictor=field,comma",
})
// Auto-grouped help using extras.
root.SetHelpFunc(cobracli.HelpFunc(r, cobracli.Sections))
// Completion flags (hidden).
comp := cobracli.NewCompletion(root)
gen := complete.NewGenerator("catalog").FromFlags(cobracli.FlagMeta(root))
handled, err := comp.Handle(gen, nil)Use Extend to attach clib metadata to urfave/cli flags:
queryFlag := &clilib.StringFlag{Name: "query", Aliases: []string{"q"}, Usage: "Filter results by query"}
formatFlag := &clilib.StringFlag{Name: "format", Aliases: []string{"f"}, Usage: "Output format", Value: "table"}
fieldsFlag := &clilib.GenericFlag{Name: "fields", Usage: "Fields to show", Value: &cliurfave.CSVFlag{}}
cliurfave.Extend(queryFlag, cliurfave.FlagExtra{
Group: "Filters", Placeholder: "text", Complete: "predictor=query", Order: complete.OrderKeep,
})
cliurfave.Extend(formatFlag, cliurfave.FlagExtra{
Group: "Output", Placeholder: "format", Enum: []string{"table", "json", "yaml"}, EnumDefault: "table",
})
cliurfave.Extend(fieldsFlag, cliurfave.FlagExtra{
Complete: "predictor=field,comma",
})
// Custom help using clib themed renderer.
clilib.HelpPrinter = cliurfave.HelpPrinter(r, cliurfave.Sections)
// Completion flags (hidden).
comp := cliurfave.NewCompletion(root)
gen := complete.NewGenerator("catalog").FromFlags(cliurfave.FlagMeta(cmd))
handled, err := comp.Handle(gen, nil)The complete package generates shell completion scripts from flag
metadata. The complete tag (Kong) or FlagExtra.Complete field (Cobra/urfave)
controls completion behavior:
predictor=<name>- dynamic completion via<app> --@complete=<name>comma- comma-separated multi-value modevalues=<space-separated>- static completion values
The terse key provides a very short description for completions (falls back to help).
Use order=keep (Kong) or Order: complete.OrderKeep (Cobra/urfave) to preserve fish completion order for a flag by emitting complete -k.
Use order=shell or Order: complete.OrderShell to force the shell's normal ordering for a flag.
Use complete.WithOrder(complete.OrderKeep) to make keep-order the generator default.
Flags hidden from --help are omitted from completions by default. Use complete-hidden (Kong) or FlagExtra.CompleteHidden (Cobra/urfave) to still offer a specific hidden flag as a completion, or complete.WithIncludeHidden() to offer every hidden flag across the command tree.
// Styled enum with shortcut letters: [text, json, yaml]
th.FmtEnum([]theme.EnumValue{
{Name: "text", Bold: "t"},
{Name: "json", Bold: "j"},
{Name: "yaml", Bold: "y"},
})
// With default annotation: [text, json, yaml] (default: text)
th.FmtEnumDefault("text", []theme.EnumValue{
{Name: "text", Bold: "t"},
{Name: "json", Bold: "j"},
{Name: "yaml", Bold: "y"},
})
// Dim default/note annotations for flag descriptions.
th.DimDefault("30") // (default: 30)
th.DimNote("required") // (required)Render short markdown strings for inline display with themed code spans:
th.RenderMarkdown("Use `--verbose` for debug output")shell := shell.Detect() // COMPLETE_SHELL env -> parent process -> SHELL envWorking examples for each framework adapter are in the examples/ directory: