The good thing with the 256c palette is that colors in the 16-255 range are fixed, which gives us a very high level of confidence that 146 will be a muted violet and so on. This is very useful for colorscheme developers because it allows us to provide a pretty good and consistent experience across the widest range of terminal emulators.
If the 256c palette is generated from a -- potentially wild -- 16c palette then there is no guarantee anymore that 146 will indeed be the 146 I expect.
Turning 16-255 into the same kind of minefield as 0-15 seems very misguided to me.
I know 16 colours is limiting, but one of my biggest pet peeves is CLI / TUI developers creating their own custom themes using colours outside of that because odds are, they’re going to generate a colour scheme that is harder to read for a lot of people with visual impairments, people who prefer a white or coloured background for eye comfort, people are dyslexic and find non-black backgrounds easier to read, and others with visual difficulties, reading difficulties, or those who just like a different colour scheme per project or environment they’re working in so they can multitask more easily.
And the developers answer to this loss of control is to create multiple colour schemes and allow the user to configure the app. Which then means their users have to set up their terminal defaults and then configure every fscking app that ignores those terminal defaults(!!!) instead of defining their required colour schemes once in the terminal.
People use the terminal not because it’s pretty but because they find a text interface more efficient. If you want to make pretty things then build a web frontend. But please do not break my terminal because you feel the need to impose on me your own favourite colours of the hour.
I agree. I always customize the blue color on my terminal because dark blue on black is completely unreadable to me (and I'm not even color blind!). For some reason, every single terminal emulator defaults to a blue that's unreadable on a black background (I think typically #00f).
If a tool overrides my color settings, it too usually picks a dark blue that's unreadable on my black background.
Not really, because the dark yellow (not brown) is used... it's similar, but not the same in most terminals... brown as dark yellow for cga was a kind of short to a different color mix than the natural position which most terminals now use... actual screen effectiveness/brightness is different as well.
Kind of anal about this since I started with a lot of CGA and EGA displays when I was in my late teens and early 20s and relatively involved in the ANSi art scene.
Here's a related project I'm working on for playing doors in a web browser.
I have no idea if this was the reason behind turning the dark yellow into brown, but the brown was a much better looking color for DOS games so it was a good call
They could also have done something about the two magentas though... E.g. made one of them orange?
I think it was just determined that brown would be more useful than the darker yellow in practice. Other xterm colors are also a bit off from CGA/EGA/VGA DOS colors.
And I filed a PR because an author used yellow and hadn’t assigned orange to any purpose, which is actually legible on a white terminal where yellow never is.
If I was the maintainer of a terminal emulator, I would see a quite obvious way to improve the situation for my users: change the default colors so that dark blue is brighter.
There's no obvious way to unilaterally improve the situation across the whole ecosystem, that's true. But I don't understand why individual terminal emulator maintainers don't fix it for their users.
Because it means making choices, breaking assumptions, etc.. They have made it user-customizable so they don't have to go through all that.
FWIW, the current de-facto standard is set by xterm. Here is a relevant excerpt of its source code:
! Disclaimer: there are no standard colors used in terminal emulation.
!
! The choice for color4 and color12 is a tradeoff between contrast, depending
! on whether they are used for text or backgrounds. Note that either color4 or
! color12 would be used for text, while only color4 would be used for a
! background. These are treated specially, since the luminosity of blue is
! only about half that of red/green, and is typically not accounted for in the
! RGB scheme.
!
! Blue text on a black background should be readable.
! Blue backgrounds should not be "too" bright.
!
! Originally color4/color12 were set to the names blue3/blue
!*VT100*color4: blue3
!*VT100*color12: blue
!
! They are from rgb.txt respectively:
! 0 0 205 blue3
! 0 0 255 blue
! However, blue3 is not readable on a black background.
!
! Another choice was from the Debian settings:
!*VT100*color4: DodgerBlue1
!*VT100*color12: SteelBlue1
!
! From rgb.txt:
! 30 144 255 DodgerBlue1
! 99 184 255 SteelBlue1
!
! Some users object to this choice because the background (color4) is brighter
! than they are accustomed. Others point out that the different weights for
! the red/green components make it appear to be not really blue. Finally, it
! provides poor contrast against color13 and color14.
!
! The current choice uses equal weights for red/green (effectively adding a
! gray to the result). It is brighter than the original choice, and provides
! more contrast between color12 and color13, color14 than SteelBlue1 did.
! Contrast of color4 against black is slightly improved over the original.
!
! Some refinement is certainly possible (you are welcome to try) -TD
There are fewer blue cones in the fovea centralis than there are in the surrounding parts of the macula, so humans can't resolve details as well in blue light.
Which is why people who understand color tend to add a bit of green in to make a color which still looks deep blue but is much brighter than what #00f looks like
If I make a terminal emulator, I would probably not support true colours in text but only in pictures (and it would be possible to disable pictures). I probably would not implement 256-colours either, because I agree with you; the user configures their own colours to use, and the terminal should use them. For text, only sixteen colours can be used.
Similarly, the user can also set their own fonts for the terminal, just as you can with colours and other functions. (However, some programs will have a reason to configure the fonts and palettes for the specific use, although most won't and even if they do the user might disable those features.)
A program can have an option (possibly by environment variable) to disable colours entirely; this might be necessary even if you can disable colours in the terminal emulator, because a program might want to use such things as reverse video, underlined text, etc to indicate some things when colours are disabled. (Disabled colours can also be useful if you do not have a colour display or if you want to print out a screenshot without a colour printer.)
gdb (the debugger) sometimes prints dark blue text on a black background, which is unreadable. I customize the dark blue color when possible in VTE's due to this, but it's not always possible everywhere
But I wonder what the developers of gdb were using that made them not notice this
yes, this.
the reason i use wolf (firefox fork) is because i can easily disallow styles overriding, font overriding, and use bitmap fonts. nothing else.
now that react devs finished destroying the web they have to impose their superior taste into terminal through 800mbs TUIs.
Color usage in the terminal should be largely semantic, not stylistic.
Speaking for the group of people I know and work with, we don't want a "consistent experience" and hate TUIs that try to manhandle the color palette. Use color sparingly and with intention. Respect that different people have different settings.
First, I make third-party Vim colorschemes, not app. People install my colorschemes because they like the colors, not because I'm a monster with a gun pointed at their face. No one is harmed. No one is forced to do anything they don't want.
Outside of my text editor, where colors matter a lot to me for syntax highlighting, I'm definitely in the NO_COLORS camp (and in the NO_EMOJI camp, nowadays).
> Color usage in the terminal should be largely semantic, not stylistic.
I wholeheartedly agree but 0-15 sadly have zero inherent semantics, which is the single reason behind every terminal colors-related drama since forever: developer choses 9 to highlight an error message because it is generally a bright red by default --> user sets 9 to whatever makes sense to them --> error message is illegible.
It would be much better if application developers (and web developers, too) -only- had access to semantic color labels like TEXT, BACKGROUND, ERROR, WARNING, INFO, HIGHLIGHT, and so on, rather than red, yellow, blue, green, black.
I don’t want my applications to decide “this element must be red text on green background.” I want my applications to annotate the UI with things like “warning message” and “title.”
That could be done with a few influential terminal emulators adopting a consensus extension to ISO8613-6, like this: ESC[38:99:‹purpose›m for foreground, ESC[48:99:‹purpose›m for background.
e.g.
Foreground Background Purpose
----------- ----------- -------
ESC[38:99:0m ESC[48:99:0m normal ( same as ESC[39m and ESC[49m )
ESC[38:99:1m ESC[48:99:1m emphasise
ESC[38:99:2m ESC[48:99:2m de-emphasise
ESC[38:99:3m ESC[48:99:3m error
ESC[38:99:4m ESC[48:99:4m warning
ESC[38:99:5m ESC[48:99:5m caution
ESC[38:99:6m ESC[48:99:6m notice
Then people (themes) could easily choose foreground colour or background highlighting for particular roles. Some terminal emulators might also choose to configure other stylistic choices like bold, italic, etc.
(I believe ISO8613-6 defines sub-modes 0 through 5 (te;db), with 2 (rgb) and 5 (256-color indexed) being most widely implemented. But some terminals historically mess up : and ; in CSI sequences, and I know at least one would interpret ESC[38:6:1m as ESC[6;1m (blinking bold!), so here I pick 99 (ECMA-48 defines modes up to 65).)
I like this idea, although I think that they should be only one code, which might program both the foreground and background (and font styles if applicable), rather than separate codes for foreground and for background.
After thinking about it a bit more, I think the specific details of that (i.e. inventing an extended colour mode) are not ideal.
One alternative: Assign semantics to colour indexes above 256.
Both of those have the disadvantage that they separate foreground and background colour, but a user really wants a combined semantic presentation. For instance, a user might want a warning message to be black text on a yellow background, and not have to rely on the program remembering to set both foreground and background to ‘warning’ colour.
So another possibility is just to invent new SGR numbers, e.g.
Control Purpose
------------ -------
CSI 2 0 0 m normal (undoes any CSI 1 x x m)
CSI 2 0 1 m emphasise
CSI 2 0 2 m de-emphasise
CSI 2 0 3 m error
CSI 2 0 4 m warning
CSI 2 0 5 m caution
CSI 2 0 6 m notice
⋮
Then the user can configure those as they please with any combination of foreground, background, weight, slant, etc.
I'm now thinking about writing up pros and cons of alternatives.
My proposal would be to define a set of intents for 0-15 with sensible defaults and let terminal themes assign any color they would like to those. 0 would be background, 7 for foreground , 1 for highlight, 3 for titles, 4 for frames and from there work on backgrounds also..
I prefer my background dark so light colorschemes are not really an area I've explored seriously. Also, dark colorschemes are much easier to design than light ones due to the disproportionate amount of light a white, say, background emits compared to the amount emitted by text. It dramatically reduces the number of colors you can use.
We have many millenia of books using black text on a white background with various colors added, why are computer monitors all of a sudden so special and annoying
Yes, and giving developers control over colors, text size, typeface and so on has also been a usability and accessibility disaster on the web, too! The user should have this control.
> which gives us a very high level of confidence that 146 will be a muted violet
Is there anything you can do with that information though? This piece of information only becomes useful if you know what colour the background is. And you should also know the colour of text and everything else.
What if the background is muted violet? What if the background is white and the foreground is muted violet? I don't want you to ever use "muted violet" in my terminal, since you have no idea what colours there are in my terminal.
I make Vim colorschemes so I'm fully in control of all those aspects. If I decide I want a given token in muted violet it is because I know that it will works well with the background… that I have defined myself.
The exact values of your 0-15 don't matter to me and they don't matter to you either, because you chose to use my 256c colorscheme to begin with.
Then you're not really covered by the article? A colorscheme is all about... color. A TUI is about the content and function. I think there's room to have user-defined 256 palettes that are used by default, while colorschemes can use true color and be chosen by the user if they desire.
I would posit then that this article simply doesn't apply to you at all. The feature being described is targetted at users who are effectively developing their own schemes (albeit in a rather simplified automated manner). If I'm taking something off the shelf, I'm using the appropriate recommended base16. I have no expectation that a wild base16 is going to align with any 3rd-party's curated scheme.
I do understand that this logic isn't always going to click with people given the differing contexts of a terminal-wide -vs- app-specific (i.e. vim) approach, but again: that disparity seems either a legacy issue (caused by things like this 16-256 mis-alignment) OR simply a philosophical difference (whereby people who customise at the term level shouldn't at the app level & vice-versa).
For far too long I'm ashamed to admit, I would use vim with the adventure time theme on iterm2. Looking at it now I'm shocked my eyes didn't bleed more. I think the worst part was that visual mode was neon yellow bold text with neon pink bg. Relying on visual mode quite a bit while using vim I was self inoculating my subconscious with stills of a poor Jackson Pollock imitator while on multiple different amphetamines. Hopefully I find out my resistance soon.
> and consistent experience across the widest range of terminal emulators.
Instead of aiming to provide a "consistent experience", you should instead prioritize providing consistent functionality, while avoiding impeding users' control over their own particular experience.
No, because I don't develop programs. I make third-party Vim colorschemes that users install because they like the colors. There is no impending happening, here.
Yes, I know that (see the venerable https://github.com/trapd00r/colorcoke, etc.) but those tricks are not used widely enough for them to be a concern. Using those tricks is also a deliberate choice so it is definitely on the user if my lovingly crafted 256c colorscheme is broken.
Having all terminal emulators run the equivalent of colorcoke without asking the user is not a very bright idea.
I'm sorry, but I find this mentality from app developers extremely annoying.
I personally prefer light themes everywhere, both in IDEs and in the terminal. I thought that just choosing my own color scheme for 0-15 would give me the color pallette that I prefer, but because app developers like you for some reason decided that you know better what colors do I prefer, this is actually not enough. I also have to configure each TUI application separately to have the color scheme that I like.
And I do not understand why people do it. Like, why would you deliberately break the universal customization system and force users to use your own, specific to your app?
Honesty, each time I encounter an app that uses 16-255 colors, I feel like someone just violated my personal space and intruded into my chosen color pallette with their own colors that don't fit.
I'm not an app developper. I make third-party colorschemes for Vim, which I assume are downloaded, installed, and used by people on their own volition, after they have looked at, and liked, the screenshots. Moreover, I take great care to make sure they are still usable in 16c, within reason.
Because all my work is based on 16-255, I can actually guarantee to my users that, given a properly configured terminal emulator, they will get the colors on the screenshots.
If I can't rely on 16-255 to be fixed anymore, then I won't be able to make any promise anymore. In practice, it just means adding a caveat in the README.md, but I'd prefer not to. Here's hoping this breaking change gets hidden behind a checkbox/flag.
That's okay. Because the user has to reach out and choose a colour scheme they like, you can assume if they installed your colour scheme, they like the colours.
Is that really optimal? It is already true in that case that your colour schemes do not work for people with opinionated colour settings. Isn't this just relying on a quirk? The point of not using truecolor is to respect the colour preferences of the user.
Semantic styles limit the use - not all interfaces need e.g. "error" context. Take, for example, Task Warrior interface. There is no place for the "error" semantics in it. But there's a place for "critical task" semantics, which is usually also some shade of red.
This will be fascinating to see in practice, with ghostty for example shipping these changes! I expect that the concern you have here will largely be for naught, with some exception. What are some terminal apps you think might be affected, what are test cases?
I didn't read in fully, but what I was thinking in my head is not that we would just totally replace the rest of the colors with arbitrary palette. But that we would sub in better versions of the palette that also used user colors as the base. What was magenta is derived from what the user picked from blue and red.
There's always been such tension between design/creative and users. Apps & designers want their own brand identity, want creative control to make things just so. And are willing to throw user preference & desire on the pyre to get that exacting control. Personally that was always rubbed me extremely the wrong way; I would way rather allow some weirdness & funkiness in, if it leaves the user in control. But I understand the risk aversion, understand the Murphy's law corporatism that makes people and companies want to build strong laws that forbid anything but strictly approved systems, for fear that things go wrong. I understand. But I also things that's a dogshit world to live in.
0-15 are, as I said, a minefield because they are user-customizable: there is no guarantee whatsoever that my user's 1 will be the same dark-ish red as mine… or that it will be dark-ish… or that it will even be vaguely red-ish. It is actually somewhat fun to design colorschemes within those crazy constraints but oh well.
On the other side of the spectrum, truecolors is a nice idea in principle but support is still spotty and inconsistent. In theory, this gives me, the designer, full control over the colors used in the UI, which is a good thing for us and for my users. In fine, if I want my colorscheme to be usable by most users, then I can't blindly rely on this.
Which leaves me with 16-255, which are more widely supported than truecolors and, more importantly, dependable. They have problems, as mentioned in the article, but their _fixed_ nature gives me confidence that the background color of the status-line, for example, will look exactly the same -- and exactly how I want it to look -- in all my user's environments. Which, again, is good for my users and for me. Losing that confidence is what worries me, here.
Like you said, maybe 146 will still be a muted violet —— just not exactly the same -- but I'm not sure about this and I think that, at the minimum, this "feature" should be put behind a checkbox/flag.
You define a baseline color in HSV and then everything else is a multiplier of that
For example
[style]
HSV = [0.7, 0.5, 0.5]
Dark = { H = 1.0, S = 1.2, V = 0.25 } # Make dark elements less saturated and darker
Symbol = { H = 1.0, S = 1.8, V = 1.8 } # Make symbols more vibrant
As a result you can simply move around the HSV to your preference in the config and things don't look like garbage where you have to hand tweak every color to get something legible.
Though, I have a problem with even just the basic 16 colours:
black
red
green
yellow
blue
magenta
cyan
white
bright black
bright red
bright green
bright yellow
bright blue
bright magenta
bright cyan
bright white
~~~
Many themes take `black` to mean `black` and `white` to mean `white`. How is it supposed to work when one switches the theme between the dark and the light version?
What are `black`, `white`, `bright black`, and `bright white` supposed mean?
I take those as meaning (in order): `almost invisible on current terminal background`, `pretty contrasty`, `visible but not contrasty`, and `the contrastiest`.
I wish the colour names reflected that, instead of `black` and `white`: you usually care about the contrast, not about the precise colour.
The way it's supposed to work is you don't touch the terminal colors but instead configure the program to use different colors. So you don't invert black for a dark theme, instead the program uses white instead of black.
By the way, the terminal foreground and background colors are independent of the standard 16 colors, which complicates things.
> The way it's supposed to work is you don't touch the terminal colors but instead configure the program to use different colors.
That makes sense, but... seems infeasible in practice? "The program"? I tell you what program I need to configure: all of them! Ideally even the programs I'm not even using yet.
I think I'll continue doing it my wrong way then: redefining the meanings to mean less/more contrasty. That allows me to effortlessly switch the terminal between light[0] and dark[1] backgrounds. I've done worse things: I also hijacked a part of the 256-colors-cube for my own purposes...
Unless you provide a way to configure the colors, it’s better to simply rely on bold, reverse, and standout. If you using the 16p, don’t use black and white unless you know ehat the background is, and use the others sparingly and semantically (no rainbow soup). If you’re going for 256p, it should be in a theme engine that’s user configurable.
The word “should” is way too strong. It’s ultimately just a personal preference. For me I would prefer a two-tier approach.
There are different programs inside the terminal that I would prefer to have different color treatment. A full-fledged editor like emacs should have full 24-bit color support because I have already configured it to have my preferred color schemes and I prefer to switch themes inside emacs. On the other hand, almost all other TUI programs should not be permitted to use more than the traditional 16 colors. I haven’t configured them myself so I don’t trust them to make good choices.
In other words different terminal capabilities for different programs.
I’m concerned not everyone have their base colors set sensibly - as in “there’s no guarantee the base garish RGB green is green on this machine”. Maybe the right thing would be to put the color closest to a base color on the corresponding corner of the RGB cube, but that’s also not ideal - I have had terminal palettes that were all green or all orange/red, or the green/yellow of EL displays.
Maybe applying the saturation of the base set across all the generated palette would also work.
Yeah, when you point it out, this makes complete sense and every terminal should probably add this feature. I think I would generalize this to 24-bit color as well; 16 colors isn't enough to identify a unique tonemap, but if you fiddle with the parameters a bit I think it shouldn't be too hard to come up with something hacky that works.
Although, this should probably be optional (both as an option for terminals to have in their own settings, and via an escape sequence that opts out), because some users will have configured some programs with a color scheme that they don't want transformed. For example, if your terminal uses the Solarized color scheme, and your text editor _also_ uses the Solarized color scheme, then this could lead to double-applying a color transform and getting something odd.
Interesting. You could build a LUT from the 16 color palette to map the 24 bit color space to something 24 bits or less. A bit like mapping 10 bit HDR to 24 bit sRGB.
Perhaps instead of the application overriding the setting, it could be done with an environment var, so the user can easily override it if the mapping messes with the look/usability of the program.
Really interested in this for cargo/rustc. We run into issues where we need one or two more colors but all that is left after going for the basic semantic colors is magenta (odd choice), and black and white (not safe without inspecting the theme).
Other than red and green, for semantic reasons, a CLI tools shouldn’t bother with colors. And it should support text markers instead of colors for the occasional piping.
That's what cargo/rustc do: all of the information is conveyed through text, but colors are used to make it easier to scan. It ends up using almost every usable base-16 color: red for the error marker and their primary spans, yellow for warnings and their primary spans, blue for secondary spans, the gutter separator and line numbers, bold text for the main message, cyan for notes and their primary spans, green for helps and their primary spans, green and red for structured suggestions, bright magenta for very specific hand-picked highlights (used to be bold/bright white, but that wasn't obvious enough in lots of terminals, used semantically equivalent to bold or italics in text, the case most people will encounter these in is in E0308 type errors where a specific type parameter didn't match) and white for anything else. Note that of the mentioned output the only thing that is differentiated in color only is the message highlights, and that's because it is generally done for either extra clarification ("Trait is not implemented for Foo, but it is implemented for Bar") or within code that we wouldn't want to pollute with additional non-code ASCII markers (people should be able to copy&paste those types without causing parse errors). Some people deride this variety as being too "christmas tree", but IMO it works quite well for scanning output. Color helps a lot when scanning longer lists and dense output. Colors might not help much if the tool is emitting a single line of output for each event, but rustc emits dozens of lines per error. And no, reducing the amount of output would not be the answer for rustc, you can already use `--message-format=short` if you want that, or try/contribute to one of the TUI projects consuming the json output for dynamic navigation of the output (to expand and contract sections). rustc and cargo default configuration have to cater to the most common case, while also keeping the number of non-essential features (like a built-in TUI) to a minimum.
We're probably close enough to a future with the technology and engineering able to implement it, to justify designing 48-bit perceptual bit depth standards. Optimistically presuming breakthroughs enabling in vivo biological upgrades to our eyes to match those of mantis shrip, we could design 160-bit standards knowing that is a "proven" biological technology capability. That gets within the same galactic supercluster of the known limits of physics limits.
At the currently known limits of physics where Heisenberg Uncertainty Principle, Abbe's Limit, Quantum Shot Noise and such become our sensing barriers, we suspect we need only about 6000 bits per pixel to represent a digital twin of the electromagnetic field of the sensor-covered volume of space. At 60 fps, that is 1.8 Zettabits per second. Scale out data volume accordingly when using using 18.5 sexdecillion fps (Planck time fps).
What surprises me is these "limits of the fabric of reality as we know it" mind experiments fairly concretely point the way on the many roads towards Kardashev Scale implementations, and is not that different from Archimedes' "Sand Reckoner" and Hindu cosmological Kalpa time scales. History doesn't quite repeat, but rhymes yet again.
Oddly enough, I'm colorblind and I have had the worst time with color schemes. Many are completely unreadable and lack sufficient contrast. Others I just don't like
So, I've started using AI models to generate color schemes for me.
Take an unreadable theme I like and generate one that is high contrast and still coherent. It's probably not good enough for a full spectrum vision person to use but wow has it improved my quality of life.
It wouldn't surprise me if this is exactly the type of problem that is solved in the same way for the rest of you
> Many are completely unreadable and lack sufficient contrast.
I am not colorblind, and have the same experience. It's made worse by the fact that different apps use colors differently, so if I find a theme that works well for some clis and tuis, there will be others that will have unreadably low contrast with the default theme. So I have to tweak the colorscheme for each application as well.
The problem with this change is that it breaks setups for people who have already adjusted their color schemes to work with the 256-color palette as it is. It's now essentially double-adjusted.
(…and people wonder why I use gvim rather than vim…)
I see TFA mentions Solarized. I've been using Solarized light for longer than I can remember, even on Windows where I can (eg VSCode), and it goes a long way to making my eyes happy. I share the irritation with dark blue on black and can't stand dark mode (maybe I'm now old and no longer 31337 ... alas ...)
Kde has their own palette, and I hate it, the colours are all wrong, and the scheme is fugly... I usually set it to "Linux default" and hope its good enough to read
We should define a set of base colors for terminal apps that are used for themes so that we have a common set of colors for all term apps.
Text, background, borders, hilight, muted then let the terminal set its theme.
Wild, potentially stupid thought: why couldn't a terminal let users supply a user.css like browsers? They'd only have to support the small subset of text styles.
Color 0 to 15 are user-customizable by all terminals I know of. Color 16 to 255 are standardized, and the same across all terminals. Most (good?) cli and TUI use the first sets, while any that uses the second set usually are used through a theme engine (per app customization though).
This definitely seems like a sensible starting option to generate 256 colours from a custom set of 8 (and then let the really pedantic users fiddle with the extended set). I would presume for "standard" themes these values would be pregenerated and adjusted slightly if needed.
The mainstream solution is to use truecolor and gain access to 16 million colors. But there are drawbacks:
Each truecolor program needs its own theme configuration.
Changing your color scheme means editing multiple config files.
Light/dark switching requires explicit support from program maintainers.
Truecolor escape codes are longer and slower to parse.
Fewer terminals support truecolor.
> Each truecolor program needs its own theme configuration.
Yes, but programs that need more than 16 colors are already often doing this.
> Changing your color scheme means editing multiple config files.
Already has been implemented at least several times over.
> Light/dark switching requires explicit support from program maintainers.
Yes, we have an escape sequence to ask the terminal to ask the OS for this. Most programs that need to care about this already use it.
> Truecolor escape codes are longer and slower to parse.
Not in a way that matters. It only shows up on torture test benchmarks on especially slow parsers. It wouldn't effect normal usage even on a terminal running on some tiny SBC.
> Fewer terminals support truecolor.
XTerm itself, rxvt, iterm2, Alacritty, Wez, Kitty, Ghostty, wt/modern conhost, mintty, st, everything that uses libvte, everything that uses libvterm (such as neovim's built in term), emacs's term, asciinema; tmux, screen, dvtm safely handle them; the linux console snaps it to the nearest 256 color; iterm.app, the original garbage osx one, is the only major term I can think of that does not handle it.
What I would like is HDR colors, just to access more saturated light colors. I don't want less saturated blue to make it lighter, just crank up the blue channel to 11. I still don't want brighter colors than #fff though.
I think your wish is self-contradicting. `#fff` is so-called _device_ colour -- a device like a LED-based display uses it directly to drive the LEDs, where `#fff` means that the red, the green and the blue channel are already "cranked to 11". The `f` here is equivalent to 11. HDR uses a different color format, I think -- exactly because `#fff` is otherwise either ambigous, or has to map to a different colour gamut -- where, for instance, `#fff` actually means the whitest white cranked up to 11, at however many nits (say 1500) the monitor may emit, which would make your "standard" or "SDR" white (per sRGB, say) that's usually has the emitted strength of around 100 nits, be somewhere at `#888` (I haven't taken into account the _curve_ implied here, at any rate I don't think it's going to be a linear relationship between nits and device primary N-bit colour numbers).
Also, `#fff` is ambigous -- if you mean device colour, then there's no brightness (nits) specified at all, it may be 200 or 2000 or 10,000. If sRGB is implied, as in `#fff in sRGB colour space` then the standard specifies 80 nits, so when you say you don't want brighter than that, then you can't have much of HDR since sRGB precludes HDR by definition (can't go brighter than 80 nits for the "whitepoint" aka white).
I think if you want HDR you need a different colour space entirely, which either has a different peak brightness, or one where the brightness is specified additionally to e.g. R, G and B primaries. But here my HDR knowledge is weak -- perhaps someone else may chime in. I just find colour science fascinating, sorry to go on a tangent here.
It wasn't obvious to me -- I misread "blue" as "white".
`#fff` is device color, it's short for `#ffffff` which is 24-bit RGB that predates sRGB, as does true color device support. I was sending 24-bit RGB to VESA-compliant graphics cards before sRGB became a thing. `#fff` was supported by Photoshop and Macromedia products as straightforward device colour format, before sRGB was adopted by at least the latter, mind you. The use by CSS is co-incidental, not where the format was introduced.
I meant #fff as the nominal white point, which is not the brightest white the device can produce. It's how #fff is displayed on Firefox on an otherwise HDR screen. Assuming the screen is not set to max brightness and otherwise HDR capable, it means that it's not the max brightness an individual pixel/subpixel can produce, so desaturating blue color just to make it brighter can be an unnecessary compromise only dictated by color representation in the software stack.
> If you've spent much time in the terminal, you've probably set a custom base16 theme.
Hmm, I suspect that almost everyone who works in the terminal has never done this. I don’t really care what the colors look like, beyond choosing between whatever built in themes my terminal has. Is this really the minority experience?
I'm pretty sure the word "custom" refers to the act of choosing among builtin themes in the terminal. Some terminals like ghostty have hundreds builtin.
I’d also add a quantization slider that would quantize the in-between colors to less than 256 different colors; in the extreme position to just the 16 colors.
The article is well argued and well written, as far as I’m concerned.
What’s needed if you really want adoption is to define a term; something like 256-ex for extended. Or whatever.
But folks and apps need to be able to say; we’ve implemented or we support 256-ex. Without this label is hard to drive adoption.
The heartbleed thing from a few years back best taught me this.
Good luck I hope to see broad adoption it’s a great idea.
Give it a name, better yet move the copy onto a website with the same name also and a little icon folks can add to their website if they implement this k to their terminal app.
That's ridiculous, even if you extend third-party to mean 'not bundled', with Linux depending on distro that's just everything except the kernel anyway, it's not some 'oh my god it's not bundled it doesn't just work', that's exactly the way it does work - if you want something you install it.
(And if you don't make such an extension, what, you have no third-party graphics drivers for example?)
Windows doesn’t even have a framebuffer console, so you’re not exactly comparing apples to apples here. In a Linux GUI (X or Wayland) running a modern terminal you get what you are asking for. Same as Windows except that standard Windows lacks the ability to run without a GUI.
That's hardly a harsh truth. We use the terminal model because it works good enough and there are decades of software that rely on it. There are certainly other models that could work, but so far they haven't been adopted. I'd love Mathematica style notebooks for my shell work.
Again, don't confuse the shell (command line interpreter) with a terminal with escape codes and the like. Check how 9font does it, you get the rc shell and a few more languages with a REPL (lua ports and the like) inside a graphical window, not by emulating a VT220 terminal running the shell inside. You can freely resize the 9front's rio window manager's windows running rc (or anything else, even games, graphical browsers, images, video players...), copy, paste, cut the text, save the history, grep the contents of a window's text itself and tons more.
You are confusing the unix terminal model with specific terminals. The TTY concept doesn't mandate an 80x24 text only device. Outside of applications that specifically rely upon the existence of a directly addressable grid of characters, Unix TTYs and PTYs would work perfectly fine in a mathematica notebook style interface.
As a text interface lover and someone who dived deep into terminal quirks, I do think you have a valid point. We need to design a text interface without all the legacy cruft, better suited for modern needs (including colors), and better mixed-mode output and interaction, something similar to what we have with Jupyter, for example (without the Web/JS/Python baggage though). It would require rebuilding whole ecosystem from scratch though, thus unlikely to happen any time soon.
Terminal emulators are user facing. Most programs don’t care about the terminal and have no awareness of it. They communicate through streams of texts and that’s it. I use Emacs and it’s another text interface different from the standard terminal. Think dired, proced, magit…
I'm rapidly developing grumpy old man habits about this gulf between "web" and "terminal". Imagine a world where we do `ls | grep .files.size` or something.
I mean, I get why we're here, but it feels so close to giving us all the power of html/css/etc while also having pipes and shells.
It's perennially baffling to me why we're still clinging to VT220/xterm compatible terminals. I even see people claiming they prefer working in the terminal, though it's not clear to me what type of work those people are doing.
Give me a proper graphical application any day, but I recognize that it's historically been a lot more work to produce a GUI in the pre-LLM era.
But golly gee whizz if we're going to keep the command line around, can we move on from 1983?
GUI apps are good for discoverability. They generally are not optimized for rapid use by power users though. That's of course not an inherent limitation of GUI apps, it's just that dominant paradigms hardly seem to consider power users.
I'm still annoyed and baffled by the fact that Ubuntu had searchable application menus 10 years ago, which were awesome and worked for just about any program, and then dropped them when they abandoned Unity. And neither KDE not Gnome thought to bring them back. In stead, many apps have since dropped application menus entirely, in favour of... some mishmash of icons and ad hoc menu buttons?
Also, even in the post-LLM era, building a decent GUI app is a lot more work than building a decent terminal app.
Another factor is the lack of a good cross-platform GUI toolkit (by which I mean one that (a) doesn't feel out-of-place and jarring on any platform and (b) doesn't turn a 50K app into a 1GB download.)
Between that and the level of complexity of modern GUI toolkits - and the size of their dependency trees - distribution of a GUI app is a much bigger headache than distributing a terminal app.
That hasn't been true for a while, it's easily the best of the bunch at this point. It's also always been trivial to change, which can't be said of the others.
Terminals are text. Text adds features missing from gui namely:
* Ad Hoc
requirements change and terminal gives ultimate empty workbench flexibility. awesome for tasks you never new you had until that moment.
* Precision
run precisely what you want, when you want it. you are not constrained by gui UX limits.
* Pipeline
cat file.txt | perl/awk/sed/jq | tee output.result
* Equal Status
everything is text so you can combine clipboard, files, netcat output, curl output and then you can transform (above) and save. whatever you like in whatever form you like, named whatever you like.
Unix is not about a terminal, that the obsolete medium, kinda like preaching about DOS PC with 386's... and CGA video cards.
9front copes with actual text throwing the terminal as a different tool to run legacy stuff in such as SSH or some small ANSI C tools either with the APE compat layer or NPE binding ANSI C code to Plan9 native functins.
You can resize windows with shells under 9front freely, no more SIGWINCH. No more broken cuts and pastes while running a terminal multiplexer. No control code risks executing potential malware.
In 9front, a decades old fork of Plan9. It's basically more Unix than Unix itself, by expanding the 'everything it's a file motto' and now for real and leaving out useless VT220 emulators (and any TTY/serial emulating connections) for legacy stuff such as the 'vt' emulator itself running under a graphical window and, for instance, when running SSH against Unix machines sending you a PTY plus a shell.
Why? There is huge compatibility layer build on top of this and changing even these minor things will break stuff in places you do not expect. Want a fancy terminal? Install another one. By default most allow changing to many terminal formats. Break things to move forward is fun when it's not your problem to solve down the line.
Personally, I find a REPL-based programming interface to be the most flexible and powerful way to interact with code.
My typical interface is that I have an editor open where I write package code, and then I have a julia REPL open beside it where I load the package (or includet the script or testset). Any changes I make with my editor to functions or structs in the package / script / testset are automatically reflected in my running julia session via Revise.jl.
I then execute the functions interactively from the REPL, introspect into data or generated code, debug, run benchmarks etc all from the REPL.
GUIs are great for many things, but they lack the flexibility I need for my day to day work.
Graphical applications are great if your workflow mirrors the workflow that the GUI was designed for. However if your workflow differs then you’ll often be fighting the GUI.
Think of it like different types of programming languages. Some are more suited on different types of problems than others.
For me, my workflow is about composing and gluing different processes together rather than using a standard defined tool repeatedly in the same way as that tools UI was originally designed. So the CLI is ideally suited for me in all the areas where a GUI would be high friction.
> it's not clear to me what type of work those people are doing.
As little as possible. Anything that can be done in a terminal can be scripted and automated, put under version control, and deployed using modern CI/CD and devops tools.
It's a shame to see you get downvoted (presumably because you don't cite any evidence for your assertions). As a counter-point, I will give the oft-quoted-by-me 1990s promotional video of the use of IBM CallPath on an AS/400 which should get you all misty-eyed https://youtu.be/5pY6Xxptp9A?t=2058
I don't know any GUI that beats tmux work portability.
Of course everything depends on exact nature of the work, but personally I would gladly leave text based interfaces behind, it's just that there's nothing better.
I don't want "a terminal", I want a command based interface combined with being able to use the same set of tools/commands on all the files I interact with.
Like, it gets taken for granted, but being able to literally grep my html file, my program source and my readme file, instead of having to open a separate gui program and using its bespoke seach menu feature, is really, really nice.
There are downsides of course, like the way we keep jamming everything into the square hole that is 1980s terminal emulators and character based displays, but frequently this is worth it.
Thankfully Xerox PARC has an answer for that across Smalltalk, Interlisp-D, XDE, and Cedar, and copied to certain extent in modern programming languages, REPL environments and notebooks.
Augmented nowadays with agent environments and tools in IDEs, which can even be voice controlled.
9front does that without emulating a terminal. Grep, cc, awk, walk (no find and magical incantations with -print0 there), functions instead of aliases on rc, better lists () in rc, and so on. And you can launch these command inside your graphical editor such as sam or better, Acme. And even as a pipe to selections.
9front/plan9 leaves tmux and the like as toys. The moment you can use system tools, 9p and files on everything (even the text of the editor itself) you wont be back to these unusable teletype emulators, be XTerm clones or terminal multiplexors.
Unix downvoters should have a look on 9front (the most featureful/supported plan9 fork out there) in order to realize that you can follow the Unix philosophy (even more than OpenBSD itself) tossing the VT100 emulators to the legacy 'vt' emulator if you want somehow use ancient software (or SSH) while setting actual graphical windows with the shell running inside with no terminals at all. No more damn control codes messing up everything. No more linebreaks. You can cut down your text with the mouse from day one. Even under Sam, which is something like a graphical Ed crossed with Notepad and much more powerful expressions than Ex/Vi ones.
(I didn't downvote you.) Plan 9 made some really cool design decisions, and I keep looking for places to use 9P. I also believe that Plan 9, as an artifact of its era, bet too heavily on the mouse and pixel-mapped graphics. Text, character-cell terminal emulation, and SSH won for good reasons. "GUI > terminal" is a separate matter from "Plan 9 > Unix".
In some important ways, even text with hacky escape codes is more useful and more robust than a fundamentally graphical interface. Text scales up and down with display size and pixel density. Text works over high-latency links and enables simple latency compensation like in Mosh. Text gives you universal copy-paste. Text is more accessible for humans and for machines.
I use a virtual terminal daily on my phone. If we literally used rio GUIs designed around the three-button mouse and desktop pixel density, it would be a lot less ergonomic. I'd like to see a successor to the VT220 lineage, but it's easier to imagine it built on text.
> I also believe that Plan 9, as an artifact of its era, bet too heavily on the mouse and pixel-mapped graphics. Text, character-cell terminal emulation, and SSH won for good reasons. "GUI > terminal" is a separate matter from "Plan 9 > Unix".
What era? That is exactly the workflow of everyone using macOS and Windows around here.
Connecting to cloud environemnts is also done via a mix of RDP, VNC, Web GUI based tooling, akin to a modern X Windows replacement.
Classic Xerox PARC-derived GUIs are very useful but not a replacement for the terminal. I also connect to my workstation over RDP, then use a terminal emulator.
Windows is a good example of what I mean. Windows system administration has become unmistakably more text- and console-centric over time with the rise of PowerShell. Windows has started shipping an SSH service and made its graphical interface optional on the server.
The web has avoided falling into the same trap. Web UIs are, for the most part, delivered to the user as hypertext rather than rio-style pixels. They rarely hard-require a mouse and have adapted well to touchscreens. Graphics in new web UIs is usually vector (SVG).
You are missing the part that PowerShell has exactly a Xerox PARC like experience, first with PowerShell Integrated Scripting Environment, nowadays the same experience is available in VSCode.
Replicating the experience of using something like Smalltalk transcript window.
Of course Windows has SSH support, it needs to interoperate with UNIX, given that UNIX won the server room.
No need for SSH to talk with Windows Core/Nano, it can be done via Web GUI administration, or PowerShell remoting.
> Replicating the experience of using something like Smalltalk transcript window.
As far as I know from Pharo, the Smalltalk transcript logs plain text and is less capable than xterm. So what you care about is not the capabilities of the terminal but having a long-lived interactive session/REPL or a REPL integrated with an editor?
> No need for SSH to talk with Windows Core/Nano, it can be done via Web GUI administration, or PowerShell remoting.
I was thinking of the administrator connecting to Windows from their Mac or Linux/BSD machine. I don't know if that's a good idea compared to them getting a Windows VM and using Windows-to-Windows PowerShell remoting as you suggest.
With 9front you don't use SSH except against Unix. The motho there is too use 9p and import remote 'cpus', devices, auth against different servers... total orthogonality. You can spawn remote windows as if they were local. Heck, you can debug remote processes as if they were local too. By comparison SSH looks primitive...
No, it's the opposite. in order to send commands to a hosts you shouldn't need a terminal emulator (twice or thrice, depending on the SSH, tmux and the VTY subsystem under Unix) and even sending baud information. 9front just gives you the graphical window and the shell. Mosh? Ok, 9p and more can be almost stateless in order to not drop the connections. Still, you aren't bound to neither escape codes nor to crude hacks as SINWINCH and horrors to copy and paste text under Tmux/Screen. Don't get me started on trying to do such tasks with URL's.
Text? I do that under 9front, too. Heck, rc it's simpler there than sh itself.
I can bind remote machines and use their scripts as if they were my own. I can import remote devices. I can do stuff without resorting to crude hacks with openssl and nc. C itself it's far simpler. Text, you say? No locales, and UTF8 everywhere. I can freely resize the windows and still cut and paste stuff like nothing. It's 2025. The closest workflow under Unix would be Bitlbee + any client for it, msmtp and mbsync for Email and any graphical client against the SLRN cache in order to be as usable.
Rio can use different fonts just fine, you know. There are several users using 24 px fonts on HD screens without no issues. With riow you get 'virtual desktops' a la cwm/i3 and the like.
>Three button mouse.
I don't do mouse chords, but I get more universal copy and paste as I stated that the old Unix itself, with shorter and easier scripts again... than Unix.
On snarf/paste instead of the menu, modyfing rio/sam and the like for a keybinding can be something done under an afternoon. Riow can already manage windows and close then with keybings among the mentioned virtual desktops.
Oh, and BTW... for vi users... I consider the Sam regular expresions far more powerful than the vi keys themselves. I can highlight the text with the mouse and write a sam command (on acme too) which affects the selection and in an easier way than the old syntax. The best of both worlds. RSI? Well, that's a point for Unix, but with the Windows key + 1-4 the mouse usage can be reduced a lot.
And, again, the 9front API it's dumb simple; I'm pretty sure doing stuff like mapping the Windows key +j-k-l to mouse button 1-2-3 would be something relatively easy, even setting sticky menus. With that small patch tons of usability issues would go away. Meanwhile, under X.org, Wayland, evdev and the $toolkit of the day... good luck.
I don't think there is a client that will let me connect to 9front from Android, is there?
I see what you mean in this and the other comment. With 9front, you rely less on issuing commands to remote machines because you can directly access their resources. It's worth keeping in mind when comparing Plan 9 and Unix from a Unix user's perspective.
Being able to pick large fonts on the server isn't the same as leaving the fonts up to the client. When I use terminal emulators, SSH, and tmux, I can switch between different clients with different resolution, pixel density, and screen orientation and have the text display acceptably on each (minus text reflow for history, which is an issue).
> I consider the Sam regular expresions far more powerful than the vi keys themselves.
I agree, structural regular expressions seem like a better version of vi commands. It was reasonably easy to make some complex edits in https://github.com/martanne/vis when I tried it, and it felt like I'd only scratched the surface. I could see myself still using vis if it had tabs like Vim. (Tabs are a stated non-goal for vis.)
If the 256c palette is generated from a -- potentially wild -- 16c palette then there is no guarantee anymore that 146 will indeed be the 146 I expect.
Turning 16-255 into the same kind of minefield as 0-15 seems very misguided to me.
And the developers answer to this loss of control is to create multiple colour schemes and allow the user to configure the app. Which then means their users have to set up their terminal defaults and then configure every fscking app that ignores those terminal defaults(!!!) instead of defining their required colour schemes once in the terminal.
People use the terminal not because it’s pretty but because they find a text interface more efficient. If you want to make pretty things then build a web frontend. But please do not break my terminal because you feel the need to impose on me your own favourite colours of the hour.
If a tool overrides my color settings, it too usually picks a dark blue that's unreadable on my black background.
https://int10h.org/blog/2022/06/ibm-5153-color-true-cga-pale...
Kind of anal about this since I started with a lot of CGA and EGA displays when I was in my late teens and early 20s and relatively involved in the ANSi art scene.
Here's a related project I'm working on for playing doors in a web browser.
https://github.com/bbs-land/webterm-dos-ansi
They could also have done something about the two magentas though... E.g. made one of them orange?
ex: https://16colo.rs/pack/ice-200207a/ti-war.ice
I have to select that text to change the background to read it.
But there is no standard or standard body anywhere for terminal colors so there is no obvious way to improve this situation.
And no urgency either, because all terminal emulators allow users to customize the palette anyway.
There's no obvious way to unilaterally improve the situation across the whole ecosystem, that's true. But I don't understand why individual terminal emulator maintainers don't fix it for their users.
FWIW, the current de-facto standard is set by xterm. Here is a relevant excerpt of its source code:
Make that what you will :-).That’s true for 256 colour and various other escape codes too. But I wouldn’t say it’s true for 16 colour pallet.
Similarly, the user can also set their own fonts for the terminal, just as you can with colours and other functions. (However, some programs will have a reason to configure the fonts and palettes for the specific use, although most won't and even if they do the user might disable those features.)
A program can have an option (possibly by environment variable) to disable colours entirely; this might be necessary even if you can disable colours in the terminal emulator, because a program might want to use such things as reverse video, underlined text, etc to indicate some things when colours are disabled. (Disabled colours can also be useful if you do not have a colour display or if you want to print out a screenshot without a colour printer.)
An even bigger one is hardcoding black and white instead of using foreground/background and use reverse when needed.
But I wonder what the developers of gdb were using that made them not notice this
now that react devs finished destroying the web they have to impose their superior taste into terminal through 800mbs TUIs.
Please just don't. This is not the web.
Color usage in the terminal should be largely semantic, not stylistic.
Speaking for the group of people I know and work with, we don't want a "consistent experience" and hate TUIs that try to manhandle the color palette. Use color sparingly and with intention. Respect that different people have different settings.
Outside of my text editor, where colors matter a lot to me for syntax highlighting, I'm definitely in the NO_COLORS camp (and in the NO_EMOJI camp, nowadays).
> Color usage in the terminal should be largely semantic, not stylistic.
I wholeheartedly agree but 0-15 sadly have zero inherent semantics, which is the single reason behind every terminal colors-related drama since forever: developer choses 9 to highlight an error message because it is generally a bright red by default --> user sets 9 to whatever makes sense to them --> error message is illegible.
I don’t want my applications to decide “this element must be red text on green background.” I want my applications to annotate the UI with things like “warning message” and “title.”
e.g.
Then people (themes) could easily choose foreground colour or background highlighting for particular roles. Some terminal emulators might also choose to configure other stylistic choices like bold, italic, etc.(I believe ISO8613-6 defines sub-modes 0 through 5 (te;db), with 2 (rgb) and 5 (256-color indexed) being most widely implemented. But some terminals historically mess up : and ; in CSI sequences, and I know at least one would interpret ESC[38:6:1m as ESC[6;1m (blinking bold!), so here I pick 99 (ECMA-48 defines modes up to 65).)
Anyone interested, ping me (address in profile) and encourage me to set up a repo to discuss and formulate a concrete proposal.
I’m working on a terminal emulator. It’s not big like Ghostty but this is something I might adopt
One alternative: Assign semantics to colour indexes above 256.
Both of those have the disadvantage that they separate foreground and background colour, but a user really wants a combined semantic presentation. For instance, a user might want a warning message to be black text on a yellow background, and not have to rely on the program remembering to set both foreground and background to ‘warning’ colour.
So another possibility is just to invent new SGR numbers, e.g.
Then the user can configure those as they please with any combination of foreground, background, weight, slant, etc.I'm now thinking about writing up pros and cons of alternatives.
- Apprentice, a low-contrast colorscheme I made years ago and used for a long time: https://github.com/romainl/Apprentice.
- Malotru, my curent colorscheme, more contrasted: https://github.com/romainl/vim-malotru.
- Dichromatic, for colorblind users: https://github.com/romainl/vim-dichromatic.
- Bruin, which only uses typography: https://git.sr.ht/~romainl/vim-bruin
I have one here: https://github.com/romainl/vim-sweet16 but it is intentionally weird and essentially unmaintained.
We have many millenia of books using black text on a white background with various colors added, why are computer monitors all of a sudden so special and annoying
And because monitors are giant light bulbs. So a large white background is harder on the eyes than black.
Is there anything you can do with that information though? This piece of information only becomes useful if you know what colour the background is. And you should also know the colour of text and everything else.
What if the background is muted violet? What if the background is white and the foreground is muted violet? I don't want you to ever use "muted violet" in my terminal, since you have no idea what colours there are in my terminal.
The exact values of your 0-15 don't matter to me and they don't matter to you either, because you chose to use my 256c colorscheme to begin with.
Then you're not really covered by the article? A colorscheme is all about... color. A TUI is about the content and function. I think there's room to have user-defined 256 palettes that are used by default, while colorschemes can use true color and be chosen by the user if they desire.
I would posit then that this article simply doesn't apply to you at all. The feature being described is targetted at users who are effectively developing their own schemes (albeit in a rather simplified automated manner). If I'm taking something off the shelf, I'm using the appropriate recommended base16. I have no expectation that a wild base16 is going to align with any 3rd-party's curated scheme.
I do understand that this logic isn't always going to click with people given the differing contexts of a terminal-wide -vs- app-specific (i.e. vim) approach, but again: that disparity seems either a legacy issue (caused by things like this 16-256 mis-alignment) OR simply a philosophical difference (whereby people who customise at the term level shouldn't at the app level & vice-versa).
Instead of aiming to provide a "consistent experience", you should instead prioritize providing consistent functionality, while avoiding impeding users' control over their own particular experience.
If the user sets a sensible 16 color palette though, many old utils could look great out of the box. I'm enticed by the idea.
Having all terminal emulators run the equivalent of colorcoke without asking the user is not a very bright idea.
I personally prefer light themes everywhere, both in IDEs and in the terminal. I thought that just choosing my own color scheme for 0-15 would give me the color pallette that I prefer, but because app developers like you for some reason decided that you know better what colors do I prefer, this is actually not enough. I also have to configure each TUI application separately to have the color scheme that I like.
And I do not understand why people do it. Like, why would you deliberately break the universal customization system and force users to use your own, specific to your app?
Honesty, each time I encounter an app that uses 16-255 colors, I feel like someone just violated my personal space and intruded into my chosen color pallette with their own colors that don't fit.
Because all my work is based on 16-255, I can actually guarantee to my users that, given a properly configured terminal emulator, they will get the colors on the screenshots.
If I can't rely on 16-255 to be fixed anymore, then I won't be able to make any promise anymore. In practice, it just means adding a caveat in the README.md, but I'd prefer not to. Here's hoping this breaking change gets hidden behind a checkbox/flag.
But defaults should be simple.
XKCD 1172? https://xkcd.com/1172/
What would be optimal is semantic _styles_ (not colors):
- The developer marks the string "XXX" as an error message without even trying to style it.
- The platform/user agent/terminal/whatever displays the string in the default style for "error".
- The user can adjust the theme of their platform/user agent/terminal/whatever to fit their needs/wants.
We use an ansible task to ensure SYSTEMD_COLORS=16 is in /etc/environment on every system and it at least solves that problem...
I didn't read in fully, but what I was thinking in my head is not that we would just totally replace the rest of the colors with arbitrary palette. But that we would sub in better versions of the palette that also used user colors as the base. What was magenta is derived from what the user picked from blue and red.
There's always been such tension between design/creative and users. Apps & designers want their own brand identity, want creative control to make things just so. And are willing to throw user preference & desire on the pyre to get that exacting control. Personally that was always rubbed me extremely the wrong way; I would way rather allow some weirdness & funkiness in, if it leaves the user in control. But I understand the risk aversion, understand the Murphy's law corporatism that makes people and companies want to build strong laws that forbid anything but strictly approved systems, for fear that things go wrong. I understand. But I also things that's a dogshit world to live in.
0-15 are, as I said, a minefield because they are user-customizable: there is no guarantee whatsoever that my user's 1 will be the same dark-ish red as mine… or that it will be dark-ish… or that it will even be vaguely red-ish. It is actually somewhat fun to design colorschemes within those crazy constraints but oh well.
On the other side of the spectrum, truecolors is a nice idea in principle but support is still spotty and inconsistent. In theory, this gives me, the designer, full control over the colors used in the UI, which is a good thing for us and for my users. In fine, if I want my colorscheme to be usable by most users, then I can't blindly rely on this.
Which leaves me with 16-255, which are more widely supported than truecolors and, more importantly, dependable. They have problems, as mentioned in the article, but their _fixed_ nature gives me confidence that the background color of the status-line, for example, will look exactly the same -- and exactly how I want it to look -- in all my user's environments. Which, again, is good for my users and for me. Losing that confidence is what worries me, here.
Like you said, maybe 146 will still be a muted violet —— just not exactly the same -- but I'm not sure about this and I think that, at the minimum, this "feature" should be put behind a checkbox/flag.
You define a baseline color in HSV and then everything else is a multiplier of that
For example
[style]
HSV = [0.7, 0.5, 0.5]
Dark = { H = 1.0, S = 1.2, V = 0.25 } # Make dark elements less saturated and darker
Symbol = { H = 1.0, S = 1.8, V = 1.8 } # Make symbols more vibrant
As a result you can simply move around the HSV to your preference in the config and things don't look like garbage where you have to hand tweak every color to get something legible.
For example, this simple loop https://github.com/day50-dev/Streamdown?tab=readme-ov-file#c...
It's effectively a swatch
Though, I have a problem with even just the basic 16 colours:
black red green yellow blue magenta cyan white bright black bright red bright green bright yellow bright blue bright magenta bright cyan bright white
~~~
Many themes take `black` to mean `black` and `white` to mean `white`. How is it supposed to work when one switches the theme between the dark and the light version?
What are `black`, `white`, `bright black`, and `bright white` supposed mean?
I take those as meaning (in order): `almost invisible on current terminal background`, `pretty contrasty`, `visible but not contrasty`, and `the contrastiest`.
I wish the colour names reflected that, instead of `black` and `white`: you usually care about the contrast, not about the precise colour.
By the way, the terminal foreground and background colors are independent of the standard 16 colors, which complicates things.
That makes sense, but... seems infeasible in practice? "The program"? I tell you what program I need to configure: all of them! Ideally even the programs I'm not even using yet.
I think I'll continue doing it my wrong way then: redefining the meanings to mean less/more contrasty. That allows me to effortlessly switch the terminal between light[0] and dark[1] backgrounds. I've done worse things: I also hijacked a part of the 256-colors-cube for my own purposes...
[0]: https://github.com/tasuki/dotrc/blob/master/.config/kitty/so...
[1]: https://github.com/tasuki/dotrc/blob/master/.config/kitty/so...
There are different programs inside the terminal that I would prefer to have different color treatment. A full-fledged editor like emacs should have full 24-bit color support because I have already configured it to have my preferred color schemes and I prefer to switch themes inside emacs. On the other hand, almost all other TUI programs should not be permitted to use more than the traditional 16 colors. I haven’t configured them myself so I don’t trust them to make good choices.
In other words different terminal capabilities for different programs.
Maybe applying the saturation of the base set across all the generated palette would also work.
Although, this should probably be optional (both as an option for terminals to have in their own settings, and via an escape sequence that opts out), because some users will have configured some programs with a color scheme that they don't want transformed. For example, if your terminal uses the Solarized color scheme, and your text editor _also_ uses the Solarized color scheme, then this could lead to double-applying a color transform and getting something odd.
Perhaps instead of the application overriding the setting, it could be done with an environment var, so the user can easily override it if the mapping messes with the look/usability of the program.
It’s been a fairly decent stop gap measure. I use tinted shell to switch between color schemes.
> Fewer terminals support truecolor.
From what I know all modern terminal emulators in all operating systems support it now.
[1] https://github.com/termstandard/colors
urxvt prominently doesn't (fully)
At the currently known limits of physics where Heisenberg Uncertainty Principle, Abbe's Limit, Quantum Shot Noise and such become our sensing barriers, we suspect we need only about 6000 bits per pixel to represent a digital twin of the electromagnetic field of the sensor-covered volume of space. At 60 fps, that is 1.8 Zettabits per second. Scale out data volume accordingly when using using 18.5 sexdecillion fps (Planck time fps).
What surprises me is these "limits of the fabric of reality as we know it" mind experiments fairly concretely point the way on the many roads towards Kardashev Scale implementations, and is not that different from Archimedes' "Sand Reckoner" and Hindu cosmological Kalpa time scales. History doesn't quite repeat, but rhymes yet again.
So, I've started using AI models to generate color schemes for me.
Take an unreadable theme I like and generate one that is high contrast and still coherent. It's probably not good enough for a full spectrum vision person to use but wow has it improved my quality of life.
It wouldn't surprise me if this is exactly the type of problem that is solved in the same way for the rest of you
I am not colorblind, and have the same experience. It's made worse by the fact that different apps use colors differently, so if I find a theme that works well for some clis and tuis, there will be others that will have unreadably low contrast with the default theme. So I have to tweak the colorscheme for each application as well.
(…and people wonder why I use gvim rather than vim…)
[0] https://ctx.graphics/terminal/ametameric/
For my ncurses brothers, saw this but have not used yet: https://github.com/dankamongmen/notcurses
For my plan9 brothers: one day we will have a new acme, written in common lisp and displaying all the correct colors, and lo it will be glorious.
All the more reason for developers to keep the app itself responsive to the user’s environment by default.
Don’t bake in elaborate visual choices. It’s a usability thing first and a style thing somewhere much farther down the list.
Keep it simple from the factory. Don’t get in the way of customization. Let the user’s environment do the work of adapting it to the user.
The mainstream solution is to use truecolor and gain access to 16 million colors. But there are drawbacks:
Yes, but programs that need more than 16 colors are already often doing this.
> Changing your color scheme means editing multiple config files.
Already has been implemented at least several times over.
> Light/dark switching requires explicit support from program maintainers.
Yes, we have an escape sequence to ask the terminal to ask the OS for this. Most programs that need to care about this already use it.
> Truecolor escape codes are longer and slower to parse.
Not in a way that matters. It only shows up on torture test benchmarks on especially slow parsers. It wouldn't effect normal usage even on a terminal running on some tiny SBC.
> Fewer terminals support truecolor.
XTerm itself, rxvt, iterm2, Alacritty, Wez, Kitty, Ghostty, wt/modern conhost, mintty, st, everything that uses libvte, everything that uses libvterm (such as neovim's built in term), emacs's term, asciinema; tmux, screen, dvtm safely handle them; the linux console snaps it to the nearest 256 color; iterm.app, the original garbage osx one, is the only major term I can think of that does not handle it.
Also, `#fff` is ambigous -- if you mean device colour, then there's no brightness (nits) specified at all, it may be 200 or 2000 or 10,000. If sRGB is implied, as in `#fff in sRGB colour space` then the standard specifies 80 nits, so when you say you don't want brighter than that, then you can't have much of HDR since sRGB precludes HDR by definition (can't go brighter than 80 nits for the "whitepoint" aka white).
I think if you want HDR you need a different colour space entirely, which either has a different peak brightness, or one where the brightness is specified additionally to e.g. R, G and B primaries. But here my HDR knowledge is weak -- perhaps someone else may chime in. I just find colour science fascinating, sorry to go on a tangent here.
And no, #fff is not a "device color". The syntax originates from the web where sRGB is implied ever since we had displays brighter than that.
`#fff` is device color, it's short for `#ffffff` which is 24-bit RGB that predates sRGB, as does true color device support. I was sending 24-bit RGB to VESA-compliant graphics cards before sRGB became a thing. `#fff` was supported by Photoshop and Macromedia products as straightforward device colour format, before sRGB was adopted by at least the latter, mind you. The use by CSS is co-incidental, not where the format was introduced.
Hmm, I suspect that almost everyone who works in the terminal has never done this. I don’t really care what the colors look like, beyond choosing between whatever built in themes my terminal has. Is this really the minority experience?
The article is well argued and well written, as far as I’m concerned.
What’s needed if you really want adoption is to define a term; something like 256-ex for extended. Or whatever. But folks and apps need to be able to say; we’ve implemented or we support 256-ex. Without this label is hard to drive adoption.
The heartbleed thing from a few years back best taught me this.
Good luck I hope to see broad adoption it’s a great idea.
Give it a name, better yet move the copy onto a website with the same name also and a little icon folks can add to their website if they implement this k to their terminal app.
Damn if only there was some other system that could be operating with that in mind
(And if you don't make such an extension, what, you have no third-party graphics drivers for example?)
- A shell is not a terminal.
- Rc it's simpler than sh.
- You can totally put shells under graphical windows as in 9front
- You can do a better Unix than Unix itself while ditching out for good the VT220 interface
- Serial terminals aren't a thing under rio(9)
Oh, wait, it is.
I'm rapidly developing grumpy old man habits about this gulf between "web" and "terminal". Imagine a world where we do `ls | grep .files.size` or something.
I mean, I get why we're here, but it feels so close to giving us all the power of html/css/etc while also having pipes and shells.
Give me a proper graphical application any day, but I recognize that it's historically been a lot more work to produce a GUI in the pre-LLM era.
But golly gee whizz if we're going to keep the command line around, can we move on from 1983?
I'm still annoyed and baffled by the fact that Ubuntu had searchable application menus 10 years ago, which were awesome and worked for just about any program, and then dropped them when they abandoned Unity. And neither KDE not Gnome thought to bring them back. In stead, many apps have since dropped application menus entirely, in favour of... some mishmash of icons and ad hoc menu buttons?
Also, even in the post-LLM era, building a decent GUI app is a lot more work than building a decent terminal app.
Between that and the level of complexity of modern GUI toolkits - and the size of their dependency trees - distribution of a GUI app is a much bigger headache than distributing a terminal app.
Super easy to use, fast, almost zero ram usage and battle tested for 2 decades.
* Ad Hoc
requirements change and terminal gives ultimate empty workbench flexibility. awesome for tasks you never new you had until that moment.
* Precision
run precisely what you want, when you want it. you are not constrained by gui UX limits.
* Pipeline
cat file.txt | perl/awk/sed/jq | tee output.result
* Equal Status
everything is text so you can combine clipboard, files, netcat output, curl output and then you can transform (above) and save. whatever you like in whatever form you like, named whatever you like.
9front copes with actual text throwing the terminal as a different tool to run legacy stuff in such as SSH or some small ANSI C tools either with the APE compat layer or NPE binding ANSI C code to Plan9 native functins.
You can resize windows with shells under 9front freely, no more SIGWINCH. No more broken cuts and pastes while running a terminal multiplexer. No control code risks executing potential malware.
My typical interface is that I have an editor open where I write package code, and then I have a julia REPL open beside it where I load the package (or includet the script or testset). Any changes I make with my editor to functions or structs in the package / script / testset are automatically reflected in my running julia session via Revise.jl.
I then execute the functions interactively from the REPL, introspect into data or generated code, debug, run benchmarks etc all from the REPL.
GUIs are great for many things, but they lack the flexibility I need for my day to day work.
Think of it like different types of programming languages. Some are more suited on different types of problems than others.
For me, my workflow is about composing and gluing different processes together rather than using a standard defined tool repeatedly in the same way as that tools UI was originally designed. So the CLI is ideally suited for me in all the areas where a GUI would be high friction.
As little as possible. Anything that can be done in a terminal can be scripted and automated, put under version control, and deployed using modern CI/CD and devops tools.
Sure, next time I'll need to quickly edit a configuration file I'll setup a complete CI/CD pipeline to run vim (or nano, or whatever) inside it.
Because that Kitty protocol seems limited in that interaction was not one of their goals.
https://github.com/chase/awrit
Since this is really just a legacy system operator monk / retrocool interface, they spend years debating ancient DEC theology.
Enjoy.
Unfortunely, given that we are stuck with UNIX derived OSes, this is indeed a possible issue.
However I would argue, for fancy stuff there is the GUI right there.
Of course everything depends on exact nature of the work, but personally I would gladly leave text based interfaces behind, it's just that there's nothing better.
More so, I use the terminal as strictly necessary and nothing more.
Like, it gets taken for granted, but being able to literally grep my html file, my program source and my readme file, instead of having to open a separate gui program and using its bespoke seach menu feature, is really, really nice.
There are downsides of course, like the way we keep jamming everything into the square hole that is 1980s terminal emulators and character based displays, but frequently this is worth it.
Augmented nowadays with agent environments and tools in IDEs, which can even be voice controlled.
https://9front.org
In some important ways, even text with hacky escape codes is more useful and more robust than a fundamentally graphical interface. Text scales up and down with display size and pixel density. Text works over high-latency links and enables simple latency compensation like in Mosh. Text gives you universal copy-paste. Text is more accessible for humans and for machines.
I use a virtual terminal daily on my phone. If we literally used rio GUIs designed around the three-button mouse and desktop pixel density, it would be a lot less ergonomic. I'd like to see a successor to the VT220 lineage, but it's easier to imagine it built on text.
What era? That is exactly the workflow of everyone using macOS and Windows around here.
Connecting to cloud environemnts is also done via a mix of RDP, VNC, Web GUI based tooling, akin to a modern X Windows replacement.
Windows is a good example of what I mean. Windows system administration has become unmistakably more text- and console-centric over time with the rise of PowerShell. Windows has started shipping an SSH service and made its graphical interface optional on the server.
The web has avoided falling into the same trap. Web UIs are, for the most part, delivered to the user as hypertext rather than rio-style pixels. They rarely hard-require a mouse and have adapted well to touchscreens. Graphics in new web UIs is usually vector (SVG).
Replicating the experience of using something like Smalltalk transcript window.
Of course Windows has SSH support, it needs to interoperate with UNIX, given that UNIX won the server room.
No need for SSH to talk with Windows Core/Nano, it can be done via Web GUI administration, or PowerShell remoting.
As far as I know from Pharo, the Smalltalk transcript logs plain text and is less capable than xterm. So what you care about is not the capabilities of the terminal but having a long-lived interactive session/REPL or a REPL integrated with an editor?
> No need for SSH to talk with Windows Core/Nano, it can be done via Web GUI administration, or PowerShell remoting.
I was thinking of the administrator connecting to Windows from their Mac or Linux/BSD machine. I don't know if that's a good idea compared to them getting a Windows VM and using Windows-to-Windows PowerShell remoting as you suggest.
Text? I do that under 9front, too. Heck, rc it's simpler there than sh itself. I can bind remote machines and use their scripts as if they were my own. I can import remote devices. I can do stuff without resorting to crude hacks with openssl and nc. C itself it's far simpler. Text, you say? No locales, and UTF8 everywhere. I can freely resize the windows and still cut and paste stuff like nothing. It's 2025. The closest workflow under Unix would be Bitlbee + any client for it, msmtp and mbsync for Email and any graphical client against the SLRN cache in order to be as usable.
Rio can use different fonts just fine, you know. There are several users using 24 px fonts on HD screens without no issues. With riow you get 'virtual desktops' a la cwm/i3 and the like.
>Three button mouse. I don't do mouse chords, but I get more universal copy and paste as I stated that the old Unix itself, with shorter and easier scripts again... than Unix.
On snarf/paste instead of the menu, modyfing rio/sam and the like for a keybinding can be something done under an afternoon. Riow can already manage windows and close then with keybings among the mentioned virtual desktops.
Oh, and BTW... for vi users... I consider the Sam regular expresions far more powerful than the vi keys themselves. I can highlight the text with the mouse and write a sam command (on acme too) which affects the selection and in an easier way than the old syntax. The best of both worlds. RSI? Well, that's a point for Unix, but with the Windows key + 1-4 the mouse usage can be reduced a lot.
And, again, the 9front API it's dumb simple; I'm pretty sure doing stuff like mapping the Windows key +j-k-l to mouse button 1-2-3 would be something relatively easy, even setting sticky menus. With that small patch tons of usability issues would go away. Meanwhile, under X.org, Wayland, evdev and the $toolkit of the day... good luck.
I see what you mean in this and the other comment. With 9front, you rely less on issuing commands to remote machines because you can directly access their resources. It's worth keeping in mind when comparing Plan 9 and Unix from a Unix user's perspective.
Being able to pick large fonts on the server isn't the same as leaving the fonts up to the client. When I use terminal emulators, SSH, and tmux, I can switch between different clients with different resolution, pixel density, and screen orientation and have the text display acceptably on each (minus text reflow for history, which is an issue).
> I consider the Sam regular expresions far more powerful than the vi keys themselves.
I agree, structural regular expressions seem like a better version of vi commands. It was reasonably easy to make some complex edits in https://github.com/martanne/vis when I tried it, and it felt like I'd only scratched the surface. I could see myself still using vis if it had tabs like Vim. (Tabs are a stated non-goal for vis.)