如需了解 CLI、gRPC 和 REST 在 Cosmos SDK 应用中如何协同工作的概念性概览,请参阅 CLI、gRPC 与 REST。
概览
autocli 会为你的 gRPC 服务中定义的每个方法生成 CLI 命令和标志。默认情况下,它会为每个 gRPC 服务方法生成一个命令。这些命令的名称基于服务方法名。
例如,给定如下服务的 protobuf 定义:
autocli 包会为 MyMethod 方法生成一个名为 my-method 的命令。该命令会为 MyRequest 消息中的每个字段生成对应的标志。
你也可以通过为每个服务定义选项,自定义交易和查询命令的生成。
应用接线
以下是使用 AutoCLI 的步骤:- 确保你应用中的模块实现了
appmodule.AppModule接口。 - (可选)通过在模块上实现
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions方法,配置autocli在命令生成期间的行为。 - 调用
app.AutoCliOpts()获取一个由模块管理器填充的autocli.AppOptions,然后为其设置ClientCtx以接入 keyring。 - 调用
EnhanceRootCommand(),将生成的 CLI 命令添加到根命令中。
Keyring
AutoCLI 使用client.Context 中的 keyring 来解析密钥名并对交易进行签名。在运行时,它会从命令的活动上下文中读取 keyring(由 PersistentPreRunE 中的 SetCmdClientContextHandler 设置,参见根命令设置),并在内部通过 keyring.NewAutoCLIKeyring 将其适配为 cosmossdk.io/client/v2/autocli/keyring 接口。
如果未提供 keyring,AutoCLI 生成的命令仍然可以查询链,但无法对交易签名。
签名
autocli 支持使用 keyring 对交易进行签名。
cosmos.msg.v1.signer protobuf 注解定义了消息的签名者字段。
使用 --from 标志或将签名者定义为位置参数时,该字段会被自动填充。
模块接线与自定义
模块上的AutoCLIOptions() 方法允许你在 RpcCommandOptions 结构体中像配置 cobra.Command 实例一样,为每个服务指定自定义命令、子命令或标志。定义这些选项后,可以自定义 autocli 的命令生成行为;默认情况下,它会为你的 gRPC 服务中的每个方法生成一个命令。
指定子命令
默认情况下,autocli 会为你的 gRPC 服务中的每个方法生成一个命令。不过,你可以通过指定子命令将相关命令组织在一起。要指定子命令,请使用 autocliv1.ServiceCommandDescriptor 结构体。
如需查看真实示例,请参阅 Cosmos SDK 中 gov 模块的 autocli.go。该文件在同一处演示了 ServiceCommandDescriptor、RpcCommandOptions、PositionalArgs、SubCommands、EnhanceCustomCommand 和 GovProposal 的用法。
位置参数
默认情况下,autocli 会为 protobuf 消息中的每个字段生成一个标志。不过,你也可以选择对某些字段使用位置参数,而不是标志。
要为命令添加位置参数,请使用 autocliv1.PositionalArgDescriptor 结构体,如下面的示例所示。指定 ProtoField 参数,它表示应作为位置参数使用的 protobuf 字段名称。此外,如果该参数是可变长度参数,你可以将 Varargs 参数指定为 true。这只能应用于最后一个位置参数,并且 ProtoField 必须是一个重复字段。
如需查看真实示例,请参阅 Cosmos SDK 中 auth 模块的 autocli.go。它展示了如何为每个查询方法接入位置参数,并将 Account 方法中的 address 设为位置参数。
接入位置参数后,可以像下面这样使用该命令,而不必指定 --address 标志:
位置参数中的扁平化字段
AutoCLI 还支持将嵌套消息字段扁平化为位置参数。这意味着你可以在ProtoField 参数中使用点表示法访问嵌套字段。当你希望直接将嵌套消息字段设置为位置参数时,这项功能尤其有用。
例如,如果你有如下嵌套消息结构:
自定义标志名称
默认情况下,autocli 会根据 protobuf 消息中字段的名称生成标志名。不过,你可以通过提供 FlagOptions 来自定义标志名。该参数允许你根据消息字段名为标志指定自定义名称。
例如,如果你有一个包含 test 和 test1 字段的消息,可以使用以下命名选项来自定义标志:
在模块内将 AutoCLI 与其他命令结合使用
AutoCLI 可以与模块内的其他命令一起使用。例如,gov 模块将 AutoCLI 用于其查询命令,同时仍保留了为 submit-proposal、weighted-vote 等命令手写的 tx 命令。
在每个你希望 AutoCLI 与现有命令并存添加生成命令的 ServiceCommandDescriptor 上设置 EnhanceCustomCommand: true:
EnhanceCustomCommand 未设置为 true,对于任何已经通过 GetTxCmd() 或 GetQueryCmd() 注册了命令的服务,AutoCLI 都会跳过命令生成。
跳过某个命令
AutoCLI 会检查cosmos_proto.method_added_in protobuf 注解,并跳过那些引入版本比当前运行的 SDK 版本更新的命令。
此外,也可以通过 autocliv1.RpcCommandOptions 手动跳过某个命令:
将 AutoCLI 用于非模块命令
也可以将AutoCLI 用于非模块命令。常见模式是在调用 AutoCliOpts() 后,直接将选项添加到 autoCliOpts.ModuleOptions:
AutoCliOpts() 只会提取已注册到模块管理器中的模块;非模块命令始终需要手动添加到 ModuleOptions 中,就像示例链中对 nodeservice.NewNodeCommands() 的处理一样。
如需查看这一模式的更完整示例,请参阅 Cosmos SDK 中的 client/grpc/cmtservice/autocli.go 和 client/grpc/node/autocli.go。
根命令设置
为了让 AutoCLI 生成的命令(以及手写命令)能够正常工作,包括签名交易、查询链和读取配置,根命令必须在PersistentPreRunE 函数中设置 client.Context 和 server.Context。该函数会在每个子命令执行前运行,并使这两个上下文对所有子命令可用。完整示例请参阅 simapp/simd/cmd/root.go。
PersistentPreRun 中有两个关键调用:
SetCmdClientContextHandler会通过ReadPersistentCommandFlags读取持久标志,创建一个client.Context,并将其设置到命令上下文中。这正是 AutoCLI 和手写命令用来签名交易并连接节点的机制。InterceptConfigsPreRunHandler会创建server.Context,从节点 home 目录加载app.toml和config.toml,并将它们绑定到 server context 的 viper 实例上。这使得应用配置在启动时可用。
自定义 logger
默认情况下,InterceptConfigsPreRunHandler 会设置默认的 SDK logger。要使用自定义 logger,请改用 InterceptConfigsAndCreateContext,然后手动设置 logger:
环境变量
每个 CLI flag 都会自动绑定到一个环境变量。该变量名由应用的basename 转为大写后,加上 flag 名称组成,并将 - 替换为 _。例如,对于 basename 为 GAIA 的应用,--node 会绑定到 GAIA_NODE。
这样你就可以预先配置常用 flag,而不用在每次执行命令时都传入:
手写命令
AutoCLI 覆盖的是标准场景:一个 protobuf RPC 方法映射为一个 CLI 命令。对于不符合这一模型的命令,你可以手动编写 Cobra 命令,并通过EnhanceCustomCommand: true 将其与 AutoCLI 结合使用。
需要手动编写命令的常见原因包括:
- 复杂参数解析 — 在构建消息之前,需要对多个位置参数执行自定义校验或 coin 解析
- 跨多个 RPC 调用的命令 — 例如,根据需要先执行查询得到的输入来构建交易
- 非标准 UX — 交互式提示、离线签名流程,或生成输出而不是广播的命令
模式
一个手动交易命令会使用client.GetClientTxContext 获取签名上下文,构造消息,然后将其传给 tx.GenerateOrBroadcastTxCLI:
client.GetClientTxContext(cmd)获取客户端上下文(签名者、节点连接、codec)flags.AddTxFlagsToCmd(cmd)添加标准交易 flag(--from、--fees、--gas等)tx.GenerateOrBroadcastTxCLI同时处理--generate-only(离线)和实时广播模式
For a conceptual overview of how CLI, gRPC, and REST fit together in a Cosmos SDK app, see CLI, gRPC & REST.
Overview
autocli generates CLI commands and flags for each method defined in your gRPC service. By default, it generates a command for each gRPC service method. The commands are named based on the name of the service method.
For example, given the following protobuf definition for a service:
autocli package will 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:- Ensure your app’s modules implement the
appmodule.AppModuleinterface. - (optional) Configure how
autoclibehaves during command generation, by implementing thefunc (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptionsmethod on the module. - Call
app.AutoCliOpts()to get anautocli.AppOptionspopulated from the module manager, then setClientCtxon it to wire in the keyring. - Call
EnhanceRootCommand()to add the generated CLI commands to your root command.
Keyring
AutoCLI resolves key names and signs transactions using the keyring fromclient.Context. At runtime, it reads the keyring from the command’s live context (set by SetCmdClientContextHandler in PersistentPreRunE — see Root Command Setup) and adapts it to the cosmossdk.io/client/v2/autocli/keyring interface via keyring.NewAutoCLIKeyring internally.
If no keyring is provided, AutoCLI-generated commands can still query the chain but cannot sign transactions.
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.
Module wiring & Customization
TheAutoCLIOptions() 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.
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.
For a real-world example, see the gov module’s autocli.go in the Cosmos SDK. It demonstrates ServiceCommandDescriptor with RpcCommandOptions, PositionalArgs, SubCommands, EnhanceCustomCommand, and GovProposal all in one file.
Positional Arguments
By defaultautocli 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.
For a real-world example, see the auth module’s autocli.go in the Cosmos SDK. It shows positional args wired for every query method, with address as a positional argument on the Account method.
After wiring positional args, the command can be used as follows, instead of having to specify the --address flag:
Flattened Fields in Positional Arguments
AutoCLI also supports flattening nested message fields as positional arguments. This means you can access nested fields using dot notation in theProtoField parameter. This is particularly useful when you want to directly set nested
message fields as positional arguments.
For example, if you have a nested message structure like this:
Customizing Flag Names
By default,autocli generates flag names based on the names of the fields in your protobuf message. However, you can customize 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 customize the flags:
Combining AutoCLI with Other Commands Within A Module
AutoCLI can be used alongside other commands within a module. For example, thegov module uses AutoCLI for its query commands while also keeping hand-written tx commands for submit-proposal, weighted-vote, and similar.
Set EnhanceCustomCommand: true on each ServiceCommandDescriptor where you want AutoCLI to add generated commands alongside existing ones:
EnhanceCustomCommand is not set to true, AutoCLI skips command generation for any service that already has commands registered via GetTxCmd() or GetQueryCmd().
Skip a command
AutoCLI checks thecosmos_proto.method_added_in protobuf annotation and skips commands that were introduced in a newer SDK version than the one currently running.
Additionally, a command can be manually skipped using the autocliv1.RpcCommandOptions:
Use AutoCLI for non module commands
It is possible to useAutoCLI for non-module commands. The pattern is to add the options directly to autoCliOpts.ModuleOptions after calling AutoCliOpts():
AutoCliOpts() only picks up modules registered with the module manager — non-module commands always need to be added to ModuleOptions manually, as the example chain does with nodeservice.NewNodeCommands().
For a more complete example of this pattern, see client/grpc/cmtservice/autocli.go and client/grpc/node/autocli.go in the Cosmos SDK.
Root Command Setup
For AutoCLI-generated commands (and hand-written commands) to work correctly — signing transactions, querying the chain, reading configuration — the root command must set up theclient.Context and server.Context in a PersistentPreRunE function. This runs before every subcommand and makes both contexts available to all child commands. See simapp/simd/cmd/root.go for a complete example.
The two key calls inside PersistentPreRun are:
SetCmdClientContextHandlerreads persistent flags viaReadPersistentCommandFlags, creates aclient.Context, and sets it on the command context. This is what AutoCLI and hand-written commands use to sign transactions and connect to a node.InterceptConfigsPreRunHandlercreates theserver.Context, loadsapp.tomlandconfig.tomlfrom the node home directory, and binds them to the server context’s viper instance. This is what makes application configuration available at startup.
Custom logger
By default,InterceptConfigsPreRunHandler sets the default SDK logger. To use a custom logger, use InterceptConfigsAndCreateContext instead and set the logger manually:
Environment Variables
Every CLI flag is automatically bound to an environment variable. The variable name is the app’sbasename in uppercase followed by the flag name, with - replaced by _. For example, --node for an app with basename GAIA binds to GAIA_NODE.
This lets you pre-configure common flags instead of passing them on every command:
Hand-Written Commands
AutoCLI covers the standard case: one protobuf RPC method maps to one CLI command. For commands that don’t fit that model, you can write Cobra commands manually and combine them with AutoCLI usingEnhanceCustomCommand: true.
Common reasons to write a command manually:
- Complex argument parsing — multiple positional args that require custom validation or coin parsing before the message is built
- Commands that span multiple RPC calls — e.g., building a transaction from inputs that require a preceding query
- Non-standard UX — interactive prompts, offline signing flows, or commands that generate output rather than broadcast
Pattern
A manual transaction command usesclient.GetClientTxContext to retrieve the signing context, constructs a message, and passes it to tx.GenerateOrBroadcastTxCLI:
client.GetClientTxContext(cmd)retrieves the client context (signer, node connection, codec)flags.AddTxFlagsToCmd(cmd)adds standard transaction flags (--from,--fees,--gas, etc.)tx.GenerateOrBroadcastTxCLIhandles both--generate-only(offline) and live broadcast modes