go-cobra
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCobra CLI Framework Skill
Cobra CLI框架技能
Write, scaffold, and debug Go CLI applications using the spf13/cobra library. Use this skill whenever the user wants to build a command-line interface in Go, add commands/subcommands to a CLI, work with flags (persistent, local, required), implement shell completions, generate documentation, or asks anything about cobra-based CLI development -- even if they just say "I want to build a CLI tool" or "how do I add commands to my Go app".
使用spf13/cobra库编写、搭建脚手架和调试Go CLI应用。当用户想要用Go构建命令行界面、为CLI添加命令/子命令、处理标志(持久化、本地、必填)、实现Shell补全、生成文档,或者询问任何基于Cobra的CLI开发相关问题时——哪怕他们只是说“我想构建一个CLI工具”或“如何在我的Go应用中添加命令”,都可以使用本技能。
Quick Start
快速开始
Installation
安装
bash
go get -u github.com/spf13/cobra@latestFor the CLI generator (optional but recommended for scaffolding):
bash
go install github.com/spf13/cobra-cli@latestbash
go get -u github.com/spf13/cobra@latest对于CLI生成器(可选,但推荐用于搭建脚手架):
bash
go install github.com/spf13/cobra-cli@latestProject Structure
项目结构
myapp/
cmd/
root.go # Root command and Execute()
version.go # Additional commands
serve.go
main.go # Just calls cmd.Execute()myapp/
cmd/
root.go # 根命令和Execute()方法
version.go # 额外命令
serve.go
main.go # 仅调用cmd.Execute()Minimal main.go
最简main.go
go
package main
import "myapp/cmd"
func main() {
cmd.Execute()
}go
package main
import "myapp/cmd"
func main() {
cmd.Execute()
}Minimal root.go
最简root.go
go
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "myapp",
Short: "A brief description of your application",
Long: `A longer description that spans multiple lines.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hello from myapp!")
},
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}go
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "myapp",
Short: "应用简要描述",
Long: `跨多行的完整描述。`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hello from myapp!")
},
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}Core Concepts
核心概念
Commands represent actions. Args are things. Flags modify behavior.
Pattern:
APPNAME COMMAND ARG --FLAGExamples:
- — "server" is command, "port" is flag
hugo server --port=1313 - — "clone" is command, "URL" is arg, "bare" is flag
git clone URL --bare
**Commands(命令)**代表操作,**Args(参数)**是操作对象,**Flags(标志)**用于修改行为。
模式:
APPNAME COMMAND ARG --FLAG示例:
- — "server"是命令,"port"是标志
hugo server --port=1313 - — "clone"是命令,"URL"是参数,"bare"是标志
git clone URL --bare
Command Structure
命令结构
Creating Commands
创建命令
go
var serveCmd = &cobra.Command{
Use: "serve", // How to call it
Short: "Start the server", // One-line help
Long: `Detailed description here...`, // Full help text
Example: ` myapp serve --port 8080`, // Usage examples
Run: func(cmd *cobra.Command, args []string) {
// Command logic here
},
}
func init() {
rootCmd.AddCommand(serveCmd)
}go
var serveCmd = &cobra.Command{
Use: "serve", // 调用方式
Short: "启动服务器", // 一行简短帮助
Long: `此处为详细描述...`, // --help显示的完整描述
Example: ` myapp serve --port 8080`, // 使用示例(缩进2个空格)
Run: func(cmd *cobra.Command, args []string) {
// 命令逻辑
},
}
func init() {
rootCmd.AddCommand(serveCmd)
}Key Command Fields
命令关键字段
| Field | Purpose |
|---|---|
| Usage pattern: |
| Alternative names: |
| Brief description for help listings |
| Full description for |
| Usage examples (indent with 2 spaces) |
| The actual command logic |
| Same as Run but returns error |
| Positional argument validation |
| Static list for shell completion |
| Dynamic completion function |
| Hide from help output |
| Mark as deprecated with message |
| Version string (enables --version) |
| 字段 | 用途 |
|---|---|
| 使用格式: |
| 别名: |
| 帮助列表中的简要描述 |
| |
| 使用示例(缩进2个空格) |
| 实际命令逻辑 |
| 与Run功能相同,但返回错误 |
| 位置参数验证 |
| Shell补全的静态列表 |
| 动态补全函数 |
| 在帮助输出中隐藏命令 |
| 将命令标记为已废弃并附带提示信息 |
| 版本字符串(启用--version标志) |
Run vs RunE
Run与RunE的区别
Use when you need to return errors to the caller:
RunEgo
var tryCmd = &cobra.Command{
Use: "try",
Short: "Try something",
RunE: func(cmd *cobra.Command, args []string) error {
if err := doSomething(); err != nil {
return err // Error handled by Cobra
}
return nil
},
}当你需要向调用者返回错误时,使用:
RunEgo
var tryCmd = &cobra.Command{
Use: "try",
Short: "尝试执行操作",
RunE: func(cmd *cobra.Command, args []string) error {
if err := doSomething(); err != nil {
return err // 由Cobra处理错误
}
return nil
},
}Flags
标志
Flag Types
标志类型
Persistent Flags — Available to this command AND all subcommands:
go
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file path")
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")Local Flags — Only for this specific command:
go
serveCmd.Flags().IntVarP(&port, "port", "p", 8080, "port to listen on")
serveCmd.Flags().StringVar(&host, "host", "localhost", "host address")持久化标志 — 对当前命令及其所有子命令生效:
go
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "配置文件路径")
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "详细输出")本地标志 — 仅对当前特定命令生效:
go
serveCmd.Flags().IntVarP(&port, "port", "p", 8080, "监听端口")
serveCmd.Flags().StringVar(&host, "host", "localhost", "主机地址")Flag Methods
标志方法
| Method | Example |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| 方法 | 示例 |
|---|---|
| |
| |
| |
| |
| |
| |
| |
Required Flags
必填标志
go
cmd.Flags().StringVarP(®ion, "region", "r", "", "AWS region")
cmd.MarkFlagRequired("region")
// For persistent flags
cmd.MarkPersistentFlagRequired("config")go
cmd.Flags().StringVarP(®ion, "region", "r", "", "AWS区域")
cmd.MarkFlagRequired("region")
// 持久化标志设置为必填
cmd.MarkPersistentFlagRequired("config")Flag Groups
标志组
go
// Must be used together
cmd.MarkFlagsRequiredTogether("username", "password")
// Cannot be used together
cmd.MarkFlagsMutuallyExclusive("json", "yaml")
// At least one required
cmd.MarkFlagsOneRequired("json", "yaml")
// Exactly one required (combine both)
cmd.MarkFlagsOneRequired("json", "yaml")
cmd.MarkFlagsMutuallyExclusive("json", "yaml")go
// 必须同时使用
cmd.MarkFlagsRequiredTogether("username", "password")
// 不能同时使用
cmd.MarkFlagsMutuallyExclusive("json", "yaml")
// 至少需要指定一个
cmd.MarkFlagsOneRequired("json", "yaml")
// 必须且只能指定一个(组合上述两个方法)
cmd.MarkFlagsOneRequired("json", "yaml")
cmd.MarkFlagsMutuallyExclusive("json", "yaml")Count Flags (Verbosity Pattern)
计数标志(详细度模式)
go
var verbose int
func init() {
rootCmd.PersistentFlags().CountVarP(&verbose, "verbose", "v", "verbosity (-v, -vv, -vvv)")
}
// Usage:
// myapp -v → verbose = 1
// myapp -vv → verbose = 2
// myapp -vvv → verbose = 3go
var verbose int
func init() {
rootCmd.PersistentFlags().CountVarP(&verbose, "verbose", "v", "详细度(-v, -vv, -vvv)")
}
// 使用方式:
// myapp -v → verbose = 1
// myapp -vv → verbose = 2
// myapp -vvv → verbose = 3Positional Arguments
位置参数
Built-in Validators
内置验证器
go
cmd.Args = cobra.NoArgs // No args allowed
cmd.Args = cobra.ArbitraryArgs // Any args (default)
cmd.Args = cobra.MinimumNArgs(1) // At least N
cmd.Args = cobra.MaximumNArgs(3) // At most N
cmd.Args = cobra.ExactArgs(2) // Exactly N
cmd.Args = cobra.RangeArgs(1, 3) // Between min and max
cmd.Args = cobra.OnlyValidArgs // Only from ValidArgs listgo
cmd.Args = cobra.NoArgs // 不允许传递参数
cmd.Args = cobra.ArbitraryArgs // 允许任意参数(默认)
cmd.Args = cobra.MinimumNArgs(1) // 至少传递N个参数
cmd.Args = cobra.MaximumNArgs(3) // 最多传递N个参数
cmd.Args = cobra.ExactArgs(2) // 必须传递恰好N个参数
cmd.Args = cobra.RangeArgs(1, 3) // 参数数量在最小值和最大值之间
cmd.Args = cobra.OnlyValidArgs // 只能是ValidArgs列表中的值Combining Validators
组合验证器
go
cmd.Args = cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs)go
cmd.Args = cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs)Custom Validator
自定义验证器
go
cmd.Args = func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("requires at least 1 arg")
}
if !isValidInput(args[0]) {
return fmt.Errorf("invalid argument: %s", args[0])
}
return nil
}go
cmd.Args = func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("至少需要1个参数")
}
if !isValidInput(args[0]) {
return fmt.Errorf("无效参数: %s", args[0])
}
return nil
}Lifecycle Hooks
生命周期钩子
Hooks execute in this order:
- (inherited by children)
PersistentPreRun PreRunRunPostRun- (inherited by children)
PersistentPostRun
go
var rootCmd = &cobra.Command{
Use: "app",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
// Runs before every command (including subcommands)
initLogging()
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
// Runs after every command
cleanup()
},
}
var subCmd = &cobra.Command{
Use: "sub",
PreRun: func(cmd *cobra.Command, args []string) {
// Only for this command, before Run
},
Run: func(cmd *cobra.Command, args []string) {
// Main logic
},
}Use variants to return errors:
*RunEgo
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initConfig()
}钩子执行顺序:
- (被子命令继承)
PersistentPreRun PreRunRunPostRun- (被子命令继承)
PersistentPostRun
go
var rootCmd = &cobra.Command{
Use: "app",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
// 在所有命令(包括子命令)执行前运行
initLogging()
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
// 在所有命令执行后运行
cleanup()
},
}
var subCmd = &cobra.Command{
Use: "sub",
PreRun: func(cmd *cobra.Command, args []string) {
// 仅在当前命令执行前运行
},
Run: func(cmd *cobra.Command, args []string) {
// 主逻辑
},
}使用变体返回错误:
*RunEgo
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initConfig()
}Viper Integration
Viper集成
Cobra integrates seamlessly with Viper for configuration management. See references/viper-integration.md for complete documentation.
go
import "github.com/spf13/viper"
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file")
rootCmd.PersistentFlags().String("author", "Me", "author name")
// Bind flag to viper - priority: flag > env > config > default
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
}
func initConfig() {
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
home, _ := os.UserHomeDir()
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".myapp")
}
viper.AutomaticEnv()
viper.ReadInConfig()
}
// IMPORTANT: Use viper.GetString("author"), not the flag variable
// Flag variables are NOT updated from config file valuesCobra可与Viper无缝集成进行配置管理。完整文档请参考**references/viper-integration.md**。
go
import "github.com/spf13/viper"
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "配置文件")
rootCmd.PersistentFlags().String("author", "我", "作者名称")
// 将标志绑定到Viper - 优先级:标志 > 环境变量 > 配置文件 > 默认值
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
}
func initConfig() {
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
home, _ := os.UserHomeDir()
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".myapp")
}
viper.AutomaticEnv()
viper.ReadInConfig()
}
// 重要提示:使用viper.GetString("author"),而非标志变量
// 标志变量不会从配置文件值中更新Help & Usage
帮助与使用
Automatic Features
自动功能
- /
--helpflag added automatically-h - subcommand added when you have subcommands
help - Typo suggestions: → "Did you mean 'server'?"
myapp srever
- 自动添加/
--help标志-h - 当存在子命令时自动添加子命令
help - 拼写错误建议:→ "你是不是想输入'server'?"
myapp srever
Customization
自定义配置
go
// Custom help template
cmd.SetHelpTemplate(`Custom help: {{.Use}}`)
// Custom usage template
cmd.SetUsageTemplate(`Usage: {{.UseLine}}`)
// Custom help function
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
fmt.Println("Custom help!")
})
// Disable suggestions
cmd.DisableSuggestions = true
// Adjust suggestion distance
cmd.SuggestionsMinimumDistance = 1go
// 自定义帮助模板
cmd.SetHelpTemplate(`自定义帮助: {{.Use}}`)
// 自定义使用模板
cmd.SetUsageTemplate(`使用方式: {{.UseLine}}`)
// 自定义帮助函数
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
fmt.Println("自定义帮助!")
})
// 禁用建议功能
cmd.DisableSuggestions = true
// 调整建议匹配的最小距离
cmd.SuggestionsMinimumDistance = 1Version Flag
版本标志
go
var rootCmd = &cobra.Command{
Use: "myapp",
Version: "1.0.0", // Enables --version flag
}
// Custom version template
cmd.SetVersionTemplate(`Version: {{.Version}}`)go
var rootCmd = &cobra.Command{
Use: "myapp",
Version: "1.0.0", // 启用--version标志
}
// 自定义版本模板
cmd.SetVersionTemplate(`版本: {{.Version}}`)Grouping Commands
命令分组
go
rootCmd.AddGroup(&cobra.Group{ID: "core", Title: "Core Commands:"})
rootCmd.AddGroup(&cobra.Group{ID: "util", Title: "Utility Commands:"})
serveCmd.GroupID = "core"
versionCmd.GroupID = "util"go
rootCmd.AddGroup(&cobra.Group{ID: "core", Title: "核心命令:"})
rootCmd.AddGroup(&cobra.Group{ID: "util", Title: "工具命令:"})
serveCmd.GroupID = "core"
versionCmd.GroupID = "util"Shell Completions
Shell补全
Cobra automatically provides a command. For detailed shell completion implementation, see .
completionreferences/completions.mdQuick usage:
bash
undefinedCobra自动提供命令。Shell补全的详细实现请参考。
completionreferences/completions.md快速使用:
bash
undefinedBash
Bash
source <(myapp completion bash)
source <(myapp completion bash)
Zsh
Zsh
myapp completion zsh > "${fpath[1]}/_myapp"
myapp completion zsh > "${fpath[1]}/_myapp"
Fish
Fish
myapp completion fish > ~/.config/fish/completions/myapp.fish
myapp completion fish > ~/.config/fish/completions/myapp.fish
PowerShell
PowerShell
myapp completion powershell | Out-String | Invoke-Expression
undefinedmyapp completion powershell | Out-String | Invoke-Expression
undefinedDynamic Completions
动态补全
go
cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return []cobra.Completion{"option1", "option2"}, cobra.ShellCompDirectiveNoFileComp
}go
cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return []cobra.Completion{"option1", "option2"}, cobra.ShellCompDirectiveNoFileComp
}Documentation Generation
文档生成
Cobra can generate man pages, markdown, and more. See for details.
references/docgen.mdQuick example:
go
import "github.com/spf13/cobra/doc"
// Markdown
doc.GenMarkdownTree(rootCmd, "./docs")
// Man pages
header := &doc.GenManHeader{Title: "MYAPP", Section: "1"}
doc.GenManTree(rootCmd, header, "./man")Cobra可生成手册页、Markdown等格式文档。详情请参考。
references/docgen.md快速示例:
go
import "github.com/spf13/cobra/doc"
// Markdown格式
doc.GenMarkdownTree(rootCmd, "./docs")
// 手册页
header := &doc.GenManHeader{Title: "MYAPP", Section: "1"}
doc.GenManTree(rootCmd, header, "./man")Creating Plugins
插件开发
For tools like kubectl that use plugins ( called as ):
kubectl-mypluginkubectl myplugingo
rootCmd := &cobra.Command{
Use: "kubectl-myplugin",
Annotations: map[string]string{
cobra.CommandDisplayNameAnnotation: "kubectl myplugin",
},
}对于像kubectl这样支持插件的工具(可通过调用):
kubectl-mypluginkubectl myplugingo
rootCmd := &cobra.Command{
Use: "kubectl-myplugin",
Annotations: map[string]string{
cobra.CommandDisplayNameAnnotation: "kubectl myplugin",
},
}Global Settings
全局设置
go
// Enable case-insensitive command matching
cobra.EnableCaseInsensitive = true
// Enable prefix matching (dangerous for production)
cobra.EnablePrefixMatching = true
// Execute all parent hooks (not just first found)
cobra.EnableTraverseRunHooks = true
// Disable command sorting in help
cobra.EnableCommandSorting = falsego
// 启用命令大小写不敏感匹配
cobra.EnableCaseInsensitive = true
// 启用前缀匹配(生产环境不推荐)
cobra.EnablePrefixMatching = true
// 执行所有父级钩子(而非仅第一个找到的)
cobra.EnableTraverseRunHooks = true
// 禁用帮助中的命令排序
cobra.EnableCommandSorting = falseTesting Commands
命令测试
go
func TestServeCommand(t *testing.T) {
cmd := rootCmd
// Capture output
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetErr(buf)
// Set args
cmd.SetArgs([]string{"serve", "--port", "9000"})
// Execute
err := cmd.Execute()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// Check output
if !strings.Contains(buf.String(), "expected") {
t.Errorf("unexpected output: %s", buf.String())
}
}go
func TestServeCommand(t *testing.T) {
cmd := rootCmd
// 捕获输出
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetErr(buf)
// 设置参数
cmd.SetArgs([]string{"serve", "--port", "9000"})
// 执行命令
err := cmd.Execute()
if err != nil {
t.Fatalf("意外错误: %v", err)
}
// 检查输出
if !strings.Contains(buf.String(), "预期内容") {
t.Errorf("意外输出: %s", buf.String())
}
}Context Support
Context支持
go
var rootCmd = &cobra.Command{
Use: "myapp",
Run: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
// Use context for cancellation, timeouts, etc.
},
}
// Execute with context
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
rootCmd.ExecuteContext(ctx)go
var rootCmd = &cobra.Command{
Use: "myapp",
Run: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
// 使用context进行取消、超时等操作
},
}
// 带context执行
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
rootCmd.ExecuteContext(ctx)Common Patterns
常见模式
Subcommand Organization
子命令组织
For large apps, organize subcommands in separate packages:
cmd/
root.go
config/
config.go # Defines configCmd
get.go # config get
set.go # config setgo
// cmd/config/config.go
var ConfigCmd = &cobra.Command{Use: "config", Short: "Manage configuration"}
func init() {
ConfigCmd.AddCommand(getCmd)
ConfigCmd.AddCommand(setCmd)
}
// cmd/root.go
import "myapp/cmd/config"
func init() {
rootCmd.AddCommand(config.ConfigCmd)
}对于大型应用,将子命令组织到独立包中:
cmd/
root.go
config/
config.go // 定义configCmd
get.go // config get命令
set.go // config set命令go
// cmd/config/config.go
var ConfigCmd = &cobra.Command{Use: "config", Short: "管理配置"}
func init() {
ConfigCmd.AddCommand(getCmd)
ConfigCmd.AddCommand(setCmd)
}
// cmd/root.go
import "myapp/cmd/config"
func init() {
rootCmd.AddCommand(config.ConfigCmd)
}Error Handling
错误处理
go
func Execute() {
if err := rootCmd.Execute(); err != nil {
// Error already printed by Cobra
os.Exit(1)
}
}
// To silence automatic error printing:
rootCmd.SilenceErrors = true
rootCmd.SilenceUsage = truego
func Execute() {
if err := rootCmd.Execute(); err != nil {
// Cobra已自动打印错误
os.Exit(1)
}
}
// 禁用自动错误打印:
rootCmd.SilenceErrors = true
rootCmd.SilenceUsage = trueSilent/Quiet Mode
静默/安静模式
go
var quiet bool
func init() {
rootCmd.PersistentFlags().BoolVarP(&quiet, "quiet", "q", false, "suppress output")
}
func output(msg string) {
if !quiet {
fmt.Println(msg)
}
}go
var quiet bool
func init() {
rootCmd.PersistentFlags().BoolVarP(&quiet, "quiet", "q", false, "抑制输出")
}
func output(msg string) {
if !quiet {
fmt.Println(msg)
}
}Reference Files
参考文档
For more detailed information on specific topics:
- — Shell completion implementation details
references/completions.md - — Documentation generation (man, markdown, yaml, rst)
references/docgen.md - — Advanced patterns and edge cases
references/advanced.md
如需特定主题的详细信息,请查看:
- — Shell补全实现细节
references/completions.md - — 文档生成(手册页、Markdown、YAML、RST)
references/docgen.md - — 高级模式与边缘情况
references/advanced.md