Terminal Color Schemes: An Obsession
I have spent more time than I care to admit thinking about terminal color schemes. Not using them — thinking about them. What makes one feel right at 2am versus 2pm. Why some palettes feel sharp and others feel muddy even with identical contrast ratios. Why certain color combinations cause eye strain after three hours but feel fine for thirty minutes.
This is not a normal thing to think about. I do it anyway.
Why it matters more than you think
The terminal is where I spend most of my working hours. The color scheme isn’t decoration — it’s the environment. A bad color scheme introduces low-level friction that compounds over time. Too much contrast and your eyes tire quickly. Too little and you’re squinting at muted text. Wrong hue assignments (errors in yellow? warnings in red?) and your brain has to work harder to parse what it’s seeing.
A good color scheme is one you stop thinking about.
How terminal colors actually work
Most terminal emulators support two color modes:
16-color ANSI — the classic 8 colors (black, red, green, yellow, blue, magenta, cyan, white) plus their “bright” variants. These are what most CLI tools use by default.
True color (24-bit) — any hex value, if your terminal supports it. Most modern terminals do. You need TERM=xterm-256color or better, and in Neovim, vim.opt.termguicolors = true.
The gap between these two matters. If you’ve ever seen a colorscheme look great in a screenshot but mediocre in your actual terminal, the culprit is usually a theme that uses true color values while your terminal is falling back to 256-color approximation.
Test it:
# Check if your terminal supports true color
printf "\x1b[38;2;255;0;135mTruecolor\x1b[0m\n"
# Should render as vivid pink, not approximated red
Building a palette that works
Here’s the mental model I use:
Background — low saturation, dark
Surface — 3–6% lighter than background (cards, popups)
Foreground — near-white, never pure white (too harsh)
Muted text — 50–60% of foreground brightness
Primary accent — a single saturated color for interactive elements
Secondary accents — 2–3 additional colors for syntax roles
Emphasis — one high-contrast color for errors/critical UI
The key constraint: your accent color does the heavy lifting. Everything else supports it. If you have more than one “primary” accent competing for attention, the whole palette loses clarity.
For my current scheme, teal (#0087af) is the primary. It’s distinctive, readable on dark backgrounds, and doesn’t fatigue the eye the way saturated blue or red does over long periods.
The biggest mistake people make with dark themes is using pure black (
#000000) as the background. Pure black creates too much contrast against text, which paradoxically makes reading harder. A dark gray around#1a1a1a–#242424is much easier to work in.
The syntax role assignments that matter
These are the color→role assignments that I’ve converged on after a lot of iteration:
| Role | Color | Reason |
|---|---|---|
| Keywords | Teal / primary accent | High frequency, needs to be visible but not jarring |
| Strings | Pale green | Positive, readable, distinct from keywords |
| Comments | Muted gray | Should recede, not compete |
| Functions | Pale cyan | Close to keywords but distinguishable |
| Constants | Muted lavender | Distinct from strings without being distracting |
| Errors | Red (#ff005f) | Reserved strictly for errors — never use for anything else |
| Warnings | Yellow (#ffffaf) | Distinct from errors, not as alarming |
The error/warning distinction is more important than it looks. When you train your peripheral vision to associate red with “something is broken,” you want that association to be reliable.
Recommended terminals for color accuracy
If you care about this, it matters which terminal you’re using:
- kitty — GPU-accelerated, excellent true color support, highly configurable
- WezTerm — cross-platform, Lua config, good font rendering
- Alacritty — fast, minimal, YAML config, solid true color
- iTerm2 (macOS) — the classic choice, good enough for most things
The one thing they all share: they won’t fix a bad color scheme. The palette still has to be right.
Accepting the obsession
At some point I made peace with the fact that I will never be “done” with my terminal setup. New tools appear, terminals improve their rendering, my own aesthetic preferences drift. The configuration is a living document.
What I’ve stopped doing is chasing other people’s setups. Screenshots lie — the font rendering, gamma, and monitor profile all change how colors look. The only way to know if a scheme works is to use it for a week.
The current scheme has lasted two years. That’s probably a record.