refactor: move run to its own file

Carlos Alexandro Becker created

Change summary

internal/cmd/root.go | 53 ++---------------------------------------
internal/cmd/run.go  | 58 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 50 deletions(-)

Detailed changes

internal/cmd/root.go 🔗

@@ -6,7 +6,6 @@ import (
 	"io"
 	"log/slog"
 	"os"
-	"strings"
 
 	tea "github.com/charmbracelet/bubbletea/v2"
 	"github.com/charmbracelet/crush/internal/app"
@@ -26,7 +25,6 @@ func init() {
 	rootCmd.Flags().BoolP("help", "h", false, "Help")
 	rootCmd.Flags().BoolP("yolo", "y", false, "Automatically accept all permissions (dangerous mode)")
 
-	runCmd.Flags().BoolP("quiet", "q", false, "Hide spinner")
 	rootCmd.AddCommand(runCmd)
 }
 
@@ -81,51 +79,6 @@ crush -y
 	},
 }
 
-var runCmd = &cobra.Command{
-	Use:   "run [prompt...]",
-	Short: "Run a single non-interactive prompt",
-	Long: `Run a single prompt in non-interactive mode and exit.
-The prompt can be provided as arguments or piped from stdin.`,
-	Example: `
-# Run a simple prompt
-crush run Explain the use of context in Go
-
-# Pipe input from stdin
-echo "What is this code doing?" | crush run
-
-# Run with quiet mode (no spinner)
-crush run -q "Generate a README for this project"
-  `,
-	RunE: func(cmd *cobra.Command, args []string) error {
-		quiet, _ := cmd.Flags().GetBool("quiet")
-
-		app, err := setupApp(cmd)
-		if err != nil {
-			return err
-		}
-		defer app.Shutdown()
-
-		if !app.Config().IsConfigured() {
-			return fmt.Errorf("no providers configured - please run 'crush' to set up a provider interactively")
-		}
-
-		prompt := strings.Join(args, " ")
-
-		prompt, err = maybePrependStdin(prompt)
-		if err != nil {
-			slog.Error("Failed to read from stdin", "error", err)
-			return err
-		}
-
-		if prompt == "" {
-			return fmt.Errorf("no prompt provided")
-		}
-
-		// Run non-interactive flow using the App method
-		return app.RunNonInteractive(cmd.Context(), prompt, quiet)
-	},
-}
-
 func Execute() {
 	if err := fang.Execute(
 		context.Background(),
@@ -144,7 +97,7 @@ func setupApp(cmd *cobra.Command) (*app.App, error) {
 	yolo, _ := cmd.Flags().GetBool("yolo")
 	ctx := cmd.Context()
 
-	cwd, err := resolveCwd(cmd)
+	cwd, err := ResolveCwd(cmd)
 	if err != nil {
 		return nil, err
 	}
@@ -174,7 +127,7 @@ func setupApp(cmd *cobra.Command) (*app.App, error) {
 	return appInstance, nil
 }
 
-func maybePrependStdin(prompt string) (string, error) {
+func MaybePrependStdin(prompt string) (string, error) {
 	if term.IsTerminal(os.Stdin.Fd()) {
 		return prompt, nil
 	}
@@ -192,7 +145,7 @@ func maybePrependStdin(prompt string) (string, error) {
 	return string(bts) + "\n\n" + prompt, nil
 }
 
-func resolveCwd(cmd *cobra.Command) (string, error) {
+func ResolveCwd(cmd *cobra.Command) (string, error) {
 	cwd, _ := cmd.Flags().GetString("cwd")
 	if cwd != "" {
 		err := os.Chdir(cwd)

internal/cmd/run.go 🔗

@@ -0,0 +1,58 @@
+package cmd
+
+import (
+	"fmt"
+	"log/slog"
+	"strings"
+
+	"github.com/spf13/cobra"
+)
+
+var runCmd = &cobra.Command{
+	Use:   "run [prompt...]",
+	Short: "Run a single non-interactive prompt",
+	Long: `Run a single prompt in non-interactive mode and exit.
+The prompt can be provided as arguments or piped from stdin.`,
+	Example: `
+# Run a simple prompt
+crush run Explain the use of context in Go
+
+# Pipe input from stdin
+echo "What is this code doing?" | crush run
+
+# Run with quiet mode (no spinner)
+crush run -q "Generate a README for this project"
+  `,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		quiet, _ := cmd.Flags().GetBool("quiet")
+
+		app, err := setupApp(cmd)
+		if err != nil {
+			return err
+		}
+		defer app.Shutdown()
+
+		if !app.Config().IsConfigured() {
+			return fmt.Errorf("no providers configured - please run 'crush' to set up a provider interactively")
+		}
+
+		prompt := strings.Join(args, " ")
+
+		prompt, err = MaybePrependStdin(prompt)
+		if err != nil {
+			slog.Error("Failed to read from stdin", "error", err)
+			return err
+		}
+
+		if prompt == "" {
+			return fmt.Errorf("no prompt provided")
+		}
+
+		// Run non-interactive flow using the App method
+		return app.RunNonInteractive(cmd.Context(), prompt, quiet)
+	},
+}
+
+func init() {
+	runCmd.Flags().BoolP("quiet", "q", false, "Hide spinner")
+}