argp: GNU-style command line argument parser for Go

by networkedon 3/23/2025, 12:45 PMwith 98 comments

by acmjon 3/23/2025, 2:27 PM

In general, command-line argument parsers should just follow the GNU style. No more, no less. Deviations confuse users as it is not immediately obvious to them what rules a parser is imposing.

> options can have multiple values: -a 1 2 3 means that a is an array/slice/struct of three numbers of value [1,2,3]

Allowing multiple values is inconsistent because you can't tell in "./cmd -a 1 2 3" whether 2 and 3 are positional arguments or arguments for -a. This is not a GNU style. The GNU way is "./cmd -a 1 -a 2 -a 3" (or "./cmd -a 1,2,3"). This package supports that, which is good.

> option values can be separated by a space, equal sign, or nothing: -a1 -a=1 -a 1 are all equal

"--a=1" is a GNU style but "-a=1" is not. This is a minor issue, though.

Also, does this package support "--"? Everything following "--" should be treated as positional arguments.

by latchkeyon 3/23/2025, 2:39 PM

Cobra https://github.com/spf13/cobra uses https://github.com/spf13/pflag, which supports GNU style flags. Cobra has been developed for many years now and has a ton of additional features, like automatically generating the autocompletions and has tons of unit tests.

I'd just use cobra.

by CamouflagedKiwion 3/23/2025, 3:58 PM

I've become a fan of https://github.com/jessevdk/go-flags (also enjoyed structopt which is similar for Rust). I much prefer defining the flags statically on a type which stores them after rather than building it all up programmatically.

Otherwise, I'm not really sure what this offers that alternatives don't, apart from the -a 1 2 3 -> [1,2,3] business which seems highly confusing and undesirable to me so I'd think of it as more of an anti-feature.

by edoceoon 3/23/2025, 3:11 PM

I use Kong https://github.com/alecthomas/kong

I does everything, including too complicated options.

by odcon 3/23/2025, 8:04 PM

The standard flag package in Go also supports GNU style flags.

https://pkg.go.dev/flag#hdr-Command_line_flag_syntax

by sandreason 3/23/2025, 3:24 PM

Interesting. I used

https://github.com/urfave/cli

in the past and was pretty happy with it. However sometimes it's good to try something New :-)

by dotemacson 3/23/2025, 3:05 PM

I'm glad that this package exists.

I know of UNIX parameters, with a single hyphen & a single letter, and GNU parameters, with a double parameter and a word. But a single hyphen and then a word: *mind broken*.

When I first saw that on Terraform, I was upset & conflicted.

OK, I know that Java also has mental parameter options like that ('-version', note the *single* hyphen followed by, gasp, a word!), but I just dismissed it as weird enterprise-ism.

Then I saw that this 'single hyphen + word' was an accepted convention for parameters, in the Go world & I was disappointed.

Glad that this package is fighting the good fight.

by reactordevon 3/23/2025, 3:58 PM

Aside from the other comments, an ick I have is that struct tags are being abused here. Instead of providing a grouping like json, yaml, mapstructure, gorm, etc - it just goes willy nilly with struct tags like it owns the whole space. I’d like to see it grouped like…

   type Conf struct {
      Thing string `argp:”name:thing;short:t;desc:A thing you can do”`
   }
This would follow go struct tag standards.

by typon 3/24/2025, 1:54 AM

Maybe the README should mention whether reflection (the part that would disable dead-code elimnation) is used? That was a pain point for me when I had to investigate a binary bloat issue due to reflect.

by d_burfooton 3/23/2025, 3:12 PM

I might be the only person in this camp, but I find the "standard" command line arguments style absolutely repulsive. I write tons of CL code, and I always use easy key=value notation (sometimes it's flag=true, which I consider to be a minor sacrifice of conciseness in favor of consistency and readability).

by friendzison 3/24/2025, 7:11 AM

There's already go implementation for docopt[0]

[0]: https://docopt.org/

by ameliuson 3/23/2025, 2:30 PM

Does it throw an exception when it fails to parse?

by declan_robertson 3/23/2025, 9:00 PM

Assigning values like -v as an int and allowing -vvvv to be easily parsed is a great compatibility feature for existing utils.

by braggerxyzon 3/23/2025, 5:09 PM

I really favor posix style, which is why I use pflags package for my cli Tools.

by namuolon 3/23/2025, 11:19 PM

I have yet to find a cli args solution I enjoy using more than docopt.org

by synergy20on 3/23/2025, 9:21 PM

i hope the below is agreed on, mycmd -h, and mycmd --help, are the same, - for single letter,-- for longer format

same to mycmd -v, mycmd --version

by thrillon 3/23/2025, 3:45 PM

Sanity!

by jmclnxon 3/23/2025, 2:52 PM

If you need long options because you are running out of letters, time for a rewrite :)

by arccyon 3/23/2025, 2:26 PM

> * multiple options can be combined: -abc is the same as -a -b -c

> * option values can be separated by a space, equal sign, or nothing: -a1 -a=1 -a 1 are all equal

> * options can have multiple values: -a 1 2 3 means that a is an array/slice/struct of three numbers of value [1,2,3]

while convenient, one of the reasons I dislike gnu style flags is just how inconsistent they can be and annoyingly hard to parse by humans