Show HN: Good Terminal Color Schemes Are Rare, So I Wrote a Generator

ivoronin1 pts0 comments

Good Terminal Color Schemes Are Rare, So I Wrote a Generator — octalwave

Back in the terminal

These days, a lot of my work happens in the terminal, and I’m clearly not alone. The terminal has once again become a primary environment, in a renaissance led by coding agents, modern emulators, and an explosion of quality TUI apps.

Aesthetics and ergonomics have always mattered to me. In the terminal, those come down to nice colors and readability.

The state of terminal themes

And yet, finding themes that nail this is harder than it should be, especially when you like changing things up. I scrolled through ghostty +list-themes. Hundreds of options, most meh, the same failures with different palettes: unreadable dim blue and oversaturated red/magenta on near-black backgrounds, comment color (bright black) pushed too dim, selection backgrounds that make highlighted text unreadable. The handful that don’t fail are the usual suspects (Catppuccin, Gruvbox, Tokyo Night, Rose Pine, and the venerable Modus), and you already knew that. There’s probably one in your dotfiles right now.

There’s a subtler failure too. ANSI gives you sixteen named color slots (red, green, yellow, blue, magenta, cyan, and brights), and programs use them semantically: red for errors, yellow for warnings, green for success. A git diff paints removed lines red and added lines green. But many themes pick a “yellow” that’s closer to green, a “red” leaning orange, a “blue” drifted toward purple. The colors are pretty in isolation, but WARNING: in your logs takes a half-second to register, and a git diff becomes a salad of oranges and yellows you have to untangle before you can read. That half-second matters, and it shouldn’t be the theme’s job to insert it. Random terminal colors are also why tools started using their own color schemes in the first place; the fix isn’t more bypassing, it’s themes worth trusting. Modern emulators now derive the 256-color cube from your base 16 so the slot semantic carries past 16 colors too.

From vibes to math

Making my own theme from scratch was never on the table; I was looking for a tech solution to a design problem. “Give me lots of themes that don’t fail at readability and use the right semantic colors.” That’s the kind of thing you hand to an algorithm to generate a theme. Existing tools (pywal, base16, themer) handle extraction and templating, but they check neither per-slot contrast targets nor color fidelity (reds read as red, not muddy brown).

I wanted to put a few science points into the decisions, not just go on vibes. A bit of digging led me to Julia Evans’ Terminal colours are tricky. In the comments, someone recommended APCA, the Accessible Perceptual Contrast Algorithm. That was when it clicked.

APCA is a perceptual contrast model designed for screens. Given the sRGB-Y luminance of each color in a foreground/background pair, APCA returns a single polarity-aware Lc number (its sign distinguishes dark-on-light from light-on-dark), modeled on how the eye reads text on a display. This number can be benchmarked against APCA’s named tiers: minimum Lc thresholds for different reading contexts, e.g. Lc 90 for fluent text, Lc 30 for spot text or labels, Lc 15 for non-text discernibility. The taste judgment “is this color combo readable?” becomes a numeric check: does its Lc clear the tier the slot needs?

One note for the web crowd: the familiar WCAG 2 contrast ratio misjudges contrast on dark backgrounds and isn’t recommended for dark-mode design, which is exactly where terminal themes live.

The next question: how do you generate a “red” that’s really red, and chromatic enough to read as red, not as muddy brown? OKLCH helped here. It’s a perceptually-tuned color space where “hue” stays close to a stable angle (red sits in a known arc regardless of lightness) and “chroma” is a meaningful “how vivid” axis. Evil Martians make the case for OKLCH in palette generation. Together with APCA, the “good colors” problem starts looking like math you can put in a solver.

So I built Paletty. It’s a generator with a few sliders (background lightness, accent temperature, accent lightness, accent chroma), plus optional per-slot pins (lock a slot to a specific color) and image-seeding. Push the sliders to taste, hit a button, get a scheme that hits every slot’s contrast target. Hit again, get a different one. Save the ones you like with a shareable URL, then export to whichever emulator you use: Ghostty, Kitty, iTerm2, Alacritty, and most other modern emulators.

How generation works

What a terminal palette is

A terminal color scheme is a small set of named colors the emulator uses to render everything you see. At the core are the 16 ANSI slots: eight base colors and their bright variants. Programs emit ANSI escape codes saying which slot to use; the emulator decides which color the slot maps to. On top of those, most emulators add UI extras: background, foreground, cursor, selection foreground and selection...

color terminal colors slot themes contrast

Related Articles