📖 3 min read (~ 600 words).

CLI client

swagger generate cli produces a command-line tool that wraps the generated client: it reads flags and arguments, builds the operation parameters, calls the server, and prints the response. It’s built on cobra and viper, with shell-completion support.

Tip

Source: cli/. Generated with swagger generate cli --spec ./swagger.yml --cli-app-name todoctl. It targets the same spec as auto-configure, so you can run that server and drive it from this CLI.

Command layout

The generated command tree mirrors the spec:

  • the root command holds global flags (--hostname, --scheme, auth tokens);
  • each tag becomes a sub-command (an operation group);
  • each operationId becomes a sub-command under its tag;
  • each path/query parameter becomes a flag; the body becomes a --body JSON flag, with a flag per body field layered on top.

The tag → sub-command mapping is a cobra.Command per group, wiring in one child per operation:

func makeGroupOfOperationsTodosCmd() (*cobra.Command, error) {
	parent := &cobra.Command{
		Use:  "todos",
		Long: ``,
	}

	sub0, err := makeOperationTodosAddOneCmd()
	if err != nil {
		return nil, err
	}
	parent.AddCommand(sub0)

	sub1, err := makeOperationTodosDestroyOneCmd()
	if err != nil {
		return nil, err
	}
	parent.AddCommand(sub1)

	sub2, err := makeOperationTodosFindTodosCmd()
	if err != nil {
		return nil, err
	}
	parent.AddCommand(sub2)

	sub3, err := makeOperationTodosUpdateOneCmd()
	if err != nil {
		return nil, err
	}
	parent.AddCommand(sub3)

	return parent, nil
}

Full source: cli/cli/cli.go

An operation command

Each operationId gets its own command with a RunE that calls the server, plus generated flag registration for its parameters:

func makeOperationTodosAddOneCmd() (*cobra.Command, error) {
	cmd := &cobra.Command{
		Use:   "addOne",
		Short: ``,
		RunE:  runOperationTodosAddOne,
	}

	if err := registerOperationTodosAddOneParamFlags(cmd); err != nil {
		return nil, err
	}

	return cmd, nil
}

Full source: cli/cli/add_one_operation.go

Body parameters are handled two ways at once — a whole-body --body JSON string as a base payload, and a generated flag per field (recursing into sub-definitions) that overrides it. That’s where --item.description comes from:

func registerOperationTodosAddOneBodyParamFlags(cmdPrefix string, cmd *cobra.Command) error {

	var flagBodyName string
	if cmdPrefix == "" {
		flagBodyName = "body"
	} else {
		flagBodyName = fmt.Sprintf("%v.%s", cmdPrefix, "body")
	}

	_ = cmd.PersistentFlags().String(flagBodyName, "", `Optional json string for [body]. `)

	// add flags for body
	if err := registerModelItemFlags(0, "item", cmd); err != nil {
		return err
	}

	return nil
}

Full source: cli/cli/add_one_operation.go

Running it

Drive the auto-configure server with the tool:

$ go run ./cli/cmd/todoctl/main.go --hostname localhost:12345 \
    --x-todolist-token "example token" \
    todos addOne --item.description "hi" --body "{}"
{"description":"hi"}

The path is todoctltodos (the tag) → addOne (the operationId), with --item.description setting a body field.

Config files and completion

Common flags — hostname, scheme, base_path, auth tokens — can live in a config file instead of the command line, loaded via viper from ~/.config/<app>/config.json (or --config, in JSON/YAML/env form):

{
    "hostname": "localhost:12345",
    "scheme": "http",
    "x-todolist-token": "example token"
}

Shell completions (bash, zsh, fish, PowerShell) come for free from cobra:

$ source <(./todoctl completion bash)
Note

The CLI generator is under active development. A few spec shapes aren’t covered yet — arrays/maps in a body, and enums in help text and completions.