Skip to content

Conversation

faisuc
Copy link

@faisuc faisuc commented Oct 7, 2025

As described in issue #56602, this PR modifies Laravel's console components to write auxiliary output (task progress, prompts, etc.) to STDERR when available, while maintaining full backwards compatibility. This allows commands with --json flags to pipe output without UI contamination.

Currently, console components like task(), progress bars, and prompts write to STDOUT, which contaminates piped output:

# Current behavior - task output breaks JSON
php artisan some:command --json > output.json
$ head -n+3 output.json
Doing work ...................................... 1s DONE  # ← Breaks JSON!
[
  {

Console components now use STDERR for auxiliary output when ConsoleOutputInterface is available:

# New behavior - clean JSON output
php artisan some:command --json > output.json
$ head -n+3 output.json
[
  {
    "nice": "valid JSON!"

@taylorotwell
Copy link
Member

I feel almost certain this will be a breaking change for someone.

@taylorotwell taylorotwell reopened this Oct 7, 2025
@shaedrich
Copy link
Contributor

Do we have to use standard streams or would it be perhaps better to use non-standard streams to not abuse STDERR for non-error output?

@faisuc
Copy link
Author

faisuc commented Oct 7, 2025

Thanks for the review. Two concrete, non‑breaking ways forward:

  • Opt‑in toggle (default OFF in 12.x)

    • Per command: add a small opt‑in (e.g. protected bool $componentsToStderr = true or a useErrorOutputForComponents() helper).
    • Global: config/env toggle (e.g. console.components_to_stderr=true) with per‑command override.
    • We can flip the default in the next major.
  • Optional “auto” mode (behind config)

    • Only route components to STDERR when STDOUT is not a TTY (i.e., piped). Keeps current behavior for interactive runs; enables clean piping when needed.

On using non‑standard streams: that’s not portable across shells/CI. STDERR is the conventional place for progress/debug output and Symfony explicitly supports this via getErrorStyle(), which is why many tools do it this way. Reference: “Writing to the error output” in Symfony’s console docs (symfony.com/docs/current/console/style.html#writing-to-the-error-output).

I’m happy to update the PR to:

  • keep current behavior by default,
  • add per‑command and global opt‑in,
  • optionally include an “auto when not TTY” mode behind config,
  • keep the tests covering both paths.

@Radiergummi
Copy link

Radiergummi commented Oct 8, 2025

Do we have to use standard streams or would it be perhaps better to use non-standard streams to not abuse STDERR for non-error output?

That's no abuse; it's the other way around: Standard output is reserved for the result of the command, while standard error takes any other auxiliary output like debug information, warnings, or optional info. If a command has the purpose of carrying out a single action, it shouldn't print any output to stdout at all, and just exit with 0. You can observe this with pretty much all standard Unix CLI tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants