# NO_COLOR and TTY detection

- **Pattern:** `ab-000648` (`cli-quality.io-behavior.no-color-support`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000648
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000648)

## Why it matters

When `mytool list > out.txt` writes `\x1b[32mOK\x1b[0m` into the file, the user opens `out.txt` and sees escape-code garbage. When CI logs capture ANSI codes as `^[[32m`, grep patterns break. When a blind user's screen reader hits color codes, output becomes unintelligible. The `NO_COLOR` convention (no-color.org) and TTY detection exist for exactly this reason — ignoring them corrupts piped output, log files, and accessibility tooling.

## Severity rationale

Medium because raw ANSI codes in piped output or log files corrupt downstream consumers and break accessibility.

## Remediation

Check `process.env.NO_COLOR` and `process.stdout.isTTY` before emitting ANSI codes, or use a library like picocolors that does this automatically. Wire the check once in `src/cli/lib/color.ts`:

```ts
import pc from 'picocolors'
// picocolors honors NO_COLOR and isTTY automatically
console.error(pc.green('Success'))
```

Test with `NO_COLOR=1 mytool list` and `mytool list | cat`.

## Detection

- **ID:** `no-color-support`
- **Severity:** `medium`
- **What to look for:** List all colored output locations in the CLI. For each, check for `NO_COLOR` environment variable support (see https://no-color.org). Check for TTY detection that disables colors and interactive elements when output is piped. In Node.js, look for chalk/picocolors with `NO_COLOR` support, or `process.stdout.isTTY` checks. In Python, look for `--no-color` flag or `NO_COLOR` env var handling. In Go, look for `isatty` checks or `--no-color` support. Check that `--no-color` flag or `FORCE_COLOR=0` / `NO_COLOR=1` disables all ANSI escape codes.
- **Pass criteria:** The CLI respects the `NO_COLOR` environment variable by suppressing all ANSI color codes when it is set. When stdout is not a TTY (piped), colors are automatically disabled. A `--no-color` flag is recommended but not required if `NO_COLOR` env var is supported — 100% of colored output must be suppressed when NO_COLOR environment variable is set. Report: "X colored output points found, all Y respect NO_COLOR."
- **Fail criteria:** Colors are output regardless of `NO_COLOR` env var, or colors are output when stdout is piped to a file/process, or no color control mechanism exists and the CLI outputs ANSI escape codes.
- **Skip (N/A) when:** The CLI produces no colored output — all output is plain text with no ANSI codes, chalk, picocolors, or equivalent. All checks skip when no CLI entry point is detected.
- **Detail on fail:** `"CLI uses chalk for colored output but does not check NO_COLOR env var or stdout.isTTY — colors will corrupt piped output"` or `"Colored output sent even when piped: 'mytool list > out.txt' produces ANSI escape codes in the file"`
- **Remediation:** Respect the `NO_COLOR` convention and detect pipe contexts:

  ```ts
  // Node.js — picocolors respects NO_COLOR automatically
  import pc from 'picocolors'
  // picocolors checks NO_COLOR and stdout.isTTY out of the box
  console.error(pc.green('Success'))  // no color when piped or NO_COLOR set

  // Manual check if using raw ANSI codes
  const useColor = process.stdout.isTTY && !process.env.NO_COLOR
  ```

  ```python
  # Python — click respects NO_COLOR in recent versions
  import os
  use_color = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() and not os.environ.get('NO_COLOR')
  ```

Taxons: user-experience

HTML version: https://auditbuffet.com/patterns/ab-000648
