[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6PDN3EV6466R6DWV766WK0X":3,"skill-same:01M6PDN3EV6466R6DWV766WK0X":96},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":66,"commitSha":67,"skillDirectory":68,"forksCount":14,"repositoryHtmlUrl":69,"repositoryHomepageUrl":6,"ownerHtmlUrl":70,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":71,"install":72,"resources":85},"01M6PDN3EV6466R6DWV766WK0X","golang-cli-cobra-viper",null,"Building production-quality CLI tools with Cobra command framework and Viper configuration management","castle-x\u002Fsonar","castle-x","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F68362913?v=4","01M6PDKZEWWT760P3FFZZQ42SD","castlexu","01M6PDKZJTJXTRH54309WXD6YR",0,"MIT","https:\u002F\u002Fgithub.com\u002Fcastle-x\u002Fsonar\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fgolang-cli-cobra-viper\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"golang cli cobra viper","golang","cobra","golang cli","cli","flags","implementing","Utilities","devops automation","add","bind","commands","structure","files","integrate","command","team","Tools","developer","config","2026-11-10 10:12:30",false,"---\nname: golang-cli-cobra-viper\ndescription: \"Building production-quality CLI tools with Cobra command framework and Viper configuration management\"\nversion: 1.0.0\ncategory: toolchain\nauthor: Claude MPM Team\nlicense: MIT\nprogressive_disclosure:\n  entry_point:\n    summary: \"Build robust CLI tools with Cobra's command framework and Viper's configuration management for production-grade developer tools\"\n    when_to_use: \"Creating multi-command CLIs, building developer tools\u002Futilities, implementing DevOps automation, requiring flexible configuration (flags + env vars + config files), adding shell completion\"\n    quick_start: \"1. Define command structure with Cobra 2. Integrate Viper for config priority 3. Bind flags to Viper 4. Add shell completion 5. Test CLI commands\"\n  token_estimate:\n    entry: 140\n    full: 4500\ncontext_limit: 700\ntags:\n  - cli\n  - golang\n  - cobra\n  - viper\n  - configuration\n  - shell-completion\nrequires_tools: []\n---\n\n# Go CLI Development with Cobra & Viper\n\n## Overview\n\nCobra and Viper are the industry-standard libraries for building production-quality CLIs in Go. Cobra provides command structure and argument parsing, while Viper manages configuration from multiple sources with clear precedence rules.\n\n**Key Features:**\n- ? **Cobra Commands**: POSIX-compliant CLI with subcommands (`app verb noun --flag`)\n- ⚙️ **Viper Config**: Unified configuration from flags, env vars, and config files\n- ? **Integration**: Seamless Cobra + Viper plumbing patterns\n- ? **Shell Completion**: Auto-generated completions for bash, zsh, fish, PowerShell\n- ✅ **Production Ready**: Battle-tested by kubectl, docker, gh, hugo\n\n**Used By**: Kubernetes (kubectl), Docker CLI, GitHub CLI (gh), Hugo, Helm, and 100+ major projects\n\n## When to Use This Skill\n\nActivate this skill when:\n- Building multi-command CLI tools with subcommands\n- Creating developer tools, project generators, or scaffolding utilities\n- Implementing admin CLIs for services or infrastructure\n- Requiring flexible configuration (flags > env vars > config files > defaults)\n- Adding shell completion for frequently-used CLIs\n- Building DevOps automation tools or deployment scripts\n\n## Cobra Framework\n\n### Command Structure Pattern\n\nCobra follows the `APPNAME VERB NOUN --FLAG` pattern popularized by git and kubectl.\n\n```go\n\u002F\u002F cmd\u002Froot.go\npackage cmd\n\nimport (\n    \"fmt\"\n    \"os\"\n\n    \"github.com\u002Fspf13\u002Fcobra\"\n    \"github.com\u002Fspf13\u002Fviper\"\n)\n\nvar cfgFile string\n\nvar rootCmd = &cobra.Command{\n    Use:   \"myapp\",\n    Short: \"A powerful CLI tool for developers\",\n    Long: `MyApp is a CLI tool that demonstrates best practices\nfor building production-quality command-line applications.\n\nComplete documentation is available at https:\u002F\u002Fmyapp.example.com`,\n}\n\nfunc Execute() {\n    if err := rootCmd.Execute(); err != nil {\n        fmt.Fprintln(os.Stderr, err)\n        os.Exit(1)\n    }\n}\n\nfunc init() {\n    cobra.OnInitialize(initConfig)\n\n    \u002F\u002F Persistent flags (available to all subcommands)\n    rootCmd.PersistentFlags().StringVar(&cfgFile, \"config\", \"\", \"config file (default is $HOME\u002F.myapp.yaml)\")\n    rootCmd.PersistentFlags().Bool(\"verbose\", false, \"verbose output\")\n\n    \u002F\u002F Bind persistent flags to viper\n    viper.BindPFlag(\"config\", rootCmd.PersistentFlags().Lookup(\"config\"))\n    viper.BindPFlag(\"verbose\", rootCmd.PersistentFlags().Lookup(\"verbose\"))\n}\n\nfunc initConfig() {\n    if cfgFile != \"\" {\n        viper.SetConfigFile(cfgFile)\n    } else {\n        home, err := os.UserHomeDir()\n        if err != nil {\n            fmt.Fprintln(os.Stderr, err)\n            os.Exit(1)\n        }\n\n        viper.AddConfigPath(home)\n        viper.AddConfigPath(\".\")\n        viper.SetConfigType(\"yaml\")\n        viper.SetConfigName(\".myapp\")\n    }\n\n    viper.SetEnvPrefix(\"MYAPP\")\n    viper.AutomaticEnv()\n\n    if err := viper.ReadInConfig(); err == nil {\n        if viper.GetBool(\"verbose\") {\n            fmt.Println(\"Using config file:\", viper.ConfigFileUsed())\n        }\n    }\n}\n```\n\n### Subcommands with Arguments\n\n```go\n\u002F\u002F cmd\u002Fdeploy.go\npackage cmd\n\nimport (\n    \"fmt\"\n\n    \"github.com\u002Fspf13\u002Fcobra\"\n    \"github.com\u002Fspf13\u002Fviper\"\n)\n\nvar deployCmd = &cobra.Command{\n    Use:   \"deploy [environment]\",\n    Short: \"Deploy application to specified environment\",\n    Long: `Deploy the application to the specified environment.\nSupports: dev, staging, production`,\n    Args: cobra.ExactArgs(1),\n    ValidArgs: []string{\"dev\", \"staging\", \"production\"},\n    PreRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Validation logic runs before RunE\n        env := args[0]\n        if env == \"production\" && !viper.GetBool(\"force\") {\n            return fmt.Errorf(\"production deploys require --force flag\")\n        }\n        return nil\n    },\n    RunE: func(cmd *cobra.Command, args []string) error {\n        env := args[0]\n        region := viper.GetString(\"region\")\n        force := viper.GetBool(\"force\")\n\n        fmt.Printf(\"Deploying to %s in region %s (force=%v)\\n\", env, region, force)\n\n        \u002F\u002F Actual deployment logic\n        return deploy(env, region, force)\n    },\n    PostRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Cleanup or notifications\n        fmt.Println(\"Deployment complete\")\n        return nil\n    },\n}\n\nfunc init() {\n    rootCmd.AddCommand(deployCmd)\n\n    \u002F\u002F Local flags (only for this command)\n    deployCmd.Flags().StringP(\"region\", \"r\", \"us-east-1\", \"AWS region\")\n    deployCmd.Flags().BoolP(\"force\", \"f\", false, \"Force deployment without confirmation\")\n\n    \u002F\u002F Bind flags to viper\n    viper.BindPFlag(\"region\", deployCmd.Flags().Lookup(\"region\"))\n    viper.BindPFlag(\"force\", deployCmd.Flags().Lookup(\"force\"))\n}\n\nfunc deploy(env, region string, force bool) error {\n    \u002F\u002F Implementation\n    return nil\n}\n```\n\n### Persistent vs. Local Flags\n\n```go\n\u002F\u002F Persistent flags: Available to command and all subcommands\nrootCmd.PersistentFlags().String(\"config\", \"\", \"config file path\")\nrootCmd.PersistentFlags().Bool(\"verbose\", false, \"verbose output\")\n\n\u002F\u002F Local flags: Only available to this specific command\ndeployCmd.Flags().String(\"region\", \"us-east-1\", \"deployment region\")\ndeployCmd.Flags().Bool(\"force\", false, \"force deployment\")\n\n\u002F\u002F Required flags\ndeployCmd.MarkFlagRequired(\"region\")\n\n\u002F\u002F Flag dependencies\ndeployCmd.MarkFlagsRequiredTogether(\"username\", \"password\")\ndeployCmd.MarkFlagsMutuallyExclusive(\"json\", \"yaml\")\n```\n\n### PreRun\u002FPostRun Hooks\n\nCobra provides execution hooks for setup and cleanup:\n\n```go\nvar serverCmd = &cobra.Command{\n    Use:   \"server\",\n    Short: \"Start API server\",\n\n    \u002F\u002F Execution order (all optional):\n    PersistentPreRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Runs before PreRunE, inherited by subcommands\n        return setupLogging()\n    },\n    PreRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Validation and setup before RunE\n        return validateConfig()\n    },\n    RunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Main command logic\n        return startServer()\n    },\n    PostRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Cleanup after RunE\n        return cleanup()\n    },\n    PersistentPostRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Runs after PostRunE, inherited by subcommands\n        return flushLogs()\n    },\n}\n```\n\n**Important**: Use `RunE`, `PreRunE`, `PostRunE` (error-returning versions) instead of `Run`, `PreRun`, `PostRun`.\n\n## Viper Configuration Management\n\n### Configuration Priority\n\nViper follows a strict precedence order (highest to lowest):\n\n1. **Explicit Set** (`viper.Set(\"key\", value)`)\n2. **Command-line Flags** (bound with `viper.BindPFlag`)\n3. **Environment Variables** (`MYAPP_KEY=value`)\n4. **Config File** (`~\u002F.myapp.yaml`, `.\u002Fconfig.yaml`)\n5. **Key\u002FValue Store** (etcd, Consul - optional)\n6. **Defaults** (`viper.SetDefault(\"key\", value)`)\n\n```go\nfunc initConfig() {\n    \u002F\u002F 1. Set defaults (lowest priority)\n    viper.SetDefault(\"port\", 8080)\n    viper.SetDefault(\"database.host\", \"localhost\")\n    viper.SetDefault(\"database.port\", 5432)\n\n    \u002F\u002F 2. Config file locations (checked in order)\n    viper.SetConfigName(\"config\")\n    viper.SetConfigType(\"yaml\")\n    viper.AddConfigPath(\"\u002Fetc\u002Fmyapp\u002F\")\n    viper.AddConfigPath(\"$HOME\u002F.myapp\")\n    viper.AddConfigPath(\".\")\n\n    \u002F\u002F 3. Environment variables (prefix + automatic mapping)\n    viper.SetEnvPrefix(\"MYAPP\")\n    viper.AutomaticEnv() \u002F\u002F MYAPP_PORT, MYAPP_DATABASE_HOST, etc.\n\n    \u002F\u002F 4. Read config file (optional)\n    if err := viper.ReadInConfig(); err != nil {\n        if _, ok := err.(viper.ConfigFileNotFoundError); ok {\n            \u002F\u002F Config file not found - use defaults and env vars\n        } else {\n            \u002F\u002F Config file found but error reading it\n            return err\n        }\n    }\n\n    \u002F\u002F 5. Flags will be bound in init() functions (highest priority)\n}\n```\n\n### Environment Variable Mapping\n\nViper automatically maps environment variables with prefix and dot notation:\n\n```go\nviper.SetEnvPrefix(\"MYAPP\") \u002F\u002F Prefix for env vars\nviper.AutomaticEnv()        \u002F\u002F Enable automatic mapping\n\n\u002F\u002F Config key → Environment variable\n\u002F\u002F \"port\"              → MYAPP_PORT\n\u002F\u002F \"database.host\"     → MYAPP_DATABASE_HOST\n\u002F\u002F \"database.port\"     → MYAPP_DATABASE_PORT\n\u002F\u002F \"aws.s3.region\"     → MYAPP_AWS_S3_REGION\n```\n\n**Manual mapping** for non-standard env var names:\n\n```go\nviper.BindEnv(\"database.host\", \"DB_HOST\")          \u002F\u002F Custom env var name\nviper.BindEnv(\"database.password\", \"DB_PASSWORD\")  \u002F\u002F Different naming convention\n```\n\n### Config File Formats\n\nViper supports multiple formats: YAML, JSON, TOML, HCL, INI, envfile, Java properties.\n\n**config.yaml**:\n```yaml\nport: 8080\nlog_level: info\n\ndatabase:\n  host: localhost\n  port: 5432\n  user: postgres\n  ssl_mode: require\n\naws:\n  region: us-east-1\n  s3:\n    bucket: my-app-bucket\n```\n\n**Accessing config values**:\n```go\nport := viper.GetInt(\"port\")                    \u002F\u002F 8080\ndbHost := viper.GetString(\"database.host\")      \u002F\u002F \"localhost\"\ns3Bucket := viper.GetString(\"aws.s3.bucket\")    \u002F\u002F \"my-app-bucket\"\n\n\u002F\u002F Type-safe access\nif viper.IsSet(\"database.ssl_mode\") {\n    sslMode := viper.GetString(\"database.ssl_mode\")\n}\n\n\u002F\u002F Unmarshal into struct\ntype Config struct {\n    Port     int    `mapstructure:\"port\"`\n    LogLevel string `mapstructure:\"log_level\"`\n    Database struct {\n        Host    string `mapstructure:\"host\"`\n        Port    int    `mapstructure:\"port\"`\n        User    string `mapstructure:\"user\"`\n        SSLMode string `mapstructure:\"ssl_mode\"`\n    } `mapstructure:\"database\"`\n}\n\nvar config Config\nif err := viper.Unmarshal(&config); err != nil {\n    return err\n}\n```\n\n## Cobra + Viper Integration\n\n### Critical Integration Pattern\n\nThe key to Cobra + Viper integration is binding flags to Viper keys:\n\n```go\n\u002F\u002F cmd\u002Froot.go\nfunc init() {\n    cobra.OnInitialize(initConfig) \u002F\u002F Load config before command execution\n\n    \u002F\u002F Define flags\n    rootCmd.PersistentFlags().String(\"config\", \"\", \"config file\")\n    rootCmd.PersistentFlags().String(\"log-level\", \"info\", \"log level\")\n    rootCmd.PersistentFlags().Int(\"port\", 8080, \"server port\")\n\n    \u002F\u002F Bind flags to Viper (critical step!)\n    viper.BindPFlag(\"config\", rootCmd.PersistentFlags().Lookup(\"config\"))\n    viper.BindPFlag(\"log_level\", rootCmd.PersistentFlags().Lookup(\"log-level\"))\n    viper.BindPFlag(\"port\", rootCmd.PersistentFlags().Lookup(\"port\"))\n}\n\nfunc initConfig() {\n    \u002F\u002F This runs BEFORE command execution via cobra.OnInitialize\n    if cfgFile := viper.GetString(\"config\"); cfgFile != \"\" {\n        viper.SetConfigFile(cfgFile)\n    } else {\n        viper.AddConfigPath(\"$HOME\u002F.myapp\")\n        viper.AddConfigPath(\".\")\n        viper.SetConfigName(\"config\")\n    }\n\n    viper.SetEnvPrefix(\"MYAPP\")\n    viper.AutomaticEnv()\n\n    viper.ReadInConfig() \u002F\u002F Ignore errors - config file is optional\n}\n```\n\n**Flag binding strategies**:\n\n```go\n\u002F\u002F Strategy 1: Bind each flag individually (explicit)\nviper.BindPFlag(\"log_level\", rootCmd.Flags().Lookup(\"log-level\"))\n\n\u002F\u002F Strategy 2: Bind all flags automatically (convenient)\nviper.BindPFlags(rootCmd.Flags())\n\n\u002F\u002F Strategy 3: Hybrid approach (recommended)\n\u002F\u002F - Bind persistent flags globally\n\u002F\u002F - Bind local flags in each command's init()\nrootCmd.PersistentFlags().String(\"config\", \"\", \"config file\")\nviper.BindPFlags(rootCmd.PersistentFlags())\n\ndeployCmd.Flags().String(\"region\", \"us-east-1\", \"AWS region\")\nviper.BindPFlag(\"deploy.region\", deployCmd.Flags().Lookup(\"region\"))\n```\n\n### PersistentPreRun for Config Loading\n\nUse `PersistentPreRunE` to load and validate configuration:\n\n```go\nvar rootCmd = &cobra.Command{\n    Use:   \"myapp\",\n    Short: \"My application\",\n    PersistentPreRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Runs before ALL commands (inherited by subcommands)\n\n        \u002F\u002F 1. Validate required config\n        if !viper.IsSet(\"api_key\") {\n            return fmt.Errorf(\"API key not configured (set MYAPP_API_KEY or add to config file)\")\n        }\n\n        \u002F\u002F 2. Setup logging based on config\n        logLevel := viper.GetString(\"log_level\")\n        if err := setupLogging(logLevel); err != nil {\n            return fmt.Errorf(\"invalid log level: %w\", err)\n        }\n\n        \u002F\u002F 3. Initialize clients\u002Fservices\n        apiKey := viper.GetString(\"api_key\")\n        if err := initAPIClient(apiKey); err != nil {\n            return fmt.Errorf(\"failed to initialize API client: %w\", err)\n        }\n\n        return nil\n    },\n}\n```\n\n## Shell Completion\n\nCobra generates shell completion scripts for bash, zsh, fish, and PowerShell.\n\n### Adding Completion Command\n\n```go\n\u002F\u002F cmd\u002Fcompletion.go\npackage cmd\n\nimport (\n    \"os\"\n\n    \"github.com\u002Fspf13\u002Fcobra\"\n)\n\nvar completionCmd = &cobra.Command{\n    Use:   \"completion [bash|zsh|fish|powershell]\",\n    Short: \"Generate shell completion script\",\n    Long: `Generate shell completion script for myapp.\n\nTo load completions:\n\nBash:\n  $ source \u003C(myapp completion bash)\n  # To load automatically, add to ~\u002F.bashrc:\n  $ echo 'source \u003C(myapp completion bash)' >> ~\u002F.bashrc\n\nZsh:\n  $ source \u003C(myapp completion zsh)\n  # To load automatically, add to ~\u002F.zshrc:\n  $ echo 'source \u003C(myapp completion zsh)' >> ~\u002F.zshrc\n\nFish:\n  $ myapp completion fish | source\n  # To load automatically:\n  $ myapp completion fish > ~\u002F.config\u002Ffish\u002Fcompletions\u002Fmyapp.fish\n\nPowerShell:\n  PS> myapp completion powershell | Out-String | Invoke-Expression\n  # To load automatically, add to PowerShell profile.\n`,\n    DisableFlagsInUseLine: true,\n    ValidArgs:             []string{\"bash\", \"zsh\", \"fish\", \"powershell\"},\n    Args:                  cobra.ExactValidArgs(1),\n    RunE: func(cmd *cobra.Command, args []string) error {\n        switch args[0] {\n        case \"bash\":\n            return cmd.Root().GenBashCompletion(os.Stdout)\n        case \"zsh\":\n            return cmd.Root().GenZshCompletion(os.Stdout)\n        case \"fish\":\n            return cmd.Root().GenFishCompletion(os.Stdout, true)\n        case \"powershell\":\n            return cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)\n        }\n        return nil\n    },\n}\n\nfunc init() {\n    rootCmd.AddCommand(completionCmd)\n}\n```\n\n### Custom Completion Functions\n\nProvide dynamic completions for command arguments:\n\n```go\nvar deployCmd = &cobra.Command{\n    Use:   \"deploy [environment]\",\n    Short: \"Deploy to environment\",\n    Args:  cobra.ExactArgs(1),\n    ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        \u002F\u002F Return available environments\n        envs := []string{\"dev\", \"staging\", \"production\"}\n        return envs, cobra.ShellCompDirectiveNoFileComp\n    },\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return deploy(args[0])\n    },\n}\n\n\u002F\u002F Custom flag completion\ndeployCmd.RegisterFlagCompletionFunc(\"region\", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n    regions := []string{\"us-east-1\", \"us-west-2\", \"eu-west-1\"}\n    return regions, cobra.ShellCompDirectiveNoFileComp\n})\n```\n\n## CLI Best Practices\n\n### User-Friendly Error Messages\n\n```go\n\u002F\u002F ❌ BAD: Technical jargon\nreturn fmt.Errorf(\"db connection failed: EOF\")\n\n\u002F\u002F ✅ GOOD: Actionable error message\nreturn fmt.Errorf(\"cannot connect to database at %s:%d\\nPlease check:\\n  - Database is running\\n  - Credentials are correct (MYAPP_DB_PASSWORD)\\n  - Network connectivity\", host, port)\n\n\u002F\u002F ✅ GOOD: Suggest remediation\nif !viper.IsSet(\"api_key\") {\n    return fmt.Errorf(\"API key not configured\\nSet environment variable: export MYAPP_API_KEY=your-key\\nOr add to config file: ~\u002F.myapp.yaml\")\n}\n```\n\n### Progress Indicators\n\n```go\nimport \"github.com\u002Fbriandowns\u002Fspinner\"\n\nfunc deploy(env string) error {\n    s := spinner.New(spinner.CharSets[11], 100*time.Millisecond)\n    s.Suffix = \" Deploying to \" + env + \"...\"\n    s.Start()\n    defer s.Stop()\n\n    \u002F\u002F Deployment logic\n    if err := performDeployment(env); err != nil {\n        s.Stop()\n        return err\n    }\n\n    s.Stop()\n    fmt.Println(\"✓ Deployment successful\")\n    return nil\n}\n```\n\n### Output Formatting\n\n```go\nimport (\n    \"encoding\u002Fjson\"\n    \"github.com\u002Folekukonko\u002Ftablewriter\"\n)\n\nfunc displayResults(items []Item, format string) error {\n    switch format {\n    case \"json\":\n        enc := json.NewEncoder(os.Stdout)\n        enc.SetIndent(\"\", \"  \")\n        return enc.Encode(items)\n\n    case \"table\":\n        table := tablewriter.NewWriter(os.Stdout)\n        table.SetHeader([]string{\"ID\", \"Name\", \"Status\"})\n        for _, item := range items {\n            table.Append([]string{item.ID, item.Name, item.Status})\n        }\n        table.Render()\n        return nil\n\n    default:\n        return fmt.Errorf(\"unknown format: %s (use json or table)\", format)\n    }\n}\n```\n\n### Logging vs. User Output\n\n```go\nimport (\n    \"log\"\n    \"os\"\n)\n\nvar (\n    \u002F\u002F User-facing output (stdout)\n    out = os.Stdout\n\n    \u002F\u002F Logging and errors (stderr)\n    logger = log.New(os.Stderr, \"[myapp] \", log.LstdFlags)\n)\n\nfunc RunCommand() error {\n    \u002F\u002F User output: stdout\n    fmt.Fprintln(out, \"Processing files...\")\n\n    \u002F\u002F Debug\u002Fverbose logging: stderr\n    if viper.GetBool(\"verbose\") {\n        logger.Println(\"Reading config from\", viper.ConfigFileUsed())\n    }\n\n    \u002F\u002F Errors: stderr\n    if err := process(); err != nil {\n        fmt.Fprintf(os.Stderr, \"Error: %v\\n\", err)\n        return err\n    }\n\n    \u002F\u002F Success message: stdout\n    fmt.Fprintln(out, \"✓ Complete\")\n    return nil\n}\n```\n\n## Testing CLI Applications\n\n### Testing Command Execution\n\n```go\n\u002F\u002F cmd\u002Fdeploy_test.go\npackage cmd\n\nimport (\n    \"bytes\"\n    \"testing\"\n\n    \"github.com\u002Fspf13\u002Fcobra\"\n    \"github.com\u002Fstretchr\u002Ftestify\u002Fassert\"\n    \"github.com\u002Fstretchr\u002Ftestify\u002Frequire\"\n)\n\nfunc executeCommand(root *cobra.Command, args ...string) (output string, err error) {\n    buf := new(bytes.Buffer)\n    root.SetOut(buf)\n    root.SetErr(buf)\n    root.SetArgs(args)\n\n    err = root.Execute()\n    return buf.String(), err\n}\n\nfunc TestDeployCommand(t *testing.T) {\n    tests := []struct {\n        name    string\n        args    []string\n        wantErr bool\n        wantOut string\n    }{\n        {\n            name:    \"deploy to dev\",\n            args:    []string{\"deploy\", \"dev\"},\n            wantErr: false,\n            wantOut: \"Deploying to dev\",\n        },\n        {\n            name:    \"deploy to production without force\",\n            args:    []string{\"deploy\", \"production\"},\n            wantErr: true,\n            wantOut: \"production deploys require --force flag\",\n        },\n        {\n            name:    \"deploy to production with force\",\n            args:    []string{\"deploy\", \"production\", \"--force\"},\n            wantErr: false,\n            wantOut: \"Deploying to production\",\n        },\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            output, err := executeCommand(rootCmd, tt.args...)\n\n            if tt.wantErr {\n                require.Error(t, err)\n            } else {\n                require.NoError(t, err)\n            }\n\n            assert.Contains(t, output, tt.wantOut)\n        })\n    }\n}\n```\n\n### Testing with Viper Configuration\n\n```go\nfunc TestCommandWithConfig(t *testing.T) {\n    \u002F\u002F Reset viper state before each test\n    viper.Reset()\n\n    \u002F\u002F Set test configuration\n    viper.Set(\"region\", \"eu-west-1\")\n    viper.Set(\"api_key\", \"test-key-123\")\n\n    output, err := executeCommand(rootCmd, \"deploy\", \"staging\")\n\n    require.NoError(t, err)\n    assert.Contains(t, output, \"eu-west-1\")\n}\n```\n\n### Capturing Output\n\n```go\nfunc TestOutputFormat(t *testing.T) {\n    \u002F\u002F Capture stdout\n    oldStdout := os.Stdout\n    r, w, _ := os.Pipe()\n    os.Stdout = w\n    defer func() { os.Stdout = oldStdout }()\n\n    \u002F\u002F Execute command\n    err := listCmd.RunE(listCmd, []string{})\n    require.NoError(t, err)\n\n    \u002F\u002F Read output\n    w.Close()\n    var buf bytes.Buffer\n    io.Copy(&buf, r)\n    output := buf.String()\n\n    assert.Contains(t, output, \"ID\")\n    assert.Contains(t, output, \"Name\")\n}\n```\n\n## Decision Trees\n\n### When to Use Cobra\n\n**Use Cobra when:**\n- ✅ Building multi-command CLI with subcommands (e.g., `git clone`, `docker run`)\n- ✅ Need POSIX-compliant flag parsing (`--flag`, `-f`)\n- ✅ Want built-in help generation (`--help`)\n- ✅ Require shell completion support\n- ✅ Building professional CLI used by other developers\n\n**Don't use Cobra when:**\n- ❌ Simple single-command script (use `flag` package)\n- ❌ Internal-only tool with 1-2 flags\n- ❌ Prototyping or throwaway scripts\n\n### When to Use Viper\n\n**Use Viper when:**\n- ✅ Need configuration from multiple sources (flags, env vars, files)\n- ✅ Want clear configuration precedence rules\n- ✅ Support multiple config file formats (YAML, JSON, TOML)\n- ✅ Require environment variable mapping with prefixes\n- ✅ Need live config reloading (watch config file changes)\n\n**Don't use Viper when:**\n- ❌ Only using command-line flags (Cobra alone is sufficient)\n- ❌ Hardcoded configuration values\n- ❌ Simple scripts with no configuration\n\n### When to Add Shell Completion\n\n**Add shell completion when:**\n- ✅ CLI used frequently by developers (daily\u002Fhourly)\n- ✅ Many subcommands or complex flag combinations\n- ✅ Arguments have known valid values (e.g., environments, regions)\n- ✅ Building professional developer tools\n\n**Skip shell completion when:**\n- ❌ CLI used rarely (monthly or less)\n- ❌ Simple commands with few options\n- ❌ Internal-only tools\n\n### When to Use Persistent Flags\n\n**Use persistent flags when:**\n- ✅ Flag applies to ALL subcommands (e.g., `--verbose`, `--config`)\n- ✅ Common configuration shared across commands\n- ✅ Global behavior modifiers (e.g., `--dry-run`, `--output`)\n\n**Use local flags when:**\n- ✅ Flag only relevant to specific command\n- ✅ Command-specific parameters (e.g., `--region` for deploy command)\n\n## Anti-Patterns\n\n### ❌ Not Handling Errors in PreRunE\u002FRunE\n\n**Wrong**:\n```go\nvar deployCmd = &cobra.Command{\n    Use: \"deploy\",\n    Run: func(cmd *cobra.Command, args []string) {\n        deploy(args[0]) \u002F\u002F Ignores error!\n    },\n}\n```\n\n**Correct**:\n```go\nvar deployCmd = &cobra.Command{\n    Use: \"deploy\",\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return deploy(args[0]) \u002F\u002F Proper error handling\n    },\n}\n```\n\n### ❌ Mixing Configuration Sources Without Clear Precedence\n\n**Wrong**:\n```go\n\u002F\u002F Confusing: Which takes precedence?\nconfig.Port = viper.GetInt(\"port\")\nif os.Getenv(\"PORT\") != \"\" {\n    config.Port = atoi(os.Getenv(\"PORT\"))\n}\nif *flagPort != 0 {\n    config.Port = *flagPort\n}\n```\n\n**Correct**:\n```go\n\u002F\u002F Clear: Viper handles precedence automatically\nviper.BindPFlag(\"port\", rootCmd.Flags().Lookup(\"port\"))\nviper.SetEnvPrefix(\"MYAPP\")\nviper.AutomaticEnv()\nviper.SetDefault(\"port\", 8080)\n\nconfig.Port = viper.GetInt(\"port\") \u002F\u002F Respects: flag > env > config > default\n```\n\n### ❌ Forgetting to Bind Flags to Viper\n\n**Wrong**:\n```go\nrootCmd.Flags().String(\"region\", \"us-east-1\", \"AWS region\")\n\u002F\u002F Flag not bound to Viper - won't respect precedence!\n\nfunc deploy() {\n    region := viper.GetString(\"region\") \u002F\u002F Always returns config file value\n}\n```\n\n**Correct**:\n```go\nrootCmd.Flags().String(\"region\", \"us-east-1\", \"AWS region\")\nviper.BindPFlag(\"region\", rootCmd.Flags().Lookup(\"region\")) \u002F\u002F Bind it!\n\nfunc deploy() {\n    region := viper.GetString(\"region\") \u002F\u002F Respects flag > env > config\n}\n```\n\n### ❌ Not Testing CLI Commands\n\n**Wrong**:\n```go\n\u002F\u002F No tests for CLI commands - bugs slip through\n```\n\n**Correct**:\n```go\nfunc TestDeployCommand(t *testing.T) {\n    output, err := executeCommand(rootCmd, \"deploy\", \"staging\", \"--region\", \"eu-west-1\")\n    require.NoError(t, err)\n    assert.Contains(t, output, \"Deploying to staging\")\n    assert.Contains(t, output, \"eu-west-1\")\n}\n```\n\n### ❌ Poor Error Messages\n\n**Wrong**:\n```go\nreturn fmt.Errorf(\"connection failed\") \u002F\u002F Unhelpful\n```\n\n**Correct**:\n```go\nreturn fmt.Errorf(\"cannot connect to database at %s:%d\\nCheck:\\n  - Database is running\\n  - Credentials (MYAPP_DB_PASSWORD)\\n  - Firewall rules\", host, port)\n```\n\n### ❌ Using Run Instead of RunE\n\n**Wrong**:\n```go\nvar rootCmd = &cobra.Command{\n    Use: \"myapp\",\n    Run: func(cmd *cobra.Command, args []string) {\n        if err := execute(); err != nil {\n            fmt.Println(err) \u002F\u002F Error not propagated\n        }\n    },\n}\n```\n\n**Correct**:\n```go\nvar rootCmd = &cobra.Command{\n    Use: \"myapp\",\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return execute() \u002F\u002F Cobra handles error display and exit code\n    },\n}\n```\n\n## Production Example\n\nMinimal production-ready CLI structure:\n\n```\nmyapp\u002F\n├── cmd\u002F\n│   ├── root.go          # Root command + config loading\n│   ├── deploy.go        # Deploy subcommand\n│   ├── status.go        # Status subcommand\n│   └── completion.go    # Shell completion\n├── main.go              # Entry point\n├── config.yaml          # Example config file\n└── go.mod\n```\n\n**main.go**:\n```go\npackage main\n\nimport \"myapp\u002Fcmd\"\n\nfunc main() {\n    cmd.Execute()\n}\n```\n\n**cmd\u002Froot.go**: See \"Command Structure Pattern\" section above\n\n**Building and installing**:\n```bash\n# Development\ngo run main.go deploy staging --region us-west-2\n\n# Production build\ngo build -o myapp\n\n# Install globally\ngo install\n\n# Enable shell completion\nmyapp completion bash > \u002Fetc\u002Fbash_completion.d\u002Fmyapp\n```\n\n## Resources\n\n**Official Documentation**:\n- [Cobra User Guide](https:\u002F\u002Fcobra.dev\u002F) - Official framework documentation\n- [Viper Documentation](https:\u002F\u002Fgithub.com\u002Fspf13\u002Fviper) - Configuration management guide\n\n**Learning Resources**:\n- \"Building CLI Apps in Go with Cobra & Viper\" (November 2025) - Comprehensive tutorial\n- \"The Cobra & Viper Journey\" - Learning path for CLI development\n- [Cobra Generator](https:\u002F\u002Fgithub.com\u002Fspf13\u002Fcobra-cli) - Scaffolding tool for new CLIs\n\n**Production Examples**:\n- [kubectl](https:\u002F\u002Fgithub.com\u002Fkubernetes\u002Fkubectl) - Kubernetes CLI\n- [docker](https:\u002F\u002Fgithub.com\u002Fdocker\u002Fcli) - Docker CLI\n- [gh](https:\u002F\u002Fgithub.com\u002Fcli\u002Fcli) - GitHub CLI\n- [hugo](https:\u002F\u002Fgithub.com\u002Fgohugoio\u002Fhugo) - Static site generator\n\n**Related Skills**:\n- `golang-testing-strategies` - Testing CLI commands comprehensively\n- `golang-http-servers` - Building API servers with configuration\n- `golang-concurrency-patterns` - Async operations in CLI tools\n\n## Success Criteria\n\nYou know you've mastered Cobra + Viper when:\n- ✅ Commands follow POSIX conventions (`VERB NOUN --FLAG`)\n- ✅ Configuration precedence is clear: flags > env > config > defaults\n- ✅ All flags bound to Viper for unified config access\n- ✅ Shell completion generated for all major shells\n- ✅ Error messages are actionable and user-friendly\n- ✅ CLI commands have comprehensive tests\n- ✅ Help text auto-generated and accurate\n- ✅ PersistentPreRunE used for global setup\u002Fvalidation\n- ✅ Separation of concerns: user output (stdout) vs. logging (stderr)\n- ✅ Config files optional - CLI works with flags\u002Fenv vars alone\n","# Go CLI Development with Cobra & Viper\n\n## Overview\n\nCobra and Viper are the industry-standard libraries for building production-quality CLIs in Go. Cobra provides command structure and argument parsing, while Viper manages configuration from multiple sources with clear precedence rules.\n\n**Key Features:**\n- ? **Cobra Commands**: POSIX-compliant CLI with subcommands (`app verb noun --flag`)\n- ⚙️ **Viper Config**: Unified configuration from flags, env vars, and config files\n- ? **Integration**: Seamless Cobra + Viper plumbing patterns\n- ? **Shell Completion**: Auto-generated completions for bash, zsh, fish, PowerShell\n- ✅ **Production Ready**: Battle-tested by kubectl, docker, gh, hugo\n\n**Used By**: Kubernetes (kubectl), Docker CLI, GitHub CLI (gh), Hugo, Helm, and 100+ major projects\n\n## When to Use This Skill\n\nActivate this skill when:\n- Building multi-command CLI tools with subcommands\n- Creating developer tools, project generators, or scaffolding utilities\n- Implementing admin CLIs for services or infrastructure\n- Requiring flexible configuration (flags > env vars > config files > defaults)\n- Adding shell completion for frequently-used CLIs\n- Building DevOps automation tools or deployment scripts\n\n## Cobra Framework\n\n### Command Structure Pattern\n\nCobra follows the `APPNAME VERB NOUN --FLAG` pattern popularized by git and kubectl.\n\n```go\n\u002F\u002F cmd\u002Froot.go\npackage cmd\n\nimport (\n    \"fmt\"\n    \"os\"\n\n    \"github.com\u002Fspf13\u002Fcobra\"\n    \"github.com\u002Fspf13\u002Fviper\"\n)\n\nvar cfgFile string\n\nvar rootCmd = &cobra.Command{\n    Use:   \"myapp\",\n    Short: \"A powerful CLI tool for developers\",\n    Long: `MyApp is a CLI tool that demonstrates best practices\nfor building production-quality command-line applications.\n\nComplete documentation is available at https:\u002F\u002Fmyapp.example.com`,\n}\n\nfunc Execute() {\n    if err := rootCmd.Execute(); err != nil {\n        fmt.Fprintln(os.Stderr, err)\n        os.Exit(1)\n    }\n}\n\nfunc init() {\n    cobra.OnInitialize(initConfig)\n\n    \u002F\u002F Persistent flags (available to all subcommands)\n    rootCmd.PersistentFlags().StringVar(&cfgFile, \"config\", \"\", \"config file (default is $HOME\u002F.myapp.yaml)\")\n    rootCmd.PersistentFlags().Bool(\"verbose\", false, \"verbose output\")\n\n    \u002F\u002F Bind persistent flags to viper\n    viper.BindPFlag(\"config\", rootCmd.PersistentFlags().Lookup(\"config\"))\n    viper.BindPFlag(\"verbose\", rootCmd.PersistentFlags().Lookup(\"verbose\"))\n}\n\nfunc initConfig() {\n    if cfgFile != \"\" {\n        viper.SetConfigFile(cfgFile)\n    } else {\n        home, err := os.UserHomeDir()\n        if err != nil {\n            fmt.Fprintln(os.Stderr, err)\n            os.Exit(1)\n        }\n\n        viper.AddConfigPath(home)\n        viper.AddConfigPath(\".\")\n        viper.SetConfigType(\"yaml\")\n        viper.SetConfigName(\".myapp\")\n    }\n\n    viper.SetEnvPrefix(\"MYAPP\")\n    viper.AutomaticEnv()\n\n    if err := viper.ReadInConfig(); err == nil {\n        if viper.GetBool(\"verbose\") {\n            fmt.Println(\"Using config file:\", viper.ConfigFileUsed())\n        }\n    }\n}\n```\n\n### Subcommands with Arguments\n\n```go\n\u002F\u002F cmd\u002Fdeploy.go\npackage cmd\n\nimport (\n    \"fmt\"\n\n    \"github.com\u002Fspf13\u002Fcobra\"\n    \"github.com\u002Fspf13\u002Fviper\"\n)\n\nvar deployCmd = &cobra.Command{\n    Use:   \"deploy [environment]\",\n    Short: \"Deploy application to specified environment\",\n    Long: `Deploy the application to the specified environment.\nSupports: dev, staging, production`,\n    Args: cobra.ExactArgs(1),\n    ValidArgs: []string{\"dev\", \"staging\", \"production\"},\n    PreRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Validation logic runs before RunE\n        env := args[0]\n        if env == \"production\" && !viper.GetBool(\"force\") {\n            return fmt.Errorf(\"production deploys require --force flag\")\n        }\n        return nil\n    },\n    RunE: func(cmd *cobra.Command, args []string) error {\n        env := args[0]\n        region := viper.GetString(\"region\")\n        force := viper.GetBool(\"force\")\n\n        fmt.Printf(\"Deploying to %s in region %s (force=%v)\\n\", env, region, force)\n\n        \u002F\u002F Actual deployment logic\n        return deploy(env, region, force)\n    },\n    PostRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Cleanup or notifications\n        fmt.Println(\"Deployment complete\")\n        return nil\n    },\n}\n\nfunc init() {\n    rootCmd.AddCommand(deployCmd)\n\n    \u002F\u002F Local flags (only for this command)\n    deployCmd.Flags().StringP(\"region\", \"r\", \"us-east-1\", \"AWS region\")\n    deployCmd.Flags().BoolP(\"force\", \"f\", false, \"Force deployment without confirmation\")\n\n    \u002F\u002F Bind flags to viper\n    viper.BindPFlag(\"region\", deployCmd.Flags().Lookup(\"region\"))\n    viper.BindPFlag(\"force\", deployCmd.Flags().Lookup(\"force\"))\n}\n\nfunc deploy(env, region string, force bool) error {\n    \u002F\u002F Implementation\n    return nil\n}\n```\n\n### Persistent vs. Local Flags\n\n```go\n\u002F\u002F Persistent flags: Available to command and all subcommands\nrootCmd.PersistentFlags().String(\"config\", \"\", \"config file path\")\nrootCmd.PersistentFlags().Bool(\"verbose\", false, \"verbose output\")\n\n\u002F\u002F Local flags: Only available to this specific command\ndeployCmd.Flags().String(\"region\", \"us-east-1\", \"deployment region\")\ndeployCmd.Flags().Bool(\"force\", false, \"force deployment\")\n\n\u002F\u002F Required flags\ndeployCmd.MarkFlagRequired(\"region\")\n\n\u002F\u002F Flag dependencies\ndeployCmd.MarkFlagsRequiredTogether(\"username\", \"password\")\ndeployCmd.MarkFlagsMutuallyExclusive(\"json\", \"yaml\")\n```\n\n### PreRun\u002FPostRun Hooks\n\nCobra provides execution hooks for setup and cleanup:\n\n```go\nvar serverCmd = &cobra.Command{\n    Use:   \"server\",\n    Short: \"Start API server\",\n\n    \u002F\u002F Execution order (all optional):\n    PersistentPreRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Runs before PreRunE, inherited by subcommands\n        return setupLogging()\n    },\n    PreRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Validation and setup before RunE\n        return validateConfig()\n    },\n    RunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Main command logic\n        return startServer()\n    },\n    PostRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Cleanup after RunE\n        return cleanup()\n    },\n    PersistentPostRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Runs after PostRunE, inherited by subcommands\n        return flushLogs()\n    },\n}\n```\n\n**Important**: Use `RunE`, `PreRunE`, `PostRunE` (error-returning versions) instead of `Run`, `PreRun`, `PostRun`.\n\n## Viper Configuration Management\n\n### Configuration Priority\n\nViper follows a strict precedence order (highest to lowest):\n\n1. **Explicit Set** (`viper.Set(\"key\", value)`)\n2. **Command-line Flags** (bound with `viper.BindPFlag`)\n3. **Environment Variables** (`MYAPP_KEY=value`)\n4. **Config File** (`~\u002F.myapp.yaml`, `.\u002Fconfig.yaml`)\n5. **Key\u002FValue Store** (etcd, Consul - optional)\n6. **Defaults** (`viper.SetDefault(\"key\", value)`)\n\n```go\nfunc initConfig() {\n    \u002F\u002F 1. Set defaults (lowest priority)\n    viper.SetDefault(\"port\", 8080)\n    viper.SetDefault(\"database.host\", \"localhost\")\n    viper.SetDefault(\"database.port\", 5432)\n\n    \u002F\u002F 2. Config file locations (checked in order)\n    viper.SetConfigName(\"config\")\n    viper.SetConfigType(\"yaml\")\n    viper.AddConfigPath(\"\u002Fetc\u002Fmyapp\u002F\")\n    viper.AddConfigPath(\"$HOME\u002F.myapp\")\n    viper.AddConfigPath(\".\")\n\n    \u002F\u002F 3. Environment variables (prefix + automatic mapping)\n    viper.SetEnvPrefix(\"MYAPP\")\n    viper.AutomaticEnv() \u002F\u002F MYAPP_PORT, MYAPP_DATABASE_HOST, etc.\n\n    \u002F\u002F 4. Read config file (optional)\n    if err := viper.ReadInConfig(); err != nil {\n        if _, ok := err.(viper.ConfigFileNotFoundError); ok {\n            \u002F\u002F Config file not found - use defaults and env vars\n        } else {\n            \u002F\u002F Config file found but error reading it\n            return err\n        }\n    }\n\n    \u002F\u002F 5. Flags will be bound in init() functions (highest priority)\n}\n```\n\n### Environment Variable Mapping\n\nViper automatically maps environment variables with prefix and dot notation:\n\n```go\nviper.SetEnvPrefix(\"MYAPP\") \u002F\u002F Prefix for env vars\nviper.AutomaticEnv()        \u002F\u002F Enable automatic mapping\n\n\u002F\u002F Config key → Environment variable\n\u002F\u002F \"port\"              → MYAPP_PORT\n\u002F\u002F \"database.host\"     → MYAPP_DATABASE_HOST\n\u002F\u002F \"database.port\"     → MYAPP_DATABASE_PORT\n\u002F\u002F \"aws.s3.region\"     → MYAPP_AWS_S3_REGION\n```\n\n**Manual mapping** for non-standard env var names:\n\n```go\nviper.BindEnv(\"database.host\", \"DB_HOST\")          \u002F\u002F Custom env var name\nviper.BindEnv(\"database.password\", \"DB_PASSWORD\")  \u002F\u002F Different naming convention\n```\n\n### Config File Formats\n\nViper supports multiple formats: YAML, JSON, TOML, HCL, INI, envfile, Java properties.\n\n**config.yaml**:\n```yaml\nport: 8080\nlog_level: info\n\ndatabase:\n  host: localhost\n  port: 5432\n  user: postgres\n  ssl_mode: require\n\naws:\n  region: us-east-1\n  s3:\n    bucket: my-app-bucket\n```\n\n**Accessing config values**:\n```go\nport := viper.GetInt(\"port\")                    \u002F\u002F 8080\ndbHost := viper.GetString(\"database.host\")      \u002F\u002F \"localhost\"\ns3Bucket := viper.GetString(\"aws.s3.bucket\")    \u002F\u002F \"my-app-bucket\"\n\n\u002F\u002F Type-safe access\nif viper.IsSet(\"database.ssl_mode\") {\n    sslMode := viper.GetString(\"database.ssl_mode\")\n}\n\n\u002F\u002F Unmarshal into struct\ntype Config struct {\n    Port     int    `mapstructure:\"port\"`\n    LogLevel string `mapstructure:\"log_level\"`\n    Database struct {\n        Host    string `mapstructure:\"host\"`\n        Port    int    `mapstructure:\"port\"`\n        User    string `mapstructure:\"user\"`\n        SSLMode string `mapstructure:\"ssl_mode\"`\n    } `mapstructure:\"database\"`\n}\n\nvar config Config\nif err := viper.Unmarshal(&config); err != nil {\n    return err\n}\n```\n\n## Cobra + Viper Integration\n\n### Critical Integration Pattern\n\nThe key to Cobra + Viper integration is binding flags to Viper keys:\n\n```go\n\u002F\u002F cmd\u002Froot.go\nfunc init() {\n    cobra.OnInitialize(initConfig) \u002F\u002F Load config before command execution\n\n    \u002F\u002F Define flags\n    rootCmd.PersistentFlags().String(\"config\", \"\", \"config file\")\n    rootCmd.PersistentFlags().String(\"log-level\", \"info\", \"log level\")\n    rootCmd.PersistentFlags().Int(\"port\", 8080, \"server port\")\n\n    \u002F\u002F Bind flags to Viper (critical step!)\n    viper.BindPFlag(\"config\", rootCmd.PersistentFlags().Lookup(\"config\"))\n    viper.BindPFlag(\"log_level\", rootCmd.PersistentFlags().Lookup(\"log-level\"))\n    viper.BindPFlag(\"port\", rootCmd.PersistentFlags().Lookup(\"port\"))\n}\n\nfunc initConfig() {\n    \u002F\u002F This runs BEFORE command execution via cobra.OnInitialize\n    if cfgFile := viper.GetString(\"config\"); cfgFile != \"\" {\n        viper.SetConfigFile(cfgFile)\n    } else {\n        viper.AddConfigPath(\"$HOME\u002F.myapp\")\n        viper.AddConfigPath(\".\")\n        viper.SetConfigName(\"config\")\n    }\n\n    viper.SetEnvPrefix(\"MYAPP\")\n    viper.AutomaticEnv()\n\n    viper.ReadInConfig() \u002F\u002F Ignore errors - config file is optional\n}\n```\n\n**Flag binding strategies**:\n\n```go\n\u002F\u002F Strategy 1: Bind each flag individually (explicit)\nviper.BindPFlag(\"log_level\", rootCmd.Flags().Lookup(\"log-level\"))\n\n\u002F\u002F Strategy 2: Bind all flags automatically (convenient)\nviper.BindPFlags(rootCmd.Flags())\n\n\u002F\u002F Strategy 3: Hybrid approach (recommended)\n\u002F\u002F - Bind persistent flags globally\n\u002F\u002F - Bind local flags in each command's init()\nrootCmd.PersistentFlags().String(\"config\", \"\", \"config file\")\nviper.BindPFlags(rootCmd.PersistentFlags())\n\ndeployCmd.Flags().String(\"region\", \"us-east-1\", \"AWS region\")\nviper.BindPFlag(\"deploy.region\", deployCmd.Flags().Lookup(\"region\"))\n```\n\n### PersistentPreRun for Config Loading\n\nUse `PersistentPreRunE` to load and validate configuration:\n\n```go\nvar rootCmd = &cobra.Command{\n    Use:   \"myapp\",\n    Short: \"My application\",\n    PersistentPreRunE: func(cmd *cobra.Command, args []string) error {\n        \u002F\u002F Runs before ALL commands (inherited by subcommands)\n\n        \u002F\u002F 1. Validate required config\n        if !viper.IsSet(\"api_key\") {\n            return fmt.Errorf(\"API key not configured (set MYAPP_API_KEY or add to config file)\")\n        }\n\n        \u002F\u002F 2. Setup logging based on config\n        logLevel := viper.GetString(\"log_level\")\n        if err := setupLogging(logLevel); err != nil {\n            return fmt.Errorf(\"invalid log level: %w\", err)\n        }\n\n        \u002F\u002F 3. Initialize clients\u002Fservices\n        apiKey := viper.GetString(\"api_key\")\n        if err := initAPIClient(apiKey); err != nil {\n            return fmt.Errorf(\"failed to initialize API client: %w\", err)\n        }\n\n        return nil\n    },\n}\n```\n\n## Shell Completion\n\nCobra generates shell completion scripts for bash, zsh, fish, and PowerShell.\n\n### Adding Completion Command\n\n```go\n\u002F\u002F cmd\u002Fcompletion.go\npackage cmd\n\nimport (\n    \"os\"\n\n    \"github.com\u002Fspf13\u002Fcobra\"\n)\n\nvar completionCmd = &cobra.Command{\n    Use:   \"completion [bash|zsh|fish|powershell]\",\n    Short: \"Generate shell completion script\",\n    Long: `Generate shell completion script for myapp.\n\nTo load completions:\n\nBash:\n  $ source \u003C(myapp completion bash)\n  # To load automatically, add to ~\u002F.bashrc:\n  $ echo 'source \u003C(myapp completion bash)' >> ~\u002F.bashrc\n\nZsh:\n  $ source \u003C(myapp completion zsh)\n  # To load automatically, add to ~\u002F.zshrc:\n  $ echo 'source \u003C(myapp completion zsh)' >> ~\u002F.zshrc\n\nFish:\n  $ myapp completion fish | source\n  # To load automatically:\n  $ myapp completion fish > ~\u002F.config\u002Ffish\u002Fcompletions\u002Fmyapp.fish\n\nPowerShell:\n  PS> myapp completion powershell | Out-String | Invoke-Expression\n  # To load automatically, add to PowerShell profile.\n`,\n    DisableFlagsInUseLine: true,\n    ValidArgs:             []string{\"bash\", \"zsh\", \"fish\", \"powershell\"},\n    Args:                  cobra.ExactValidArgs(1),\n    RunE: func(cmd *cobra.Command, args []string) error {\n        switch args[0] {\n        case \"bash\":\n            return cmd.Root().GenBashCompletion(os.Stdout)\n        case \"zsh\":\n            return cmd.Root().GenZshCompletion(os.Stdout)\n        case \"fish\":\n            return cmd.Root().GenFishCompletion(os.Stdout, true)\n        case \"powershell\":\n            return cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)\n        }\n        return nil\n    },\n}\n\nfunc init() {\n    rootCmd.AddCommand(completionCmd)\n}\n```\n\n### Custom Completion Functions\n\nProvide dynamic completions for command arguments:\n\n```go\nvar deployCmd = &cobra.Command{\n    Use:   \"deploy [environment]\",\n    Short: \"Deploy to environment\",\n    Args:  cobra.ExactArgs(1),\n    ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n        \u002F\u002F Return available environments\n        envs := []string{\"dev\", \"staging\", \"production\"}\n        return envs, cobra.ShellCompDirectiveNoFileComp\n    },\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return deploy(args[0])\n    },\n}\n\n\u002F\u002F Custom flag completion\ndeployCmd.RegisterFlagCompletionFunc(\"region\", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {\n    regions := []string{\"us-east-1\", \"us-west-2\", \"eu-west-1\"}\n    return regions, cobra.ShellCompDirectiveNoFileComp\n})\n```\n\n## CLI Best Practices\n\n### User-Friendly Error Messages\n\n```go\n\u002F\u002F ❌ BAD: Technical jargon\nreturn fmt.Errorf(\"db connection failed: EOF\")\n\n\u002F\u002F ✅ GOOD: Actionable error message\nreturn fmt.Errorf(\"cannot connect to database at %s:%d\\nPlease check:\\n  - Database is running\\n  - Credentials are correct (MYAPP_DB_PASSWORD)\\n  - Network connectivity\", host, port)\n\n\u002F\u002F ✅ GOOD: Suggest remediation\nif !viper.IsSet(\"api_key\") {\n    return fmt.Errorf(\"API key not configured\\nSet environment variable: export MYAPP_API_KEY=your-key\\nOr add to config file: ~\u002F.myapp.yaml\")\n}\n```\n\n### Progress Indicators\n\n```go\nimport \"github.com\u002Fbriandowns\u002Fspinner\"\n\nfunc deploy(env string) error {\n    s := spinner.New(spinner.CharSets[11], 100*time.Millisecond)\n    s.Suffix = \" Deploying to \" + env + \"...\"\n    s.Start()\n    defer s.Stop()\n\n    \u002F\u002F Deployment logic\n    if err := performDeployment(env); err != nil {\n        s.Stop()\n        return err\n    }\n\n    s.Stop()\n    fmt.Println(\"✓ Deployment successful\")\n    return nil\n}\n```\n\n### Output Formatting\n\n```go\nimport (\n    \"encoding\u002Fjson\"\n    \"github.com\u002Folekukonko\u002Ftablewriter\"\n)\n\nfunc displayResults(items []Item, format string) error {\n    switch format {\n    case \"json\":\n        enc := json.NewEncoder(os.Stdout)\n        enc.SetIndent(\"\", \"  \")\n        return enc.Encode(items)\n\n    case \"table\":\n        table := tablewriter.NewWriter(os.Stdout)\n        table.SetHeader([]string{\"ID\", \"Name\", \"Status\"})\n        for _, item := range items {\n            table.Append([]string{item.ID, item.Name, item.Status})\n        }\n        table.Render()\n        return nil\n\n    default:\n        return fmt.Errorf(\"unknown format: %s (use json or table)\", format)\n    }\n}\n```\n\n### Logging vs. User Output\n\n```go\nimport (\n    \"log\"\n    \"os\"\n)\n\nvar (\n    \u002F\u002F User-facing output (stdout)\n    out = os.Stdout\n\n    \u002F\u002F Logging and errors (stderr)\n    logger = log.New(os.Stderr, \"[myapp] \", log.LstdFlags)\n)\n\nfunc RunCommand() error {\n    \u002F\u002F User output: stdout\n    fmt.Fprintln(out, \"Processing files...\")\n\n    \u002F\u002F Debug\u002Fverbose logging: stderr\n    if viper.GetBool(\"verbose\") {\n        logger.Println(\"Reading config from\", viper.ConfigFileUsed())\n    }\n\n    \u002F\u002F Errors: stderr\n    if err := process(); err != nil {\n        fmt.Fprintf(os.Stderr, \"Error: %v\\n\", err)\n        return err\n    }\n\n    \u002F\u002F Success message: stdout\n    fmt.Fprintln(out, \"✓ Complete\")\n    return nil\n}\n```\n\n## Testing CLI Applications\n\n### Testing Command Execution\n\n```go\n\u002F\u002F cmd\u002Fdeploy_test.go\npackage cmd\n\nimport (\n    \"bytes\"\n    \"testing\"\n\n    \"github.com\u002Fspf13\u002Fcobra\"\n    \"github.com\u002Fstretchr\u002Ftestify\u002Fassert\"\n    \"github.com\u002Fstretchr\u002Ftestify\u002Frequire\"\n)\n\nfunc executeCommand(root *cobra.Command, args ...string) (output string, err error) {\n    buf := new(bytes.Buffer)\n    root.SetOut(buf)\n    root.SetErr(buf)\n    root.SetArgs(args)\n\n    err = root.Execute()\n    return buf.String(), err\n}\n\nfunc TestDeployCommand(t *testing.T) {\n    tests := []struct {\n        name    string\n        args    []string\n        wantErr bool\n        wantOut string\n    }{\n        {\n            name:    \"deploy to dev\",\n            args:    []string{\"deploy\", \"dev\"},\n            wantErr: false,\n            wantOut: \"Deploying to dev\",\n        },\n        {\n            name:    \"deploy to production without force\",\n            args:    []string{\"deploy\", \"production\"},\n            wantErr: true,\n            wantOut: \"production deploys require --force flag\",\n        },\n        {\n            name:    \"deploy to production with force\",\n            args:    []string{\"deploy\", \"production\", \"--force\"},\n            wantErr: false,\n            wantOut: \"Deploying to production\",\n        },\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            output, err := executeCommand(rootCmd, tt.args...)\n\n            if tt.wantErr {\n                require.Error(t, err)\n            } else {\n                require.NoError(t, err)\n            }\n\n            assert.Contains(t, output, tt.wantOut)\n        })\n    }\n}\n```\n\n### Testing with Viper Configuration\n\n```go\nfunc TestCommandWithConfig(t *testing.T) {\n    \u002F\u002F Reset viper state before each test\n    viper.Reset()\n\n    \u002F\u002F Set test configuration\n    viper.Set(\"region\", \"eu-west-1\")\n    viper.Set(\"api_key\", \"test-key-123\")\n\n    output, err := executeCommand(rootCmd, \"deploy\", \"staging\")\n\n    require.NoError(t, err)\n    assert.Contains(t, output, \"eu-west-1\")\n}\n```\n\n### Capturing Output\n\n```go\nfunc TestOutputFormat(t *testing.T) {\n    \u002F\u002F Capture stdout\n    oldStdout := os.Stdout\n    r, w, _ := os.Pipe()\n    os.Stdout = w\n    defer func() { os.Stdout = oldStdout }()\n\n    \u002F\u002F Execute command\n    err := listCmd.RunE(listCmd, []string{})\n    require.NoError(t, err)\n\n    \u002F\u002F Read output\n    w.Close()\n    var buf bytes.Buffer\n    io.Copy(&buf, r)\n    output := buf.String()\n\n    assert.Contains(t, output, \"ID\")\n    assert.Contains(t, output, \"Name\")\n}\n```\n\n## Decision Trees\n\n### When to Use Cobra\n\n**Use Cobra when:**\n- ✅ Building multi-command CLI with subcommands (e.g., `git clone`, `docker run`)\n- ✅ Need POSIX-compliant flag parsing (`--flag`, `-f`)\n- ✅ Want built-in help generation (`--help`)\n- ✅ Require shell completion support\n- ✅ Building professional CLI used by other developers\n\n**Don't use Cobra when:**\n- ❌ Simple single-command script (use `flag` package)\n- ❌ Internal-only tool with 1-2 flags\n- ❌ Prototyping or throwaway scripts\n\n### When to Use Viper\n\n**Use Viper when:**\n- ✅ Need configuration from multiple sources (flags, env vars, files)\n- ✅ Want clear configuration precedence rules\n- ✅ Support multiple config file formats (YAML, JSON, TOML)\n- ✅ Require environment variable mapping with prefixes\n- ✅ Need live config reloading (watch config file changes)\n\n**Don't use Viper when:**\n- ❌ Only using command-line flags (Cobra alone is sufficient)\n- ❌ Hardcoded configuration values\n- ❌ Simple scripts with no configuration\n\n### When to Add Shell Completion\n\n**Add shell completion when:**\n- ✅ CLI used frequently by developers (daily\u002Fhourly)\n- ✅ Many subcommands or complex flag combinations\n- ✅ Arguments have known valid values (e.g., environments, regions)\n- ✅ Building professional developer tools\n\n**Skip shell completion when:**\n- ❌ CLI used rarely (monthly or less)\n- ❌ Simple commands with few options\n- ❌ Internal-only tools\n\n### When to Use Persistent Flags\n\n**Use persistent flags when:**\n- ✅ Flag applies to ALL subcommands (e.g., `--verbose`, `--config`)\n- ✅ Common configuration shared across commands\n- ✅ Global behavior modifiers (e.g., `--dry-run`, `--output`)\n\n**Use local flags when:**\n- ✅ Flag only relevant to specific command\n- ✅ Command-specific parameters (e.g., `--region` for deploy command)\n\n## Anti-Patterns\n\n### ❌ Not Handling Errors in PreRunE\u002FRunE\n\n**Wrong**:\n```go\nvar deployCmd = &cobra.Command{\n    Use: \"deploy\",\n    Run: func(cmd *cobra.Command, args []string) {\n        deploy(args[0]) \u002F\u002F Ignores error!\n    },\n}\n```\n\n**Correct**:\n```go\nvar deployCmd = &cobra.Command{\n    Use: \"deploy\",\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return deploy(args[0]) \u002F\u002F Proper error handling\n    },\n}\n```\n\n### ❌ Mixing Configuration Sources Without Clear Precedence\n\n**Wrong**:\n```go\n\u002F\u002F Confusing: Which takes precedence?\nconfig.Port = viper.GetInt(\"port\")\nif os.Getenv(\"PORT\") != \"\" {\n    config.Port = atoi(os.Getenv(\"PORT\"))\n}\nif *flagPort != 0 {\n    config.Port = *flagPort\n}\n```\n\n**Correct**:\n```go\n\u002F\u002F Clear: Viper handles precedence automatically\nviper.BindPFlag(\"port\", rootCmd.Flags().Lookup(\"port\"))\nviper.SetEnvPrefix(\"MYAPP\")\nviper.AutomaticEnv()\nviper.SetDefault(\"port\", 8080)\n\nconfig.Port = viper.GetInt(\"port\") \u002F\u002F Respects: flag > env > config > default\n```\n\n### ❌ Forgetting to Bind Flags to Viper\n\n**Wrong**:\n```go\nrootCmd.Flags().String(\"region\", \"us-east-1\", \"AWS region\")\n\u002F\u002F Flag not bound to Viper - won't respect precedence!\n\nfunc deploy() {\n    region := viper.GetString(\"region\") \u002F\u002F Always returns config file value\n}\n```\n\n**Correct**:\n```go\nrootCmd.Flags().String(\"region\", \"us-east-1\", \"AWS region\")\nviper.BindPFlag(\"region\", rootCmd.Flags().Lookup(\"region\")) \u002F\u002F Bind it!\n\nfunc deploy() {\n    region := viper.GetString(\"region\") \u002F\u002F Respects flag > env > config\n}\n```\n\n### ❌ Not Testing CLI Commands\n\n**Wrong**:\n```go\n\u002F\u002F No tests for CLI commands - bugs slip through\n```\n\n**Correct**:\n```go\nfunc TestDeployCommand(t *testing.T) {\n    output, err := executeCommand(rootCmd, \"deploy\", \"staging\", \"--region\", \"eu-west-1\")\n    require.NoError(t, err)\n    assert.Contains(t, output, \"Deploying to staging\")\n    assert.Contains(t, output, \"eu-west-1\")\n}\n```\n\n### ❌ Poor Error Messages\n\n**Wrong**:\n```go\nreturn fmt.Errorf(\"connection failed\") \u002F\u002F Unhelpful\n```\n\n**Correct**:\n```go\nreturn fmt.Errorf(\"cannot connect to database at %s:%d\\nCheck:\\n  - Database is running\\n  - Credentials (MYAPP_DB_PASSWORD)\\n  - Firewall rules\", host, port)\n```\n\n### ❌ Using Run Instead of RunE\n\n**Wrong**:\n```go\nvar rootCmd = &cobra.Command{\n    Use: \"myapp\",\n    Run: func(cmd *cobra.Command, args []string) {\n        if err := execute(); err != nil {\n            fmt.Println(err) \u002F\u002F Error not propagated\n        }\n    },\n}\n```\n\n**Correct**:\n```go\nvar rootCmd = &cobra.Command{\n    Use: \"myapp\",\n    RunE: func(cmd *cobra.Command, args []string) error {\n        return execute() \u002F\u002F Cobra handles error display and exit code\n    },\n}\n```\n\n## Production Example\n\nMinimal production-ready CLI structure:\n\n```\nmyapp\u002F\n├── cmd\u002F\n│   ├── root.go          # Root command + config loading\n│   ├── deploy.go        # Deploy subcommand\n│   ├── status.go        # Status subcommand\n│   └── completion.go    # Shell completion\n├── main.go              # Entry point\n├── config.yaml          # Example config file\n└── go.mod\n```\n\n**main.go**:\n```go\npackage main\n\nimport \"myapp\u002Fcmd\"\n\nfunc main() {\n    cmd.Execute()\n}\n```\n\n**cmd\u002Froot.go**: See \"Command Structure Pattern\" section above\n\n**Building and installing**:\n```bash\n# Development\ngo run main.go deploy staging --region us-west-2\n\n# Production build\ngo build -o myapp\n\n# Install globally\ngo install\n\n# Enable shell completion\nmyapp completion bash > \u002Fetc\u002Fbash_completion.d\u002Fmyapp\n```\n\n## Resources\n\n**Official Documentation**:\n- [Cobra User Guide](https:\u002F\u002Fcobra.dev\u002F) - Official framework documentation\n- [Viper Documentation](https:\u002F\u002Fgithub.com\u002Fspf13\u002Fviper) - Configuration management guide\n\n**Learning Resources**:\n- \"Building CLI Apps in Go with Cobra & Viper\" (November 2025) - Comprehensive tutorial\n- \"The Cobra & Viper Journey\" - Learning path for CLI development\n- [Cobra Generator](https:\u002F\u002Fgithub.com\u002Fspf13\u002Fcobra-cli) - Scaffolding tool for new CLIs\n\n**Production Examples**:\n- [kubectl](https:\u002F\u002Fgithub.com\u002Fkubernetes\u002Fkubectl) - Kubernetes CLI\n- [docker](https:\u002F\u002Fgithub.com\u002Fdocker\u002Fcli) - Docker CLI\n- [gh](https:\u002F\u002Fgithub.com\u002Fcli\u002Fcli) - GitHub CLI\n- [hugo](https:\u002F\u002Fgithub.com\u002Fgohugoio\u002Fhugo) - Static site generator\n\n**Related Skills**:\n- `golang-testing-strategies` - Testing CLI commands comprehensively\n- `golang-http-servers` - Building API servers with configuration\n- `golang-concurrency-patterns` - Async operations in CLI tools\n\n## Success Criteria\n\nYou know you've mastered Cobra + Viper when:\n- ✅ Commands follow POSIX conventions (`VERB NOUN --FLAG`)\n- ✅ Configuration precedence is clear: flags > env > config > defaults\n- ✅ All flags bound to Viper for unified config access\n- ✅ Shell completion generated for all major shells\n- ✅ Error messages are actionable and user-friendly\n- ✅ CLI commands have comprehensive tests\n- ✅ Help text auto-generated and accurate\n- ✅ PersistentPreRunE used for global setup\u002Fvalidation\n- ✅ Separation of concerns: user output (stdout) vs. logging (stderr)\n- ✅ Config files optional - CLI works with flags\u002Fenv vars alone\n",{"name":5,"tags":49,"author":53,"license":15,"version":54,"category":55,"description":7,"context_limit":56,"requires_tools":57,"progressive_disclosure":58},[28,25,26,50,51,52],"viper","configuration","shell-completion","Claude MPM Team","1.0.0","toolchain",700,[],{"entry_point":59,"token_estimate":63},{"summary":60,"quick_start":61,"when_to_use":62},"Build robust CLI tools with Cobra's command framework and Viper's configuration management for production-grade developer tools","1. Define command structure with Cobra 2. Integrate Viper for config priority 3. Bind flags to Viper 4. Add shell completion 5. Test CLI commands","Creating multi-command CLIs, building developer tools\u002Futilities, implementing DevOps automation, requiring flexible configuration (flags + env vars + config files), adding shell completion",{"full":64,"entry":65},4500,140,"main","62141d825eb73b2f691358c081d3da7d67278315",".claude\u002Fskills\u002Fgolang-cli-cobra-viper","https:\u002F\u002Fgithub.com\u002Fcastle-x\u002Fsonar","https:\u002F\u002Fgithub.com\u002Fcastle-x","2026-06-01 15:59:22",{"source":8,"skillName":5,"commands":73,"prompt":83,"zipAvailable":84},[74,77,80],{"tool":75,"command":76},"npx","npx skills add castle-x\u002Fsonar --skill golang-cli-cobra-viper",{"tool":78,"command":79},"bunx","bunx skills add castle-x\u002Fsonar --skill golang-cli-cobra-viper",{"tool":81,"command":82},"pnpm","pnpm dlx skills add castle-x\u002Fsonar --skill golang-cli-cobra-viper","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fcastle-x\u002Fsonar\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fgolang-cli-cobra-viper\u002FSKILL.md",true,[86,92],{"path":87,"resourceType":88,"resourceTypeDesc":89,"sizeBytes":90,"sourceHtmlUrl":91},".skills-x-meta.json","REFERENCE","参考文档",181,"https:\u002F\u002Fgithub.com\u002Fcastle-x\u002Fsonar\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fgolang-cli-cobra-viper\u002F.skills-x-meta.json",{"path":93,"resourceType":88,"resourceTypeDesc":89,"sizeBytes":94,"sourceHtmlUrl":95},"metadata.json",407,"https:\u002F\u002Fgithub.com\u002Fcastle-x\u002Fsonar\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fgolang-cli-cobra-viper\u002Fmetadata.json",[97,128,154,178,202,221],{"skillNo":98,"name":99,"nameZh":6,"description":100,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":101,"categories":102,"keywords":109,"publishedAt":44},"01M6PE1J3SKAAEVNCW7NTJ3TWH","tailwind-css-patterns","Comprehensive Tailwind CSS utility-first styling patterns including responsive design, layout utilities, flexbox, grid, spacing, typography, colors, and modern CSS best practices. Use when styling React\u002FVue\u002FSvelte components, building responsive layouts, implementing design systems, or optimizing CSS workflow.","https:\u002F\u002Fgithub.com\u002Fcastle-x\u002Fsonar\u002Fblob\u002Fmain\u002F.legacy\u002Fdatasource\u002F.codebuddy\u002Fskills\u002Ftailwind-css-patterns\u002FSKILL.md",[103,106],{"categoryNo":104,"categoryName":105,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":107,"categoryName":108,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",[110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,31,127,30],"css","Tailwind","patterns","Tailwind CSS","tailwind css patterns","design","tailwindcss","workflow","components","react","design systems","styling","tsx","responsive design","layout","svelte","utility","spacing",{"skillNo":129,"name":130,"nameZh":6,"description":131,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":132,"categories":133,"keywords":140,"publishedAt":44},"01M6PE0PCVCSDMP855MEAXEHCD","shadcn-ui","Complete shadcn\u002Fui component library guide including installation, configuration, and implementation of accessible React components. Use when setting up shadcn\u002Fui, installing components, building forms with React Hook Form and Zod, customizing themes with Tailwind CSS, or implementing UI patterns like buttons, dialogs, dropdowns, tables, and complex form layouts.","https:\u002F\u002Fgithub.com\u002Fcastle-x\u002Fsonar\u002Fblob\u002Fmain\u002F.legacy\u002Fdatasource\u002F.codebuddy\u002Fskills\u002Fshadcn-ui\u002FSKILL.md",[134,135],{"categoryNo":104,"categoryName":105,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":136,"categoryName":137,"taxonomyType":138,"taxonomyTypeDesc":139},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[141,142,143,110,116,118,119,144,145,146,147,111,148,149,150,151,122,152,30,153],"shadcn","ui","shadcn ui","react components","component","component library","nextjs","Bash","zod","read","up","themes","ui patterns",{"skillNo":155,"name":156,"nameZh":6,"description":157,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":158,"categories":159,"keywords":165,"publishedAt":44},"01M6PDZXXE4RRAVMJB5JH8S7B7","react-patterns","Comprehensive React 19 patterns expert covering Server Components, Actions, use() hook, useOptimistic, useFormStatus, useFormState, React Compiler, concurrent features, Suspense, and modern TypeScript development. Proactively use for any React development, component architecture, state management, performance optimization, or when implementing React 19's latest features.","https:\u002F\u002Fgithub.com\u002Fcastle-x\u002Fsonar\u002Fblob\u002Fmain\u002F.legacy\u002Fdatasource\u002F.codebuddy\u002Fskills\u002Freact-patterns\u002FSKILL.md",[160,161,162],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":104,"categoryName":105,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":163,"categoryName":164,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",[119,166,112,167,168,169,118,145,170,171,172,173,148,150,174,122,175,176,177,30],"react patterns","testing","frontend","performance","architecture","component architecture","server","actions","hooks","expert","react 19","Server Components",{"skillNo":179,"name":180,"nameZh":6,"description":181,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":182,"categories":183,"keywords":185,"publishedAt":44},"01M6PDZK79YYADCGJTJDBRK1HQ","vercel-react-native-skills","React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.","https:\u002F\u002Fgithub.com\u002Fcastle-x\u002Fsonar\u002Fblob\u002Fmain\u002F.legacy\u002Fdatasource\u002F.codebuddy\u002Fskills\u002Freact-native-skills\u002FSKILL.md",[184],{"categoryNo":104,"categoryName":105,"taxonomyType":21,"taxonomyTypeDesc":22},[119,186,187,188,189,190,169,118,191,192,193,194,195,196,197,198,199,30,200,201],"vercel react native skills","react native","vercel","react native skills","native","tasks","best practices","use","modules","platform","triggers","apps","react native components","with","for","animations",{"skillNo":203,"name":204,"nameZh":6,"description":205,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":206,"categories":207,"keywords":209,"publishedAt":44},"01M6PDZ8YY9QHYZQFWHAFJSJGK","vercel-react-best-practices","React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React\u002FNext.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.","https:\u002F\u002Fgithub.com\u002Fcastle-x\u002Fsonar\u002Fblob\u002Fmain\u002F.legacy\u002Fdatasource\u002F.codebuddy\u002Fskills\u002Freact-best-practices\u002FSKILL.md",[208],{"categoryNo":104,"categoryName":105,"taxonomyType":21,"taxonomyTypeDesc":22},[119,210,192,211,188,212,169,118,144,213,191,214,215,216,217,112,218,219,196,220],"vercel react best practices","react best practices","writing","guidelines","code","Optimization","data","refactoring","next","pages","data fetching",{"skillNo":222,"name":223,"nameZh":6,"description":224,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":225,"categories":226,"keywords":227,"publishedAt":44},"01M6PDR22TXCNQ5220G6Y1WZ83","openspec-verify-change","Verify implementation matches change artifacts. Use when the user wants to validate that implementation is complete, correct, and coherent before archiving.","https:\u002F\u002Fgithub.com\u002Fcastle-x\u002Fsonar\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fopenspec-verify-change\u002FSKILL.md",[],[228,229,230,231,232,28,233,234,235,236,193,237,238,239,240],"change","openspec verify change","verify","verify change","openspec","validate","artifacts","correct","user","implementation","coherent","verify implementation","complete"]