Build production CLI tools with Cobra, Viper, and terminal UI
Build professional command-line applications with Go.
Complete guide for building CLI tools with Cobra, Viper configuration, terminal UI, and cross-platform support.
| Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | framework | string | no | "cobra" | CLI framework | | config_format | string | no | "yaml" | Config: "yaml", "json", "toml" | | interactive | bool | no | false | Include interactive prompts |
var rootCmd = &cobra.Command{
Use: "myapp",
Short: "My CLI application",
Version: version,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initConfig()
},
}
func Execute() int {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
return 1
}
return 0
}
func init() {
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file")
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")
}
var serveCmd = &cobra.Command{
Use: "serve",
Short: "Start the server",
RunE: func(cmd *cobra.Command, args []string) error {
port, _ := cmd.Flags().GetInt("port")
return runServer(port)
},
}
func init() {
serveCmd.Flags().IntP("port", "p", 8080, "server port")
rootCmd.AddCommand(serveCmd)
}
func initConfig() error {
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
home, _ := os.UserHomeDir()
viper.AddConfigPath(home)
viper.AddConfigPath(".")
viper.SetConfigName(".myapp")
viper.SetConfigType("yaml")
}
viper.SetEnvPrefix("MYAPP")
viper.AutomaticEnv()
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
return fmt.Errorf("config: %w", err)
}
}
return nil
}
type OutputFormat string
const (
FormatJSON OutputFormat = "json"
FormatYAML OutputFormat = "yaml"
FormatTable OutputFormat = "table"
)
func PrintOutput(data interface{}, format OutputFormat) error {
switch format {
case FormatJSON:
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
return enc.Encode(data)
case FormatYAML:
out, err := yaml.Marshal(data)
if err != nil {
return err
}
fmt.Print(string(out))
return nil
case FormatTable:
return printTable(data)
default:
return fmt.Errorf("unknown format: %s", format)
}
}
func runWithGracefulShutdown(fn func(ctx context.Context) error) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
errCh := make(chan error, 1)
go func() {
errCh <- fn(ctx)
}()
select {
case err := <-errCh:
return err
case sig := <-sigCh:
fmt.Printf("\nReceived %s, shutting down...\n", sig)
cancel()
return <-errCh
}
}
| Code | Meaning | |------|---------| | 0 | Success | | 1 | General error | | 2 | Invalid usage | | 64 | Command line error | | 65 | Data format error |
| Symptom | Cause | Fix | |---------|-------|-----| | Exit 0 on error | Using Run not RunE | Switch to RunE | | Flag undefined | Missing init() | Register in init() | | Config not loaded | Wrong path | Check viper paths |
Skill("go-cli-tools")
npx skills add pluginagentmarketplace/go-cli-tools下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer