mcpField
G
go-cobra

go-cobra

github.com/aaronflorey開発275 回インストール25 週間前に更新
リポジトリ

go-cobra について

spf13/cobra を使った Go のコマンドラインアプリの構築とデバッグを支援するリファレンススキルです。コマンド構成、フラグ、引数検証、補完、ドキュメント生成などを扱います。

主な機能

  1. 01コマンドとサブコマンドの構築
  2. 02ローカルフラグと永続フラグの設定
  3. 03位置引数の検証
  4. 04ライフサイクルフックとエラー処理
  5. 05シェル補完とドキュメントの生成

活用シーン

  1. 01Go アプリへのコマンド追加
  2. 02CLI のフラグと引数チェックの実装
  3. 03シェル補完やコマンドドキュメントの作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/aaronflorey/agent-skills --skill go-cobra

インストール後、Claude Code で/go-cobraを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
advanced.md
completions.md
docgen.md
viper-integration.md

詳細

Cobra CLI フレームワークのスキル

spf13/cobra ライブラリを使用して、Go の CLI アプリケーションを作成、スキャフォールド、デバッグします。ユーザーが Go でコマンドラインインターフェイスを構築したい場合、CLI にコマンド/サブコマンドを追加したい場合、フラグ(永続、ローカル、必須)を扱いたい場合、シェル補完を実装したい場合、ドキュメントを生成したい場合、または Cobra ベースの CLI 開発について何か質問した場合は、必ずこのスキルを使用してください。「CLI ツールを作りたい」や「Go アプリにコマンドを追加するには?」と言われただけの場合も対象です。


クイックスタート

インストール
go get -u github.com/spf13/cobra@latest

CLI ジェネレーター(任意ですが、スキャフォールディングに推奨):

go install github.com/spf13/cobra-cli@latest
プロジェクト構成
myapp/
  cmd/
    root.go       # Root command and Execute()
    version.go    # Additional commands
    serve.go
  main.go         # Just calls cmd.Execute()
最小限の main.go
package main

import "myapp/cmd"

func main() {
    cmd.Execute()
}
最小限の root.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)
    }
}

基本概念

コマンドは操作を表します。引数は対象を表します。フラグは動作を変更します。

パターン:APPNAME COMMAND ARG --FLAG

例:

  • hugo server --port=1313 — 「server」はコマンド、「port」はフラグです
  • git clone URL --bare — 「clone」はコマンド、「URL」は引数、「bare」はフラグです

コマンドの構造

コマンドの作成
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)
}
コマンドの主なフィールド
フィールド目的
Use使用パターン:「command [args]」
Aliases代替名:[]string{"s", "srv"}
Shortヘルプ一覧に表示する簡潔な説明
Long--help に表示する詳しい説明
Example使用例(2 つのスペースでインデント)
Run実際のコマンドロジック
RunERun と同じですが、エラーを返します
Args位置引数の検証
ValidArgsシェル補完用の静的な一覧
ValidArgsFunction動的な補完関数
Hiddenヘルプ出力から非表示にします
Deprecatedメッセージを付けて非推奨としてマークします
Versionバージョン文字列(--version を有効にします)
Run と RunE の違い

呼び出し元にエラーを返す必要がある場合は、RunE を使用します。

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
    },
}

フラグ

フラグの種類

永続フラグ — このコマンドとすべてのサブコマンドで使用できます。

rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file path")
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")

ローカルフラグ — このコマンドでのみ使用できます。

serveCmd.Flags().IntVarP(&port, "port", "p", 8080, "port to listen on")
serveCmd.Flags().StringVar(&host, "host", "localhost", "host address")
フラグのメソッド
メソッド例
StringVar--name value
StringVarP--name value または -n value
BoolVar--verbose(true)または --verbose=false
IntVar--count 5
StringSliceVar--tag a --tag b または --tag a,b
StringArrayVar--tag a --tag b(カンマで分割しません)
CountVarP-v(1)、-vv(2)、-vvv(3)
必須フラグ
cmd.Flags().StringVarP(&region, "region", "r", "", "AWS region")
cmd.MarkFlagRequired("region")

// For persistent flags
cmd.MarkPersistentFlagRequired("config")
フラググループ
// 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")
カウントフラグ(詳細度パターン)
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 = 3

位置引数

組み込みバリデーター
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 list
バリデーターの組み合わせ
cmd.Args = cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs)
カスタムバリデーター
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
}

ライフサイクルフック

フックは次の順序で実行されます。

  1. PersistentPreRun(子コマンドに継承されます)
  2. PreRun
  3. Run
  4. PostRun
  5. PersistentPostRun(子コマンドに継承されます)
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
    },
}

エラーを返すには、*RunE 版を使用します。

PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
    return initConfig()
}

Viper との統合

Cobra は設定管理用の Viper とシームレスに統合できます。詳細なドキュメントについては、references/viper-integration.md を参照してください。

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 values

ヘルプと使用方法

自動機能
  • --help / -h フラグが自動的に追加されます
  • サブコマンドがある場合、help サブコマンドが追加されます
  • 入力ミスの候補表示:myapp srever → 「Did you mean 'server'?」
カスタマイズ
// 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 = 1
バージョンフラグ
var rootCmd = &cobra.Command{
    Use:     "myapp",
    Version: "1.0.0",  // Enables --version flag
}

// Custom version template
cmd.SetVersionTemplate(`Version: {{.Version}}`)
コマンドのグループ化
rootCmd.AddGroup(&cobra.Group{ID: "core", Title: "Core Commands:"})
rootCmd.AddGroup(&cobra.Group{ID: "util", Title: "Utility Commands:"})

serveCmd.GroupID = "core"
versionCmd.GroupID = "util"

シェル補完

Cobra は completion コマンドを自動的に提供します。シェル補完の実装について詳しくは、references/completions.md を参照してください。

簡単な使用例:

# Bash
source <(myapp completion bash)

# Zsh  
myapp completion zsh > "${fpath[1]}/_myapp"

# Fish
myapp completion fish > ~/.config/fish/completions/myapp.fish

# PowerShell
myapp completion powershell | Out-String | Invoke-Expression
動的な補完
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
}

ドキュメントの生成

Cobra は man ページや Markdown などを生成できます。詳細については、references/docgen.md を参照してください。

簡単な例:

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")

プラグインの作成

プラグインを使用する kubectl のようなツール(kubectl-myplugin を kubectl myplugin として呼び出す)の場合:

rootCmd := &cobra.Command{
    Use: "kubectl-myplugin",
    Annotations: map[string]string{
        cobra.CommandDisplayNameAnnotation: "kubectl myplugin",
    },
}

グローバル設定

// 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 = false

コマンドのテスト

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())
    }
}

コンテキストのサポート

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)

一般的なパターン

サブコマンドの構成

大規模なアプリでは、サブコマンドを別々のパッケージに整理します。

cmd/
  root.go
  config/
    config.go      # Defines configCmd
    get.go         # config get
    set.go         # config set
// 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)
}
エラー処理
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 = true
サイレント/クワイエットモード
var quiet bool

func init() {
    rootCmd.PersistentFlags().BoolVarP(&quiet, "quiet", "q", false, "suppress output")
}

func output(msg string) {
    if !quiet {
        fmt.Println(msg)
    }
}

参考ファイル

特定のトピックについて詳しくは、以下をご覧ください。

  • references/completions.md — シェル補完の実装の詳細
  • references/docgen.md — ドキュメント生成(man、markdown、yaml、rst)
  • references/advanced.md — 高度なパターンと例外ケース

コメント