Skip to content

Repository files navigation

cli

cli is a minimalist, ergonomic, scalable library for building Go commands with no dependencies outside Go stdlib. Built for ease of use and ease of growth of Go commands.

Go Reference

Usage

Simple example demonstrates subcommands, flag struct tags, error handling, and a simple CLI code management pattern in a single small Go file.

Documentation

Commands document themselves in markdown, from the same synopses, descriptions and options that drive -h:

// a directory of one .md per command, root in README.md
err := root.MarkdownDocs("docs")

// a single .md, for a command with no sub-commands
err := cmd.MarkdownDocs("docs/cmd.md")

// or write a page anywhere
err := cmd.MarkdownDoc(os.Stdout)

MarkdownDocs picks the directory or the single file according to whether the command has sub-commands. Each page carries the command's own options and those it inherits from its parents, minus anything suppressed along the way.

A synopsis written as prose, as in WithSynopsis("o read and write tony"), reads as the line under the title with the command name it repeats taken off. One written as an invocation, as in WithSynopsis("o [opts] command [opts]") or WithSynopsis("cp SRC DST"), is the usage line of the page instead, spelled out from the root command.

Linking to documentation published elsewhere

A Doc adds links to the generated markdown without touching what the command prints for -h, which stays plain text:

cli.NewDoc(root).
	WithSite("https://signadot.github.io/tony-format/").
	WithTerms(cli.Terms{
		"tony format": "/",          // relative to the site
		"tony":        "/",
		"schema":      "/schema/",
		"go-tony":     "https://pkg.go.dev/github.com/signadot/tony-format/go-tony",
	}).
	Write("docs")

A desc='validate against a schema' then reads the same at the terminal and links to https://signadot.github.io/tony-format/schema/ in markdown. Terms match whole words, longest first, case sensitively, once per description, and never inside backticks or a link already written. With a Site set, each page also links to the page for its command there; WithPage says where those live and WithLinkify is the escape hatch for links the term map cannot express.

Status

cli is young but it works. The general design and organisation of the data types has mostly settled but may evolve slightly. May still have some bugs in the corners.

Why

There are lots of cli libraries out there, I've worked with many and I don't like any of them. AFAIK, only cli and kong support struct tags for command line options, which is much less cumbersome. In contrast to Kong, cli is tiny and unobtrusive.

  • Go's stdlib flag only works reasonably for the most rudimentary things and is quite difficult to get basic things working like being able to append a flag to a command line that has arguments already.
  • Cobra/Viper is huge and extremely verbose and seems to constantlly yell "you should ..." when it's just a distraction. It is also much harder to customize.
  • github.com/mitchellh/cli does too much
  • Kong does even more
  • Other attempts at finding a balance between minimalism and expressivity don't seem to hit the mark for expressivity.

About

minimalist scalable ergonomic Go library for CLI's

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages