run.go 1.6 KB

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