CLI tool
alecthomas/kong avatar
alecthomas/kong

alecthomas/kong: a Go command-line parser driven by struct tags

Kong is a command-line parser for Go

3,185 stars194 forksGoMIT

At a glance

What is it?
Kong maps Go structs and struct tags onto command-line syntax, generating help text from the same definitions. It suits Go authors who want subcommands, positional arguments and configuration files without hand-writing parser code.
Who is it for?
Adopt Kong if your CLI is already describable as nested Go structs and you want help text, configuration loading and validation to fall out of those declarations. Do not adopt it if you need a parser that works from a runtime schema rather than Go types, or if you cannot accept that command dispatch is a switch on a generated command string.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Kong solves for Go CLI authors

Writing a command-line interface in Go usually means choosing between a parser that makes you register every flag imperatively and a struct-based approach that derives the interface from types. Kong takes the second route. The README states its aim directly: to support arbitrarily complex command-line structures with as little developer effort as possible. The structure of the command line lives in Go types, and tags on those fields direct how the parser maps input onto the struct.

The audience is Go developers building tools with subcommands, positional arguments and flags. The README's shell example shows a CLI with rm and ls commands, where rm takes a force flag, a recursive flag and a variadic path argument. That whole shape is expressed in one nested struct. If your tool has a single flat set of flags, Kong is more machinery than the job needs. If it has nested commands with their own arguments, the struct mirrors the command tree and the help text is generated from the same declarations.

How struct tags become flags, commands and arguments

The mapping is tag-driven. In the README example, `Force bool` carries `help:"Force removal."`, `Paths []string` carries `arg:"" name:"path" help:"Paths to remove." type:"path"`, and the enclosing `Rm` struct carries `cmd:"" help:"Remove files."`. A bare `arg:""` marks a positional argument, `optional:""` makes it optional, `cmd:""` turns a struct into a command, and `type:"path"` selects a named decoder for the value.

The README lists supported field types, slices, maps, pointers and nested data structures as first-class concerns, so a `[]string` becomes a repeatable argument and a map becomes a key-value flag. Custom named decoders and custom decoders (mappers) let you take over conversion for types Kong does not handle natively. Variable interpolation applies inside help strings, and validation is a documented feature.

Dispatch is deliberately plain. `kong.Parse()` returns a string representation of the selected command, and the README's example switches on it, with command branches appearing as bare words and required positional arguments wrapped in angle brackets. The alternative is attaching a `Run(...) error` method to each command struct. Hooks named `BeforeReset()`, `BeforeResolve()`, `BeforeApply()` and `AfterApply()` let you run code at defined points in the parse lifecycle, and `Bind()` injects values into `Run()` methods.

Installing Kong and parsing your first command

Kong is a Go module. The repository's go.mod declares the module path as `github.com/alecthomas/kong` and requires Go 1.20. There is no separate installer; you add it to a Go project the usual way. The README's introduction gives the complete example below, which defines a `CLI` variable with an `Rm` command and an `Ls` command and then parses it in `main`.

go
package main

import "github.com/alecthomas/kong"

var CLI struct {
  Rm struct {
    Force     bool `help:"Force removal."`
    Recursive bool `help:"Recursively remove files."`

    Paths []string `arg:"" name:"path" help:"Paths to remove." type:"path"`
  } `cmd:"" help:"Remove files."`

  Ls struct {
    Paths []string `arg:"" optional:"" name:"path" help:"Paths to list." type:"path"`
  } `cmd:"" help:"List paths."`
}

Calling `kong.Parse(&CLI)` returns a context whose `Command()` method gives the selected command string, which the README example switches over. The README shows the resulting help output for this kind of structure: running the application with `--help` prints usage, flags and a list of commands, and `--help rm` prints detail for that command, including its flags and arguments. The README notes that every Kong application includes a `--help` flag automatically.

Where Kong's design constrains you

The command string is the dispatch mechanism, and that is a real constraint. The README's own example ends with a `default` branch that panics when the command does not match a known case. Adding a command means updating the switch as well as the struct, so the type declarations are not the single source of truth for dispatch even though they are for parsing and help.

Help text has its own boundaries. A command's additional help text is not shown in top-level help; it appears only in contextual help such as `--help rm`. Argument-level custom help is narrower still: the README states it is only shown for positional arguments with named fields. If you want rich descriptions on every flag, the `help:""` tag is what you get.

The 1.0.0 release notes describe one breaking change, PR 436, which the README says should affect relatively few users. It does not say what the change was, so anyone upgrading from a pre-1.0 version should read that pull request before bumping. Kong is also Go-only by construction: the parser is built around Go types and tags, so it is the wrong tool if your interface is defined at runtime, generated from a schema, or shared with a non-Go program.

Kong compared with Cobra and urfave/cli

The related searches around this project are dominated by comparisons with spf13/cobra and urfave/cli, and the difference is structural rather than cosmetic. Kong derives the command line from a Go struct and its tags. Cobra is built around explicit `Command` values that you construct and populate with flags, and urfave/cli follows a similar imperative registration model.

That distinction matters in two places. First, help text: Kong generates it from the same tags that define parsing, so the two cannot drift. With imperative registration you write the descriptions alongside the registrations, which is more code but also more freedom to vary phrasing per flag. Second, dispatch: Kong hands you a command string to switch on, while the imperative libraries typically attach a function to each command directly. Kong also documents configuration file loading through `Configuration(loader, paths...)` and default values from external sources through `Resolver(...)`, which is a different posture from parsers that treat flags as the only input.

Kong is not the only struct-tag parser in Go; go-arg appears in the related searches for the same reason. The choice between them comes down to whether you need Kong's command tree, hooks and configuration loading or a smaller surface.

Extending Kong: configuration, resolvers and plugins

Kong exposes its behaviour through options rather than requiring you to fork it. `Name(help)` and `Description(help)` set the application name and description. `Configuration(loader, paths...)` loads defaults from configuration files, which means the same struct fields can be filled from a file and overridden on the command line. `Resolver(...)` supports default values from external sources, so a value can come from an environment or a secret store instead of a literal default in code.

Mappers are the escape hatch for value conversion. The README documents both custom named decoders, selected with `type:"..."` on a field, and custom decoders (mappers) for broader control over how the command line maps to Go values. Help itself is replaceable through `ConfigureHelp(HelpOptions)` and `Help(HelpFunc)`, and `*Mapper(...)` customises the mapping step.

The README also documents plugins and dynamic commands, which matter when the set of commands is not fully known at compile time. Variable interpolation runs inside help strings, so a help tag can reference a value defined elsewhere in the struct. None of this requires code generation: the repository's top-level entries are plain Go source files such as `mapper.go`, `resolver.go`, `help.go` and `model.go`, with no generated parser artifact in the tree.

Licence and maintenance cost

Kong is MIT licensed. The repository carries a COPYING file at the top level, which is where the licence text lives. MIT is permissive: it allows use, modification and redistribution provided the copyright notice and permission notice are preserved. That is a general description of the licence, not legal advice, and anyone embedding Kong in a distributed product should read COPYING and their own organisation's policy rather than relying on a summary.

The last push to the default branch was on 2026-09-15, nine days before this writing, and the repository is not archived. The README describes Kong as having been stable for a long time, which is consistent with a project that reached 1.0.0 and does not churn. Stability cuts both ways for upgrade cost: a stable parser means few forced migrations, but it also means features you want may not arrive. The one documented breaking change in the 1.0.0 notes, PR 436, is the item to check when moving from a pre-1.0 version. The go.mod requires Go 1.20, so the toolchain floor is explicit.

Editorial conclusion

Adopt Kong if your CLI is already describable as nested Go structs and you want help text, configuration loading and validation to fall out of those declarations. Do not adopt it if you need a parser that works from a runtime schema rather than Go types, or if you cannot accept that command dispatch is a switch on a generated command string. Before committing, verify how your existing flags map onto tags, check the behaviour of the 1.0 breaking change referenced as PR 436, and confirm the positional-argument rules for branching arguments match your intended syntax.

Frequently asked questions

How do I install alecthomas/kong in a Go project?

Add it to a Go module as github.com/alecthomas/kong, the module path declared in the repository's go.mod, which also requires Go 1.20. There is no separate installer or CLI binary to download.

Does Kong generate help text automatically?

Yes. Help is generated from the command-line structure itself, including help:"" and other tags, and variables are interpolated into help strings. Every Kong application includes a --help flag, and running it with a command name shows detail for that command.

How does Kong dispatch to the command the user typed?

kong.Parse() returns a unique string representation of the command, and the README example switches on it. Command branches appear as bare words and required positional arguments appear wrapped in angle brackets. Alternatively you can attach a Run(...) error method to each command.

Can Kong load defaults from a configuration file?

The README documents a Configuration(loader, paths...) option that loads defaults from configuration files, and a Resolver(...) option for default values from external sources. Both are listed under the options for modifying Kong's behaviour.

Official sources

  1. alecthomas/kong on GitHub
  2. Issues
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/alecthomas-kong.svg)](https://hysenlabs.com/projects/alecthomas-kong)