diff --git a/cmd/cmd.go b/cmd/cmd.go
index 91819c8e..65436170 100644
--- a/cmd/cmd.go
+++ b/cmd/cmd.go
@@ -422,6 +422,12 @@ func RunHandler(cmd *cobra.Command, args []string) error {
 		Options:  map[string]interface{}{},
 	}
 
+	quiet, err := cmd.Flags().GetBool("quiet")
+	if err != nil {
+		return err
+	}
+	opts.Spinner = !quiet
+
 	format, err := cmd.Flags().GetString("format")
 	if err != nil {
 		return err
@@ -975,6 +981,7 @@ type runOptions struct {
 	Options     map[string]interface{}
 	MultiModal  bool
 	KeepAlive   *api.Duration
+	Spinner     bool
 }
 
 type displayResponseState struct {
@@ -1113,11 +1120,12 @@ func generate(cmd *cobra.Command, opts runOptions) error {
 		return err
 	}
 
-	p := progress.NewProgress(os.Stderr)
-	defer p.StopAndClear()
-
-	spinner := progress.NewSpinner("")
-	p.Add("", spinner)
+	var p *progress.Progress
+	if opts.Spinner {
+		p = progress.NewProgress(os.Stderr)
+		defer p.StopAndClear()
+		p.Add("", progress.NewSpinner(""))
+	}
 
 	var latest api.GenerateResponse
 
@@ -1140,7 +1148,9 @@ func generate(cmd *cobra.Command, opts runOptions) error {
 	var state *displayResponseState = &displayResponseState{}
 
 	fn := func(response api.GenerateResponse) error {
-		p.StopAndClear()
+		if p != nil {
+			p.StopAndClear()
+		}
 
 		latest = response
 		content := response.Response
@@ -1380,6 +1390,7 @@ func NewCLI() *cobra.Command {
 	runCmd.Flags().Bool("insecure", false, "Use an insecure registry")
 	runCmd.Flags().Bool("nowordwrap", false, "Don't wrap words to the next line automatically")
 	runCmd.Flags().String("format", "", "Response format (e.g. json)")
+	runCmd.Flags().Bool("quiet", false, "Only render the response text without any progress")
 
 	stopCmd := &cobra.Command{
 		Use:     "stop MODEL",