package main import ( "fmt" "os" "path/filepath" "strings" "github.com/spf13/cobra" ) var rootCmd = &cobra.Command{ Use: "dev", Short: "Development script runner", Long: "A CLI tool for managing and running development scripts", RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }, } var runCmd = &cobra.Command{ Use: "run [script-filters...] [-- script-args...]", Short: "Run scripts matching filters (or all if no filters)", Long: `Run scripts matching filters. Use -- to pass arguments to scripts. Scripts marked with "# REQUIRES: sudo" will automatically run with elevated privileges. Examples: dev run tools/dev.sh # Run specific script dev run tools/dev.sh -- arg1 arg2 # Run with arguments dev run --verbose install -- --force # Run with flags `, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if err := ensureRunsDir(); err != nil { return nil, cobra.ShellCompDirectiveNoFileComp } scripts, err := findScripts(nil) if err != nil { return nil, cobra.ShellCompDirectiveNoFileComp } var completions []string for _, script := range scripts { desc := script.Desc if script.RequiresSudo { desc = desc + " [SUDO]" } completions = append(completions, fmt.Sprintf("%s\t%s", script.RelPath, desc)) } return completions, cobra.ShellCompDirectiveNoFileComp }, RunE: func(cmd *cobra.Command, args []string) error { // Parse arguments manually to handle -- separator var filters []string var scriptArgs []string // Find "run" command position and -- separator in raw args cmdPos := -1 separatorPos := -1 rawArgs := os.Args for i, arg := range rawArgs { if arg == "run" { cmdPos = i break } } if cmdPos >= 0 { for i := cmdPos + 1; i < len(rawArgs); i++ { if rawArgs[i] == "--" { separatorPos = i break } } } if separatorPos >= 0 { // Get everything between 'run' and '--' as filters filters = rawArgs[cmdPos+1 : separatorPos] // Remove any flags from filters for i := 0; i < len(filters); i++ { if strings.HasPrefix(filters[i], "-") { filters = append(filters[:i], filters[i+1:]...) i-- } } // Get everything after '--' as script args scriptArgs = rawArgs[separatorPos+1:] } else { // No '--' separator found, consider all non-flag args as filters for _, arg := range args { if !strings.HasPrefix(arg, "-") { filters = append(filters, arg) } } } if err := ensureRunsDir(); err != nil { return err } scripts, err := findScripts(filters) if err != nil { return err } if len(scripts) == 0 { if len(filters) > 0 { warn("No scripts match filters: %s", strings.Join(filters, ", ")) } else { warn("No scripts found. Use 'dev new ' to create one") } return nil } for _, script := range scripts { if config.DryRun { argsStr := "" if len(scriptArgs) > 0 { argsStr = fmt.Sprintf(" with args: %s", strings.Join(scriptArgs, " ")) } sudoStr := "" if script.RequiresSudo { sudoStr = " (with sudo)" } log("Would run: %s%s%s", script.RelPath, argsStr, sudoStr) } else { if err := executeScript(script, scriptArgs, config.Verbose); err != nil { errorLog("❌ %s failed", script.RelPath) if !config.Verbose { fmt.Printf(" Check log: %s\n", filepath.Join(config.LogsDir, strings.TrimSuffix(script.Name, filepath.Ext(script.Name))+".log")) } } else { if script.RequiresSudo { sudoLog("✅ %s completed (elevated)", script.RelPath) } else { log("✅ %s completed", script.RelPath) } } } } return nil }, } var listCmd = &cobra.Command{ Use: "ls", Aliases: []string{"list"}, Short: "List all available scripts", RunE: func(cmd *cobra.Command, args []string) error { if err := ensureRunsDir(); err != nil { return err } scripts, err := findScripts(nil) if err != nil { return err } if len(scripts) == 0 { warn("No scripts found in %s", config.RunsDir) fmt.Println("Use 'dev new ' to create a new script") return nil } fmt.Printf("Available scripts in %s:\n\n", config.RunsDir) for _, script := range scripts { if script.RequiresSudo { fmt.Printf(" %s%s%s - %s %s[SUDO]%s\n", Blue, script.RelPath, NC, script.Desc, Purple, NC) } else { fmt.Printf(" %s%s%s - %s\n", Blue, script.RelPath, NC, script.Desc) } } sudoCount := 0 for _, script := range scripts { if script.RequiresSudo { sudoCount++ } } fmt.Printf("\nTotal: %d scripts", len(scripts)) if sudoCount > 0 { fmt.Printf(" (%d require elevated privileges)", sudoCount) } fmt.Println() return nil }, } var newCmd = &cobra.Command{ Use: "new ", Short: "Create a new script template", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { return createNewScript(args[0]) }, } var pushCmd = &cobra.Command{ Use: "push", Aliases: []string{"u", "ush"}, Short: "Commit, scan for secrets, and push to git origin", RunE: func(cmd *cobra.Command, args []string) error { return handlePush() }, } var depsCmd = &cobra.Command{ Use: "deps", Short: "Install dependencies", RunE: func(cmd *cobra.Command, args []string) error { return checkDependencies() }, } var completionCmd = &cobra.Command{ Use: "completion [bash|zsh|fish]", Short: "Generate completion script", Long: `To load completions: Bash: $ source <(dev completion bash) # To load completions for each session, execute once: # Linux: $ dev completion bash > /etc/bash_completion.d/dev # macOS: $ dev completion bash > $(brew --prefix)/etc/bash_completion.d/dev Zsh: # If shell completion is not already enabled in your environment, # you will need to enable it. You can execute the following once: $ echo "autoload -U compinit; compinit" >> ~/.zshrc # To load completions for each session, execute once: $ dev completion zsh > "${fpath[1]}/_dev" # You will need to start a new shell for this setup to take effect. `, DisableFlagsInUseLine: true, ValidArgs: []string{"bash", "zsh", "fish"}, Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), RunE: func(cmd *cobra.Command, args []string) error { switch args[0] { case "bash": return rootCmd.GenBashCompletion(os.Stdout) case "zsh": return rootCmd.GenZshCompletion(os.Stdout) case "fish": return rootCmd.GenFishCompletion(os.Stdout, true) } return nil }, }