diff --git a/src/Concerns/Cursor.php b/src/Concerns/Cursor.php
index 1a2f1e17..0dcb5f10 100644
--- a/src/Concerns/Cursor.php
+++ b/src/Concerns/Cursor.php
@@ -14,7 +14,7 @@ trait Cursor
      */
     public function hideCursor(): void
     {
-        static::writeDirectly("\e[?25l");
+        static::writer()->writeDirectly("\e[?25l");
 
         static::$cursorHidden = true;
     }
@@ -24,7 +24,7 @@ public function hideCursor(): void
      */
     public function showCursor(): void
     {
-        static::writeDirectly("\e[?25h");
+        static::writer()->writeDirectly("\e[?25h");
 
         static::$cursorHidden = false;
     }
@@ -58,6 +58,6 @@ public function moveCursor(int $x, int $y = 0): void
             $sequence .= "\e[{$y}B"; // Down
         }
 
-        static::writeDirectly($sequence);
+        static::writer()->writeDirectly($sequence);
     }
 }
diff --git a/src/Concerns/Erase.php b/src/Concerns/Erase.php
index 943dba6e..7de49fa2 100644
--- a/src/Concerns/Erase.php
+++ b/src/Concerns/Erase.php
@@ -18,7 +18,7 @@ public function eraseLines(int $count): void
             $clear .= "\e[G";
         }
 
-        static::writeDirectly($clear);
+        static::writer()->writeDirectly($clear);
     }
 
     /**
@@ -26,6 +26,6 @@ public function eraseLines(int $count): void
      */
     public function eraseDown(): void
     {
-        static::writeDirectly("\e[J");
+        static::writer()->writeDirectly("\e[J");
     }
 }
diff --git a/src/Concerns/FakesInputOutput.php b/src/Concerns/FakesInputOutput.php
index 2df265f1..29745cc8 100644
--- a/src/Concerns/FakesInputOutput.php
+++ b/src/Concerns/FakesInputOutput.php
@@ -74,11 +74,12 @@ public static function assertStrippedOutputDoesntContain(string $string): void
      */
     public static function content(): string
     {
-        if (! static::output() instanceof BufferedConsoleOutput) {
+        $output = static::writer()->getOutput();
+        if (! $output instanceof BufferedConsoleOutput) {
             throw new RuntimeException('Prompt must be faked before accessing content.');
         }
 
-        return static::output()->content();
+        return $output->content();
     }
 
     /**
diff --git a/src/Note.php b/src/Note.php
index b2239673..e01226d7 100644
--- a/src/Note.php
+++ b/src/Note.php
@@ -29,7 +29,7 @@ public function prompt(): bool
 
         $this->state = 'submit';
 
-        static::output()->write($this->renderTheme());
+        static::writer()->write($this->renderTheme());
 
         return true;
     }
diff --git a/src/Output/BufferedConsoleOutput.php b/src/Output/BufferedConsoleOutput.php
index b5e725b4..68fdb353 100644
--- a/src/Output/BufferedConsoleOutput.php
+++ b/src/Output/BufferedConsoleOutput.php
@@ -2,6 +2,8 @@
 
 namespace Laravel\Prompts\Output;
 
+use Symfony\Component\Console\Output\ConsoleOutput;
+
 class BufferedConsoleOutput extends ConsoleOutput
 {
     /**
diff --git a/src/Output/ConsoleOutput.php b/src/Output/PromptWriter.php
similarity index 56%
rename from src/Output/ConsoleOutput.php
rename to src/Output/PromptWriter.php
index 60381d62..23963c0b 100644
--- a/src/Output/ConsoleOutput.php
+++ b/src/Output/PromptWriter.php
@@ -2,15 +2,20 @@
 
 namespace Laravel\Prompts\Output;
 
-use Symfony\Component\Console\Output\ConsoleOutput as SymfonyConsoleOutput;
+use Symfony\Component\Console\Output\OutputInterface;
 
-class ConsoleOutput extends SymfonyConsoleOutput
+class PromptWriter
 {
     /**
      * How many new lines were written by the last output.
      */
     protected int $newLinesWritten = 1;
 
+    public function __construct(
+        private OutputInterface $output
+    ) {
+    }
+
     /**
      * How many new lines were written by the last output.
      */
@@ -22,15 +27,15 @@ public function newLinesWritten(): int
     /**
      * Write the output and capture the number of trailing new lines.
      */
-    protected function doWrite(string $message, bool $newline): void
+    public function write(string $message, bool $newline = false): void
     {
-        parent::doWrite($message, $newline);
+        $this->output->write($message, $newline);
 
         if ($newline) {
             $message .= \PHP_EOL;
         }
 
-        $trailingNewLines = strlen($message) - strlen(rtrim($message, \PHP_EOL));
+        $trailingNewLines = \strlen($message) - \strlen(rtrim($message, \PHP_EOL));
 
         if (trim($message) === '') {
             $this->newLinesWritten += $trailingNewLines;
@@ -42,8 +47,13 @@ protected function doWrite(string $message, bool $newline): void
     /**
      * Write output directly, bypassing newline capture.
      */
-    public function writeDirectly(string $message): void
+    public function writeDirectly(string $message, bool $newline = false): void
+    {
+        $this->output->write($message, $newline);
+    }
+
+    public function getOutput(): OutputInterface
     {
-        parent::doWrite($message, false);
+        return $this->output;
     }
 }
diff --git a/src/Prompt.php b/src/Prompt.php
index 1f50b102..dfd3e872 100644
--- a/src/Prompt.php
+++ b/src/Prompt.php
@@ -3,8 +3,10 @@
 namespace Laravel\Prompts;
 
 use Closure;
-use Laravel\Prompts\Output\ConsoleOutput;
+use Laravel\Prompts\Output\PromptWriter;
 use RuntimeException;
+use Symfony\Component\Console\Output\ConsoleOutput;
+use Symfony\Component\Console\Output\ConsoleOutputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
 use Throwable;
 
@@ -65,9 +67,9 @@ abstract class Prompt
     protected static ?Closure $validateUsing;
 
     /**
-     * The output instance.
+     * The writer instance.
      */
-    protected static OutputInterface $output;
+    protected static PromptWriter $writer;
 
     /**
      * The terminal instance.
@@ -91,7 +93,7 @@ public function prompt(): mixed
                 return $this->fallback();
             }
 
-            static::$interactive ??= stream_isatty(STDIN);
+            static::$interactive ??= stream_isatty(STDIN) && (stream_isatty(STDOUT) || stream_isatty(STDERR));
 
             if (! static::$interactive) {
                 return $this->default();
@@ -102,7 +104,7 @@ public function prompt(): mixed
             try {
                 static::terminal()->setTty('-icanon -isig -echo');
             } catch (Throwable $e) {
-                static::output()->writeln("<comment>{$e->getMessage()}</comment>");
+                static::writer()->write("<comment>{$e->getMessage()}</comment>", true);
                 static::fallbackWhen(true);
 
                 return $this->fallback();
@@ -154,9 +156,7 @@ public function newLinesWritten(): int
      */
     protected function capturePreviousNewLines(): void
     {
-        $this->newLinesWritten = method_exists(static::output(), 'newLinesWritten')
-            ? static::output()->newLinesWritten()
-            : 1;
+        $this->newLinesWritten = static::writer()->newLinesWritten();
     }
 
     /**
@@ -164,27 +164,22 @@ protected function capturePreviousNewLines(): void
      */
     public static function setOutput(OutputInterface $output): void
     {
-        self::$output = $output;
+        if ($output instanceof ConsoleOutputInterface && stream_isatty(STDERR) && ! stream_isatty(STDOUT)) {
+            $output = $output->getErrorOutput();
+        }
+        self::$writer = new PromptWriter($output);
     }
 
     /**
-     * Get the current output instance.
+     * Get the prompt writer.
      */
-    protected static function output(): OutputInterface
+    protected static function writer(): PromptWriter
     {
-        return self::$output ??= new ConsoleOutput();
-    }
+        if (! isset(self::$writer)) {
+            self::setOutput(new ConsoleOutput());
+        }
 
-    /**
-     * Write output directly, bypassing newline capture.
-     */
-    protected static function writeDirectly(string $message): void
-    {
-        match (true) {
-            method_exists(static::output(), 'writeDirectly') => static::output()->writeDirectly($message),
-            method_exists(static::output(), 'getOutput') => static::output()->getOutput()->write($message),
-            default => static::output()->write($message),
-        };
+        return self::$writer;
     }
 
     /**
@@ -215,7 +210,7 @@ protected function render(): void
         }
 
         if ($this->state === 'initial') {
-            static::output()->write($frame);
+            static::writer()->write($frame);
 
             $this->state = 'active';
             $this->prevFrame = $frame;
@@ -228,7 +223,7 @@ protected function render(): void
         // Ensure that the full frame is buffered so subsequent output can see how many trailing newlines were written.
         if ($this->state === 'submit') {
             $this->eraseDown();
-            static::output()->write($frame);
+            static::writer()->write($frame);
 
             $this->prevFrame = '';
 
@@ -242,7 +237,7 @@ protected function render(): void
             $this->moveCursor(0, $diffLine);
             $this->eraseLines(1);
             $lines = explode(PHP_EOL, $frame);
-            static::output()->write($lines[$diffLine]);
+            static::writer()->write($lines[$diffLine]);
             $this->moveCursor(0, count($lines) - $diffLine - 1);
         } elseif (count($diff) > 1) { // Re-render everything past the first change
             $diffLine = $diff[0];
@@ -250,7 +245,7 @@ protected function render(): void
             $this->eraseDown();
             $lines = explode(PHP_EOL, $frame);
             $newLines = array_slice($lines, $diffLine);
-            static::output()->write(implode(PHP_EOL, $newLines));
+            static::writer()->write(implode(PHP_EOL, $newLines));
         }
 
         $this->prevFrame = $frame;
diff --git a/src/Table.php b/src/Table.php
index a7de3700..40b6538a 100644
--- a/src/Table.php
+++ b/src/Table.php
@@ -56,7 +56,7 @@ public function prompt(): bool
 
         $this->state = 'submit';
 
-        static::output()->write($this->renderTheme());
+        static::writer()->write($this->renderTheme());
 
         return true;
     }