Yesterday I was thinking about how long it took me to get a colorscheme in my terminal that I was mostly happy with (SO MANY YEARS), and it made me wonder what about terminal colours made it so hard.
So I asked people on Mastodon what problems they’ve run into with colours in the terminal, and I got a ton of interesting responses! Let’s talk about some of the problems and a few possible ways to fix them.
One of the top complaints was “blue on black is hard to read”. Here’s an
example of that: if I open Terminal.app, set the background to black, and run
ls
, the directories are displayed in a blue that isn’t that easy to read:
To understand why we’re seeing this blue, let’s talk about ANSI colours!
Your terminal has 16 numbered colours – black, red, green, yellow, blue, magenta, cyan, white, and “bright” version of each of those.
Programs can use them by printing out an “ANSI escape code” – for example if you want to see each of the 16 colours in your terminal, you can run this Python program:
def color(num, text):
return f"\033[38;5;{num}m{text}\033[0m"
for i in range(16):
print(color(i, f"number {i:02}"))
This made me wonder – if blue is colour number 5, who decides what hex color that should correspond to?
The answer seems to be “there’s no standard, terminal emulators just choose colours and it’s not very consistent”. Here’s a screenshot of a table from Wikipedia, where you can see that there’s a lot of variation:
Bright yellow on white is even worse than blue on black, here’s what I get in a terminal with the default settings:
That’s almost impossible to read (and some other colours like light green cause similar issues), so let’s talk about solutions!
If you’re annoyed by these colour contrast issues (or maybe you just think the default ANSI colours are ugly), you might think – well, I’ll just choose a different “blue” and pick something I like better!
There are two ways you can do this:
Way 1: Configure your terminal emulator: I think most modern terminal emulators have a way to reconfigure the colours, and some of them even come with some preinstalled themes that you might like better than the defaults.
Way 2: Run a shell script: There are ANSI escape codes that you can print
out to tell your terminal emulator to reconfigure its colours. Here’s a shell script that does that,
from the base16-shell project.
You can see that it has a few different conventions for changing the colours –
I guess different terminal emulators have different escape codes for changing
their colour palette, and so the script is trying to pick the right style of
escape code based on the TERM
environment variable.
I prefer to use the “shell script” method, because:
The main advantage I can think of for configuring colours in your terminal emulator is that, if you use a popular terminal emulator, there are probably a lot of nice terminal themes out there that you can choose from. I think there are some more advantages I’m not thinking of though.
This is what my shell has looked like for probably the last 5 years (using the
solarized light base16 theme), and I’m pretty happy with it. Here’s htop
:
Okay, so let’s say you’ve found a terminal colorscheme that you like. What else can go wrong?
Here’s what some output of fd
, a find
alternative, looks like in my
colorscheme:
The contrast is pretty bad here, and I definitely don’t have that lime green in my normal colorscheme. What’s going on?
We can see what color codes fd
is using using the unbuffer
program to
capture its output including the color codes:
$ unbuffer fd . > out
$ vim out
[38;5;48mbad-again.sh[0m
[38;5;48mbad.sh[0m
[38;5;48mbetter.sh[0m
out
[38;5;48
means “set the foreground color to color 48
”. Terminals don’t
only have 16 colours – many terminals these days actually have 3 ways of
specifying colours:
#ffea03
So fd
is using one of the colours from the extended 256-color set. bat
(a
cat
alternative) does something similar – here’s what it looks like by
default in my terminal.
This looks fine though and it really seems like it’s trying to work well with a variety of terminal themes.
I think it’s interesting that some of these newer terminal tools (fd
, cat
,
delta
, and probably more) have support for arbitrary custom themes. I guess
the downside of this approach is that the default theme might clash with your
terminal’s background, but the upside is that it gives you a lot more control
over theming the tool’s output than just choosing 16 ANSI colours.
I don’t really use bat
, but if I did I’d probably use bat --theme ansi
to
just use the ANSI colours that I have set in my normal terminal colorscheme.
A bunch of people on Mastodon mentioned a specific issue with grays in the Solarized theme: when I list a directory, the base16 Solarized Light theme looks like this:
but iTerm’s default Solarized Light theme looks like this:
This is because in the iTerm theme, colors 9-14 (the “bright blue”, “bright
red”, etc) are mapped to a series of grays, and when I run ls
, it’s trying to
use those “bright” colours to color my directories and executables.
I’m not sure why the iTerm Solarized theme is designed this way (there must be a reason!) but I’m pretty sure I prefer the version where the “bright” colours are actually colours instead of all being shades of gray.
If I my vim theme has a different background colour than my terminal theme, I get this ugly border, like this:
This one is a pretty minor issue though and I think making your terminal background match your vim background is pretty straightforward.
A few people mentioned problems with terminal applications setting an unwanted background colour, so let’s look at an example of that.
Here ngrok
has set the background to color #16 (“black”), but the
base16-shell
script I use sets color 16 to be bright orange, so I get this,
which is pretty bad:
I think the intention is for ngrok to look something like this:
I think base16-shell
sets color #16 to orange (instead of black)
so that it can provide extra colours for use by base16-vim.
This feels reasonable to me – I use base16-vim
in the terminal, so I guess I’m
using that feature and it’s probably more important to me than ngrok
(which I
rarely use) behaving a bit weirdly.
This particular issue is a maybe obscure clash between ngrok and my colorschem, but I think this kind of clash is pretty common when a program sets an ANSI background color that the user has remapped for some reason.
A bunch of terminals (iTerm2, tabby, kitty’s text_fg_override_threshold, and folks tell me also Ghostty and Windows Terminal) have a “minimum contrast” feature that will automatically adjust colours to make sure they have enough contrast.
Here’s an example from iTerm. This ngrok accident from before has pretty bad contrast, I find it pretty difficult to read:
With “minimum contrast” set to 40 in iTerm, it looks like this instead:
I didn’t have minimum contrast turned on before but I just turned it on today because it makes such a big difference when something goes wrong with colours in the terminal.
TERM
being set to the wrong thingA few people mentioned that they’ll SSH into a system that doesn’t support the
TERM
environment variable that they have set locally, and then the colours
won’t work.
I think the way TERM
works is that systems have a terminfo
database, so if
the value of the TERM
environment variable isn’t in the system’s terminfo
database, then it won’t know how to output colours for that terminal. I don’t
know too much about terminfo, but someone linked me to this terminfo rant that talks about a few other
issues with terminfo.
I don’t have a system on hand to reproduce this one so I can’t say for sure how
to fix it, but this stackoverflow question
suggests running something like TERM=xterm ssh
instead of ssh
.
A couple of problems people mentioned with designing / finding terminal colorschemes:
Another problem people mentioned is using a program like nethack or midnight commander which you might expect to have a specific colourscheme based on the default ANSI terminal colours.
For example, midnight commander has a really specific classic look:
But in my Solarized theme, midnight commander looks like this:
The Solarized version feels like it might be pretty disorienting if you’re expecting the “classic” look.
One solution Simon Tatham mentioned to this is using some palette customization ANSI codes (like the ones base16 uses that I talked about earlier) to change the color palette right before starting the program, for example remapping yellow to a brighter yellow before starting Nethack so that the yellow characters look better.
If I run fd | less
, I see something like this, with the colours disabled.
In generan I find this useful – if I pipe a command to grep
, I don’t want it
to print out all those color escape codes, I just want the plain text. But what if you want to see the colours?
To see the colours, you can run unbuffer fd | less -r
! I just learned about
unbuffer
recently and I think it’s really cool, unbuffer
opens a tty for the
command to write to so that it thinks it’s writing to a TTY. It also fixes
issues with programs buffering their output when writing to a pipe, which is
why it’s called unbuffer
.
Here’s what the output of unbuffer fd | less -r
looks like for me:
ls
and other commandsSome people mentioned that they don’t want ls
to use colour at all, perhaps
because ls
uses blue, it’s hard to read on black, and maybe they don’t feel like
customizing their terminal’s colourscheme to make the blue more readable or
just don’t find the use of colour helpful.
Some possible solutions to this one:
ls --color=never
, which is probably easiestLS_COLORS
to customize the colours used by ls
. I think some other programs other than ls
support the LS_COLORS
environment variable too.NO_COLOR=true
(there’s a list here)Here’s an example of running LS_COLORS="fi=0:di=0:ln=0:pi=0:so=0:bd=0:cd=0:or=0:ex=0" ls
:
I think there are a lot of issues around the intersection of multiple programs, like using some combination tmux/ssh/vim that I couldn’t figure out how to reproduce well enough to talk about them. Also I’m sure I missed a lot of other things too.
We talked about a lot in this post and while I think learning about all these details is kind of fun if I’m in the mood to do a deep dive, I find it SO FRUSTRATING to deal with it when I just want my colours to work! Being surprised by unreadable text and having to find a workaround is just not my idea of a good day.
Personally I’m a zero-configuration kind of person and it’s not that appealing to me to have to put together a lot of custom configuration just to make my colours in the terminal look acceptable. I’d much rather just have some reasonable defaults that I don’t have to change.
I’ve personally had a lot of success with using
base16-shell with
base16-vim – I just need to add a couple of lines to my
fish config to set it up (+ a few .vimrc
lines) and then I can move on and
accept any remaining problems that that doesn’t solve.
I don’t think base16 is for everyone though, some limitations I’m aware of with base16 that might make it not work for you:
Just one so far but I’ll link more if people tell me about them:
My one big takeaway from writing this was to turn on “minimum contrast” in my terminal, I think it’s going to fix most of the occasional accidental unreadable text issues I run into and I’m pretty excited about it.
The Internet Archive has lost its appeal after book publishers successfully sued to block the Open Libraries Project from lending digital scans of books for free online.
Judges for the Second Circuit Court of Appeals on Wednesday rejected the Internet Archive (IA) argument that its controlled digital lending—which allows only one person to borrow each scanned e-book at a time—was a transformative fair use that worked like a traditional library and did not violate copyright law.
As Judge Beth Robinson wrote in the decision, because the IA's digital copies of books did not "provide criticism, commentary, or information about the originals" or alter the original books to add "something new," the court concluded that the IA's use of publishers' books was not transformative, hobbling the organization's fair use defense.
"IA’s digital books serve the same exact purpose as the originals: making authors’ works available to read," Robinson said, emphasizing that in copyright law, however, "[n]ot every instance will be clear cut... this one is."
The appeals court ruling affirmed the lower court's ruling, which permanently barred the IA from distributing not just the works in the suit, but all books “available for electronic licensing,” Robinson said.
"To construe IA’s use of the Works as transformative would significantly narrow―if not entirely eviscerate―copyright owners’ exclusive right to prepare (or not prepare) derivative works," Robinson wrote.
Maria Pallante, president and CEO of the Association of American Publishers, the trade organization behind the lawsuit, celebrated the ruling. She said the court upheld "the rights of authors and publishers to license and be compensated for their books and other creative works and reminds us in no uncertain terms that infringement is both costly and antithetical to the public interest."
"If there was any doubt, the Court makes clear that under fair use jurisprudence there is nothing transformative about converting entire works into new formats without permission or appropriating the value of derivative works that are a key part of the author’s copyright bundle,” Pallante said.
Lead attorneys representing publishers, Elizabeth A. McNamara and Linda Steinman, provided statements to Ars.
"The Second Circuit’s decision is animated by common sense and the desire to foster creativity," McNamara said. "The Court correctly rejected Internet Archive’s arguments that mass copyright infringement can be justified by invoking convoluted theories like the ‘one-to-one-owned to loaned-ratio.’"
"As the Court’s clear-eyed opinion demonstrates, there was nothing transformative about Internet Archive’s distribution of millions of unlicensed ebooks," Steinman said. "This unequivocal decision will serve as a clear warning to future infringers.”
The Internet Archive's director of library services, Chris Freeland, issued a statement on the loss, which comes after four years of fighting to maintain its Open Libraries Project.
"We are disappointed in today’s opinion about the Internet Archive’s digital lending of books that are available electronically elsewhere," Freeland said. "We are reviewing the court’s opinion and will continue to defend the rights of libraries to own, lend, and preserve books."
The court's fair use analysis didn't solely hinge on whether IA's digital lending of e-books was "transformative." Judges also had to consider book publishers' claims that IA was profiting off e-book lending, in addition to factoring in whether each work was original, what amount of each work was being copied, and whether the IA's e-books substituted original works, depriving authors of revenue in relevant markets.
Ultimately, for each factor, judges ruled in favor of publishers, which argued that granting IA was threatening to "'destroy the value of [their] exclusive right to prepare derivative works,' including the right to publish their authors’ works as e-books."
While the IA tried to argue that book publishers' surging profits suggested that its digital lending caused no market harms, Robinson disagreed with the IA experts' "ill-supported" market analysis and took issue with IA advertising "its digital books as a free alternative to Publishers’ print and e-books."
"IA offers effectively the same product as Publishers―full copies of the Works―but at no cost to consumers or libraries," Robinson wrote. "At least in this context, it is difficult to compete with free."
Robinson wrote that despite book publishers showing no proof of market harms, that lack of evidence did not support IA's case, ruling that IA did not satisfy its burden to prove it had not harmed publishers. She further wrote that it's common sense to agree with publishers' characterization of harms because "IA’s digital books compete directly with Publishers’ e-books" and would deprive authors of revenue if left unchecked.
"We agree with Publishers’ assessment of market harm" and "are likewise convinced" that “unrestricted and widespread conduct of the sort engaged in by [IA] would result in a substantially adverse impact on the potential market" for publishers' e-books, Robinson wrote. "Though Publishers have not provided empirical data to support this observation, we routinely rely on such logical inferences where appropriate" when determining fair use.
Judges did, however, side with IA on the matter of whether the nonprofit was profiting off loaning e-books for free, contradicting the lower court. The appeals court disagreed with book publishers' claims that IA profited off e-books by soliciting donations or earning a small percentage from used books sold through referral links on its site.
"Of course, IA must solicit some funds to keep the lights on," Robinson wrote. But "IA does not profit directly from its Free Digital Library," and it would be "misleading" to characterize it that way. "To hold otherwise would greatly restrain the ability of nonprofits to seek donations while making fair use of copyrighted works."
In her opinion, Robinson noted that both book publishers and the Internet Archive "represent potentially serious interests."
"On the one hand, e-book licensing fees may impose a burden on libraries and reduce access to creative work," Robinson said. "On the other hand, authors have a right to be compensated in connection with the copying and distribution of their original creations."
Robinson considered the fact that more than 93 percent of libraries participate in digital lending, which book publishers view as "a profitable, growing market." Instead of charging libraries for individual books, the publishers offer licenses that must be renewed at increasing expense.
"For libraries, the result is regular renegotiation of e-book licenses that often come at a steeper price and for a shorter term than print copies of the same books," Robinson noted.
The IA strove to give libraries an alternative model by digitally scanning books that can be loaned online for free, and IA supporters have rallied behind this model, with 62 libraries partnering with the project. Among IA supporters is Meredith Rose, senior policy counsel for Public Knowledge, who filed a brief on behalf of the IA and posted a statement criticizing the appeals court's ruling.
"Controlled digital lending is a critical toolkit for libraries to reach their patrons in the digital age," Rose said. "With today’s decision, the Second Circuit undermines those policy goals," including by asserting, "bafflingly, that the Internet Archive is not entitled to statutory protections because it doesn’t perform ‘traditional functions of a library.’ It is unclear what the Second Circuit believes these ‘traditional functions’ to be, if not ‘lending books to the public.’"
Rose argued that IA had no access to "market data necessary to prove that their use has not created a market harm."
"Let us be perfectly clear: The court here is asking defendants to prove a negative, while allowing plaintiffs to actively withhold the only information that the court will accept as dispositive," Rose said. "The Second Circuit has replaced the fourth factor analysis with ‘vibes.’ Franz Kafka would be proud."
Lia Holland, a campaigns and communication director for Fight for the Future—a digital rights group that also supported the IA in court—said the appeals court ruling dealt "a myopic and dangerous blow" to "libraries, diverse authors, and the readers who love them." Unlike traditional libraries, the IA's digital library offered a more privacy-focused way of lending that let readers opt out of systems surveilling their reading habits, Holland suggested.
"Big Tech’s greed has infected Big Publishing, causing them to abandon the concept of ownership for digital books, and to force all libraries and readers to buy licenses that lock them into spyware-ridden apps that turn data on readers into a new product for publishing," Holland alleged.
When the lower court's injunction forced IA to remove 500,000 books from its library, IA fans begged book publishers to restore access. Readers asked publishers to consider the negative educational impact of academics, students, and educators—"particularly in underserved communities where access is limited—who were suddenly cut off from "research materials and literature that support their learning and academic growth."
Holland addressed this impact, insisting that "no one wants a world where libraries are just some Netflix spewing out whatever content Big Publishing and Big Tech allow them to temporarily license."
"It’s a sad day for book people, particularly for disabled, rural, and low-income readers who rely on libraries, and all those who want to write without the threat of erasure or read without the fear of surveillance and punishment, including 25+ civil and human rights organizations like GLAAD, Color of Change, and Presente.org," Holland said.
But Robinson wrote that the court concluded "that both Publishers and the public will benefit if IA’s use is denied."
According to the court, "Any copyright infringer may claim to benefit the public by increasing public access to the copyrighted work," but it cannot come at the cost of negating "rewards for authorship."
"This monopolistic power is a feature, not a bug, of the Copyright Act," Robinson wrote. "If authors and creators knew that their original works could be copied and disseminated for free, there would be little motivation to produce new works. And a dearth of creative activity would undoubtedly negatively impact the public. It is this reality that the Copyright Act seeks to avoid."
If the court had decided to "bless" IA's "large scale copying and distribution of copyrighted books without permission from or payment to the Publishers or authors," Robinson wrote, that "would allow for widescale copying that deprives creators of compensation and diminishes the incentive to produce new works."
So "while IA claims that prohibiting its practices would harm consumers and researchers," the court sided with publishers because "allowing its practices would―and does―harm authors," Robinson wrote.
Rose suggested that the last hope for IA fans may be to appeal to Congress to update laws to protect the future of libraries increasingly strapped to pay publishers' e-book licensing fees.
"We call on Congress to clarify the law surrounding Controlled Digital Lending and reaffirm that libraries can, in fact, lend the books that they own—regardless of format," Rose said.
This story was updated on September 4 to add comments from publishers' attorneys.
The analysis I’m not hearing about the 2024 presidential debate that is stunningly striking to me is that Donald J. Trump was asked twice about childcare and twice about the opioid crisis and all four times he actively chose to use his time to defend attacks on himself rather than address these major issues facing millions of American people. It is painfully obvious to me that he only has one constituent that matters to him—his own ego. Trump fails the test of basic empathy and humanity time and again.