go-cobra について
spf13/cobra を使った Go のコマンドラインアプリの構築とデバッグを支援するリファレンススキルです。コマンド構成、フラグ、引数検証、補完、ドキュメント生成などを扱います。
主な機能
- 01コマンドとサブコマンドの構築
- 02ローカルフラグと永続フラグの設定
- 03位置引数の検証
- 04ライフサイクルフックとエラー処理
- 05シェル補完とドキュメントの生成
活用シーン
- 01Go アプリへのコマンド追加
- 02CLI のフラグと引数チェックの実装
- 03シェル補完やコマンドドキュメントの作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ aaronflorey/ agent-skills --skill go-cobraインストール後、Claude Code で/go-cobraを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/advanced.mdcompletions.mddocgen.mdviper-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 | 実際のコマンドロジック |
RunE | Run と同じですが、エラーを返します |
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(®ion, "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
}
ライフサイクルフック
フックは次の順序で実行されます。
PersistentPreRun(子コマンドに継承されます)PreRunRunPostRunPersistentPostRun(子コマンドに継承されます)
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— 高度なパターンと例外ケース