---
url: https://listr2.kilic.dev/renderer/process-output.md
---

# {{ $frontmatter.title }}

[ProcessOutput](/api/listr2/classes/ProcessOutput.html), [ProcessOutputStream](/api/listr2/classes/ProcessOutputStream.html), [ProcessOutputBuffer](/api/listr2/classes/ProcessOutputBuffer.html) is used to take control of the current `stdout` and `stderr` for *ListrLogger* to ensure that nothing else is written to the console and creates an abstraction for accessing `process.stdout` and `process.stderr` when needed.

## Hijack

[ProcessOutput](/api/listr2/classes/ProcessOutput.html) for renderers like *DefaultRenderer* that need updating your `vt100` compatible terminal gives the ability to hijack the current `process.stdout` and `process.stderr`, create a temporary buffer for storing anything that is trying to write to the terminal since it will corrupt the output of *Listr*. If the renderer does not request to hijack the terminal output, `process.stdout` and `process.stderr` will be used directly without any trickery.

## Release

After the renderer releases the *ProcessOutput* and marks it ready to use, everything that has been outputted to the hooked streams will be dumped. **This intends to solve the most common cause of opening an issue in the repository which is saying that the output is corrupted and not realizing something else is writing to output the terminal.**

## Writing Through Process Output

When you write your own renderer or logger, emit through the *ProcessOutput* instead of touching `process.stdout` directly, so your output stays coordinated with the hijack/release cycle. `output.toStdout(buffer)` and `output.toStderr(buffer)` write to the correct stream, and the underlying streams are also reachable through `output.stream`.

## Extending Process Output

You can override the default *ProcessOutput* by extending the class with your expected behavior (e.g. writing to a log file) on the *ListrLogger* since all the renderers, that either use or do not use the hijacking function, use *ProcessOutput* through *ListrLogger* itself. For most cases, just creating a `new ProcessOutput()` by passing your own `WriteStream` for `process.stdout` and `process.stderr` through the constructor should be good enough.

### Changing the Behavior

You can change the behavior of the *ProcessOutput* through injecting it to the logger. Since every renderer at some level uses the underlying logger, this can effectively be used to change the behavior of the ProcessOutput as well.

If you do not like the behavior of the *ProcessOutput*, you can always implement and bring your own through this interface as well.

::: details  Code Example

<<< @../../examples/docs/renderer/process-output/change-behavior.ts

:::

## Routing All Output to `stderr`

Since every renderer writes through the *ProcessOutput* on the *ListrLogger*, you can keep `stdout` clean and pipeable (e.g. emitting `JSON` to pipe into `jq`) while the live UI and the final output still show up in the terminal by routing everything to `stderr`.

Pass `process.stderr` for both the `stdout` and `stderr` slots of the *ProcessOutput*, then inject the logger into the renderer.

There is one caveat: piping `stdout` makes it non-`TTY`, which normally steps *Listr* down to the fallback renderer with a default logger. To keep the *DefaultRenderer* and route the fallback through the same logger, set `forceTTY` and provide the logger on both `rendererOptions` and `fallbackRendererOptions`.

::: details  Code Example

<<< @../../examples/docs/renderer/process-output/route-to-stderr.ts

:::
