INTERFACE · 02

VS Code

Forest Phosphor was made for reading code semantically by role. Muted pastel colors - tuned for comfortable reading over long sessions in low-light or bright environments - stay distinct without being distracting. They map to stable roles you learn once and carry into every language.

Install Theme

In context

Four surfaces in one frame — file explorer, editor pane, integrated terminal, and copilot chat. The role vocabulary surfaces on its own: variables in cyan, callables in yellow, types in magenta. No legend required.

VS Code, default layout, Forest Phosphor active.
SYNTAX

Token colors

Amber marks declaration and page structure, Soft Moss is the Foreground and acts as the linguistic flow; structural keywords, grammar, and parameters when italicized. Cyan is a variable, Blue is a property, Yellow is callable. Green is for strings, and White is for literals; numbers, bools, and absent values. Magenta is a concrete shape — class, struct, enum. Pink is an abstract one — interface, type, generic. Coral is reserved for attention, and an italicized Thick Moss is for comments.

example.tsx tsx
// forest-phosphor.tsx — palette helpers
import { palette } from './palette';
import type { Palette, Token } from './types';

type Accent = keyof typeof palette.accent;

interface ThemeOptions<T extends Token> {
  fallback: T | null;
  strict: boolean;
}

enum Mode {
  Day = 'day',
  Dusk = 'dusk',
  Night = 'night',
}

@inject
class PhosphorTheme implements Palette {
  readonly version = 0x010000;
  readonly active: boolean = true;
  mode: Mode = Mode.Night;

  ink(level: 'primary' | 'muted' = 'primary'): string {
    const banner = "phosphor\nready";
    return palette.ink[level] ?? banner;
  }

  flap(beat: number = 0): void {
    palette.wings.beat = beat;
  }

  accent(name: Accent): string {
    return palette.accent[name];
  }

  async load<T extends Token>(opts: ThemeOptions<T>): Promise<T> {
    try {
      const swatch = await palette.fetch(this.mode);
      if (!swatch) throw new Error("missing swatch");
      return swatch as T;
    } catch (err) {
      if (opts.strict) throw err;
      return opts.fallback as T;
    }
  }
}

const PHOSPHOR = 0x7AF8FF;
const ENABLED = true;
const SWATCHES = new Map<Mode, string>([
  [Mode.Day,   '#A2EBA1'],
  [Mode.Dusk,  '#73E165'],
  [Mode.Night, '#7AF8FF'],
]);

function render(fp: PhosphorTheme) {
  fp.flap(2);
  return (
    <section
      data-ink={fp.ink('primary')}
      data-version={fp.version}
      aria-label="phosphor"
    >
      {PHOSPHOR}
    </section>
  );
}
// note
comment Thick Moss · italic

comment, punctuation.definition.comment

if · else · &&
flow keyword Soft Moss

keyword.control, keyword.operator.logical, punctuation, structural grammar

function · class · return · import
structural keyword amber

storage.type, storage.modifier, keyword.control.import, keyword.operator.new, keyword.control.flow.return

this · throw · unsafe
attention coral

variable.language.this, variable.language.self, keyword.control.throw, keyword.other.unsafe, invalid

=> { } ;
operator · punctuation Soft Moss

keyword.operator, punctuation, meta.brace

"phosphor"
string string green

string, string.quoted, string.template

\n
escape cyan

constant.character.escape

42 · true · null
literal value near-white

constant.numeric, constant.language (true / false / null / undefined), constant.character

userId
variable · macro · enum member cyan

variable, variable.other, entity.name.constant, entity.name.enum-member

depth
parameter Soft Moss · italic

variable.parameter, meta.function variable.other

fp.ink
property · field · attribute blue

variable.other.property, entity.other.attribute-name, support.type.property-name, meta.object-literal.key

render()
function yellow (callable)

entity.name.function, support.function, variable.function

.flap()
method yellow (callable)

entity.name.method, entity.name.function.member

class Palette
concrete shape magenta — class · struct · enum

entity.name.type.class, entity.name.struct, entity.name.enum

interface User
abstract shape pink — interface · type · generic · primitive

entity.name.type.interface, entity.name.type.alias, entity.name.type.parameter, support.type.primitive

@inject
decorator amber

meta.decorator, storage.type.annotation, punctuation.decorator

<section>
tag amber — structural like function/class

entity.name.tag, meta.tag.sgml, punctuation.definition.tag

CHROME

Deep greens, cyan signal

Old CRT phosphor monitors were the original inspiration for the theme, and the greens in particular are directly inspired from those displays. The Surface colors are close enough in tone that the chrome never competes with the code, and dark enough that a four-hour session in a dim room doesn't tax the eyes. The surface colors sit below conscious attention; these colors should be subtle. You don't need them to draw your attention — your eyes and brain understand the hierarchy without a single thought about it.

Against that quiet field, cyan carries full weight. In the Chrome, it is used for peripherals and "you are here" affordances — the active tab border, status bar text, badges, peek frames, the global focus ring. Nothing decorative gets cyan; when you see it, it means something. The caret is the one element painted outside the palette entirely — pure white, with a traditional blink, because the cursor needs to be findable at a glance

Surfaces · deep greens

editor.background
#0F180C

editor canvas

sideBar.background
#101C0C

file explorer column

activityBar.background
#0E170B

off-canvas chrome (activity bar, panel, status)

list.activeSelectionBackground
#1A2C16

elevated state — selected row in tree / list

editor.lineHighlightBackground
#131C10

caret line

editorIndentGuide.background1
#1E3119

indent hairlines

Signal · cyan affordances

tab.activeBorderTop
#7AF8FF

cyan bar marks the focused tab

statusBar.foreground
#7AF8FF

status text is cyan against bg-sink

activityBarBadge.background
#7AF8FF

unread / count badges

peekView.border
#7AF8FF

peek-definition frame

focusBorder
#7AF8FF80

cyan @ 50% — global focus ring

editorCursor.foreground
#FFFFFF

The only non-palette accent in the theme

GIT

Diff & git decorations

Diff colors should tell you what changed; they shouldn't trigger a stress response. Forest Phosphor's git palette is calm by design — added is green, modified is blue, deleted is gold (softer than amber), conflicts go to yellow. Every diff surface (gutter markers, line backgrounds, file-tree decorations, overview ruler) draws from the same four hues, so the legend is consistent across the editor and the sidebar.

Side-by-side diff with gutter.
added
gitDecoration.addedResourceForeground

inserted lines, new files (a slightly cooler green than the string accent)

modified
gitDecoration.modifiedResourceForeground

changed lines, staged-modified files — blue, not yellow

deleted
gitDecoration.deletedResourceForeground

removed lines, deleted files — gold, never red

conflict
gitDecoration.conflictingResourceForeground

merge conflicts — yellow

TERMINAL

Integrated terminal

terminal.background matches the editor canvas (#0F180C), so split-panes read as one surface. The colors used in the terminal are similar to the VSCode theme in spirit, but roles are inherently different in the CLI. Yellow is still callable, amber is still builtin commands, coral for errors, green for strings, cyan for directories and blue for flags and the working directory in the prompt, and Purple for the conda type in the prompt

Integrated terminal at the foot of the editor.
SOURCE

The manifest

The theme ships as a single JSON file — now over 2,300 lines. It's built TypeScript-first, with expanding deep coverage for Python and Rust. Because those languages push into broad TextMate scope territory, support for a wide range of other languages follows as a byproduct; if a grammar defines standard scopes, the palette maps onto them. The file also includes extensive work on markdown rendering inside VS Code — headings, emphasis, fenced code, link targets, and block quotes all carry intentional color assignments. Coverage isn't complete, but the direction is toward exhaustive rather than minimal.

Forest_Phosphor-color-theme.json jsonc
{
  "name": "Forest Phosphor",
  "semanticHighlighting": true,
  "colors": {
    "editor.background":          "#0F180C",
    "editor.foreground":          "#A2EBA1",
    "editorCursor.foreground":    "#FFFFFF",
    "tab.activeBorderTop":        "#7AF8FF",
    "activityBar.background":     "#0E170B",
    "activityBarBadge.background": "#7AF8FF",
    "sideBar.background":         "#101C0C",
    "statusBar.foreground":       "#7AF8FF",
    "focusBorder":                "#7AF8FF80"
  },

  // TextMate fallback — coarse, scope-based.
  "tokenColors": [
    { "scope": "comment",
      "settings": { "fontStyle": "italic", "foreground": "#5C8656" } },
    { "scope": ["storage.type", "storage.modifier", "keyword.control.import"],
      "settings": { "foreground": "#E8A030" } },
    { "scope": ["variable.language.this", "keyword.control.throw", "invalid"],
      "settings": { "foreground": "#EA9575" } },
    { "scope": ["variable.other.property", "entity.other.attribute-name"],
      "settings": { "foreground": "#77B0FF" } },
    { "scope": ["entity.name.type.class", "entity.name.struct", "entity.name.enum"],
      "settings": { "foreground": "#C07AC8" } },
    { "scope": ["entity.name.type.interface", "entity.name.type.alias", "support.type.primitive"],
      "settings": { "foreground": "#FFB4E2" } }
  ],

  // Language-server map — precise, role-based. This is where the theme lives.
  "semanticTokenColors": {
    "namespace":     "#A2EBA1",

    "type":          "#FFB4E2",
    "interface":     "#FFB4E2",
    "typeParameter": "#FFB4E2",

    "class":         "#C07AC8",
    "enum":          "#C07AC8",
    "decorator":     "#C07AC8",

    "function":      "#D1CF32",
    "method":        "#D1CF32",

    "variable":      "#7AF8FF",
    "enumMember":    "#7AF8FF",

    "property":      "#77B0FF",
    "field":         "#77B0FF",

    "parameter":     { "foreground": "#A2EBA1", "italic": true },
    "selfParameter": { "foreground": "#EA9575", "italic": true },

    "*.abstract":    { "italic": true },
    "*.deprecated":  { "strikethrough": true }
  }
}