golang-spf13-cobra

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
Persona: You are a Go CLI engineer building command trees that feel native to the Unix shell. You design the user-facing surface first, then wire behavior into the right hook.
Modes:
  • Build — creating a new CLI from scratch: follow command tree setup, hook wiring, and flag sections sequentially.
  • Extend — adding subcommands, flags, or completions to an existing CLI: read the current command tree first, then apply changes consistent with the existing structure.
  • Review — auditing an existing CLI: check the Common Mistakes table, verify
    RunE
    usage,
    OutOrStdout()
    , hook chain ordering, and args validation.
角色定位: 你是一名Go CLI工程师,正在构建贴合Unix Shell原生体验的命令树。你先设计用户交互界面,再将行为关联到合适的钩子上。
模式:
  • Build(构建)——从零创建新CLI:依次遵循命令树设置、钩子关联和标志配置流程。
  • Extend(扩展)——为现有CLI添加子命令、标志或自动补全:先查看当前命令树,再根据现有结构进行一致性修改。
  • Review(审查)——审计现有CLI:检查常见错误表格,验证
    RunE
    使用方式、
    OutOrStdout()
    、钩子链顺序以及参数验证情况。

Using spf13/cobra for CLI command trees in Go

在Go中使用spf13/cobra构建CLI命令树

Cobra is the de facto standard for Go CLI applications. It provides the command/subcommand tree, flag parsing (via
pflag
), args validation, shell completion generation, and documentation generation. It does not handle configuration layering — that's viper's job.
Official Resources:
This skill is not exhaustive. Please refer to library documentation and code examples for more information. Context7 can help as a discoverability platform.
bash
go get github.com/spf13/cobra@latest
Cobra是Go CLI应用的事实标准。它提供命令/子命令树、标志解析(基于
pflag
)、参数验证、Shell自动补全生成以及文档生成功能。它处理配置分层——这是viper的职责。
官方资源:
本技能内容并非详尽无遗。如需更多信息,请参考库文档和代码示例。Context7可作为发现平台提供帮助。
bash
go get github.com/spf13/cobra@latest

Cobra vs. viper

Cobra与viper对比

These libraries do fundamentally different things and can be used independently.
Concerncobraviper
OwnsCommand tree, flags, arg validation, completionsConfiguration value resolution
User-facing?Yes — subcommands, flags, help textNo — purely a key-value resolver
Without the other?Yes — a CLI with flags only needs cobraYes — a daemon reading YAML + env needs only viper
Integration seamHands
pflag.Flag
to viper via
BindPFlag
Treats the cobra flag as the highest-precedence layer
Use cobra alone when your binary takes flags and args but needs no config file or env resolution. Use viper alone when you have a long-running service reading config from YAML + env with no CLI subcommands. Use both when you need both — bind at
PersistentPreRunE
on the root command.
→ See
samber/cc-skills-golang@golang-spf13-viper
for the viper side of this integration.
这两个库的核心功能完全不同,可独立使用。
关注点cobraviper
负责内容命令树、标志、参数验证、自动补全配置值解析
是否面向用户?是——子命令、标志、帮助文本否——纯键值解析器
可独立使用吗?是——仅含标志的CLI只需cobra是——读取YAML+环境变量的守护进程只需viper
集成方式通过
BindPFlag
pflag.Flag
传递给viper
将cobra标志视为最高优先级层级
单独使用cobra:当你的二进制文件仅接收标志和参数,无需配置文件或环境变量解析时。单独使用viper:当你有一个长期运行的服务,仅需从YAML+环境变量读取配置,无需CLI子命令时。当两者都需要时同时使用——在根命令的
PersistentPreRunE
中进行绑定。
→ 如需了解该集成的viper部分,请查看
samber/cc-skills-golang@golang-spf13-viper

Command tree

命令树

Every cobra CLI has a root command plus zero or more subcommands registered with
AddCommand
. The root command name is the binary name.
go
var rootCmd = &cobra.Command{
    Use:          "myapp",
    Short:        "One-line summary",
    SilenceUsage: true,  // ✓ prevents usage wall on every error
    SilenceErrors: true, // ✓ lets you control error output format
}
Use
AddGroup
to label subcommands in help output — register groups before the
AddCommand
calls that reference them; cobra does not retroactively assign groups.
每个cobra CLI都包含一个根命令,以及零个或多个通过
AddCommand
注册的子命令。根命令名称即为二进制文件名称。
go
var rootCmd = &cobra.Command{
    Use:          "myapp",
    Short:        "One-line summary",
    SilenceUsage: true,  // ✓ 避免每次出错都显示大量使用说明
    SilenceErrors: true, // ✓ 让你可以控制错误输出格式
}
使用
AddGroup
在帮助输出中为子命令添加分组标签——请在调用引用分组的
AddCommand
之前先注册分组;cobra不会追溯分配分组。

The Run* family

Run*系列钩子

Cobra commands have five run hooks executed in order:
PersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE
Always use
*E
variants — the non-
E
forms cannot return errors. Key rules:
  • PersistentPreRunE
    on the root runs before every subcommand — use it for config init and auth checks.
  • A child
    PersistentPreRunE
    replaces the parent's entirely — call the parent explicitly if you need both.
  • PostRunE
    runs only if
    RunE
    succeeded.
For the full lifecycle and inheritance rules, see commands-and-args.md.
Cobra命令有五个按顺序执行的运行钩子:
PersistentPreRunE → PreRunE → RunE → PostRunE → PersistentPostRunE
始终使用
*E
变体——非
E
形式无法返回错误。核心规则:
  • 根命令的
    PersistentPreRunE
    会在每个子命令之前运行——可用于配置初始化和身份验证检查。
  • 子命令的
    PersistentPreRunE
    完全替换父命令的钩子——如果需要同时执行两者,请显式调用父命令的钩子。
  • PostRunE
    仅在
    RunE
    执行成功后才会运行。
如需了解完整生命周期和继承规则,请查看commands-and-args.md

Args validators

参数验证器

Cobra validates positional arguments before
RunE
runs. Never write
len(args)
checks inside
RunE
— that bypasses cobra's standard error messages and arg count tracking.
Built-ins:
NoArgs
,
ExactArgs(n)
,
MinimumNArgs(n)
,
MaximumNArgs(n)
,
RangeArgs(min,max)
,
OnlyValidArgs
,
ExactValidArgs(n)
. Compose with
MatchAll(v1, v2)
. Custom validator:
func(cmd *cobra.Command, args []string) error
.
For the full validator set with examples and
MatchAll
patterns, see commands-and-args.md.
Cobra会在
RunE
运行之前验证位置参数。永远不要在
RunE
内部编写
len(args)
检查——这会绕过cobra的标准错误消息和参数计数跟踪。
内置验证器:
NoArgs
ExactArgs(n)
MinimumNArgs(n)
MaximumNArgs(n)
RangeArgs(min,max)
OnlyValidArgs
ExactValidArgs(n)
。可通过
MatchAll(v1, v2)
组合使用。自定义验证器:
func(cmd *cobra.Command, args []string) error
如需查看完整的验证器集合、示例及
MatchAll
模式,请查看commands-and-args.md

Flags primer

标志入门

Cobra delegates flag parsing to
pflag
. Persistent flags (
PersistentFlags()
) are inherited by all subcommands; local flags (
Flags()
) apply only to the declaring command.
go
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file path") // inherited by all subcommands
serveCmd.Flags().IntVar(&port, "port", 8080, "listen port")                     // local to serveCmd only
serveCmd.MarkFlagRequired("port")
serveCmd.MarkFlagsMutuallyExclusive("json", "yaml")
For pflag types, custom flag values, flag groups, and viper binding, see flags.md.
Cobra将标志解析委托给
pflag
全局标志
PersistentFlags()
)会被所有子命令继承;局部标志
Flags()
)仅适用于声明该标志的命令。
go
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file path") // 被所有子命令继承
serveCmd.Flags().IntVar(&port, "port", 8080, "listen port")                     // 仅适用于serveCmd
serveCmd.MarkFlagRequired("port")
serveCmd.MarkFlagsMutuallyExclusive("json", "yaml")
如需了解pflag类型、自定义标志值、标志组及viper绑定,请查看flags.md

Completions primer

自动补全入门

Cobra generates shell completions automatically. Extend them with:
  • ValidArgs []string
    — static positional arg completion.
  • ValidArgsFunction
    — dynamic:
    func(cmd, args, toComplete string) ([]string, ShellCompDirective)
    . Return
    ShellCompDirectiveNoFileComp
    to suppress file fallback.
  • RegisterFlagCompletionFunc(name, fn)
    — flag value completion.
For
ShellCompDirective
values, annotations, and testing, see completions.md.
Cobra会自动生成Shell自动补全。可通过以下方式扩展:
  • ValidArgs []string
    —— 静态位置参数补全。
  • ValidArgsFunction
    —— 动态补全:
    func(cmd, args, toComplete string) ([]string, ShellCompDirective)
    。返回
    ShellCompDirectiveNoFileComp
    可禁用文件补全回退。
  • RegisterFlagCompletionFunc(name, fn)
    —— 标志值补全。
如需了解
ShellCompDirective
取值、注解及测试,请查看completions.md

Testing commands

命令测试

Test commands by executing them programmatically. Never use
os.Stdout
/
os.Stderr
directly
in command handlers — use
cmd.OutOrStdout()
/
cmd.ErrOrStderr()
so tests can redirect output.
go
func TestServeCmd(t *testing.T) {
    buf := new(bytes.Buffer)
    rootCmd.SetOut(buf)
    rootCmd.SetArgs([]string{"serve", "--port", "9090"})
    require.NoError(t, rootCmd.Execute())
    assert.Contains(t, buf.String(), "listening on :9090")
}
Cobra accumulates flag state across
Execute()
calls — build a fresh command tree per test. For isolation patterns, golden files, and testing completions, see testing.md.
通过编程方式执行命令进行测试。永远不要在命令处理程序中直接使用
os.Stdout
/
os.Stderr
——使用
cmd.OutOrStdout()
/
cmd.ErrOrStderr()
,以便测试时可以重定向输出。
go
func TestServeCmd(t *testing.T) {
    buf := new(bytes.Buffer)
    rootCmd.SetOut(buf)
    rootCmd.SetArgs([]string{"serve", "--port", "9090"})
    require.NoError(t, rootCmd.Execute())
    assert.Contains(t, buf.String(), "listening on :9090")
}
Cobra会在多次
Execute()
调用之间累积标志状态——每次测试都要构建全新的命令树。如需了解隔离模式、黄金文件及自动补全测试,请查看testing.md

Best Practices

最佳实践

  1. Always use
    RunE
    , never
    Run
    Run
    cannot return an error; the only escape is
    os.Exit
    or panic, bypassing defers.
  2. Put config initialization in
    PersistentPreRunE
    — it runs before every subcommand; the right place for viper binding and auth checks.
  3. Validate positional args with
    Args
    , not inside
    RunE
    Args
    gives cobra's standard error messages;
    MatchAll
    composes validators.
  4. Use
    cmd.OutOrStdout()
    /
    cmd.ErrOrStderr()
    for all output
    — direct
    os.Stdout
    writes cannot be captured by tests.
  5. Re-create the command tree per test — cobra accumulates flag state across
    Execute()
    calls on the same instance.
  1. 始终使用
    RunE
    ,绝不使用
    Run
    ——
    Run
    无法返回错误;唯一的退出方式是
    os.Exit
    或panic,会跳过defer语句。
  2. 将配置初始化放在
    PersistentPreRunE
    —— 它会在每个子命令之前运行,是viper绑定和身份验证检查的合适位置。
  3. 使用
    Args
    验证位置参数,而非在
    RunE
    内部
    ——
    Args
    会提供cobra的标准错误消息;
    MatchAll
    可组合多个验证器。
  4. 所有输出都使用
    cmd.OutOrStdout()
    /
    cmd.ErrOrStderr()
    —— 直接写入
    os.Stdout
    的内容无法被测试捕获。
  5. 每次测试重新创建命令树 —— Cobra会在同一实例的多次
    Execute()
    调用之间累积标志状态。

Common Mistakes

常见错误

MistakeWhy it failsFix
Using
Run
instead of
RunE
Cannot return an error — only escape is
os.Exit
or panic, bypassing defers
Use
RunE
— return the error, let cobra handle the exit
Writing
len(args)
checks in
RunE
Bypasses cobra's standard error messages ("accepts 1 arg, received 2")Declare
Args: cobra.ExactArgs(1)
on the command
Writing to
os.Stdout
directly
Tests cannot capture output — os-level file handles can't be redirectedUse
cmd.OutOrStdout()
/
cmd.ErrOrStderr()
Child
PersistentPreRunE
silently drops parent's
Cobra does not chain — the child replaces the parent's hook entirelyCall
parent.PersistentPreRunE(cmd, args)
from the child's hook
Reusing a root command across testsCobra accumulates flag state; second
Execute()
sees flags from the first
Build a fresh command tree per test
错误行为失败原因修复方案
使用
Run
而非
RunE
无法返回错误;只能通过
os.Exit
或panic退出,会跳过defer语句
使用
RunE
——返回错误,让cobra处理退出逻辑
RunE
内部编写
len(args)
检查
绕过了cobra的标准错误消息(如“接受1个参数,实际收到2个”)在命令上声明
Args: cobra.ExactArgs(1)
直接写入
os.Stdout
测试无法捕获输出——操作系统级别的文件句柄无法重定向使用
cmd.OutOrStdout()
/
cmd.ErrOrStderr()
子命令的
PersistentPreRunE
静默覆盖父命令的钩子
Cobra不会链式执行——子命令会完全替换父命令的钩子在子命令的钩子中显式调用
parent.PersistentPreRunE(cmd, args)
跨测试重用根命令Cobra会累积标志状态;第二次
Execute()
会看到第一次的标志
每次测试都构建全新的命令树

Further Reading

扩展阅读

  • commands-and-args.md — full PreRun*/PostRun* chain, every Args validator, PersistentPreRunE inheritance rules
  • flags.md — pflag types, required/exclusive/oneRequired groups, custom value types, viper binding
  • completions.md — ShellCompDirective set, annotation-based completions, testing completions
  • generators.md — man page, markdown, YAML, RST doc generation;
    cobra-cli
    scaffolder
  • testing.md — isolation patterns, golden files, testing completions, table-driven command tests
  • commands-and-args.md —— 完整的PreRun*/PostRun*钩子链、所有参数验证器、PersistentPreRunE继承规则
  • flags.md —— pflag类型、必填/互斥/单选必填标志组、自定义值类型、viper绑定
  • completions.md —— ShellCompDirective取值、基于注解的自动补全、自动补全测试
  • generators.md —— 手册页、Markdown、YAML、RST文档生成;
    cobra-cli
    脚手架工具
  • testing.md —— 隔离模式、黄金文件、自动补全测试、表格驱动命令测试

Cross-References

交叉引用

  • → See
    samber/cc-skills-golang@golang-cli
    skill for general CLI architecture — project layout, exit codes, signal handling, I/O patterns
  • → See
    samber/cc-skills-golang@golang-spf13-viper
    skill for configuration layering alongside cobra (flag → env → file → default precedence)
  • → See
    samber/cc-skills-golang@golang-testing
    skill for general Go testing patterns
If you encounter a bug or unexpected behavior in spf13/cobra, open an issue at https://github.com/spf13/cobra/issues.
  • → 如需了解通用CLI架构(项目布局、退出码、信号处理、I/O模式),请查看
    samber/cc-skills-golang@golang-cli
    技能
  • → 如需结合cobra实现配置分层(标志→环境变量→文件→默认值优先级),请查看
    samber/cc-skills-golang@golang-spf13-viper
    技能
  • → 如需了解通用Go测试模式,请查看
    samber/cc-skills-golang@golang-testing
    技能
如果在使用spf13/cobra时遇到bug或意外行为,请在https://github.com/spf13/cobra/issues提交问题。