MODULO 4.8

🎨 Theme & Styling

Como o Claude Code transforma uma string ThemeName em output colorido no terminal -- do sistema de tipos com 6 paletas ao clamping de chalk level ao comando /color.

8
Topicos
~70
Minutos
Deep
Nivel
Source
Tipo
1

🏗️ Arquitetura em 4 Camadas

Layer 1: utils/theme.ts -- Semantic Color Palette

6 temas nomeados, cada um mapeando ~70 tokens semanticos para valores raw (RGB, hex ou ANSI)

Layer 2: ink/colorize.ts -- Chalk Normalization

Detecta ambiente terminal no module load, boost ou clamp do nivel de cor do chalk

Layer 3: ink/styles.ts -- Layout + Style Types

Tipos TypeScript Styles e TextStyles que componentes Ink Box/Text aceitam

Layer 4: design-system/color.ts -- Theme-Aware Colorizer

Helper curried que aceita theme key ou raw color, resolve e delega para colorize()

2

🌈 Os Seis Temas

dark
light
light-daltonized
dark-daltonized
light-ansi
dark-ansi

💡 Daltonized: Azul em vez de Verde

Temas daltonized substituem sistematicamente distincoes verde-vermelho por azul-vermelho. Deuteranopia (forma mais comum de daltonismo) afeta o canal verde. success em dark-daltonized e azul brilhante, nao verde.

3

⚡ Terminal Environment Fixes

VS Code Boost

xterm.js suporta truecolor desde 2017, mas chalk detecta como level 2. rgb(215,119,87) (Claude orange) vira salmon lavado.

TERM_PROGRAM=vscode AND level=2 -> level=3

tmux Clamp

tmux parseia truecolor corretamente mas re-emite apenas se outer terminal anunciar Tc/RGB. Sem isso, backgrounds sao dropados.

TMUX AND level > 2 -> level=2

💡 Ordenacao importa

Boost roda primeiro. Se alguem esta no VS Code dentro do tmux, o boost acontece e o clamp re-clamp de volta para 2. O clamp vence pois limitacao do tmux e um hard constraint. Escape hatch: CLAUDE_CODE_TMUX_TRUECOLOR=1.

4

🎯 colorize() Dispatch Table

String-prefix dispatch significa que o formato de cor e auto-descritivo:

if (color.startsWith('ansi:'))   -> chalk.red / chalk.bgRed
if (color.startsWith('#'))       -> chalk.hex(color)
if (color.startsWith('ansi256')) -> chalk.ansi256(N)
if (color.startsWith('rgb'))     -> chalk.rgb(r,g,b)
5

🔗 design-system/color.ts -- Theme Bridge

Unico local onde theme key strings sao resolvidas para raw color values. Retorna funcao curried, nao string:

export function color(
  c: keyof Theme | Color | undefined,
  theme: ThemeName,
  type: ColorType = 'foreground',
): (text: string) => string {
  return text => {
    if (c.startsWith('rgb(') || c.startsWith('#') || ...)
      return colorize(text, c, type)    // raw bypass
    return colorize(text, getTheme(theme)[c], type)  // theme lookup
  }
}

Separacao Arquitetural

styles.ts e colorize.ts sao completamente inconscientes de temas. Apenas design-system/color.ts faz a ponte de theme tokens para raw colors.

6

🎮 Comandos /theme e /color

/theme

Abre picker interativo com preview ao vivo. usePreviewTheme() seta tema temporario. Enter salva, Escape cancela e restaura.

/color

Para sessoes sub-agent. 8 cores: red, blue, green, yellow, purple, orange, pink, cyan. Proibido para teammates de swarm.

💡 Reset usa "default", nao string vazia

String vazia seria falsy e nao seria escrita por guard de truthiness em sessionStorage.ts. O sentinel "default" garante que o reset persiste entre restarts de sessao.

7

👥 AgentColorManager

Mapeia agent type strings para slots de cor do tema via sufixo _FOR_SUBAGENTS_ONLY:

AGENT_COLOR_TO_THEME_COLOR = {
  red:    'red_FOR_SUBAGENTS_ONLY',
  blue:   'blue_FOR_SUBAGENTS_ONLY',
  ...
} as const satisfies Record<AgentColorName, keyof Theme>

O satisfies garante em compile-time que cada entrada aponta para uma chave valida do tipo Theme. Agent type general-purpose retorna undefined -- intencionalmente sem cor.

8

🗺️ Fluxo Completo de Resolucao de Cores

flowchart TD
    A[User selects theme via /theme] --> B[useTheme setTheme called]
    B --> C[ThemeSetting saved to settings.json]
    C --> D[ThemeName resolved at runtime\nauto -> dark or light]
    D --> E[getTheme returns Theme object]
    E --> F[Component calls color fn\nfrom design-system/color.ts]
    F --> G{Is c a raw color?\nstarts with rgb/hash/ansi}
    G -- Yes --> H[colorize directly]
    G -- No --> I[getTheme key lookup\nraw value]
    I --> H
    H --> J{chalk.level}
    J -- 3 truecolor --> K[chalk.rgb / chalk.hex]
    J -- 2 256-color --> L[chalk.ansi256]
    J -- 0/1 no color --> M[plain string]
    K --> N[ANSI escape to terminal]
    L --> N
    M --> N
                    

📋 Resumo do Modulo

3 fases distintas: definicao de paleta (6 Theme objects), normalizacao de ambiente (chalk boost/clamp), renderizacao (theme key -> raw color -> chalk)
Dois ajustes de chalk level (VS Code boost + tmux clamp) disparam uma vez no import time e afetam todo output subsequente
Resolucao de tema separada da renderizacao de cor -- styles.ts e colorize.ts sao inconscientes de temas
Temas daltonized substituem azul por verde em todos os tokens semanticos success/diff-added
Convencoes de naming _FOR_SUBAGENTS_ONLY e Shimmer sao guardrails intencionais no tipo Theme
/color usa sentinel "default" (nao string vazia) para garantir persistencia do reset
Modulo Anterior Voltar para Trilha