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