1package cmd
2
3import (
4 "fmt"
5 "log/slog"
6 "os"
7 "strings"
8
9 "github.com/spf13/cobra"
10)
11
12var runCmd = &cobra.Command{
13 Use: "run [prompt...]",
14 Short: "Run a single non-interactive prompt",
15 Long: `Run a single prompt in non-interactive mode and exit.
16The prompt can be provided as arguments or piped from stdin.`,
17 Example: `
18# Run a simple prompt
19crush run Explain the use of context in Go
20
21# Pipe input from stdin
22echo "What is this code doing?" | crush run
23
24# Run with quiet mode (no spinner)
25crush run -q "Generate a README for this project"
26 `,
27 RunE: func(cmd *cobra.Command, args []string) error {
28 quiet, _ := cmd.Flags().GetBool("quiet")
29
30 app, err := setupApp(cmd)
31 if err != nil {
32 return err
33 }
34 defer app.Shutdown()
35
36 if !app.Config().IsConfigured() {
37 return fmt.Errorf("no providers configured - please run 'crush' to set up a provider interactively")
38 }
39
40 prompt := strings.Join(args, " ")
41
42 prompt, err = MaybePrependStdin(prompt)
43 if err != nil {
44 slog.Error("Failed to read from stdin", "error", err)
45 return err
46 }
47
48 if prompt == "" {
49 return fmt.Errorf("no prompt provided")
50 }
51
52 // TODO: Make this work when redirected to something other than stdout.
53 // For example:
54 // crush run "Do something fancy" > output.txt
55 // echo "Do something fancy" | crush run > output.txt
56 //
57 // TODO: We currently need to press ^c twice to cancel. Fix that.
58 return app.RunNonInteractive(cmd.Context(), os.Stdout, prompt, quiet)
59 },
60}
61
62func init() {
63 runCmd.Flags().BoolP("quiet", "q", false, "Hide spinner")
64}