Stdout/stderr separation
Why it matters
When a CLI mixes data output and status messages on stdout, any pipeline that consumes the output breaks silently. Running mytool list-users | jq '.[].email' will fail or produce corrupt results if progress text like "Fetching 42 users..." lands in the same stream as the JSON. Docker, xargs, tee, and CI log parsers all assume stdout carries only data. Sending error messages to stdout also defeats shell && semantics: a caller checking exit code sees 0 but its stdin feed contains garbage. This is classified as a critical reliability failure under ISO 25010:2011 usability.operability because the entire composability contract of the Unix tool model breaks at this seam.
Severity rationale
Critical because stdout/stderr mixing silently corrupts downstream pipeline consumers and CI log parsers — fixing exit codes alone does not restore composability.
Remediation
Route all data to stdout and all messages (progress, warnings, errors) to stderr. Test the separation by redirecting each stream independently:
// Node.js — data to stdout, everything else to stderr
async function listUsers(format: string) {
console.error('Fetching users...') // status → stderr
const users = await fetchUsers()
process.stdout.write(JSON.stringify(users, null, 2) + '\n') // data → stdout
console.error(`Found ${users.length} users`) // status → stderr
}
# Python — click.echo(err=True) for all non-data output
@cli.command()
def list_users():
click.echo('Fetching users...', err=True)
users = fetch_users()
for u in users:
click.echo(f'{u.name} <{u.email}>') # data → stdout
click.echo(f'Found {len(users)} users', err=True)
Verify with: mytool list-users > data.txt — the terminal should show status lines while data.txt contains only clean output.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the CLI Quality Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- iso-25010:2011 · usability.operability — Usability — Operability
Taxons
History
- 2026-04-18·v1.0.0·Initial import from cli-quality·automated