203 comments

[ 2.7 ms ] story [ 253 ms ] thread
Title is incorrect. It should be NO_COLOR in all caps, like the environment variable.
Maybe Hacker News automatically recapitalized the title. It would make sense if it tries to forbid clickbaity titles like "ExampleDB, a POWERFUL NEW DATABASE".
> Why not just set $TERM to dumb or xterm without color support? Or change all color definitions in the terminal to print the same color?

> The terminal is capable of color and should be able to print color when instructed. NO_COLOR is a hint to the software running in the terminal to suppress addition of color, not to the terminal to prevent any color from being shown.

I have to admit I don't really get this. I personally like colorized output, and I can't even think of situations where the colors chosen by a developer were so bad I wanted to disable them completely.

I respect others like no color (and there's already a solution per that, above), but I don't quite get the desire to have just some color (prompts but not applications). Can someone with this opinion explain their rationale?

Normally I wouldn't care, -- individual preferences are like opinions and everyone is entitled to their own -- but this imposes work on every developer/application. There's certainly ways to implement this that minimize impact, but it's still a non-zero up-front and ongoing maintenance/testing cost.

> I have to admit I don't really get this. I personally like colorized output, and I can't even think of situations where the colors chosen by a developer were so bad I wanted to disable them completely.

There's a few programs i use where the colours were clearly chosen to work on a dark theme terminal. I use a light theme terminal, and they're illegible.

I suppose the real problem here is that the output is tagged with physical colour, rather than some kind of semantic label which could be mapped to a colour in terminal configuration. But it's probably too late to do anything about that.

IME most programs still use the 8 traditional ANSI colors, which are exactly that (labels mapped to actual colors through config).
The problem here is that the 8 (or 16) ANSI colors are labels for just that: colors. 0 for black, 1 for red, etc. What OP is suggesting is more "abstract" labels, probably like "error" or "warning". More akin to text editor themes, which assign colors to particular semantic groups.
The labels are abstract. You can make them whatever color you want. Basically every terminal theme does this.
The abstraction level is not high enough. As labels goes, color1 doesn't have the same semantic strength than error_color.
The less you know about them, the higher the abstraction. A program can distribute meaning over colorN in any way it wants. Any fixed semantic mapping would prove insufficient in the universe of all possible programs.
Perhaps in theory. Almost every application under the sun I've encountered expects 1 to be red, or 4 to be blue, or 3 to be yellow, or whatever.

As an example, take solarized, or really any of the base16 themes. When I've used solarized in the past, many terminal programs that expect to print something in red are actually printing in a slightly-dimmed-background color, or purple, or something else where the intention of the tool author and the intention of the theme author conflict.

Don't most terminal emulators allow you to set your own color palette? So what would show up as yellow text on a normal black background, you could change to show up as maybe as gold? Obviously it would mess with the meaning behind why the developer chose that particular color (like red errors, yellow or orange warnings) but I'm sure you'd get used to it.
Even though my terminal lets me do that, I’d rather just disable colors on some programs that choose poorly than spend time configuring that. I like your basic red=failure stuff so I don’t want to disable color entirely but I’m not going to spend time tweaking just because some joker decided dark blue on black looks neat.
There’s a few different sets of ansi escape sequences for managing colour. The ones you’re on about are the 8/16 colour palette. Unfortunately there is a trend these days for developers to use 8-bit (256 colours) pallet or even the true colour (24-bit). Both of the latter are not customisable in the terminal.

Coincidentally I’ve gone into rants a number of times in the past on here about developers not using the correct colour palettes and the answer I always receive back for why it’s ok is because “developers should be able to chose how their application looks like”, which is fine if they control the entire design stack like they would on a website. But it makes zero sense in the terminal.

Interesting, I didn't realize both kinds of control characters existed

[checks the color library I'm currently using to build a CLI]

That makes sense. I've been wondering if we've been doing something subtly awkward with our internal tooling. However, most are just using the 8 or 16 color palette with a simple convention like "Use red (or technically, color 1, which just happens to be red for us) as error, yellow as warning, green as success" and let the terminal theme and the user figure out how it should look on their screen.
As the GP says, the problem is when the color is specified as RGB triples by the software.
I find it's more of a problem when applications use the color palette instead of 24-bit color. Someone might pick foreground and background colors that contrast perfectly well in their 8 color palette, but that in mine are impossible to distinguish. And changing them for one case might break legibility somewhere else. When the colors come from the 24-bit RGB selection, contrast will always be as the author intended.

I've had that problem with the default LS_COLORS/DIR_COLORS settings in some Linux installs. It's very annoying.

If your palette does not have good contrast between foreground colors 31-37 and background color 40, that's on you. If you cange the default background color to something other than 40 that's also on you - if you want the default background to be white, change the palette so that color 40 is white (instead of changing the backgound color to e.g. 47) and make the foreground colors dark enough so that they contrast well.
That configuration would be at the terminal level, but it would potentially need to be different for each program. The default ls colours are fine, and i don't want to change them, but the colours in our internal package management tool are broken, and i do.

Given the existence of shell pipelines, i might even want different palettes within a single stream of output, so this mapping couldn't even be done by hooking command execution to apply a different mapping in the terminal.

The physical colors are what the terminal configuration maps to. At least, modern terminals that I've used since the DOS era. Even back then, I had a tiny utility that I used to set the EGA palette for different text-mode programs. Amberscale tones on a deep low-saturation blue was one of my favorites.

Obviously won't help if you're using a teletype or punched cards or something like that.

Guilty [1]. But it's really hard to handle both light and dark color themes! On a dark terminal you're probably more likely to use the "Bright" variants when using the default 16 color palette, but then you'll have less contrast in a light theme. Some color schemes intentionally invert the "bright" colors and makes them darker for a light colored scheme. This is what Gruvbox [2] does, but most other palettes don't. I also have an issue with Solarized which makes some of the Bright colors almost exactly the same as the foreground or background, which can make text printed in certain colors seem invisible.

I've used ANSI codes to invert colors (which works pretty well for highlighting), and dim colors, but those can't solve everything.

[1]: https://github.com/PaulJuliusMartinez/jless/issues/4 [2]: https://github.com/morhetz/gruvbox

The design intent for Solarized is to minimize contrast, so this may lie somewhere between “you’re holding it wrong” territory, and aggressive cargo-culting advertising making this theme show up everywhere as an implied default good option. It is a nice set of color choices, but is not really appropriate for many situations where it gets used.
> On a dark terminal you're probably more likely to use the "Bright" variants when using the default 16 color palette, but then you'll have less contrast in a light theme.

The bright theme should invert the "dark" and "light" colors.

Most software that I use regularly which does color output does it well, and it's probably a net benefit for me.

But sometimes software that I use irregularly, or only in specific circumstances, does it poorly, and it's a real pita. I've had occasions where I missed entire pieces of output because they rendered as the background color for some reason. So for those cases it'd be nice to have a universal switch, so to speak, to just turn it off.

I also get that for some people it's just an aesthetic choice... I don't think color is _that_ helpful that someone would be impaired by not having it.

All that said, this proposal reminds me of that one xkcd with the 13 competing standards.

Every application that supports colour already needs to support no colour for dumb terminals and pipes.
I still prefer color for matching quotes in editors. And they're useful in tui programs like cmus and tmux. And git add -p. That's about it for me though. I don't find it helpful in the output of package managers, ffmpeg, etc. It's clown vomit that makes things even harder to read imo.

This env var wasn't a universal enough solution the last time I tried it, so I just set almost all my term colors except red (for the quote matching) to black.

On the whole I'm really put off by the aesthetics of programming. The default still seems to be very "gamer": dark mode, neon everything—I can practically smell the Mtn Dew through my screen sometimes.

I like the colors from some commands (like ls) but I think everyone has had some experience with a command that has very bad colors, making some important information hard to read or just being really ugly. So the variable also provides a universal way to run any individual command without color if desired.

>The default still seems to be very "gamer": dark mode, neon everything

Dark mode is common but I've seen dull tones predominate for normal text over the last decade at least.

>On the whole I'm really put off by the aesthetics of programming. The default still seems to be very "gamer": dark mode, neon everything—I can practically smell the Mtn Dew through my screen sometimes.

Oh, come on... Look at the original terminals from the old days. Dark background with green or amber text. Dark terminals are the normal thing, nothing to do with gamers. My guess is it was less power to only light up the text parts instead of the inverse. Light themes, on a computer, seem unnatural in the way they force as much light as possible on. They're trying to emulate paper, which is white by default, but I don't think that should be considered normal on a computer.

1. I think you're right about power. Even with PCs the folk wisdom during the CRT era was that having a black background would save energy.

2. Those early terminals were monochromatic though. They were stark and utilitarian, not the Vegas-ass colors some of my coworkers are rocking.

3. Paper is what I aim for. I have read black text all my life, including the textbooks that taught me to program, so it makes a lot of sense to work like this as well. I don't go full white though; Plan 9's Acme theme is the acme of palettes to me.

> I don't find it helpful in the output of package managers, ffmpeg, etc. It's clown vomit that makes things even harder to read imo.

IMO in the case of package managers it actually makes it more readable. For example zypper (in openSUSE) uses a colored heading to group the packages it is going to install/upgrade/remove/etc and it uses a color for the first letter of each package, both making it very simple to quickly scan the packages that are going to be installed or affected whenever there is a big list of them - e.g. i can quickly skip all the libraries (since they begin with "l").

You've never had a program ANSI puke into a sink that expressly is not a terminal and expects only plain text -- for example, an Emacs buffer. Tired of setting magic flags on Maven to suppress color output when I do M-x compile, for instance.
Seems like it would be easy to make a program that strips color controls from stdin and pipes everything else to stdout
This is generally the behavior I've seen on my everyday apps that support color in their output. Often they have a `--color auto|never|always` command line option, with "auto" being the default, which detects if the output is a TTY or some other interactive terminal
Auto-detecting is good, but I was suggesting a third-party program that just takes arbitrary input, strips the control characters, and produces the resulting output, in case the original app can't do what you need as a user
Ah, yes. Sorry, I misread your comment. Yes, that is a good idea :)
I think Plan9port’s nobs command does this. It is my default pager when using acme or 9term (also from P9P).
I did a quick GitHub search and found two of them:

https://github.com/kurtbuilds/no-ansi

Written in rust and ultimately uses vte from alacritty to write through a virtual terminal. Can be given a file on the command line.

https://github.com/emptymonkey/dumb

Written in Lex and just strips a number of specific escape sequences (written 9 years ago so likely doesn't include a few). Only stdin to stdout.

Edit: And now I see the discussion below about nofun and the equivalent sed command that use regex. ... and reading more I see ansi2txt in colorized-logs (the one most likely to be packaged) that also effectively is a regex, although written out in C.

One case I can think of is parsing output without the intermittent hidden unicode codes to change the color. Changing terminal settings won’t change that.
Programs should disable terminal color codes when the output is not a terminal. Arguably, this is already an established best practice.
If checking isatty() wasn't an established practice, pipes would be pretty useless.
(comment deleted)
> I respect others like no color (and there's already a solution per that, above), but I don't quite get the desire to have just some color (prompts but not applications). Can someone with this opinion explain their rationale?

The output is sometimes 'too busy' and the colours are of arbitrary values which may mean any number of things, and if you don't what they mean they're just noise.

Further the same thing may be signified by different colours by different programs (editor A may have, e.g., variables as colour X, but editor B may have variables as colour Y, and the pager as colour Z).

Perhaps if I was a coder, using one environment/editor/IDE, I could learn things. But as a sysadmin (whose been doing this for a few decades: Linux, BSD, Solaris, IRIX), I have never found colour† useful since I'm doing things in all sorts of contexts in the course of a day, and have never really found a need.

† Besides the prompt perhaps.

I imagine if you're hopping on and of dozens of different systems daily, it might help to have the host and username pop out at you even if everything else is greyscale.

It's sort of how I always set VMs to have a dark grey flat background. Makes it easier to see at a glance whether you're in a fullscreen VM or the host system.

Personally, I use NO_COLOR or other techniques to disable color when I'm logging output or using a CI/CD pipeline. Color codes tend to create all kinds of garbage in your logs otherwise.
Software shouldn‘t output color when the output is redirected, unless something like `--color=always` is specified.
CI often runs software in a pseudo-terminal.
Huh, I seem to have the opposite problem in that our CI doesn't emulate a terminal. (It should… but alas.) We're even moving to Github Actions, and that also doesn't.
I like color in my CI logs because it makes it easier for a human to spot various information.

Obviously sometimes you might want to grep your logs and then color sequences might be annoying. I guess there is a command line tool / sed / awk oneliner to remove them. Unix filters are from the 1970s after all.

The question is just what is the tool. I'd guess SO knows... But it's Sunday morning and I am on my phone not motivated to work :)

I like colour, but can easily empathise and visualize that I may like colour in applications I've configured, but found it obtrusive in something that vomits inconsistent, garish, distracting coloured output. So while I would not necessarily use this environment wetting, I can understand why some would treasure predictability and consistency.

Note btw that one might have a wildly different perspective as e.G. Developer using a few tools on their own controlled desktop a lot, vs e.G. a sysadmin constantly jumping between large number of tools on large number of systems. As such, having a simple variable to shut up all the apps on all the servers may be quite handy.

> I can't even think of situations where the colors chosen by a developer were so bad I wanted to disable them completely.

The main use case for this is that there are tools that use ANSI color libraries and don't handle non-colorization in non-TTY contexts. So what ends up happening is a user of said tool pipes its output to a log file and since ANSI escape codes are in-band, the log file becomes an unreadable mess. NO_COLOR provides a way for the library to give control over colorization to the user, even if the tool consuming the library hard codes colorization logic.

I'm not at all disagreeing with the premise, but I'd like to point out that having the ANSI escape codes written to the (in this example) log file shouldn't be that much of a problem. Many tools support them (though I admit that sometimes it's not default behavior). For example, I often use `less -R` for this purpose.
It's pretty bad for usability for all downstream tooling. Grepping log files is immediately worse... Ingestion into pipelines (like ELK) is considerably degraded... I can imagine almost every other tool would be similarly degraded.

I think it's fine if the logs are going straight to stdout/stderr in a console. Any other destination (piped output, logfile) should default to no color.

Grepping anything that has ANSI color codes would, I would think, be awful. Same for lots of other tools: sed, awk etc. So agreed, piped output should default to no color, and not just for the log file situation.
A lot of display tools support them (though you might find issues with CI systems that show the lot in a web page) but a lot of processing tools don’t. For example, you might have difficulty using grep on your log file if there are escape codes sprinkled through it.
Unfortunately, NO_COLOR is only the tip of the iceberg. Yes you can clean up ANSI escape codes upon human consumption in some cases, but not always. E.g. often these log files are meant to be displayed in web UIs (e.g. Jenkins). Things get really chaotic when tools call other tools via child processes. Then, you might have one tool forcing colors via the FORCE_COLOR ad hoc standard to force colors through non-TTY pipes, but the user of the tool wants to, again, pipe the output to a log for display on the web...

Don't even get me started on TrueColor :)

This does not make any sense at all. The intent is to fix programs that don't handle non-colorization in non-TTY context, and the solution is to do so by patching them by responding to an environment variable or command-line option to explicitly request no colors. Why not just fix them to handle non-colorization in non-TTY context correctly?

This is also in opposition to the motivation explicitly laid out in the website itself.

>An increasing number of command-line software programs output text with ANSI color escape codes by default. While some developers and users obviously prefer seeing these colors, some users don’t. Unfortunately, every new piece of software seems to have a different way of disabling colored text output and some software has no way at all.

Clearly, the motivation laid out here is in fact to provide a standard mechanism to disable the colors seen by the user on the terminal. Not to disable coloring when output is being redirected.

> Why not just fix them to handle non-colorization in non-TTY context correctly

"Why not just" = lack of experience in the domain

From my experience, the usual reasons are: unwillingness from tool author to accept PRs, tool is unmaintained/abandoned, tool forces color across a non-TTY in child processes calling other tools inside of itself, "ain't nobody got time to patch hundreds of random tools that are downstream of some popular colorization library", etc.

Your reading of the motivation is naive. Piping is something users do. Whether a single user never wants colors or only sometimes is kinda irrelevant to the point that the feature is desired by users at all.

As I mentioned in my other comment, colorization wonkiness doesn't end with NO_COLOR; there's also FORCE_COLOR, --color/--colors/--no-color/--no-colors, TERM, CI, glue tools calling other tools with one or more of those flags, users who sometimes want colors but sometimes not, regardless of TTY-ness, configurable terminal colors, user-facing non-TTY pipes, fragmented TrueColor support, etc.

There's probably enough wonkiness in the domain of terminal colors in the wild to write one of those "falsehoods programmers believe about" articles.

The answer is super easy: I want JSON to be shown with syntax highlight but when I pipe it elsewhere I want porcelain output. $NO_COLOR is an additional indicator that the output might need further processing and it’s not for human consumption (in a terminal)

What you might be missing is that “color” on the CLI is actually extra characters before and after a colored word. If the viewer does not interpret them (for example a web UI), they will just be extra characters. This is akin to printing `<strong>8000 bytes</strong>` and expect it to be rendered correctly everywhere it’s shown.

Example: shell uses color for the prompt, but nothing else does. That way you can quickly scroll up and see your command prompt entries.
If you start using color, you need to consider accessibility. What if you use some combinations of foreground and background inadvertently that renders it unreadable. Also, there's no guarantee color pallets will be the same.

There also needs to be a NO_EMOJI flag. I'm tired of having random garbage glyphs show up because I'm not using the latest electron based terminal that uses mono-spaced web-fonts.

> I'm tired of having random garbage glyphs show up because I'm not using the latest electron based terminal that uses mono-spaced web-fonts.

It doesn't take a Electron based terminal. iTerm2 on OS X supports emoji, and Terminal.app mostly does. Terminator on Linux supports them. (& which is based on VTE, so I sort of presume all VTE-based terminals do.) None of which are Electron based. (& I can understand not wanting that.)

(Not to imply that a NO_EMOJI might have other merits.)

The noto emoji font is usually all you need, just having it installed is often enough for them to show if your terminal emulator supports fallback fonts (I think st doesn't, but most do).

I support the idea of a NO_EMOJI env var anyway. I think theming should be left up to the user in nearly all cases and we shouldn't have colors or emoji forced on us. Devs could have something like alt text to show when emoji aren't there for cases where they're showing a meaning that the text doesn't.

> I don't quite get the desire to have just some color (prompts but not applications). Can someone with this opinion explain their rationale?

The more sparingly you use colour, the more effective it is as a means to highlight important information. Different users think different information is important.

I'm not sure how widespread it is but I work in the mining industry and I've seen a trend on newer installations towards keeping the general appearance of the entire interface to a couple of modestly contrasting neutral greys. Only parts of the plant which require operator attention are shown in colour (I think plant that's not in the normal automatic operation mode was yellow and alarms were red). The information's still all there and easy to read if the operator wants to, but it's not screaming for your attention unless it actually needs it.

Compare this with the usual visual confetti of brightly flashing colours that a SCADA system devolves into, especially after a few years when a lot of 'important new features' have been added 'which the operator needs to see'.

It depends on the app, personally I prefer non-colorised UI of mc to the colorised UI. Elsewhere I used the colorised version.
my vision is degrading, and I have never seen a colored output where every color worked on the background color, it's really irritating with dark red error messages on black backgrounds for example because error messages are the kind of thing you really want to read and then I either need to zoom in a lot or in some cases copy the text of the message and put it into a text editor where I can read it.
> I have to admit I don't really get this. I personally like colorized output, and I can't even think of situations where the colors chosen by a developer were so bad I wanted to disable them completely.

Colorized output really sucks when the output is displayed in a terminal that doesn’t support it. Visual Studio’s build output, online build terminals like CircleCI, log viewers, …

(Unsure if the ones I list above actually do have an issue with colors, but absolutely sure that I have seen it many times.)

There can be situations where the output intended for an ANSI terminal is shown as a raw text, including the color control sequences. Being able to switch off color should help with these situations.
A lot of these tools assume that you’re using a dark theme. If you’re using a white-ish background (even worse somewhat beige, like I do), things like text highlighted in yellow become invisible.

Also, some of these tools don’t detect when they are run in a non interactive shell and will continue to write color codes when piped.

A NO_COLOR flag is not perfect but better than nothing and easier to implement than theme or interactivity detection

> A NO_COLOR flag is not perfect but better than nothing and easier to implement than theme or interactivity detection

Is checking an environment variable that much easier than an isatty(3) call? I'm concerned that if this becomes widely implemented, developers will try using it as a poor substitute for isatty.

For me no, but I think it depends a lot on the experience of the developer and the language it is using. And environment variable is more common knowledge, it's cross platform and supported in any decent language. I bet that many don't even know that something like isatty(3) exists.
> I bet that many don't even know that something like isatty(3) exists.

Also shell scripts can't directly use that.

Sure, and that's why POSIX provides `test -t`.
Something like COLOR=(light|dark|none) would be much better.
Please don’t make me implement multiple color schemes for my shell scripts.
shell scripts? No, it's for CLI applications that provide colored output. Some assume dark background and some assume light background, making a mess.

A simple 3-state variable solves the problem easily.

That sounds like a problem with the palette your terminal is using, and not with the fact that programs use colour.
ANSI terminals only offer 8 colours (extended to 16 with some tricks) based on grey-on-black screens of old. They, by default, have a certain set of features (like which colour contrasts which colour). Basically, it's a very limited palette, and it's up to the theme to maintain all the properties and features that hold between original colours.

While developers can make use of more than 8/16 colours today, I find that extremely rare, and if a colour display for an app does not work on your theme, it's either an app problem in that it wouldn't work well in any terminal, or a theme problem.

If it's an app issue, what makes you believe an author would rather implement NO_COLOR instead of fixing colour choices they made?

Agreed. I'm guilty of scratching my own itch and inferring dark themes and interactive sessions, but it's nice to build things in a manner that may allow for a better integration with something else.
Implementing a flag like COLOR=light|dark|none puts the onus on application developers to interpret the user's configuration.

I think it would be more reasonable to define a standard set of environment variables based on semantics that can then be used explicitly by scripts and programs. Like CL_WARN=(code for red) CL_HILIGHT=(code for yellow) CL_OPTIONAL=(code for gray). This would make it very easy on script developers, who would only need to use these variables instead of their hard-coded ones.

I feel like that's a problem with the terminal's theme. If you use a light theme, you should change yellow's color to be readable.
CI pipelines - I need clean readable output constantly, and having random escape codes all over the output just garbages up the flow into messages nobody reads. Setting NO_COLOR=1 once in the pipeline fixes 80% of output issues.

Would it be nice if every pipeline tool supported the gambit of colors? Maybe, maybe I wouldn't care then. But as it is, more often than not, your cute colors just garbage up my build output.

1. I want to see color output in some commands, but not all of them (in some cases like with grep/ag it is very useful, in some cases colors are not useful or even makes it harder to read command output). NO_COLOR allows me to control output per-command by creating aliases 'env NO_COLOR=1 command'

2. Some color-using CLI tools assume white-ish background and actively use dark blue which is hard to see on a black background.

You must have never have dealt with Jenkins or some tool trying to parse standard error/output: it is hell with colorised outputs.
Some environments (e.g: AWS CloudWatch, many CI tools) won't parse colors and you end up with polluted text.
Why focus on imposing additional work on developers, rather than users (which, by the definition, is much wider audience) having to workaround hard-coded behavior? Adding color support to cli tools is an additional work for developers in the first place
>> so bad I wanted to disable them

ls -la

Some terminals have picked their default ls colors so bad that some entries are almost unreadable. Dark blue on black etc. Forced me to configure the LS_COLORS.

> I can't even think of situations where the colors chosen by a developer were so bad I wanted to disable them completely.

PuTTY comes to mind immediately upon reading this sentence. It is used more often than I like.

https://www.chiark.greenend.org.uk/~sgtatham/putty/

The default colorscheme is extremely bad and if you use Vim to open log files, the comments are unreadable because they're colored as dark blue on a black background. Most of the other colors are unreadable as well. The widespread usage of PuTTY in my organization is the reason I have never written scripts or programs with colors, even though colors would help a lot of people differentiate between benign, warning, and error messages.

How generally are people dealing with these coloured logs when ingesting them into a centralized logging system? Is there much overhead in stripping these sort of things out.
Most of the time they’re not printed out at all because of isatty in underlying libraries. Centralized logging doesn’t usually go through a TTY.
This is the correct answer (or at least it should be). Only print colors when going to a TTY, not when writing logs to a file.
I think that in some cases you end up capturing the control codes that control these colors, so then you want to disable the colored output explicitly.
I think state of the art is to add a json output mode, then berate people that complain that neither option is ergonomic if you actually need to read production logs.
I reported this issue four years ago to Google Cloud (not sure if it was ever fixed, no updates to the report), as they don't stripe out ANSI color codes nor render them, so our logs in their log viewer were full of gibberish from any colored messages.
While this is a good standard, I often find myself just doing `somecommand | cat` whenever I want to get rid of colors. Usually they're disabled when outputting to a non-tty device.
Definitely adding this to my todo list to add to the CLI tools I help maintain. A lot of modern tools add emojis to output as well, which I sometimes find unnecessary in a similar way to terminal colours.

NO_COLOR and NO_EMOJI seem reasonable. Any other ideas?

I think this is a fine idea but I wonder about this part:

"... should check for the presence of a NO_COLOR environment variable that, when present (regardless of its value), prevents the addition of ANSI color ..."

How common is this behavior ?

That is, the presence of the env var regardless of its value trips the conditional ?

That seems like asking for trouble / confusion ... especially since there is a very well understood practice of setting 0/1 false/true for settings like this.

Is this commonly done and I have just never noticed it ?

I think it's fairly common.

  NO_COLOR=1
  NO_COLOR=true
  NO_COLOR=yes
Rather than parsing all the permutations, the usual evaluation of env vars that are expected to hold a boolean type is just the equivalent of:

  #ifdef NO_COLOR
Well, in ZSH [[ -v VAR ]] can actually differentiate between unset and null variables

And

NO_COLOR=

would lead to an non-intuitive behavior

I think the implication is that it should have a value.
> That is, the presence of the env var regardless of its value trips the conditional ?

Pretty normal, yeah. You can `unset FOO` a variable to set it to false.

It makes the logic simple in C (where the empty string is truthy); you can just write `if (getenv("FOO"))`.
For tools that don't honor NO_COLOR, I have a filter called nofun, which gets rid of color and animations.

https://github.com/alrs/nofun

You can also use col -bx
Neat. col -bx leaves more artifacts lying around, but it does get the job done.
I hope the author of the article sees this, because this is absolutely the best solution to what they want to do.

I'm sure you can even do some clever bash-foo to run your term sessions through it, like how screen or tmux work.

It works on stdout when using a pipe output, but it won't work with interactive apps using rich terminal capabilities and ncurses.
What would prevent it from working with ncurses programs?
You can also pipe it through

    sed 's/\x1b\[[;0-9]*m//g'
As noted in the repo README:

> One could do this with GNU sed, but developers working in proprietary operating systems don't have GNU sed.

Do we even need NO_COLOR if this works as promised?

Why prefer

  NO_COLOR=true command
over

  command | nofun 
?

The latter seems both cleaner to me and it doesn’t require modification of all existing CLI programs to work.

Because you can set NO_COLOR=true in your shell config and not have to type it ever again.
but you can set also an alias for the solution above and dont depend on wether the tool supports the ENV var or not
But then you need to alias every single command
Oh yes! I am so over programs that output yellow text into a terminal with a white background and somehow expect people to be able to read the result
Don't most terminal themes map colors such that they're all mostly legible? And if not, wouldn't it be trivial to change yellow to an orange or brown?

As a rule, I don't see any reason why a terminal theme should have any color that is illegible on its background. That feels like a problem with the theme more than with the program running on it.

The exception is "true color" output[1]. In supported terminals you can make text any rgb value, regardless of theme.

[1] https://gist.github.com/XVilka/8346728

Fair. But presumably if you're doing that you're also specifying a good background color.
You should? Yes. You are? Likely not. Developers will pick coliurs that look good on their theme and not even think about overriding the background colour until they get a bug report.
My pet peeve is purple and dark blue on black or gray backgrounds.
I wrote a shell script some time back that stripped ansi color from piped output. Haven't needed it since, but can't be hard to make again. So probably we don't need this kind of quasi-standard.

(what's up with all the non-IETF "standards" all over HN and GitHub? there is an open standards process for technology, people. is the problem that us old folks never taught the youngsters how to make them?)

> While some developers and users obviously prefer seeing these colors, many users don’t.

This is bold. (Pun intended).

Colors are immensely beneficial for opt-in. I haven't heard very many complaints about it -- why does the author assume many users don't?

Many doesn’t mean most, just a non-insignificant minority.
Ah, it's a weasel word -- an assertion that takes 10X the amount of effort to disprove than to make. Got it.
I think the context here is trying to imply most: "While some developers ..., many users don’t."

It's that 'many' is comparative to 'some' here.

You hit the nail on the head. Until this thread, I've never heard complaints from developers I've worked with regarding terminal colors. I agree with the few comments that mention a fixed coloring on white background being miserable is a common-enough edge case that I hadn't considered before now (I've met two developers out of thousands who use light mode instead of dark mode, so my prior expectations were low).
... but which colours?

Windows terminals mercifully had simply white-on-black for decades, but thanks to the various Azure and .NET Core teams, Microsoft has been invaded by Linux and Mac users. Now everything has to be CoLoUr all the time.

Random colours.

Colours that make no sense.

RED ERRORS that are actually just titles.

GREEN OKAY that's actually just a table header.

Etc...

I had the misfortune of being forced to use some Node and NPM tooling recently, having come from Visual Studio and C# programming.

It was strangely nostalgic, like... stepping back in time to the 1990s and almost childish user interfaces. The spinning |/-\ symbols (with colours!) just killed me. I hadn't seen those since DOS 6.

There's something perversely conservative about Linux. There's all this talk of how it's the best development environment, but to me all this "colors in the terminal" stuff just seems like a throwback to the days when I had a 486...

In my experience, color is used to convey information for quick scanning, and is solid human-centered design.

Developers are human too, surprisingly, and benefit from good UX!

I'm a bit surprised a seasoned programmer feel these design patterns and tools for humans is childish. Do Visual Studio/C# coders typically see the many different universes of tooling outside of the limited MS Stack as childish or less evolved?

The differences is that a cohesive, consistent UI like the Visual Studio IDE allows complete customisation of the color scheme, uses subtle queues, and has colours that make sense in the context.

Typical open source command line tools are written by random people from all over the place, and there is no consistency at all, except perhaps seeing orange for warning and red for error. All other bets are off.

It's not like PowerShell, where there's separate output streams for Debug, Verbose, Information, Console, Warning, Error, and Progress! Where those can be styled consistently by the terminal, instead of the l33t coder that sprinkled some random Christmas lights into the output of his "xvtj7" tool or whatever.

The reason "NO_COLOR" makes sense and is needed is because color in Linux-style tools is done at the wrong layer, in the wrong way.

Format and style the output as the last step, not first.

> Do Visual Studio/C# coders typically see the many different universes of tooling outside of the limited MS Stack as childish or less evolved?

Don’t extrapolate too much from N=1. I used to work in a shop that mainly uses Microsoft technology. From those dozens of engineers, I don’t think I’ve ever heard that opinion. I would say the opposite, my impression was that most of them were quite happy with the increasing Unix-ification of Microsoft’s stack.

>Windows terminals mercifully had simply white-on-black for decades,

Ahem. Linux' actual HARDWARE terminals were green on black or orange on black.

I don't like it. I find it distracting, and harder to read. It feels as if I see more color than text. Then again, I'm colorblind, and slightly more sensitive to contrast, so perhaps that accounts for my preference.
Unrelated but is there a standard that keeps my ~/ home directory clean? I don't want billion apps to write ~/.foo_software_config to my home dir. It is a complete mess.
Nowadays well-behaved apps tend to use a single file or directory under ~/.config/. I believe it is a FreeDesktop.org standard: https://specifications.freedesktop.org/basedir-spec/latest/a...
And on Windows that has just made the mess even worse. Applications writing to %USERPROFILE%\Documents, %APPDATA%, %LOCALAPPDATA%, %USERPROFILE%, and %USERPROFILE%\.config

Every language needs something like this library as part of the standard library https://pypi.org/project/appdirs/ It would at least make it a little more likely that files end up where they should.

Yep, the XDG Base Directory specification [0]. Specifically the $XDG_CONFIG_HOME variable.

[0]: https://specifications.freedesktop.org/basedir-spec/basedir-...

The few things I have written always have the configs in here, seems like the polite thing to do without cluttering up home for the end user, but I can't help laugh when I look my own system and apps are storing gigabytes of data in there.

It's not really a config folder anymore, more a misused general store for files.

Yeah, if an app were truly compliant it would store caches in $XDG_CACHE_HOME and data (icons, packages, sounds, images, level data, etc. required for behavior) in $XDG_DATA_HOME. It's unfortunate that not all apps follow it
$XDG_CACHE_HOME makes sense as having a directory that you can just blow away without fear but the $XDG_DATA_HOME / $XDG_CONFIG_HOME split, while not entirely unjustified, causes more problems than it solves because a) it is not always clear what is data and what is config, b) peeople disagree on what is data and what is config and c) other operating systems don't make this distinction for application files so ported software is almost guaranteed to just pick one and call it a day - so in practice you have both config and other data spread between ~/.local/share and ~/.config.
That's a standard that apps need to adhere to. It doesn't stop apps from polluting $HOME[1].

[1] https://news.ycombinator.com/item?id=30379890

All standards are by definition something that needs to be adhered to and don't magically stop anything. If you want to force uncooperative programs to behave there are different tools for that.
(comment deleted)
One question this leaves me with is regarding other ANSI escapes. Would a user with NO_COLOR be okay with bold, invert, italic, underline, or other effects? I’m happy to add support for NO_COLOR to the tool I maintain, but I think this proposal should be more clear in this regard.

I would assume that COLOR implies that only color escapes should be disabled, but the description also mentions “plain” output.

This problem was solved using the TERM environment variable, and it will just work when people use terminfo (and libraries that use it, such as ncurses).

The problem is when people use explicit escape codes in their code rather than using libraries that solved this problem all the way back in the 80's.

Yes, I'm somewhat grumpy about this because far too many times I have found log files filled with escape codes, or colours that are absolutely unreadable when using a terminal with white background.

What drives me insane is the UEFI shell using dark blue text for some things. That's impossible to read with a black background. The last place I want to squint and guess at what something says is when I'm applying a firmware update via a uefi tool, or un-foobaring a bootloader..
Competing standard for CLICOLOR and CLICOLOR_FORCE variables that have some support: https://bixense.com/clicolors/
Yeah this is the earlier and better standard (more powerful and more precedent). The NO_COLOR guy should have dropped it as soon as people told him about this but now we have a stupid competing standards situation.

If you support NO_COLOR you're making things worse.

> many users don’t.

I doubt the "many" parts.

It sooo much more readable if your program outputs a lot of data.

And any (proper) implementation automatically switches the escape codes of if piping to another program instead of terminal so it rarely causes problems.

I'm sure there are still some people which do not like it, and there are some libraries which mess up colors without doubt.

So I'm fully in support of NO_COLOR as a "de-facto" standard.

I get what you mean, but you're not adding much to the discussion. I think of a few reasons you'd want to disable color that aren't for pure aesthetics:

- Visually impaired users might have trouble with a lot of colors

- Fully blind users won't see the color, so if it ties into a core feature of the tool, a NO_COLOR flag would force the developer to address it.

For the record, I think the article OP linked to is pretty stupid in general, but I like playing devils advocate.

If someone else becoming happy when their tools suit them better bothers you so much, maybe you should consider seeing one yourself.
I think it's reasonable to want an easy way to disable colored output, but I don't get why TERM doesn't work. Unless the request here is not for no colors but instead for fewer colors.

But if it's to disable all colors in applications, then I believe changing TERM should work. And if you run something that you want colored you can override TERM for that process.

TERM is a rather blunt instrument which changes support for many features besides ANSI color. SSH sessions further complicate matters.

TERM=dumb is useful for cases where you absolutely want serialized output, such as CI logging. Interactive cases require you to choose a value that both your terminal emulator and the software supports.

I didn't know about TERM=dumb at all until last weekend when I was messing with Haskell. Without it, the line editor in the REPL was broken when moving through the history (in both Terminal.app and iTerm2). I was surprised that it worked though since I expected that TERM=dumb would result in the REPL not being able to use any ANSI escape codes.
Great idea!

For those wondering why anyone might not like their oh so beautiful colours...

I like to set the background colour of the terminal to light green, and the text to black. It's much more relaxing. Coloured output is often illegible with this setup. Plus the colours are silly anyway...

Like MSX's BASIC prompt.
Wasn't that white on blue? I think it was the TRS CoCo that was black on green.
I'm starting to be of the mind that environment variables in general are an anti-pattern. They have arbitrary scope, their lifetime is not clear, and they are not easily composable. This was not something that bothered me so acutely until I started using declarative config with NixOS to configure my system, and found environment variables to be a big wart on this.
Also, why NO_COLOR? That's "anti". It should be COLOR and set it to true or false.
Possibly because the established default is colored output, and the absence of a boolean environment variable is generally treated as "false".

It might also be that COLOR is already used for other purposes by some software.

Let's call it MONOCHROME then. I too think that "disableSomething=enabled" naming schemes are confusing.
COLOR=(light|dark|none) would be much better.
This also misses options such as letting COLOR=1 force colours which would be nice when I want to redirect "human" output to a file without bothering to set up a TTY.

But I guess that ship has sailed.

It’s a real pain when two things use the same name. Spent ages trying to debug an issue and it ended up being the distro I was using was setting “VERSION” which is generic enough that something else happened to be using it as well..
Environment variables are fine when used for things that usually don't change once they're set. For example, XDG_CONFIG_HOME or GOPATH. They are, however, absolutely awful when used to configure values that will probably change inside a session. A good example is BEMENU_OPTS from the bemenu program, which is used to change colors, font etc. Should I relogin into my session just to make a program use dark mode colors?

https://github.com/Cloudef/bemenu#environment-variables

In such cases, environment variables lose their intended purpose and they need to be stuffed into wrapper scripts or overridden on the command line before executing a command, which is extremely annoying.

Is not that the exact same thing as global variables vs constants
> In such cases, environment variables lose their intended purpose and they need to be stuffed into wrapper scripts

Why is this so annoying? It's a very common workflow that allows you to customize how an application behaves and simplify how you run it. It's no different than setting up an alias, and I'd rather use a wrapper script or alias than have to remember how the app is configured, or search my history for the correct invocation.

In fact, environment variables are a very flexible way of configuring an app. They're generic, work the same across apps (no worries about the various ways of specifying flags), avoid the need for a custom configuration file, you can have multiple .env files and load them with env(1), etc.

I'm a big fan of following the 12factor[1] approach.

[1]: https://12factor.net/config

> Why is this so annoying? It's a very common workflow that allows you to customize how an application behaves and simplify how you run it.

I don't know about others but I'm not a fan of monstrosity like this

https://github.com/ayushnix/dotfiles/commit/2eb66eff8a03a5bf...

If I stuff it into a wrapper script, I'm essentially trying to emulate config files, which is what should've been used in the first place. This is why I prefer using config files rather than creating uglier and harder to maintain wrapper scripts.

> I'm a big fan of following the 12factor[1] approach.

I guess if you don't want state associated with your deployments, environment variables are better but I would still argue that they aren't manageable when their values become large as shown above or if their numbers start approaching double digits because when that happens, you're essentially emulating config files anyways.

> I don't know about others but I'm not a fan of monstrosity like this

I think in that case bemenu is abusing env vars to just stuff CLI arguments in a single one, so it defeats the benefit I mentioned above. It could be argued that having individual env vars for every option is cumbersome and pollutes the environment, but this is practically not a problem.

> If I stuff it into a wrapper script, I'm essentially trying to emulate config files, which is what should've been used in the first place.

Sure, but I see that as a positive. You don't have to worry about the many configuration file formats and their idiosincracies, where they're located and how they're passed to the application. Environment variables work across language stacks and platforms, are simple to implement and use.

> This is why I prefer using config files rather than creating uglier and harder to maintain wrapper scripts.

It's a matter of preference I guess, and I also don't use them for every app. In some cases they might be limiting, so a configuration file is the only option, but I appreciate whenever a program reads all configuration from the environment. It certainly simplifies a lot of things, e.g. running it in a container.