Summary
Honor the NO_COLOR environment variable in the Microsoft.Testing.Platform terminal output. Today MTP only suppresses ANSI escape sequences via --no-ansi, --ansi off, or the LLMEnvironmentDetector (see src/Platform/Microsoft.Testing.Platform/OutputDevice/TerminalOutputDevice.cs:147-184); it does not look at NO_COLOR at all.
Motivation
NO_COLOR is the de-facto cross-tool convention for "I am piped/redirected/aren't a fan of color, please don't emit ANSI." Tools that honor it include git, ripgrep, bat, gh, cargo, the .NET SDK itself, modern Node.js CLIs, and most coding-agent runtimes (Claude Code, Cursor, Codex, Aider).
- Coding agents and CI systems commonly set
NO_COLOR=1 rather than the MTP-specific --no-ansi flag. Today they get ANSI noise in failure output, which costs tokens and breaks log scraping.
- The fix is small and matches existing precedence:
--ansi on|off|auto still wins, then --no-ansi, then NO_COLOR, then LLMEnvironmentDetector, then CI detection.
Proposed behavior
In TerminalOutputDevice.cs (resolution of AnsiMode):
explicit --ansi on -> AnsiMode.ForceAnsi
explicit --ansi off -> AnsiMode.NoAnsi
--no-ansi (no --ansi override) -> AnsiMode.NoAnsi
NO_COLOR env var is non-empty -> AnsiMode.NoAnsi (NEW)
LLMEnvironmentDetector matches -> AnsiMode.NoAnsi
in CI -> AnsiMode.SimpleAnsi
default -> AnsiMode.AnsiIfPossible
Per the NO_COLOR spec: "All command-line software which outputs text with ANSI color added should check for the presence of a NO_COLOR environment variable that, when present (regardless of its value), prevents the addition of ANSI color."
We treat any non-empty NO_COLOR value as enabling the behavior, matching the spec.
Notes
NO_COLOR only affects colors, not progress. Progress is independently controlled by --no-progress and the existing CI/LLM path that already forces AnsiMode.NoAnsi which in turn disables progress. We could choose to also disable progress when NO_COLOR is set, but that's a separate decision — open question in the umbrella.
- Should use the injected
IEnvironment.GetEnvironmentVariable("NO_COLOR") (not the static Environment.GetEnvironmentVariable) so the behavior is unit-testable.
Acceptance criteria
- Setting
NO_COLOR (any non-empty value) to a process running MTP causes terminal output to be plain text (no ANSI escapes).
--ansi on overrides NO_COLOR (forces ANSI on).
--ansi off, --no-ansi, and LLM-mode detection continue to work unchanged.
- Unit test covers each precedence branch.
- No XLF / help / info changes needed (env vars aren't surfaced in
--help).
References
Summary
Honor the
NO_COLORenvironment variable in the Microsoft.Testing.Platform terminal output. Today MTP only suppresses ANSI escape sequences via--no-ansi,--ansi off, or theLLMEnvironmentDetector(seesrc/Platform/Microsoft.Testing.Platform/OutputDevice/TerminalOutputDevice.cs:147-184); it does not look atNO_COLORat all.Motivation
NO_COLORis the de-facto cross-tool convention for "I am piped/redirected/aren't a fan of color, please don't emit ANSI." Tools that honor it includegit,ripgrep,bat,gh,cargo, the .NET SDK itself, modern Node.js CLIs, and most coding-agent runtimes (Claude Code, Cursor, Codex, Aider).NO_COLOR=1rather than the MTP-specific--no-ansiflag. Today they get ANSI noise in failure output, which costs tokens and breaks log scraping.--ansi on|off|autostill wins, then--no-ansi, thenNO_COLOR, thenLLMEnvironmentDetector, then CI detection.Proposed behavior
In
TerminalOutputDevice.cs(resolution ofAnsiMode):Per the NO_COLOR spec: "All command-line software which outputs text with ANSI color added should check for the presence of a NO_COLOR environment variable that, when present (regardless of its value), prevents the addition of ANSI color."
We treat any non-empty
NO_COLORvalue as enabling the behavior, matching the spec.Notes
NO_COLORonly affects colors, not progress. Progress is independently controlled by--no-progressand the existing CI/LLM path that already forcesAnsiMode.NoAnsiwhich in turn disables progress. We could choose to also disable progress whenNO_COLORis set, but that's a separate decision — open question in the umbrella.IEnvironment.GetEnvironmentVariable("NO_COLOR")(not the staticEnvironment.GetEnvironmentVariable) so the behavior is unit-testable.Acceptance criteria
NO_COLOR(any non-empty value) to a process running MTP causes terminal output to be plain text (no ANSI escapes).--ansi onoverridesNO_COLOR(forces ANSI on).--ansi off,--no-ansi, and LLM-mode detection continue to work unchanged.--help).References
src/Platform/Microsoft.Testing.Platform/OutputDevice/TerminalOutputDevice.cs(around lines 147-184)--no-ansi/--no-progressflags and LLM detection)