Calm slate. Living color.
A color scheme where the background stays quiet and the code comes alive.
For editors, terminals, browsers and the web.
This is the core of Living Code: the palette, the color math that resolves it, semantic roles, the [lc] brand and
shared tooling. It is agnostic to any app. Each port lives in its own repository in
living-code-theme, and living-code.dev lists them all.
Every flavor shares the same slate foundation and semantic roles. Night is the default.
| Flavor | Appearance | Syntax and accents |
|---|---|---|
| Night | Dark slate, full palette | Cool structure, green strings, copper numbers and amber warnings. The default. |
| Frost | Lifted, bluer slate | Lower-chroma accents with green strings and copper numbers. |
| Paper | Near-white slate | Darker accents with green strings and copper numbers. |
| Signal | Dark slate, one accent | Minimal variant of Night: teal keywords and tags, everything else neutral. |
Install the port for your app: find it on living-code.dev/ports or in the organization's repositories. Each port's README has its installation steps. Nobody needs to clone this repository to use the theme.
- The ground stays calm. Backgrounds, panels, selections, punctuation and comments live on one slate ramp, so the eye goes to the code, not the chrome.
- Cool for structure, warm for data.
Teal, aqua and steel mark keywords, functions and types;
moss,
amber and
copper mark strings, numbers and warnings.
- Same roles everywhere. Each port maps the same semantic roles (keyword, string, error, border...), so a theme feels the same in your editor, terminal and browser.
- Built in OKLCH. Every palette value is defined in OKLCH; hex and RGB are derived. The build checks 24 text roles for WCAG AA contrast (≥ 4.5:1) against each flavor's background.
The default. Dark slate ground, teal structure, green strings and gray comments. Amber warnings and copper numbers keep their warm contrast.
Palette
Neutrals
Accents
ANSI
| black | red | green | yellow | blue | magenta | cyan | white | |
|---|---|---|---|---|---|---|---|---|
| normal | ||||||||
| bright |
Night on a lifted, bluer slate with a third less chroma. Calmer for long sessions; the warm/cool split survives at low saturation.
Palette
Neutrals
Accents
ANSI
| black | red | green | yellow | blue | magenta | cyan | white | |
|---|---|---|---|---|---|---|---|---|
| normal | ||||||||
| bright |
Daylight. Same two temperatures on near-white slate, lightness inverted so every syntax color keeps WCAG AA contrast.
Palette
Neutrals
Accents
ANSI
| black | red | green | yellow | blue | magenta | cyan | white | |
|---|---|---|---|---|---|---|---|---|
| normal | ||||||||
| bright |
A minimal variant of Night with a single accent. Teal marks keywords, tags and focus; everything else stays on the slate ramp. No warm literals or multicolor diagnostics.
Accent names such as amber, copper and moss remain available for port compatibility,
but in Signal they are aliases of teal or neutral colors. Diagnostics are told apart by labels, signs and underlines instead of hue.
Palette
Neutrals
Accent
| Name | Hex | OKLCH | Used for | |
|---|---|---|---|---|
teal |
#00a692 |
oklch(0.65 0.15 180) |
accent · cursor · borderActive · match · modified · keyword · builtin · decorator · tag · heading · link |
ANSI
| black | red | green | yellow | blue | magenta | cyan | white | |
|---|---|---|---|---|---|---|---|---|
| normal | ||||||||
| bright |
The table shows resolved roles for every flavor. The full role map (UI, diagnostics, markup) is in
palette/flavors.mjs: defaultRoles plus each flavor's roles overrides.
Ports ship every flavor, except browser themes (Firefox and Chrome), which ship Night and Paper only: in a browser's few theme slots, Frost and Signal look the same as or barely different from Night, and both stores reject duplicate themes.
Any app can follow the theme: read palette.json (hex, OKLCH, RGB, roles and ANSI for every flavor),
or map these semantic roles onto the app's own color slots:
| Slot | Role | Night |
|---|---|---|
| background / foreground | bg / fg |
#05080b / #e2e9ee |
| panels, sidebars | bgDeep, bgAlt |
#020405, #090e11 |
| accent, cursor, focus ring | accent |
#00a692 |
| selection | selection |
#2d3438 |
| borders | border / borderActive |
#1d2226 / #00a692 |
| error / warning / info / success | error … |
#e96560 #f0be6d #80b6d3 #8acb83 |
From JavaScript, install @living-code/palette; for CSS custom
properties, @living-code/css.
Turn any image, such as a wallpaper, into a Living Code version. Requires ImageMagick 7.
node scripts/recolor.mjs wallpaper.jpg --flavor night --mode lut| Mode | Result |
|---|---|
lut |
Starts with the theme's slate ramp. Shadows and muted areas stay neutral; colorful midtones receive the selected flavor's accents over that base. Lightness is fitted to the theme's range. Tune the accent amount with --color (default: 0.65). Core accents are teal, mint, aqua, steel, amber and copper; --accents all includes the remaining accents. |
gradient |
Maps brightness onto dark slate, an accent and light text. Pick the accent with --accent amber. |
remap |
Posterizes to the exact palette colors. Add --no-dither for flat areas. |
all |
Writes one file per mode. |
In lut mode, --color 0 uses only the slate ramp; --color 1 allows stronger accents while still protecting shadows and muted areas.
Unlike --strength, lowering --color does not bring back the original photo's colors. It controls accent blending, not a fixed percentage of the image's area.
Other controls are --spread (hue blending), --keep-light (brightness preservation) and --smooth (color-noise smoothing).
Use --flavor signal for slate and teal only; compatibility names such as amber do not add warm hues in Signal.
Output defaults to <image>-<flavor>-<mode>.png next to the input. Run with --help for every option.
| You want to | Where |
|---|---|
| Report wrong colors or a broken install in one app | That app's repository: open its page on living-code.dev/ports, then Report an issue |
| Ask for Living Code in another app | Request a port |
| Change a color or role in every app | Palette or color feedback |
Each port is its own repository in living-code-theme with a root port.json
and a README following the shared template; the website discovers it automatically.
Start with Creating and contributing a port, the
metadata/README contract, or CONTRIBUTING.md to find the right repository.
Map roles, never colors: take every color from a semantic role in palette.json, so the same kind of
token gets the same color in every app.
Requires Node 22.22 or newer and pnpm 12.9.0. Run pnpm install --frozen-lockfile for maintainer tooling.
Palette generation uses only Node built-ins; port tooling dependencies are development-only.
| Command | What it does |
|---|---|
pnpm build |
Regenerates palette.json, the portable port palette, this README, swatches, brand SVGs and the landing export from palette/flavors.mjs. |
pnpm check |
Fails if a generated file is stale or a text role drops below 4.5:1. CI runs it. |
pnpm test |
Runs the test suite. |
pnpm preview |
Live palette preview with sliders and exports at http://localhost:4173/preview/. |
pnpm screenshots |
Recaptures assets/preview-*.png from the palette preview only, with headless Chrome (CHROME_BIN overrides google-chrome); app captures live in each port. |
pnpm icons:brand |
Rasterizes the brand SVGs to PNG and ICO. See assets/brand. |
pnpm new:port <directory> --name "App" --group "Editors" --emoji "📝" |
Scaffolds a port's README, metadata and license, not its implementation or maintenance harness. |
pnpm package:ports --ports-root <directory> |
Plans publication packaging from port-owned metadata. Add --output <new-directory> --apply to collect packages, checksums and submission instructions; never publishes. See Packaging and publication. |
pnpm palette:update:ports --ports-root <directory> |
Plans a local palette rollout. Explicit --apply invokes each clean port's own updater, build, check and tests; never commits or pushes. |
pnpm sync:ports --landing <checkout> |
Discovers public ports and writes validated snapshots/captures to the website. Supports --dry-run, --refresh and optional --r2 storage. |
pnpm preview:port <directory> --landing <checkout> |
Validates a local port and previews it in an isolated website copy. |
pnpm export:landing --landing <checkout> |
Delivers the generated theme JSON, CSS and hosted port schema to the website. Run pnpm build first. |
pnpm test:standalone --landing <checkout> |
Installs, builds and tests only the website in isolation. Supports --keep. |
pnpm test:scale --landing <checkout> |
Exercises 400 synthetic ports, immutable publication and a real isolated offline website build/test. Supports --keep and --report <new-file>. |
To change a color, edit palette/flavors.mjs and run pnpm build. Do not edit generated files directly.
A palette change does not touch any port: each port repository owns its generator, application mappings, tests and files.
Core exports app-agnostic resolved inputs in exports/ports/palette.json. A port explicitly
adopts a committed core revision with pnpm palette:update /path/to/core, then regenerates and reviews its own files.
Normal port builds use the checked-in pin and never read a sibling checkout or fetch from GitHub.
For an explicitly reviewed multi-port update, use the batch palette rollout, which delegates
to port-owned commands instead of generating application formats in core.
The website takes committed inputs from exports/landing/. After pnpm build, run
pnpm export:landing --landing <checkout> and review the changes there. Port discovery, validation, templates and
preview/verification runners live here in core; landing contains Astro and website presentation only. No normal
website build imports core or needs GitHub access. New ports require automatic native 2560×1600 captures and direct flavor-selected installation.
See Port repositories for authoring and
Port publication and capacity for the split index/documents, batched discovery,
optional external capture storage and 400-port acceptance check.
MIT © Elliot Luque



