Core plugin providing: - Skills: core CLI reference, PHP patterns, Go patterns - Commands: /core:remember for context persistence - Hooks: - PreToolUse: block dangerous commands (rm -rf, sed -i, grep -l |) - PreToolUse: enforce core CLI over raw go/php commands - PostToolUse: auto-format Go/PHP, check for debug statements - PostToolUse: warn about uncommitted work after git commit - PreCompact: save state to prevent amnesia after auto-compact - SessionStart: restore context from recent sessions (<3h) - MCP: core CLI server integration Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
193 lines
7.3 KiB
Go
193 lines
7.3 KiB
Go
package cli
|
|
|
|
import (
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Command Type Re-export
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
// Command is the cobra command type.
|
|
// Re-exported for convenience so packages don't need to import cobra directly.
|
|
type Command = cobra.Command
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Command Builders
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
// NewCommand creates a new command with a RunE handler.
|
|
// This is the standard way to create commands that may return errors.
|
|
//
|
|
// cmd := cli.NewCommand("build", "Build the project", "", func(cmd *cli.Command, args []string) error {
|
|
// // Build logic
|
|
// return nil
|
|
// })
|
|
func NewCommand(use, short, long string, run func(cmd *Command, args []string) error) *Command {
|
|
cmd := &Command{
|
|
Use: use,
|
|
Short: short,
|
|
RunE: run,
|
|
}
|
|
if long != "" {
|
|
cmd.Long = long
|
|
}
|
|
return cmd
|
|
}
|
|
|
|
// NewGroup creates a new command group (no RunE).
|
|
// Use this for parent commands that only contain subcommands.
|
|
//
|
|
// devCmd := cli.NewGroup("dev", "Development commands", "")
|
|
// devCmd.AddCommand(buildCmd, testCmd)
|
|
func NewGroup(use, short, long string) *Command {
|
|
cmd := &Command{
|
|
Use: use,
|
|
Short: short,
|
|
}
|
|
if long != "" {
|
|
cmd.Long = long
|
|
}
|
|
return cmd
|
|
}
|
|
|
|
// NewRun creates a new command with a simple Run handler (no error return).
|
|
// Use when the command cannot fail.
|
|
//
|
|
// cmd := cli.NewRun("version", "Show version", "", func(cmd *cli.Command, args []string) {
|
|
// cli.Println("v1.0.0")
|
|
// })
|
|
func NewRun(use, short, long string, run func(cmd *Command, args []string)) *Command {
|
|
cmd := &Command{
|
|
Use: use,
|
|
Short: short,
|
|
Run: run,
|
|
}
|
|
if long != "" {
|
|
cmd.Long = long
|
|
}
|
|
return cmd
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Flag Helpers
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
// StringFlag adds a string flag to a command.
|
|
// The value will be stored in the provided pointer.
|
|
//
|
|
// var output string
|
|
// cli.StringFlag(cmd, &output, "output", "o", "", "Output file path")
|
|
func StringFlag(cmd *Command, ptr *string, name, short, def, usage string) {
|
|
if short != "" {
|
|
cmd.Flags().StringVarP(ptr, name, short, def, usage)
|
|
} else {
|
|
cmd.Flags().StringVar(ptr, name, def, usage)
|
|
}
|
|
}
|
|
|
|
// BoolFlag adds a boolean flag to a command.
|
|
// The value will be stored in the provided pointer.
|
|
//
|
|
// var verbose bool
|
|
// cli.BoolFlag(cmd, &verbose, "verbose", "v", false, "Enable verbose output")
|
|
func BoolFlag(cmd *Command, ptr *bool, name, short string, def bool, usage string) {
|
|
if short != "" {
|
|
cmd.Flags().BoolVarP(ptr, name, short, def, usage)
|
|
} else {
|
|
cmd.Flags().BoolVar(ptr, name, def, usage)
|
|
}
|
|
}
|
|
|
|
// IntFlag adds an integer flag to a command.
|
|
// The value will be stored in the provided pointer.
|
|
//
|
|
// var count int
|
|
// cli.IntFlag(cmd, &count, "count", "n", 10, "Number of items")
|
|
func IntFlag(cmd *Command, ptr *int, name, short string, def int, usage string) {
|
|
if short != "" {
|
|
cmd.Flags().IntVarP(ptr, name, short, def, usage)
|
|
} else {
|
|
cmd.Flags().IntVar(ptr, name, def, usage)
|
|
}
|
|
}
|
|
|
|
// StringSliceFlag adds a string slice flag to a command.
|
|
// The value will be stored in the provided pointer.
|
|
//
|
|
// var tags []string
|
|
// cli.StringSliceFlag(cmd, &tags, "tag", "t", nil, "Tags to apply")
|
|
func StringSliceFlag(cmd *Command, ptr *[]string, name, short string, def []string, usage string) {
|
|
if short != "" {
|
|
cmd.Flags().StringSliceVarP(ptr, name, short, def, usage)
|
|
} else {
|
|
cmd.Flags().StringSliceVar(ptr, name, def, usage)
|
|
}
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Persistent Flag Helpers
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
// PersistentStringFlag adds a persistent string flag (inherited by subcommands).
|
|
func PersistentStringFlag(cmd *Command, ptr *string, name, short, def, usage string) {
|
|
if short != "" {
|
|
cmd.PersistentFlags().StringVarP(ptr, name, short, def, usage)
|
|
} else {
|
|
cmd.PersistentFlags().StringVar(ptr, name, def, usage)
|
|
}
|
|
}
|
|
|
|
// PersistentBoolFlag adds a persistent boolean flag (inherited by subcommands).
|
|
func PersistentBoolFlag(cmd *Command, ptr *bool, name, short string, def bool, usage string) {
|
|
if short != "" {
|
|
cmd.PersistentFlags().BoolVarP(ptr, name, short, def, usage)
|
|
} else {
|
|
cmd.PersistentFlags().BoolVar(ptr, name, def, usage)
|
|
}
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Command Configuration
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
// WithArgs sets the Args validation function for a command.
|
|
// Returns the command for chaining.
|
|
//
|
|
// cmd := cli.NewCommand("build", "Build", "", run).WithArgs(cobra.ExactArgs(1))
|
|
func WithArgs(cmd *Command, args cobra.PositionalArgs) *Command {
|
|
cmd.Args = args
|
|
return cmd
|
|
}
|
|
|
|
// WithExample sets the Example field for a command.
|
|
// Returns the command for chaining.
|
|
func WithExample(cmd *Command, example string) *Command {
|
|
cmd.Example = example
|
|
return cmd
|
|
}
|
|
|
|
// ExactArgs returns a PositionalArgs that accepts exactly N arguments.
|
|
func ExactArgs(n int) cobra.PositionalArgs {
|
|
return cobra.ExactArgs(n)
|
|
}
|
|
|
|
// MinimumNArgs returns a PositionalArgs that accepts minimum N arguments.
|
|
func MinimumNArgs(n int) cobra.PositionalArgs {
|
|
return cobra.MinimumNArgs(n)
|
|
}
|
|
|
|
// MaximumNArgs returns a PositionalArgs that accepts maximum N arguments.
|
|
func MaximumNArgs(n int) cobra.PositionalArgs {
|
|
return cobra.MaximumNArgs(n)
|
|
}
|
|
|
|
// NoArgs returns a PositionalArgs that accepts no arguments.
|
|
func NoArgs() cobra.PositionalArgs {
|
|
return cobra.NoArgs
|
|
}
|
|
|
|
// ArbitraryArgs returns a PositionalArgs that accepts any arguments.
|
|
func ArbitraryArgs() cobra.PositionalArgs {
|
|
return cobra.ArbitraryArgs
|
|
}
|