/ utils / theme.ts
theme.ts
  1  import chalk, { Chalk } from 'chalk'
  2  import { env } from './env.js'
  3  
  4  export type Theme = {
  5    autoAccept: string
  6    bashBorder: string
  7    claude: string
  8    claudeShimmer: string // Lighter version of claude color for shimmer effect
  9    claudeBlue_FOR_SYSTEM_SPINNER: string
 10    claudeBlueShimmer_FOR_SYSTEM_SPINNER: string
 11    permission: string
 12    permissionShimmer: string // Lighter version of permission color for shimmer effect
 13    planMode: string
 14    ide: string
 15    promptBorder: string
 16    promptBorderShimmer: string // Lighter version of promptBorder color for shimmer effect
 17    text: string
 18    inverseText: string
 19    inactive: string
 20    inactiveShimmer: string // Lighter version of inactive color for shimmer effect
 21    subtle: string
 22    suggestion: string
 23    remember: string
 24    background: string
 25    // Semantic colors
 26    success: string
 27    error: string
 28    warning: string
 29    merged: string
 30    warningShimmer: string // Lighter version of warning color for shimmer effect
 31    // Diff colors
 32    diffAdded: string
 33    diffRemoved: string
 34    diffAddedDimmed: string
 35    diffRemovedDimmed: string
 36    // Word-level diff highlighting
 37    diffAddedWord: string
 38    diffRemovedWord: string
 39    // Agent colors
 40    red_FOR_SUBAGENTS_ONLY: string
 41    blue_FOR_SUBAGENTS_ONLY: string
 42    green_FOR_SUBAGENTS_ONLY: string
 43    yellow_FOR_SUBAGENTS_ONLY: string
 44    purple_FOR_SUBAGENTS_ONLY: string
 45    orange_FOR_SUBAGENTS_ONLY: string
 46    pink_FOR_SUBAGENTS_ONLY: string
 47    cyan_FOR_SUBAGENTS_ONLY: string
 48    // Grove colors
 49    professionalBlue: string
 50    // Chrome colors
 51    chromeYellow: string
 52    // TUI V2 colors
 53    clawd_body: string
 54    clawd_background: string
 55    userMessageBackground: string
 56    userMessageBackgroundHover: string
 57    /** Message-actions selection. Cool shift toward `suggestion` blue; distinct from default AND userMessageBackground. */
 58    messageActionsBackground: string
 59    /** Text-selection highlight background (alt-screen mouse selection). Solid
 60     *  bg that REPLACES the cell's bg while preserving its fg — matches native
 61     *  terminal selection. Previously SGR-7 inverse (swapped fg/bg per cell),
 62     *  which fragmented badly over syntax highlighting. */
 63    selectionBg: string
 64    bashMessageBackgroundColor: string
 65  
 66    memoryBackgroundColor: string
 67    rate_limit_fill: string
 68    rate_limit_empty: string
 69    fastMode: string
 70    fastModeShimmer: string
 71    // Brief/assistant mode label colors
 72    briefLabelYou: string
 73    briefLabelClaude: string
 74    // Rainbow colors for ultrathink keyword highlighting
 75    rainbow_red: string
 76    rainbow_orange: string
 77    rainbow_yellow: string
 78    rainbow_green: string
 79    rainbow_blue: string
 80    rainbow_indigo: string
 81    rainbow_violet: string
 82    rainbow_red_shimmer: string
 83    rainbow_orange_shimmer: string
 84    rainbow_yellow_shimmer: string
 85    rainbow_green_shimmer: string
 86    rainbow_blue_shimmer: string
 87    rainbow_indigo_shimmer: string
 88    rainbow_violet_shimmer: string
 89  }
 90  
 91  export const THEME_NAMES = [
 92    'dark',
 93    'light',
 94    'light-daltonized',
 95    'dark-daltonized',
 96    'light-ansi',
 97    'dark-ansi',
 98  ] as const
 99  
100  /** A renderable theme. Always resolvable to a concrete color palette. */
101  export type ThemeName = (typeof THEME_NAMES)[number]
102  
103  export const THEME_SETTINGS = ['auto', ...THEME_NAMES] as const
104  
105  /**
106   * A theme preference as stored in user config. `'auto'` follows the system
107   * dark/light mode and is resolved to a ThemeName at runtime.
108   */
109  export type ThemeSetting = (typeof THEME_SETTINGS)[number]
110  
111  /**
112   * Light theme using explicit RGB values to avoid inconsistencies
113   * from users' custom terminal ANSI color definitions
114   */
115  const lightTheme: Theme = {
116    autoAccept: 'rgb(135,0,255)', // Electric violet
117    bashBorder: 'rgb(255,0,135)', // Vibrant pink
118    claude: 'rgb(215,119,87)', // Claude orange
119    claudeShimmer: 'rgb(245,149,117)', // Lighter claude orange for shimmer effect
120    claudeBlue_FOR_SYSTEM_SPINNER: 'rgb(87,105,247)', // Medium blue for system spinner
121    claudeBlueShimmer_FOR_SYSTEM_SPINNER: 'rgb(117,135,255)', // Lighter blue for system spinner shimmer
122    permission: 'rgb(87,105,247)', // Medium blue
123    permissionShimmer: 'rgb(137,155,255)', // Lighter blue for shimmer effect
124    planMode: 'rgb(0,102,102)', // Muted teal
125    ide: 'rgb(71,130,200)', // Muted blue
126    promptBorder: 'rgb(153,153,153)', // Medium gray
127    promptBorderShimmer: 'rgb(183,183,183)', // Lighter gray for shimmer effect
128    text: 'rgb(0,0,0)', // Black
129    inverseText: 'rgb(255,255,255)', // White
130    inactive: 'rgb(102,102,102)', // Dark gray
131    inactiveShimmer: 'rgb(142,142,142)', // Lighter gray for shimmer effect
132    subtle: 'rgb(175,175,175)', // Light gray
133    suggestion: 'rgb(87,105,247)', // Medium blue
134    remember: 'rgb(0,0,255)', // Blue
135    background: 'rgb(0,153,153)', // Cyan
136    success: 'rgb(44,122,57)', // Green
137    error: 'rgb(171,43,63)', // Red
138    warning: 'rgb(150,108,30)', // Amber
139    merged: 'rgb(135,0,255)', // Electric violet (matches autoAccept)
140    warningShimmer: 'rgb(200,158,80)', // Lighter amber for shimmer effect
141    diffAdded: 'rgb(105,219,124)', // Light green
142    diffRemoved: 'rgb(255,168,180)', // Light red
143    diffAddedDimmed: 'rgb(199,225,203)', // Very light green
144    diffRemovedDimmed: 'rgb(253,210,216)', // Very light red
145    diffAddedWord: 'rgb(47,157,68)', // Medium green
146    diffRemovedWord: 'rgb(209,69,75)', // Medium red
147    // Agent colors
148    red_FOR_SUBAGENTS_ONLY: 'rgb(220,38,38)', // Red 600
149    blue_FOR_SUBAGENTS_ONLY: 'rgb(37,99,235)', // Blue 600
150    green_FOR_SUBAGENTS_ONLY: 'rgb(22,163,74)', // Green 600
151    yellow_FOR_SUBAGENTS_ONLY: 'rgb(202,138,4)', // Yellow 600
152    purple_FOR_SUBAGENTS_ONLY: 'rgb(147,51,234)', // Purple 600
153    orange_FOR_SUBAGENTS_ONLY: 'rgb(234,88,12)', // Orange 600
154    pink_FOR_SUBAGENTS_ONLY: 'rgb(219,39,119)', // Pink 600
155    cyan_FOR_SUBAGENTS_ONLY: 'rgb(8,145,178)', // Cyan 600
156    // Grove colors
157    professionalBlue: 'rgb(106,155,204)',
158    // Chrome colors
159    chromeYellow: 'rgb(251,188,4)', // Chrome yellow
160    // TUI V2 colors
161    clawd_body: 'rgb(215,119,87)',
162    clawd_background: 'rgb(0,0,0)',
163    userMessageBackground: 'rgb(240, 240, 240)', // Slightly darker grey for optimal contrast
164    userMessageBackgroundHover: 'rgb(252, 252, 252)', // ≥250 to quantize distinct from base at 256-color level
165    messageActionsBackground: 'rgb(232, 236, 244)', // cool gray — darker than userMsg 240 (visible on white), slight blue toward `suggestion`
166    selectionBg: 'rgb(180, 213, 255)', // classic light-mode selection blue (macOS/VS Code-ish); dark fgs stay readable
167    bashMessageBackgroundColor: 'rgb(250, 245, 250)',
168  
169    memoryBackgroundColor: 'rgb(230, 245, 250)',
170    rate_limit_fill: 'rgb(87,105,247)', // Medium blue
171    rate_limit_empty: 'rgb(39,47,111)', // Dark blue
172    fastMode: 'rgb(255,106,0)', // Electric orange
173    fastModeShimmer: 'rgb(255,150,50)', // Lighter orange for shimmer
174    // Brief/assistant mode
175    briefLabelYou: 'rgb(37,99,235)', // Blue
176    briefLabelClaude: 'rgb(215,119,87)', // Brand orange
177    rainbow_red: 'rgb(235,95,87)',
178    rainbow_orange: 'rgb(245,139,87)',
179    rainbow_yellow: 'rgb(250,195,95)',
180    rainbow_green: 'rgb(145,200,130)',
181    rainbow_blue: 'rgb(130,170,220)',
182    rainbow_indigo: 'rgb(155,130,200)',
183    rainbow_violet: 'rgb(200,130,180)',
184    rainbow_red_shimmer: 'rgb(250,155,147)',
185    rainbow_orange_shimmer: 'rgb(255,185,137)',
186    rainbow_yellow_shimmer: 'rgb(255,225,155)',
187    rainbow_green_shimmer: 'rgb(185,230,180)',
188    rainbow_blue_shimmer: 'rgb(180,205,240)',
189    rainbow_indigo_shimmer: 'rgb(195,180,230)',
190    rainbow_violet_shimmer: 'rgb(230,180,210)',
191  }
192  
193  /**
194   * Light ANSI theme using only the 16 standard ANSI colors
195   * for terminals without true color support
196   */
197  const lightAnsiTheme: Theme = {
198    autoAccept: 'ansi:magenta',
199    bashBorder: 'ansi:magenta',
200    claude: 'ansi:redBright',
201    claudeShimmer: 'ansi:yellowBright',
202    claudeBlue_FOR_SYSTEM_SPINNER: 'ansi:blue',
203    claudeBlueShimmer_FOR_SYSTEM_SPINNER: 'ansi:blueBright',
204    permission: 'ansi:blue',
205    permissionShimmer: 'ansi:blueBright',
206    planMode: 'ansi:cyan',
207    ide: 'ansi:blueBright',
208    promptBorder: 'ansi:white',
209    promptBorderShimmer: 'ansi:whiteBright',
210    text: 'ansi:black',
211    inverseText: 'ansi:white',
212    inactive: 'ansi:blackBright',
213    inactiveShimmer: 'ansi:white',
214    subtle: 'ansi:blackBright',
215    suggestion: 'ansi:blue',
216    remember: 'ansi:blue',
217    background: 'ansi:cyan',
218    success: 'ansi:green',
219    error: 'ansi:red',
220    warning: 'ansi:yellow',
221    merged: 'ansi:magenta',
222    warningShimmer: 'ansi:yellowBright',
223    diffAdded: 'ansi:green',
224    diffRemoved: 'ansi:red',
225    diffAddedDimmed: 'ansi:green',
226    diffRemovedDimmed: 'ansi:red',
227    diffAddedWord: 'ansi:greenBright',
228    diffRemovedWord: 'ansi:redBright',
229    // Agent colors
230    red_FOR_SUBAGENTS_ONLY: 'ansi:red',
231    blue_FOR_SUBAGENTS_ONLY: 'ansi:blue',
232    green_FOR_SUBAGENTS_ONLY: 'ansi:green',
233    yellow_FOR_SUBAGENTS_ONLY: 'ansi:yellow',
234    purple_FOR_SUBAGENTS_ONLY: 'ansi:magenta',
235    orange_FOR_SUBAGENTS_ONLY: 'ansi:redBright',
236    pink_FOR_SUBAGENTS_ONLY: 'ansi:magentaBright',
237    cyan_FOR_SUBAGENTS_ONLY: 'ansi:cyan',
238    // Grove colors
239    professionalBlue: 'ansi:blueBright',
240    // Chrome colors
241    chromeYellow: 'ansi:yellow', // Chrome yellow
242    // TUI V2 colors
243    clawd_body: 'ansi:redBright',
244    clawd_background: 'ansi:black',
245    userMessageBackground: 'ansi:white',
246    userMessageBackgroundHover: 'ansi:whiteBright',
247    messageActionsBackground: 'ansi:white',
248    selectionBg: 'ansi:cyan', // lighter named bg for light-ansi; dark fgs stay readable
249    bashMessageBackgroundColor: 'ansi:whiteBright',
250  
251    memoryBackgroundColor: 'ansi:white',
252    rate_limit_fill: 'ansi:yellow',
253    rate_limit_empty: 'ansi:black',
254    fastMode: 'ansi:red',
255    fastModeShimmer: 'ansi:redBright',
256    briefLabelYou: 'ansi:blue',
257    briefLabelClaude: 'ansi:redBright',
258    rainbow_red: 'ansi:red',
259    rainbow_orange: 'ansi:redBright',
260    rainbow_yellow: 'ansi:yellow',
261    rainbow_green: 'ansi:green',
262    rainbow_blue: 'ansi:cyan',
263    rainbow_indigo: 'ansi:blue',
264    rainbow_violet: 'ansi:magenta',
265    rainbow_red_shimmer: 'ansi:redBright',
266    rainbow_orange_shimmer: 'ansi:yellow',
267    rainbow_yellow_shimmer: 'ansi:yellowBright',
268    rainbow_green_shimmer: 'ansi:greenBright',
269    rainbow_blue_shimmer: 'ansi:cyanBright',
270    rainbow_indigo_shimmer: 'ansi:blueBright',
271    rainbow_violet_shimmer: 'ansi:magentaBright',
272  }
273  
274  /**
275   * Dark ANSI theme using only the 16 standard ANSI colors
276   * for terminals without true color support
277   */
278  const darkAnsiTheme: Theme = {
279    autoAccept: 'ansi:magentaBright',
280    bashBorder: 'ansi:magentaBright',
281    claude: 'ansi:redBright',
282    claudeShimmer: 'ansi:yellowBright',
283    claudeBlue_FOR_SYSTEM_SPINNER: 'ansi:blueBright',
284    claudeBlueShimmer_FOR_SYSTEM_SPINNER: 'ansi:blueBright',
285    permission: 'ansi:blueBright',
286    permissionShimmer: 'ansi:blueBright',
287    planMode: 'ansi:cyanBright',
288    ide: 'ansi:blue',
289    promptBorder: 'ansi:white',
290    promptBorderShimmer: 'ansi:whiteBright',
291    text: 'ansi:whiteBright',
292    inverseText: 'ansi:black',
293    inactive: 'ansi:white',
294    inactiveShimmer: 'ansi:whiteBright',
295    subtle: 'ansi:white',
296    suggestion: 'ansi:blueBright',
297    remember: 'ansi:blueBright',
298    background: 'ansi:cyanBright',
299    success: 'ansi:greenBright',
300    error: 'ansi:redBright',
301    warning: 'ansi:yellowBright',
302    merged: 'ansi:magentaBright',
303    warningShimmer: 'ansi:yellowBright',
304    diffAdded: 'ansi:green',
305    diffRemoved: 'ansi:red',
306    diffAddedDimmed: 'ansi:green',
307    diffRemovedDimmed: 'ansi:red',
308    diffAddedWord: 'ansi:greenBright',
309    diffRemovedWord: 'ansi:redBright',
310    // Agent colors
311    red_FOR_SUBAGENTS_ONLY: 'ansi:redBright',
312    blue_FOR_SUBAGENTS_ONLY: 'ansi:blueBright',
313    green_FOR_SUBAGENTS_ONLY: 'ansi:greenBright',
314    yellow_FOR_SUBAGENTS_ONLY: 'ansi:yellowBright',
315    purple_FOR_SUBAGENTS_ONLY: 'ansi:magentaBright',
316    orange_FOR_SUBAGENTS_ONLY: 'ansi:redBright',
317    pink_FOR_SUBAGENTS_ONLY: 'ansi:magentaBright',
318    cyan_FOR_SUBAGENTS_ONLY: 'ansi:cyanBright',
319    // Grove colors
320    professionalBlue: 'rgb(106,155,204)',
321    // Chrome colors
322    chromeYellow: 'ansi:yellowBright', // Chrome yellow
323    // TUI V2 colors
324    clawd_body: 'ansi:redBright',
325    clawd_background: 'ansi:black',
326    userMessageBackground: 'ansi:blackBright',
327    userMessageBackgroundHover: 'ansi:white',
328    messageActionsBackground: 'ansi:blackBright',
329    selectionBg: 'ansi:blue', // darker named bg for dark-ansi; bright fgs stay readable
330    bashMessageBackgroundColor: 'ansi:black',
331  
332    memoryBackgroundColor: 'ansi:blackBright',
333    rate_limit_fill: 'ansi:yellow',
334    rate_limit_empty: 'ansi:white',
335    fastMode: 'ansi:redBright',
336    fastModeShimmer: 'ansi:redBright',
337    briefLabelYou: 'ansi:blueBright',
338    briefLabelClaude: 'ansi:redBright',
339    rainbow_red: 'ansi:red',
340    rainbow_orange: 'ansi:redBright',
341    rainbow_yellow: 'ansi:yellow',
342    rainbow_green: 'ansi:green',
343    rainbow_blue: 'ansi:cyan',
344    rainbow_indigo: 'ansi:blue',
345    rainbow_violet: 'ansi:magenta',
346    rainbow_red_shimmer: 'ansi:redBright',
347    rainbow_orange_shimmer: 'ansi:yellow',
348    rainbow_yellow_shimmer: 'ansi:yellowBright',
349    rainbow_green_shimmer: 'ansi:greenBright',
350    rainbow_blue_shimmer: 'ansi:cyanBright',
351    rainbow_indigo_shimmer: 'ansi:blueBright',
352    rainbow_violet_shimmer: 'ansi:magentaBright',
353  }
354  
355  /**
356   * Light daltonized theme (color-blind friendly) using explicit RGB values
357   * to avoid inconsistencies from users' custom terminal ANSI color definitions
358   */
359  const lightDaltonizedTheme: Theme = {
360    autoAccept: 'rgb(135,0,255)', // Electric violet
361    bashBorder: 'rgb(0,102,204)', // Blue instead of pink
362    claude: 'rgb(255,153,51)', // Orange adjusted for deuteranopia
363    claudeShimmer: 'rgb(255,183,101)', // Lighter orange for shimmer effect
364    claudeBlue_FOR_SYSTEM_SPINNER: 'rgb(51,102,255)', // Bright blue for system spinner
365    claudeBlueShimmer_FOR_SYSTEM_SPINNER: 'rgb(101,152,255)', // Lighter bright blue for system spinner shimmer
366    permission: 'rgb(51,102,255)', // Bright blue
367    permissionShimmer: 'rgb(101,152,255)', // Lighter bright blue for shimmer
368    planMode: 'rgb(51,102,102)', // Muted blue-gray (works for color-blind)
369    ide: 'rgb(71,130,200)', // Muted blue
370    promptBorder: 'rgb(153,153,153)', // Medium gray
371    promptBorderShimmer: 'rgb(183,183,183)', // Lighter gray for shimmer
372    text: 'rgb(0,0,0)', // Black
373    inverseText: 'rgb(255,255,255)', // White
374    inactive: 'rgb(102,102,102)', // Dark gray
375    inactiveShimmer: 'rgb(142,142,142)', // Lighter gray for shimmer effect
376    subtle: 'rgb(175,175,175)', // Light gray
377    suggestion: 'rgb(51,102,255)', // Bright blue
378    remember: 'rgb(51,102,255)', // Bright blue
379    background: 'rgb(0,153,153)', // Cyan (color-blind friendly)
380    success: 'rgb(0,102,153)', // Blue instead of green for deuteranopia
381    error: 'rgb(204,0,0)', // Pure red for better distinction
382    warning: 'rgb(255,153,0)', // Orange adjusted for deuteranopia
383    merged: 'rgb(135,0,255)', // Electric violet (matches autoAccept)
384    warningShimmer: 'rgb(255,183,50)', // Lighter orange for shimmer
385    diffAdded: 'rgb(153,204,255)', // Light blue instead of green
386    diffRemoved: 'rgb(255,204,204)', // Light red
387    diffAddedDimmed: 'rgb(209,231,253)', // Very light blue
388    diffRemovedDimmed: 'rgb(255,233,233)', // Very light red
389    diffAddedWord: 'rgb(51,102,204)', // Medium blue (less intense than deep blue)
390    diffRemovedWord: 'rgb(153,51,51)', // Softer red (less intense than deep red)
391    // Agent colors (daltonism-friendly)
392    red_FOR_SUBAGENTS_ONLY: 'rgb(204,0,0)', // Pure red
393    blue_FOR_SUBAGENTS_ONLY: 'rgb(0,102,204)', // Pure blue
394    green_FOR_SUBAGENTS_ONLY: 'rgb(0,204,0)', // Pure green
395    yellow_FOR_SUBAGENTS_ONLY: 'rgb(255,204,0)', // Golden yellow
396    purple_FOR_SUBAGENTS_ONLY: 'rgb(128,0,128)', // True purple
397    orange_FOR_SUBAGENTS_ONLY: 'rgb(255,128,0)', // True orange
398    pink_FOR_SUBAGENTS_ONLY: 'rgb(255,102,178)', // Adjusted pink
399    cyan_FOR_SUBAGENTS_ONLY: 'rgb(0,178,178)', // Adjusted cyan
400    // Grove colors
401    professionalBlue: 'rgb(106,155,204)',
402    // Chrome colors
403    chromeYellow: 'rgb(251,188,4)', // Chrome yellow
404    // TUI V2 colors
405    clawd_body: 'rgb(215,119,87)',
406    clawd_background: 'rgb(0,0,0)',
407    userMessageBackground: 'rgb(220, 220, 220)', // Slightly darker grey for optimal contrast
408    userMessageBackgroundHover: 'rgb(232, 232, 232)', // ≥230 to quantize distinct from base at 256-color level
409    messageActionsBackground: 'rgb(210, 216, 226)', // cool gray — darker than userMsg 220, slight blue
410    selectionBg: 'rgb(180, 213, 255)', // light selection blue; daltonized fgs are yellows/blues, both readable on light blue
411    bashMessageBackgroundColor: 'rgb(250, 245, 250)',
412  
413    memoryBackgroundColor: 'rgb(230, 245, 250)',
414    rate_limit_fill: 'rgb(51,102,255)', // Bright blue
415    rate_limit_empty: 'rgb(23,46,114)', // Dark blue
416    fastMode: 'rgb(255,106,0)', // Electric orange (color-blind safe)
417    fastModeShimmer: 'rgb(255,150,50)', // Lighter orange for shimmer
418    briefLabelYou: 'rgb(37,99,235)', // Blue
419    briefLabelClaude: 'rgb(255,153,51)', // Orange adjusted for deuteranopia (matches claude)
420    rainbow_red: 'rgb(235,95,87)',
421    rainbow_orange: 'rgb(245,139,87)',
422    rainbow_yellow: 'rgb(250,195,95)',
423    rainbow_green: 'rgb(145,200,130)',
424    rainbow_blue: 'rgb(130,170,220)',
425    rainbow_indigo: 'rgb(155,130,200)',
426    rainbow_violet: 'rgb(200,130,180)',
427    rainbow_red_shimmer: 'rgb(250,155,147)',
428    rainbow_orange_shimmer: 'rgb(255,185,137)',
429    rainbow_yellow_shimmer: 'rgb(255,225,155)',
430    rainbow_green_shimmer: 'rgb(185,230,180)',
431    rainbow_blue_shimmer: 'rgb(180,205,240)',
432    rainbow_indigo_shimmer: 'rgb(195,180,230)',
433    rainbow_violet_shimmer: 'rgb(230,180,210)',
434  }
435  
436  /**
437   * Dark theme using explicit RGB values to avoid inconsistencies
438   * from users' custom terminal ANSI color definitions
439   */
440  const darkTheme: Theme = {
441    autoAccept: 'rgb(175,135,255)', // Electric violet
442    bashBorder: 'rgb(253,93,177)', // Bright pink
443    claude: 'rgb(215,119,87)', // Claude orange
444    claudeShimmer: 'rgb(235,159,127)', // Lighter claude orange for shimmer effect
445    claudeBlue_FOR_SYSTEM_SPINNER: 'rgb(147,165,255)', // Blue for system spinner
446    claudeBlueShimmer_FOR_SYSTEM_SPINNER: 'rgb(177,195,255)', // Lighter blue for system spinner shimmer
447    permission: 'rgb(177,185,249)', // Light blue-purple
448    permissionShimmer: 'rgb(207,215,255)', // Lighter blue-purple for shimmer
449    planMode: 'rgb(72,150,140)', // Muted sage green
450    ide: 'rgb(71,130,200)', // Muted blue
451    promptBorder: 'rgb(136,136,136)', // Medium gray
452    promptBorderShimmer: 'rgb(166,166,166)', // Lighter gray for shimmer
453    text: 'rgb(255,255,255)', // White
454    inverseText: 'rgb(0,0,0)', // Black
455    inactive: 'rgb(153,153,153)', // Light gray
456    inactiveShimmer: 'rgb(193,193,193)', // Lighter gray for shimmer effect
457    subtle: 'rgb(80,80,80)', // Dark gray
458    suggestion: 'rgb(177,185,249)', // Light blue-purple
459    remember: 'rgb(177,185,249)', // Light blue-purple
460    background: 'rgb(0,204,204)', // Bright cyan
461    success: 'rgb(78,186,101)', // Bright green
462    error: 'rgb(255,107,128)', // Bright red
463    warning: 'rgb(255,193,7)', // Bright amber
464    merged: 'rgb(175,135,255)', // Electric violet (matches autoAccept)
465    warningShimmer: 'rgb(255,223,57)', // Lighter amber for shimmer
466    diffAdded: 'rgb(34,92,43)', // Dark green
467    diffRemoved: 'rgb(122,41,54)', // Dark red
468    diffAddedDimmed: 'rgb(71,88,74)', // Very dark green
469    diffRemovedDimmed: 'rgb(105,72,77)', // Very dark red
470    diffAddedWord: 'rgb(56,166,96)', // Medium green
471    diffRemovedWord: 'rgb(179,89,107)', // Softer red (less intense than bright red)
472    // Agent colors
473    red_FOR_SUBAGENTS_ONLY: 'rgb(220,38,38)', // Red 600
474    blue_FOR_SUBAGENTS_ONLY: 'rgb(37,99,235)', // Blue 600
475    green_FOR_SUBAGENTS_ONLY: 'rgb(22,163,74)', // Green 600
476    yellow_FOR_SUBAGENTS_ONLY: 'rgb(202,138,4)', // Yellow 600
477    purple_FOR_SUBAGENTS_ONLY: 'rgb(147,51,234)', // Purple 600
478    orange_FOR_SUBAGENTS_ONLY: 'rgb(234,88,12)', // Orange 600
479    pink_FOR_SUBAGENTS_ONLY: 'rgb(219,39,119)', // Pink 600
480    cyan_FOR_SUBAGENTS_ONLY: 'rgb(8,145,178)', // Cyan 600
481    // Grove colors
482    professionalBlue: 'rgb(106,155,204)',
483    // Chrome colors
484    chromeYellow: 'rgb(251,188,4)', // Chrome yellow
485    // TUI V2 colors
486    clawd_body: 'rgb(215,119,87)',
487    clawd_background: 'rgb(0,0,0)',
488    userMessageBackground: 'rgb(55, 55, 55)', // Lighter grey for better visual contrast
489    userMessageBackgroundHover: 'rgb(70, 70, 70)',
490    messageActionsBackground: 'rgb(44, 50, 62)', // cool gray, slight blue
491    selectionBg: 'rgb(38, 79, 120)', // classic dark-mode selection blue (VS Code dark default); light fgs stay readable
492    bashMessageBackgroundColor: 'rgb(65, 60, 65)',
493  
494    memoryBackgroundColor: 'rgb(55, 65, 70)',
495    rate_limit_fill: 'rgb(177,185,249)', // Light blue-purple
496    rate_limit_empty: 'rgb(80,83,112)', // Medium blue-purple
497    fastMode: 'rgb(255,120,20)', // Electric orange for dark bg
498    fastModeShimmer: 'rgb(255,165,70)', // Lighter orange for shimmer
499    briefLabelYou: 'rgb(122,180,232)', // Light blue
500    briefLabelClaude: 'rgb(215,119,87)', // Brand orange
501    rainbow_red: 'rgb(235,95,87)',
502    rainbow_orange: 'rgb(245,139,87)',
503    rainbow_yellow: 'rgb(250,195,95)',
504    rainbow_green: 'rgb(145,200,130)',
505    rainbow_blue: 'rgb(130,170,220)',
506    rainbow_indigo: 'rgb(155,130,200)',
507    rainbow_violet: 'rgb(200,130,180)',
508    rainbow_red_shimmer: 'rgb(250,155,147)',
509    rainbow_orange_shimmer: 'rgb(255,185,137)',
510    rainbow_yellow_shimmer: 'rgb(255,225,155)',
511    rainbow_green_shimmer: 'rgb(185,230,180)',
512    rainbow_blue_shimmer: 'rgb(180,205,240)',
513    rainbow_indigo_shimmer: 'rgb(195,180,230)',
514    rainbow_violet_shimmer: 'rgb(230,180,210)',
515  }
516  
517  /**
518   * Dark daltonized theme (color-blind friendly) using explicit RGB values
519   * to avoid inconsistencies from users' custom terminal ANSI color definitions
520   */
521  const darkDaltonizedTheme: Theme = {
522    autoAccept: 'rgb(175,135,255)', // Electric violet
523    bashBorder: 'rgb(51,153,255)', // Bright blue
524    claude: 'rgb(255,153,51)', // Orange adjusted for deuteranopia
525    claudeShimmer: 'rgb(255,183,101)', // Lighter orange for shimmer effect
526    claudeBlue_FOR_SYSTEM_SPINNER: 'rgb(153,204,255)', // Light blue for system spinner
527    claudeBlueShimmer_FOR_SYSTEM_SPINNER: 'rgb(183,224,255)', // Lighter blue for system spinner shimmer
528    permission: 'rgb(153,204,255)', // Light blue
529    permissionShimmer: 'rgb(183,224,255)', // Lighter blue for shimmer
530    planMode: 'rgb(102,153,153)', // Muted gray-teal (works for color-blind)
531    ide: 'rgb(71,130,200)', // Muted blue
532    promptBorder: 'rgb(136,136,136)', // Medium gray
533    promptBorderShimmer: 'rgb(166,166,166)', // Lighter gray for shimmer
534    text: 'rgb(255,255,255)', // White
535    inverseText: 'rgb(0,0,0)', // Black
536    inactive: 'rgb(153,153,153)', // Light gray
537    inactiveShimmer: 'rgb(193,193,193)', // Lighter gray for shimmer effect
538    subtle: 'rgb(80,80,80)', // Dark gray
539    suggestion: 'rgb(153,204,255)', // Light blue
540    remember: 'rgb(153,204,255)', // Light blue
541    background: 'rgb(0,204,204)', // Bright cyan (color-blind friendly)
542    success: 'rgb(51,153,255)', // Blue instead of green
543    error: 'rgb(255,102,102)', // Bright red
544    warning: 'rgb(255,204,0)', // Yellow-orange for deuteranopia
545    merged: 'rgb(175,135,255)', // Electric violet (matches autoAccept)
546    warningShimmer: 'rgb(255,234,50)', // Lighter yellow-orange for shimmer
547    diffAdded: 'rgb(0,68,102)', // Dark blue
548    diffRemoved: 'rgb(102,0,0)', // Dark red
549    diffAddedDimmed: 'rgb(62,81,91)', // Dimmed blue
550    diffRemovedDimmed: 'rgb(62,44,44)', // Dimmed red
551    diffAddedWord: 'rgb(0,119,179)', // Medium blue
552    diffRemovedWord: 'rgb(179,0,0)', // Medium red
553    // Agent colors (daltonism-friendly, dark mode)
554    red_FOR_SUBAGENTS_ONLY: 'rgb(255,102,102)', // Bright red
555    blue_FOR_SUBAGENTS_ONLY: 'rgb(102,178,255)', // Bright blue
556    green_FOR_SUBAGENTS_ONLY: 'rgb(102,255,102)', // Bright green
557    yellow_FOR_SUBAGENTS_ONLY: 'rgb(255,255,102)', // Bright yellow
558    purple_FOR_SUBAGENTS_ONLY: 'rgb(178,102,255)', // Bright purple
559    orange_FOR_SUBAGENTS_ONLY: 'rgb(255,178,102)', // Bright orange
560    pink_FOR_SUBAGENTS_ONLY: 'rgb(255,153,204)', // Bright pink
561    cyan_FOR_SUBAGENTS_ONLY: 'rgb(102,204,204)', // Bright cyan
562    // Grove colors
563    professionalBlue: 'rgb(106,155,204)',
564    // Chrome colors
565    chromeYellow: 'rgb(251,188,4)', // Chrome yellow
566    // TUI V2 colors
567    clawd_body: 'rgb(215,119,87)',
568    clawd_background: 'rgb(0,0,0)',
569    userMessageBackground: 'rgb(55, 55, 55)', // Lighter grey for better visual contrast
570    userMessageBackgroundHover: 'rgb(70, 70, 70)',
571    messageActionsBackground: 'rgb(44, 50, 62)', // cool gray, slight blue
572    selectionBg: 'rgb(38, 79, 120)', // classic dark-mode selection blue (VS Code dark default); light fgs stay readable
573    bashMessageBackgroundColor: 'rgb(65, 60, 65)',
574  
575    memoryBackgroundColor: 'rgb(55, 65, 70)',
576    rate_limit_fill: 'rgb(153,204,255)', // Light blue
577    rate_limit_empty: 'rgb(69,92,115)', // Dark blue
578    fastMode: 'rgb(255,120,20)', // Electric orange for dark bg (color-blind safe)
579    fastModeShimmer: 'rgb(255,165,70)', // Lighter orange for shimmer
580    briefLabelYou: 'rgb(122,180,232)', // Light blue
581    briefLabelClaude: 'rgb(255,153,51)', // Orange adjusted for deuteranopia (matches claude)
582    rainbow_red: 'rgb(235,95,87)',
583    rainbow_orange: 'rgb(245,139,87)',
584    rainbow_yellow: 'rgb(250,195,95)',
585    rainbow_green: 'rgb(145,200,130)',
586    rainbow_blue: 'rgb(130,170,220)',
587    rainbow_indigo: 'rgb(155,130,200)',
588    rainbow_violet: 'rgb(200,130,180)',
589    rainbow_red_shimmer: 'rgb(250,155,147)',
590    rainbow_orange_shimmer: 'rgb(255,185,137)',
591    rainbow_yellow_shimmer: 'rgb(255,225,155)',
592    rainbow_green_shimmer: 'rgb(185,230,180)',
593    rainbow_blue_shimmer: 'rgb(180,205,240)',
594    rainbow_indigo_shimmer: 'rgb(195,180,230)',
595    rainbow_violet_shimmer: 'rgb(230,180,210)',
596  }
597  
598  export function getTheme(themeName: ThemeName): Theme {
599    switch (themeName) {
600      case 'light':
601        return lightTheme
602      case 'light-ansi':
603        return lightAnsiTheme
604      case 'dark-ansi':
605        return darkAnsiTheme
606      case 'light-daltonized':
607        return lightDaltonizedTheme
608      case 'dark-daltonized':
609        return darkDaltonizedTheme
610      default:
611        return darkTheme
612    }
613  }
614  
615  // Create a chalk instance with 256-color level for Apple Terminal
616  // Apple Terminal doesn't handle 24-bit color escape sequences well
617  const chalkForChart =
618    env.terminal === 'Apple_Terminal'
619      ? new Chalk({ level: 2 }) // 256 colors
620      : chalk
621  
622  /**
623   * Converts a theme color to an ANSI escape sequence for use with asciichart.
624   * Uses chalk to generate the escape codes, with 256-color mode for Apple Terminal.
625   */
626  export function themeColorToAnsi(themeColor: string): string {
627    const rgbMatch = themeColor.match(/rgb\(\s?(\d+),\s?(\d+),\s?(\d+)\s?\)/)
628    if (rgbMatch) {
629      const r = parseInt(rgbMatch[1]!, 10)
630      const g = parseInt(rgbMatch[2]!, 10)
631      const b = parseInt(rgbMatch[3]!, 10)
632      // Use chalk.rgb which auto-converts to 256 colors when level is 2
633      // Extract just the opening escape sequence by using a marker
634      const colored = chalkForChart.rgb(r, g, b)('X')
635      return colored.slice(0, colored.indexOf('X'))
636    }
637    // Fallback to magenta if parsing fails
638    return '\x1b[35m'
639  }