This doc is about indicating the preference for color or no color output via environment variables in command line programs. There are some "standards" out there, which many tools luckily support. The support is quirky though.
- To force color: set
FORCE_COLOR=1andCLICOLOR_FORCE=1(+ unsetNO_COLORif unsure if it might be set). - To force no color: set
NO_COLOR=1(+ unsetFORCE_COLOR,CLICOLOR_FORCEandCLICOLORif unsure if they might be set).
The primary use case here is to colorize output of tools in CI, in particular GitHub and GitLab.
Some tools go as far as detecting the CI flavor and doing the right thing (subjective: colorizing) based on their findings, and some tools support more granular color config than just a boolean (but making use of that might throw off some other tools using the same variables (for example specifying a larger number than 1)), etc.
For such tools, the force color recipe here might actually make the output less colorful or "less truecolor" than the tool+env env combo would yield without these variables set as the deeper checks they can do would not be done in presence of these vars. Anyway, I believe it's a net win overall as a rule of thumb for those who don't want to take a deep dive in details.
Suggested, opinionated and combined check sequence:
- If
FORCE_COLORis set to any non-empty value: color is on, look no further. - If command line args and/or config files explicitly turn color on or off: color is on or off respectively, look no further.
- If
NO_COLORis set to any non-empty value: color is off, look no further. - If
CLICOLOR_FORCEis set to any non-empty value: color is on, look no further. - If
CLICOLORis set to any non-empty value and outputting to a terminal: color is on, look no further. - New programs behave as if
CLICOLORis on, older programs gaining color support have color off by default.
This recipe favors command line arg precedence of FORCE_COLOR/NO_COLOR and ignores that of CLICOLOR_FORCE. Having both is no go as the former is "stronger" (applies to both being turned on or off) and earlier in precedence, so the latter would be redundant (never reached) with it per the algorithm above. It also takes the FORCE_COLOR/NO_COLOR consideration for config files into account.
It also resolves the CLICOLOR_FORCE inconsistencies mentioned below by taking the approach of "on" meaning "set to any non-empty value".
In many cases, for example a library one, checking command line args or config files is not straightforward as it might not be the library's business to do anything with either. (Some libraries in existence do command line arg sniffing though.) But the library could be constructed to take a function as a parameter that returns whether colorizing was explicitly requested on or off in command line args or config files, and plug that function in to its evaluation sequence.
If one does not want to do the whole dance above, I would personally skip the CLICOLOR_FORCE and CLICOLOR steps. The spec for those has seemed more ambiguous and less maintained to me than the two others. Caveat: I don't have numbers how widespread use of each of these vars is. If the CLICOLOR* ones have more substantial "market share" than I guess they do, might want to reconsider.
Visited 2025-11-09
FORCE_COLOR and NO_COLOR
Check sequence:
- If
FORCE_COLORis on: color is on, look no further. - If command line args and/or config files explicitly turn color on or off: color is on or off respectively, look no further.
- If
NO_COLORis on: color is off.
NO_COLOR and FORCE_COLOR are considered on if they're set to any non-empty value.
Check sequence:
- If
NO_COLORis on or command line args explicitly turn color off: color is off, look no further. - If
CLICOLOR_FORCEis on or command line args explicitly turn color on: color is on, look no further. - If
CLICOLORis on and outputting to a terminal: color is on, look no further. - New programs behave as if
CLICOLORis on, older programs gaining color support have color off by default.
There are inconsistencies in text and example code with regards to set vs set-but-empty, jhasse/clicolors#24.
Config files are not mentioned.
There are many, but here's a few.
The Go colorprofile package as of 0.3.3:
- Does not support
FORCE_COLOR. NO_COLOR,CLICOLOR_FORCEandCLICOLORtruthiness implementations deviate from the specs, is Go'sstrconv.ParseBoolinstead, and considers only values parsing to true. Refs https://github.com/charmbracelet/colorprofile/blob/v0.3.3/env.go#L115-L116, https://github.com/charmbracelet/colorprofile/blob/v0.3.3/env.go#L125-L126, https://github.com/charmbracelet/colorprofile/blob/v0.3.3/env.go#L120-L121- Notably used by Lip Gloss.
The npm supports-color package as of 10.2.2:
- Does not support
NO_COLOR(ref chalk/supports-color#105 (comment)) orCLICOLOR_FORCE/CLICOLOR. - Only accepts
FORCE_COLORvalues that are unsigned integers,true,falseor empty; other values are treated as if not set. Values1,2and3are color "levels", values >=3are clamped to3.trueis treated same as1.0andfalseare treated as forcefully disabling color. Ref https://github.com/chalk/supports-color/blob/v10.2.2/index.js#L33 - Notably used by (vendored in) Chalk.
Many CI/CD systems support color output even if TTYness tests may not return true in them.
- GitHub Actions supports color, and sets
GITHUB_ACTIONS=true. - GitLab CI/CD supports color, and sets
GITLAB_CI=true.