https://github.com/mzattahri/argv
A Go command-line library shaped like net/HTTP
https://github.com/mzattahri/argv
cli golang
Last synced: about 1 month ago
JSON representation
A Go command-line library shaped like net/HTTP
- Host: GitHub
- URL: https://github.com/mzattahri/argv
- Owner: mzattahri
- License: mit
- Created: 2026-03-31T22:17:46.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-05-01T16:06:37.000Z (2 months ago)
- Last Synced: 2026-05-01T18:12:38.344Z (2 months ago)
- Topics: cli, golang
- Language: Go
- Homepage: https://mz.attahri.com/code
- Size: 372 KB
- Stars: 6
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# argv
[](https://pkg.go.dev/mz.attahri.com/code/argv)
**`argv` treats the command line as a transport protocol.**
POSIX argv is a wire format: tokens in, structured input out. `argv` handles the
transport. The pipeline mirrors `net/http`; values are strings.
## Quickstart
```go
package main
import (
"context"
"fmt"
"os"
"os/signal"
"mz.attahri.com/code/argv"
)
func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
mux := &argv.Mux{}
mux.Flag("verbose", "v", false, "Verbose output")
greet := &argv.Command{
Description: "Print a greeting",
Run: func(out *argv.Output, call *argv.Call) error {
_, err := fmt.Fprintf(out.Stdout, "hello %s\n", call.Args.Get("name"))
return err
},
}
greet.Arg("name", "Who to greet")
mux.Handle("greet", "Say hello", greet)
(&argv.Program{Summary: "A demo CLI"}).Run(ctx, mux, os.Args)
}
```
```
$ app greet gopher
hello gopher
```
## Subcommands
```go
repo := &argv.Mux{}
repo.Handle("init", "Initialize a repository", initCmd)
repo.Handle("clone", "Clone a repository", cloneCmd)
mux.Handle("repo", "Repository operations", repo)
```
## Middleware
```go
var WithAuth = argv.NewMiddleware(func(out *argv.Output, call *argv.Call, next argv.Runner) error {
if err := checkAuth(call.Context()); err != nil {
return err
}
return next.RunArgv(out, call)
})
mux.Handle("deploy", "Deploy", WithAuth(WithLogging(deployCmd)))
```
## Environment fallback
```go
envMW := argv.EnvMiddleware(map[string]string{
"verbose": "APP_VERBOSE",
"host": "APP_HOST",
}, nil)
mux.Handle("deploy", "Deploy", envMW(deployCmd))
```
## Tab completion
```go
mux.Handle("complete", "Output completions", argv.CompletionCommand(mux))
```
## Introspection
```go
for help, _ := range (&argv.Program{}).Walk("app", mux) {
fmt.Printf("%s: %s\n", help.FullPath, help.Summary)
}
```
## Testing
```go
import "mz.attahri.com/code/argv/argvtest"
recorder := argvtest.NewRecorder()
call := argvtest.NewCall("greet gopher")
err := mux.RunArgv(recorder.Output(), call)
// recorder.Stdout() == "hello gopher\n"
```
See the [package documentation](https://pkg.go.dev/mz.attahri.com/code/argv) for
the full API and godoc examples.