Code of the Day
IntermediateBetter Interfaces

Colour conventions

Establish consistent colour semantics across your tool so users build reliable intuitions about what each colour means.

UtilitiesIntermediate5 min read
By the end of this lesson you will be able to:
  • Describe the standard colour-to-state mapping (green/yellow/red) and why it matches user expectations
  • Explain how inconsistent colour use erodes user trust
  • Apply colour consistently through a shared Rich Console or theme object

Colour is a signal. Like road signs, it only works when the mapping is consistent. Green means go. Red means stop. Yellow means caution. These associations are pre-loaded in every user's mind before they run your tool. Working with those associations makes your tool instantly legible. Fighting them forces users to learn a new vocabulary every time they encounter a coloured line.

The standard mapping

Most well-designed CLI tools converge on the same colour semantics:

ColourMeaningExamples
GreenSuccess, OK, readyBuild passed, file written, test passed
YellowWarning, notice, something to checkDeprecated option, skipped file, slow
RedError, failure, action requiredException, missing file, invalid input
BlueInformation, in progressConnecting, loading, status message
Dim/greySecondary detail, less important textFile paths, timestamps, counts

This is not a law — but deviating from it without a strong reason will confuse experienced CLI users who have internalised this convention from decades of tools that follow it.

The cost of inconsistency

Suppose your tool uses red for both errors and for "items that were deleted successfully." A user who sees red output stops and re-reads it every time, because they cannot trust the signal. The cognitive overhead compounds: every red line is a question mark until they decode the context.

Consistent colour removes that overhead. After the first run, users know without thinking: green lines are fine, red lines need attention. They can scan a hundred-line output in seconds.

Centralising your colour scheme

The easiest way to stay consistent is to define your status messages in one place rather than sprinkling [bold green] markup throughout the code:

from rich.console import Console

console = Console()

def ok(msg: str) -> None:
    console.print(f"[bold green]OK[/]  {msg}")

def warn(msg: str) -> None:
    console.print(f"[yellow]WARN[/] {msg}")

def error(msg: str) -> None:
    console.print(f"[bold red]ERR[/] {msg}", stderr=True)

Now every status line in your tool comes from one of these three functions. If you ever decide to change the styling — say, adding an icon or changing the label — you change it in one place.

Accessibility note

Some users have colour-vision deficiencies, and some terminals are used without colour support. Never convey information through colour alone. The examples above use OK, WARN, and ERR prefixes so the meaning is clear even in a plain-text log. Colour reinforces meaning; it does not replace text.

Rich respects the NO_COLOR environment variable. When NO_COLOR is set, Rich strips all colour automatically. This is a community standard for accessibility and for CI environments. You get compliance for free.

Where to go next

Next: lab — rich tool — apply everything from this module by upgrading a plain-text CLI script to use Rich tables, progress bars, and error panels.

Finished reading? Mark it complete to track your progress.

On this page