ax-check rule

AXC-C011: NO_COLOR not honoured

With NO_COLOR=1 set, output still contained ANSI colour codes.

ax-check is a checker being prepared for release. This page documents the rule ahead of that release; see all 50 rules.

Severitywarn
KindObserved. Depends on the program and environment at run time.
Modeax-check probe-cli
Applies toCommand-line programs, run as a subprocess
Pattern tagsnon-interactive
Fix in one lineWhen NO_COLOR is set and not empty, never add ANSI colour.

With the environment variable NO_COLOR=1 set, the output still contained ANSI colour codes. NO_COLOR is the standard way for a user, a harness or an agent to say “no colour, please”.

What it checks

The no-color probe runs <cmd> --help with NO_COLOR=1 in the environment. The rule fires when the output still contains ANSI colour sequences, that is, escape codes of the form ESC[...m. Other escape codes, such as cursor movement, are reported by AXC-C010 instead.

Why it matters

Harnesses and users set NO_COLOR when they want clean text, because they cannot always change the command line. The standard at no-color.org says: “Command-line software which adds ANSI color to its output by default should check for a NO_COLOR environment variable that, when present and not an empty string (regardless of its value), prevents the addition of ANSI color.” The Command Line Interface Guidelines list it among the conditions for disabling colour. A program that ignores it leaves the caller with no way to turn the codes off except by stripping them afterwards.

How to fix

Check NO_COLOR before you add any colour. If it is present and not an empty string, add none, whatever its value and whether or not the output is a TTY. Also support --no-color as a flag.

Example

Before

$ NO_COLOR=1 invoicer --help </dev/null | cat -v
^[[1mUsage:^[[0m invoicer <command> [options]
^[[1mCommands:^[[0m
  create   Create a draft invoice

After

$ NO_COLOR=1 invoicer --help </dev/null | cat -v
Usage: invoicer <command> [options]
Commands:
  create   Create a draft invoice

A Node fix:

const noColour = Boolean(process.env.NO_COLOR) || process.argv.includes('--no-color');
const bold = (s) => (noColour || !process.stdout.isTTY ? s : `\x1b[1m${s}\x1b[0m`);

A Python fix:

no_colour = bool(os.environ.get("NO_COLOR")) or "--no-color" in sys.argv

How ax-check detects it

The probe sets NO_COLOR=1 and removes FORCE_COLOR and CLICOLOR_FORCE so that the test is fair. It runs --help only, which is read-only for almost every CLI. It then searches stdout and stderr for ANSI colour codes (ESC[...m).

Because the probes already run without a terminal, a program that follows AXC-C010 will pass this one too. This rule mainly catches programs that always add colour, for example because the colour library was configured to force it, or because a help renderer ignores the environment.

To reproduce by hand: NO_COLOR=1 invoicer --help </dev/null | cat -v | grep -n '\^\[\['.

Silence the rule with --disable AXC-C011 if your program colours only help output that is documented as a fixed format.

Safety note: This rule uses the default no-color probe, which runs --help with NO_COLOR=1. probe-cli executes your program under your own OS account. The temporary working directory and HOME it uses are not a sandbox: the program can still read and write anything your account can, and use the network. Probe a CLI you have not reviewed only inside a container or a throwaway virtual machine. Run ax-check probe-cli --dry-run -- invoicer first to see the probes that would run, and see the “Probe safety” section of the ax-check README for what is and is not isolated.

Sources

  • Specification: NO_COLOR, no-color.org. https://no-color.org/ . Says that when NO_COLOR is present and not an empty string, regardless of its value, ANSI colour should not be added.
  • Guideline: Command Line Interface Guidelines, clig.dev. https://clig.dev/ . Lists NO_COLOR and --no-color among the cases where colour should be disabled.

Records in the AX evidence register that share a pattern tag with this rule. A shared tag means the record is about the same pattern, not that it tests this rule. Read the evidence class before the number.