一键导入
add-parent-command
Add a parent/root command that has subcommands
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Add a parent/root command that has subcommands
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Add a new runtime implementation to the kdn runtime system
Guide to using the instances manager API for workspace management and project detection
Guide to understanding and working with the kdn runtime system architecture
Guide to configuring the Podman runtime including image setup, agent configuration, and containerfile generation
Conventional Commit Message Generator
Guide to the autoconf package — how secret detection, filtering, and the runner are wired together, and how to extend the system with new detector types
| name | add-parent-command |
| description | Add a parent/root command that has subcommands |
| argument-hint | <parent-command-name> |
This skill helps you create a parent (root) command that organizes related subcommands under a common namespace (e.g., workspace with subcommands list, remove, init).
Create pkg/cmd/<parent>.go with the following structure:
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func New<Parent>Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "<parent>",
Short: "Short description of the parent command category",
Long: `Long description explaining what this command category does and what subcommands are available.`,
Example: `# Show available subcommands
kdn <parent> --help
# Execute a subcommand
kdn <parent> <subcommand>`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath())
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}
// Add subcommands
cmd.AddCommand(New<Parent><SubCommand1>Cmd())
cmd.AddCommand(New<Parent><SubCommand2>Cmd())
cmd.AddCommand(New<Parent><SubCommand3>Cmd())
return cmd
}
Example: Creating the workspace parent command
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func NewWorkspaceCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "workspace",
Short: "Manage workspace instances",
Long: `The workspace command provides subcommands for managing workspace instances.
Use these commands to initialize, list, and remove workspace configurations.`,
Example: `# Show available workspace subcommands
kdn workspace --help
# List all workspaces
kdn workspace list
# Remove a workspace
kdn workspace remove <id>`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath())
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}
// Add subcommands
cmd.AddCommand(NewWorkspaceListCmd())
cmd.AddCommand(NewWorkspaceRemoveCmd())
cmd.AddCommand(NewWorkspaceInitCmd())
return cmd
}
For each subcommand, create a separate file following the command patterns:
add-command-with-json skill for subcommands with JSON outputadd-command-simple skill for subcommands without JSON outputFile naming convention:
pkg/cmd/<parent>_<subcommand>.go for each subcommandNew<Parent><SubCommand>Cmd()Example subcommand structure:
// File: pkg/cmd/workspace_list.go
package cmd
import (
"github.com/spf13/cobra"
)
func NewWorkspaceListCmd() *cobra.Command {
c := &workspaceListCmd{}
cmd := &cobra.Command{
Use: "list",
Short: "List all workspaces",
Long: `List all initialized workspace instances with their details.`,
Example: `# List all workspaces
kdn workspace list
# List with JSON output
kdn workspace list --output json`,
Args: cobra.NoArgs,
PreRunE: c.preRun,
RunE: c.run,
}
cmd.Flags().StringVarP(&c.output, "output", "o", "", "Output format (supported: json)")
return cmd
}
In pkg/cmd/root.go, add to the NewRootCmd() function:
rootCmd.AddCommand(New<Parent>Cmd())
Optional: Assign to a command group
If you want the parent command to appear in a specific group in the help output:
// Define a group if it doesn't exist yet
rootCmd.AddGroup(&cobra.Group{
ID: "mygroup",
Title: "My Command Group:",
})
// Create and assign parent command to the group
parentCmd := New<Parent>Cmd()
parentCmd.GroupID = "mygroup"
rootCmd.AddCommand(parentCmd)
Existing groups:
main - Main Commands (for commonly used workspace operations)workspace - Workspace Commands (for the workspace parent command)Create pkg/cmd/<parent>_test.go:
package cmd
import (
"testing"
"github.com/openkaiden/kdn/pkg/cmd/testutil"
)
func Test<Parent>Cmd_Structure(t *testing.T) {
t.Parallel()
cmd := New<Parent>Cmd()
// Verify the command has subcommands
if !cmd.HasSubCommands() {
t.Fatal("Expected parent command to have subcommands")
}
// Verify specific subcommands exist
expectedSubcommands := []string{"<subcommand1>", "<subcommand2>", "<subcommand3>"}
for _, name := range expectedSubcommands {
if _, _, err := cmd.Find([]string{name}); err != nil {
t.Errorf("Expected subcommand '%s' to exist, but not found", name)
}
}
}
func Test<Parent>Cmd_NoArgs(t *testing.T) {
t.Parallel()
cmd := New<Parent>Cmd()
// Verify Args validator
if cmd.Args == nil {
t.Error("Expected Args validator to be set")
}
// Verify it accepts no args
err := cmd.Args(cmd, []string{"unexpected-arg"})
if err == nil {
t.Error("Expected error when passing arguments to parent command")
}
}
func Test<Parent>Cmd_Examples(t *testing.T) {
t.Parallel()
cmd := New<Parent>Cmd()
if cmd.Example == "" {
t.Fatal("Example field should not be empty")
}
commands, err := testutil.ParseExampleCommands(cmd.Example)
if err != nil {
t.Fatalf("Failed to parse examples: %v", err)
}
// Parent commands typically have 2-3 examples
expectedCount := 2
if len(commands) != expectedCount {
t.Errorf("Expected %d example commands, got %d", expectedCount, len(commands))
}
rootCmd := NewRootCmd()
err = testutil.ValidateCommandExamples(rootCmd, cmd.Example)
if err != nil {
t.Errorf("Example validation failed: %v", err)
}
}
# Run tests for the parent command
go test ./pkg/cmd -run Test<Parent>
# Run all tests
make test
Update relevant documentation to describe the parent command and its subcommands.
RunE (showing help) so that Cobra treats them as runnable and runs Args validation. Without RunE, Cobra skips Args entirely and returns exit code 0 for unknown subcommands.Args function instead of cobra.NoArgs to produce unknown command "foo" for "kdn parent" rather than the generic accepts 0 arg(s), received 1.cmd.AddCommand() to register all subcommands.func NewParentCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "parent",
Short: "Parent command category",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath())
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}
cmd.AddCommand(NewParentSubCmd1())
cmd.AddCommand(NewParentSubCmd2())
return cmd
}
If you want flags available to all subcommands:
func NewParentCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "parent",
Short: "Parent command category",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath())
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}
// Persistent flags are inherited by subcommands
cmd.PersistentFlags().Bool("verbose", false, "Verbose output for all subcommands")
cmd.AddCommand(NewParentSubCmd1())
cmd.AddCommand(NewParentSubCmd2())
return cmd
}
If subcommands need common setup:
func NewParentCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "parent",
Short: "Parent command category",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath())
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
PersistentPreRun: func(cmd *cobra.Command, args []string) {
// Common initialization for all subcommands
// This runs before any subcommand's PreRun
},
}
cmd.AddCommand(NewParentSubCmd1())
cmd.AddCommand(NewParentSubCmd2())
return cmd
}
For a parent command named workspace with subcommands list, remove, init:
pkg/cmd/
├── workspace.go # Parent command: NewWorkspaceCmd()
├── workspace_test.go # Parent command tests
├── workspace_list.go # Subcommand: NewWorkspaceListCmd()
├── workspace_list_test.go # Subcommand tests
├── workspace_remove.go # Subcommand: NewWorkspaceRemoveCmd()
├── workspace_remove_test.go
├── workspace_init.go # Subcommand: NewWorkspaceInitCmd()
└── workspace_init_test.go
File: pkg/cmd/workspace.go
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func NewWorkspaceCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "workspace",
Short: "Manage workspace instances",
Long: `The workspace command provides subcommands for managing workspace instances.
Use these commands to initialize new workspaces, list existing ones, and remove
workspaces that are no longer needed.`,
Example: `# Show available workspace subcommands
kdn workspace --help
# List all workspaces
kdn workspace list
# Remove a workspace
kdn workspace remove <id>
# Initialize a new workspace
kdn workspace init /path/to/project`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath())
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}
// Add subcommands
cmd.AddCommand(NewWorkspaceListCmd())
cmd.AddCommand(NewWorkspaceRemoveCmd())
cmd.AddCommand(NewWorkspaceInitCmd())
return cmd
}
File: pkg/cmd/workspace_test.go
package cmd
import (
"testing"
"github.com/openkaiden/kdn/pkg/cmd/testutil"
)
func TestWorkspaceCmd_Structure(t *testing.T) {
t.Parallel()
cmd := NewWorkspaceCmd()
if !cmd.HasSubCommands() {
t.Fatal("Expected workspace command to have subcommands")
}
expectedSubcommands := []string{"list", "remove", "init"}
for _, name := range expectedSubcommands {
if _, _, err := cmd.Find([]string{name}); err != nil {
t.Errorf("Expected subcommand '%s' to exist, but not found", name)
}
}
}
func TestWorkspaceCmd_NoArgs(t *testing.T) {
t.Parallel()
cmd := NewWorkspaceCmd()
if cmd.Args == nil {
t.Error("Expected Args validator to be set")
}
err := cmd.Args(cmd, []string{"unexpected-arg"})
if err == nil {
t.Error("Expected error when passing arguments to workspace command")
}
}
func TestWorkspaceCmd_Examples(t *testing.T) {
t.Parallel()
cmd := NewWorkspaceCmd()
if cmd.Example == "" {
t.Fatal("Example field should not be empty")
}
commands, err := testutil.ParseExampleCommands(cmd.Example)
if err != nil {
t.Fatalf("Failed to parse examples: %v", err)
}
expectedCount := 4
if len(commands) != expectedCount {
t.Errorf("Expected %d example commands, got %d", expectedCount, len(commands))
}
rootCmd := NewRootCmd()
err = testutil.ValidateCommandExamples(rootCmd, cmd.Example)
if err != nil {
t.Errorf("Example validation failed: %v", err)
}
}
pkg/cmd/workspace.go - Complete parent command implementationpkg/cmd/workspace_test.go - Parent command tests