Skip to main content
Version: Next

AutoCLI

Synopsis

This document details how to build CLI and REST interfaces for a module. Examples from various Cosmos SDK modules are included.

Pre-requisite Readings

The autocli (also known as client/v2) package is a Go library for generating CLI (command line interface) interfaces for Cosmos SDK-based applications. It provides a simple way to add CLI commands to your application by generating them automatically based on your gRPC service definitions. Autocli generates CLI commands and flags directly from your protobuf messages, including options, input parameters, and output parameters. This means that you can easily add a CLI interface to your application without having to manually create and manage commands.

Overview

autocli generates CLI commands and flags for each method defined in your gRPC service. By default, it generates commands for each gRPC services. The commands are named based on the name of the service method.

For example, given the following protobuf definition for a service:

service MyService {
rpc MyMethod(MyRequest) returns (MyResponse) {}
}

For instance, autocli would generate a command named my-method for the MyMethod method. The command will have flags for each field in the MyRequest message.

It is possible to customize the generation of transactions and queries by defining options for each service.

Application Wiring

Here are the steps to use AutoCLI:

  1. Ensure your app's modules implements the appmodule.AppModule interface.
  2. (optional) Configure how to behave as autocli command generation, by implementing the func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions method on the module.
  3. Use the autocli.AppOptions struct to specify the modules you defined. If you are using depinject / app v2, it can automatically create an instance of autocli.AppOptions based on your app's configuration.
  4. Use the EnhanceRootCommand() method provided by autocli to add the CLI commands for the specified modules to your root command.
tip

AutoCLI is additive only, meaning enhancing the root command will only add subcommands that are not already registered. This means that you can use AutoCLI alongside other custom commands within your app.

Here's an example of how to use autocli in your app:

// Define your app's modules
testModules := map[string]appmodule.AppModule{
"testModule": &TestModule{},
}

// Define the autocli AppOptions
autoCliOpts := autocli.AppOptions{
Modules: testModules,
}

// Create the root command
rootCmd := &cobra.Command{
Use: "app",
}

if err := appOptions.EnhanceRootCommand(rootCmd); err != nil {
return err
}

// Run the root command
if err := rootCmd.Execute(); err != nil {
return err
}

Keyring

autocli uses a keyring for key name resolving and signing transactions. Providing a keyring is optional, but if you want to use the autocli generated commands to sign transactions, you must provide a keyring.

tip

This provides a better UX as it allows to resolve key names directly from the keyring in all transactions and commands.

<appd> q bank balances alice
<appd> tx bank send alice bob 1000denom

The keyring to be provided to client/v2 must match the client/v2 keyring interface. The keyring should be provided in the appOptions struct as follows, and can be gotten from the client context:

tip

The Cosmos SDK keyring and Hubl keyring both implement the client/v2/autocli/keyring interface, thanks to the following wrapper:

keyring.NewAutoCLIKeyring(kb)
danger

When using AutoCLI the keyring will only be created once and before any command flag parsing.

// Set the keyring in the appOptions
appOptions.Keyring = keyring

err := autoCliOpts.EnhanceRootCommand(rootCmd)
...

Signing

autocli supports signing transactions with the keyring. The cosmos.msg.v1.signer protobuf annotation defines the signer field of the message. This field is automatically filled when using the --from flag or defining the signer as a positional argument.

danger

AutoCLI currently supports only one signer per transaction.

Module wiring & Customization

The AutoCLIOptions() method on your module allows to specify custom commands, sub-commands or flags for each service, as it was a cobra.Command instance, within the RpcCommandOptions struct. Defining such options will customize the behavior of the autocli command generation, which by default generates a command for each method in your gRPC service.

*autocliv1.RpcCommandOptions{
RpcMethod: "Params", // The name of the gRPC service
Use: "params", // Command usage that is displayed in the help
Short: "Query the parameters of the governance process", // Short description of the command
Long: "Query the parameters of the governance process. Specify specific param types (voting|tallying|deposit) to filter results.", // Long description of the command
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "params_type", Optional: true}, // Transform a flag into a positional argument
},
}
tip

AutoCLI can create a gov proposal of any tx by simply setting the GovProposal field to true in the autocli.RpcCommandOptions struct. Users can however use the --no-proposal flag to disable the proposal creation (which is useful if the authority isn't the gov module on a chain).

Specifying Subcommands

By default, autocli generates a command for each method in your gRPC service. However, you can specify subcommands to group related commands together. To specify subcommands, use the autocliv1.ServiceCommandDescriptor struct.

This example shows how to use the autocliv1.ServiceCommandDescriptor struct to group related commands together and specify subcommands in your gRPC service by defining an instance of autocliv1.ModuleOptions in your autocli.go.

x/gov/autocli.go
loading...

Positional Arguments

By default autocli generates a flag for each field in your protobuf message. However, you can choose to use positional arguments instead of flags for certain fields.

To add positional arguments to a command, use the autocliv1.PositionalArgDescriptor struct, as seen in the example below. Specify the ProtoField parameter, which is the name of the protobuf field that should be used as the positional argument. In addition, if the parameter is a variable-length argument, you can specify the Varargs parameter as true. This can only be applied to the last positional parameter, and the ProtoField must be a repeated field.

Here's an example of how to define a positional argument for the Account method of the auth service:

x/auth/autocli.go
loading...

Then the command can be used as follows, instead of having to specify the --address flag:

<appd> query auth account cosmos1abcd...xyz

Customising Flag Names

By default, autocli generates flag names based on the names of the fields in your protobuf message. However, you can customise the flag names by providing a FlagOptions. This parameter allows you to specify custom names for flags based on the names of the message fields.

For example, if you have a message with the fields test and test1, you can use the following naming options to customise the flags:

autocliv1.RpcCommandOptions{ 
FlagOptions: map[string]*autocliv1.FlagOptions{
"test": { Name: "custom_name", },
"test1": { Name: "other_name", },
},
}

FlagsOptions is defined like sub commands in the AutoCLIOptions() method on your module.

Combining AutoCLI with Other Commands Within A Module

AutoCLI can be used alongside other commands within a module. For example, the gov module uses AutoCLI to generate commands for the query subcommand, but also defines custom commands for the proposer subcommands.

In order to enable this behavior, set in AutoCLIOptions() the EnhanceCustomCommand field to true, for the command type (queries and/or transactions) you want to enhance.

x/gov/autocli.go
loading...

If not set to true, AutoCLI will not generate commands for the module if there are already commands registered for the module (when GetTxCmd() or GetTxCmd() are defined).

Use AutoCLI for non module commands

It is possible to use AutoCLI for non module commands. The trick is still to implement the appmodule.Module interface and append it to the appOptions.ModuleOptions map.

For example, here is how the SDK does it for cometbft gRPC commands:

client/grpc/cmtservice/autocli.go
loading...

Summary

autocli lets you generate CLI to your Cosmos SDK-based applications without any cobra boilerplate. It allows you to easily generate CLI commands and flags from your protobuf messages, and provides many options for customising the behavior of your CLI application.

To further enhance your CLI experience with Cosmos SDK-based blockchains, you can use hubl. hubl is a tool that allows you to query any Cosmos SDK-based blockchain using the new AutoCLI feature of the Cosmos SDK. With hubl, you can easily configure a new chain and query modules with just a few simple commands.

For more information on hubl, including how to configure a new chain and query a module, see the Hubl documentation.