---
title: "Write results to stdout and everything · Agent Wranglers"
url: https://agentwranglers.se/playbook/desktop-apps/command-line-tools/stdout-stderr
id: DSK-21
level: Recommended
updated: 2026-10-22
tokens: 871
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Write results to stdout and everything else to stderr

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Command-line tools](https://agentwranglers.se/playbook/desktop-apps/command-line-tools.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-22.

- ID: DSK-21
- Level: Recommended
- Chapter: [Command-line tools](https://agentwranglers.se/playbook/desktop-apps/command-line-tools.md)
- Rule: Write only the command's result to standard output. Progress, warnings, prompts and errors go to standard error. Colour and spinners appear only when the stream is a terminal and `NO_COLOR` is unset.
- Check: A test runs each command with standard output sent to a file and standard error to another. The output file holds only the result, with no escape codes. With `NO_COLOR=1` set, standard error holds no escape codes either.
- How: A pipe such as `invoices list | wc -l` breaks when a progress line lands in the result. POSIX says standard error is for diagnostic messages. Check whether each stream is a terminal before you add colour, progress bars or tables made for the eye. Honour the `NO_COLOR` environment variable, which many tools read. A `--quiet` flag silences standard error except for errors. Machine-readable output follows [offer JSON output with a stable shape](https://agentwranglers.se/playbook/desktop-apps/command-line-tools/json-output.md).

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### Python example

```python
import os, sys

use_colour = sys.stderr.isatty() and "NO_COLOR" not in os.environ

def warn(message: str) -> None:
    print(f"\033[33m{message}\033[0m" if use_colour else message, file=sys.stderr)

for invoice in invoices:
    warn(f"exporting {invoice.number}") if not args.quiet else None
    print(invoice.to_csv_row())
```

### Go example

```go
func warn(message string) {
	if term.IsTerminal(int(os.Stderr.Fd())) && os.Getenv("NO_COLOR") == "" {
		message = "\033[33m" + message + "\033[0m"
	}
	fmt.Fprintln(os.Stderr, message)
}

for _, invoice := range invoices {
	warn("exporting " + invoice.Number)
	fmt.Println(invoice.CSVRow())
}
```

## Sources

- [POSIX.1-2024, Utility Description Defaults](https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap01.html)

## Related rules

- DSK-22 [Offer JSON output with a stable shape](https://agentwranglers.se/playbook/desktop-apps/command-line-tools/json-output.md) in Desktop apps, extensions and CLIs

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/desktop-apps/command-line-tools/stdout-stderr">Agent Wranglers desktop apps, extensions and CLIs playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Exit with zero only when the command did everything it was asked](https://agentwranglers.se/playbook/desktop-apps/command-line-tools/exit-codes.md)
- Next: [Offer JSON output with a stable shape](https://agentwranglers.se/playbook/desktop-apps/command-line-tools/json-output.md)
- [Command-line tools](https://agentwranglers.se/playbook/desktop-apps/command-line-tools.md)
