/doki-theme-picker: browse 88 Doki themes and the termcn themes in a pane with a preview. Enter or a click applies the theme to Claude Code and Windows…

A theme picker for Claude Code on Windows. Type /doki-theme-picker to open a pane with 88 Doki themes (dark and light) and 40 termcn themes. Use the arrow keys to see each theme in the preview at the top of the pane. Press Enter, or click a theme, to apply the theme to Claude Code and Windows Terminal.
In Claude Code, type these two commands:
/plugin marketplace add shelmecha/doki-themes
/plugin install doki-theme-picker@doki-themes
Restart Claude Code. Then type /doki-theme-picker.
Type /doki-theme-picker to open the picker.
| Key | Action |
|---|---|
| Up / Down or Tab | Move through the list and see the preview |
| Enter | Apply the theme |
| Mouse click on a theme | Apply that theme |
| Esc | Close the picker |
To apply a theme without the picker, type its name after the command:
/doki-theme-picker rem
/doki-theme-picker termcn dracula
Claude Code's own /theme command also lists each theme that the picker applied one time. If you pick one of these themes with /theme, the picker sets the Windows Terminal scheme and the accent file at your next prompt.
When you press Enter, the picker writes only these files:
%USERPROFILE%\.claude\themes\<theme>.json: the Claude Code theme.%USERPROFILE%\.claude\settings.json: the theme value.settings.json: it adds a color scheme and sets it on one profile. The profile is the one of the tab that runs Claude Code. If the picker cannot find that profile, it uses your default profile.%USERPROFILE%\.claude\mods\theme-accent.json: an accent color that other mods can read. The picker writes this file only if the %USERPROFILE%\.claude\mods folder already exists.Before it changes settings.json or the Windows Terminal settings, it copies the old file to %USERPROFILE%\.claude\backups\. To undo a change, copy the backup back. The picker does not delete old backups. You can delete them when you do not need them.
/plugin marketplace update doki-themes
/plugin update doki-theme-picker@doki-themes
Restart Claude Code after the update.
/plugin uninstall doki-theme-picker@doki-themes
The uninstall does not change your current theme. To go back to a built-in theme, use /config. To remove all the files that the picker wrote:
doki-*.json and termcn-*.json files in %USERPROFILE%\.claude\themes\.Doki ... and termcn ... schemes.%USERPROFILE%\.claude\mods\theme-accent.json, if it exists.settings.json has comments or trailing commas, because it cannot read that file safely.claude plugin test .claude plugin validate --strict .tsconfig.json extends .claude-plugin/types/tsconfig.json. That folder holds the mod types for your editor, and git ignores it. The test and validate commands work without it.node scripts/build-themes.mjs <path to the Doki Theme VS Code extension> writes hooks/themes.ts.node scripts/build-termcn.mjs writes hooks/termcn-themes.ts.version in .claude-plugin/plugin.json for each release. If the version does not change, installed copies do not update.The theme colors come from the Doki Theme and termcn projects. See CREDITS.md. This repo uses the MIT license. See LICENSE.
hooks/register.tsx 438 lines1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register } from 'claude-code'
3
4import type { DokiTheme } from '../types'
5import {
6 findTheme,
7 ordered,
8 preferenceOf,
9 slugOfPreference,
10 sourceLabel,
11 stamp,
12 swatchCells,
13 toAccent,
14 toClaudeTheme,
15 toWtScheme,
16 updateClaudeSettings,
17 updateWtSettings,
18 windowStart,
19} from './theme'
20
21const PANE = 'doki-theme-picker'
22const COMMAND = 'doki-theme-picker'
23const PREVIEW_ROWS = 11 // title, 2 swatch rows, 5 mock-terminal rows (with padding), hint, 2 spacers
24// Windows Terminal settings under %LOCALAPPDATA%: the Store build, the Preview build, the unpackaged build.
25const WT_SETTINGS = [
26 'Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState/settings.json',
27 'Packages/Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe/LocalState/settings.json',
28 'Microsoft/Windows Terminal/settings.json',
29]
30
31const highlight = atom({ plugin: 'doki-theme-picker', key: 'highlight' } as const, '')
32const current = atom({ plugin: 'doki-theme-picker', key: 'current' } as const, '')
33// The theme whose scheme and accent were last written, for follow() when there is no accent file.
34const followed = atom({ plugin: 'doki-theme-picker', key: 'followed' } as const, '')
35
36const LIST = ordered()
37// The rows the list draws, group headers included: what the window slides over.
38type Row = { kind: 'header'; label: string } | { kind: 'theme'; theme: DokiTheme }
39const ROWS: Row[] = []
40// The header row each row sits under, so the sticky header can name the source.
41const HEADER_OF: number[] = []
42for (const source of ['doki', 'termcn'] as const) {
43 for (const dark of [true, false]) {
44 const group = LIST.filter(t => (t.source ?? 'doki') === source && t.dark === dark)
45 if (group.length === 0) continue
46 const header = ROWS.length
47 ROWS.push({ kind: 'header', label: `${source.toUpperCase()} · ${dark ? 'DARK' : 'LIGHT'} (${group.length})` })
48 HEADER_OF.push(header)
49 for (const theme of group) {
50 ROWS.push({ kind: 'theme', theme })
51 HEADER_OF.push(header)
52 }
53 }
54}
55const FALLBACK = findTheme('ram') ?? LIST[0]!
56
57// The body height the last render saw: the hooks need it to know which rows a window holds.
58let bodyRows = 30
59
60/** The rows the window draws around `slug`, one of them taken for the sticky group header. */
61function windowAround(slug: string, rows: number = bodyRows): { start: number; visible: Row[]; buttons: string[] } {
62 const size = Math.max(6, rows - PREVIEW_ROWS)
63 const rowIndex = ROWS.findIndex(row => row.kind === 'theme' && row.theme.slug === slug)
64 const start = windowStart(rowIndex, ROWS.length, size - 1)
65 const visible = ROWS.slice(start, start + size - 1)
66 const buttons = visible.flatMap(row => (row.kind === 'theme' ? [row.theme.slug] : []))
67 return { start, visible, buttons }
68}
69
70/**
71 * The ring is tracked by SLOT, not by theme. Every button is keyed `slot-<n>`, n the place among the drawn buttons.
72 * The engine keeps the ring on the same slot when the window slides, and when several keys arrive before a redraw
73 * (a burst, a fast typist) it works out each "next button" from the SLOT the ring still holds in the old drawing.
74 * Names from that old drawing are stale then (observed 2026-10-04: 8 Downs sent 8 ui.focus events that all named
75 * the same theme, so the highlight moved 1 row). A slot is the same in every drawing, so the move is
76 * (slot named) - (slot the ring is on): one Down is +1 however many redraws are still pending.
77 */
78const slotKey = (slot: number) => `slot-${slot}`
79const slotOfKey = (element: string | undefined) => {
80 const match = /^slot-(\d+)$/.exec(element ?? '')
81 return match ? Number(match[1]) : -1
82}
83/** The slot `slug` takes among the buttons of the window drawn around it. */
84const slotOfTheme = (slug: string) => windowAround(slug).buttons.indexOf(slug)
85
86// The slot the engine's ring sits on, as this module last set it or was told.
87let ringSlot = -1
88// Moves arrive one at a time: each reads the ring slot and the highlight the one before left.
89let queue: Promise<unknown> = Promise.resolve()
90function inOrder<T>(job: () => Promise<T>): Promise<T> {
91 const run = queue.then(job, job)
92 queue = run.catch(() => undefined)
93 return run
94}
95
96/** Moves the highlight to `slug`; says which slot the ring must take so it sits on that theme in the new window. */
97async function moveHighlight($: EngineInterface, slug: string): Promise<number> {
98 await update($, highlight, () => slug)
99 ringSlot = slotOfTheme(slug)
100 return ringSlot
101}
102
103async function home($: EngineInterface): Promise<string> {
104 return ((await $.env.get('USERPROFILE')) ?? (await $.env.get('HOME')) ?? '').replace(/\\/g, '/')
105}
106
107async function readOr($: EngineInterface, path: string): Promise<string | undefined> {
108 try {
109 if (!(await $.fs.exists(path))) return undefined
110 const text = await $.fs.read(path)
111 return typeof text === 'string' ? text : undefined
112 } catch {
113 return undefined
114 }
115}
116
117/** Copies a user file to ~/.claude/backups/<name>.<stamp> before it is changed. */
118async function backup($: EngineInterface, root: string, path: string, name: string, text: string): Promise<string> {
119 const target = `${root}/.claude/backups/${name}.${stamp(new Date())}`
120 await $.fs.write(target, text)
121 return target
122}
123
124/** The theme preference in the user settings.json, as `custom:doki-ram`; undefined when there is none. */
125async function currentPreference($: EngineInterface): Promise<unknown> {
126 const settings = await readOr($, `${await home($)}/.claude/settings.json`)
127 try {
128 return (JSON.parse(settings ?? '{}') as { theme?: unknown }).theme
129 } catch {
130 return undefined
131 }
132}
133
134async function currentSlug($: EngineInterface): Promise<string> {
135 return slugOfPreference(await currentPreference($))
136}
137
138/** Writes the theme everywhere it shows: Claude Code, Windows Terminal, the shared accent file. */
139async function apply($: EngineInterface, theme: DokiTheme): Promise<string[]> {
140 const root = await home($)
141 const notes: string[] = []
142 const preference = preferenceOf(theme)
143
144 // 1. The Claude Code theme file (hot-reloaded from ~/.claude/themes).
145 const themeFile = `${preference.replace(/^custom:/, '')}.json`
146 const themePath = `${root}/.claude/themes/${themeFile}`
147 const oldTheme = await readOr($, themePath)
148 if (oldTheme !== undefined) await backup($, root, themePath, themeFile, oldTheme)
149 await $.fs.write(themePath, JSON.stringify(toClaudeTheme(theme), null, 2) + '\n')
150 notes.push(`theme file ${themePath}`)
151
152 // 2. Switch Claude Code to it: the /config row first, then make sure settings.json agrees.
153 // The /config row takes only the built-in themes, so a refusal is expected; settings.json does the switch.
154 try {
155 const { deny } = await $.config.set({ key: 'theme', value: preference })
156 if (!deny) notes.push('config.set theme')
157 } catch (error) {
158 notes.push(`config.set failed (${String(error).slice(0, 80)})`)
159 }
160 const settingsPath = `${root}/.claude/settings.json`
161 const settings = await readOr($, settingsPath)
162 try {
163 if (settings === undefined) {
164 // A fresh install can have no user settings.json yet: make one that holds only the theme.
165 await $.fs.write(settingsPath, JSON.stringify({ theme: preference }, null, 2) + '\n')
166 notes.push('settings.json theme')
167 } else if ((JSON.parse(settings) as { theme?: unknown }).theme !== preference) {
168 const next = updateClaudeSettings(settings, preference)
169 await backup($, root, settingsPath, 'settings.json', settings)
170 await $.fs.write(settingsPath, next)
171 notes.push('settings.json theme')
172 }
173 } catch (error) {
174 notes.push(`settings.json skipped (${String(error).slice(0, 80)})`)
175 }
176
177 // 3 and 4. Windows Terminal and the accent file.
178 notes.push(...(await applyOutside($, root, theme)))
179
180 await update($, followed, () => theme.slug)
181 await update($, current, () => theme.slug)
182 $.ui.toast(`Theme: ${sourceLabel(theme)} ${theme.name}`)
183 return notes
184}
185
186/** What Claude Code's own theme setting does not reach: the Windows Terminal scheme and the accent file. */
187async function applyOutside($: EngineInterface, root: string, theme: DokiTheme): Promise<string[]> {
188 const notes: string[] = []
189 // 3. Windows Terminal: the scheme, set on the profile of the tab Claude Code runs in.
190 const local = ((await $.env.get('LOCALAPPDATA')) ?? '').replace(/\\/g, '/')
191 let wtPath = ''
192 let wt: string | undefined
193 for (const candidate of local ? WT_SETTINGS : []) {
194 wt = await readOr($, `${local}/${candidate}`)
195 if (wt !== undefined) {
196 wtPath = `${local}/${candidate}`
197 break
198 }
199 }
200 if (wt !== undefined) {
201 try {
202 const next = updateWtSettings(wt, toWtScheme(theme), await $.env.get('WT_PROFILE_ID'))
203 await backup($, root, wtPath, 'wt-settings.json', wt)
204 await $.fs.write(wtPath, next)
205 notes.push('Windows Terminal scheme')
206 } catch (error) {
207 notes.push(`Windows Terminal skipped (${String(error).slice(0, 80)})`)
208 }
209 } else {
210 notes.push('Windows Terminal not found, skipped')
211 }
212
213 // 4. The accent other mods draw with. Written only when ~/.claude/mods already exists, so a
214 // person without local mods gets no extra folder.
215 try {
216 if (await $.fs.exists(`${root}/.claude/mods`)) {
217 await $.fs.write(`${root}/.claude/mods/theme-accent.json`, JSON.stringify(toAccent(theme), null, 2) + '\n')
218 notes.push('accent file')
219 }
220 } catch (error) {
221 notes.push(`accent file skipped (${String(error).slice(0, 80)})`)
222 }
223 return notes
224}
225
226/**
227 * Claude Code's /theme picked a theme: if it is one of ours, bring the Windows Terminal
228 * scheme and the accent file along, so both commands leave the same result. Does nothing when the
229 * accent file already holds the theme.
230 */
231async function follow($: EngineInterface, preference: unknown): Promise<string[]> {
232 const theme = findTheme(slugOfPreference(preference))
233 if (!theme) return []
234 const root = await home($)
235 if (await $.fs.exists(`${root}/.claude/mods`)) {
236 const accent = await readOr($, `${root}/.claude/mods/theme-accent.json`)
237 if (accent === JSON.stringify(toAccent(theme), null, 2) + '\n') return []
238 } else if ((await read($, followed)) === theme.slug) {
239 // No accent file to compare with: the last theme this session followed stands in for it.
240 return []
241 }
242 const notes = await applyOutside($, root, theme)
243 await update($, followed, () => theme.slug)
244 await update($, current, () => theme.slug)
245 return notes
246}
247
248const openPicker = async ($: EngineInterface) => {
249 const now = (await read($, current)) || (await currentSlug($))
250 await update($, current, () => now)
251 const start = findTheme(now)?.slug ?? FALLBACK.slug
252 await update($, highlight, () => start)
253 ringSlot = slotOfTheme(start)
254 return $.ui.open({ id: PANE, title: 'Themes', focus: true, closeOnEscape: true, columns: 48 })
255}
256
257export const register: Register = on => {
258 on('session.start', async ($, e, next) => {
259 await update($, current, () => '')
260 const atStart = await currentSlug($)
261 await update($, followed, was => was || atStart)
262 await $.command.register({
263 name: COMMAND,
264 description: 'Pick a Doki or termcn theme for Claude Code and Windows Terminal (arrows + Enter)',
265 argumentHint: '[theme name]',
266 })
267 return next(e)
268 })
269
270 on('command.run', { command: COMMAND }, async ($, e) => {
271 const query = e.args.trim()
272 if (query) {
273 const theme = findTheme(query)
274 if (!theme) return { text: `No theme matches "${query}". Run /${COMMAND} to browse.`, exitCode: 1 }
275 const notes = await apply($, theme)
276 return { text: `Theme: ${sourceLabel(theme)} ${theme.name} (${notes.join('; ')})` }
277 }
278 const opened = await openPicker($)
279 return { text: opened.isPlaced ? 'Theme picker opened: arrows to move, Enter to apply.' : 'Theme picker is waiting for room.' }
280 })
281
282 // Claude Code's /theme writes settings.json only and raises no event (seen live 2026-10-06): check at each prompt.
283 // A slash command another plugin answers may not reach this hook; the next typed prompt does.
284 on('prompt.submit', async ($, e, next) => {
285 try {
286 await follow($, await currentPreference($))
287 } catch {
288 // Never block a prompt over a theme.
289 }
290 return next(e)
291 })
292
293 // The person's Tab, arrows or click moved the ring onto a slot: move the highlight by the slots it travelled.
294 on('ui.focus', { requestId: PANE }, async ($, e, next) => {
295 const slot = slotOfKey(e.element)
296 if (slot < 0) return next(e)
297 if (e.origin.kind !== 'person') {
298 // The first drawing's autoFocus, or this module's own redirect: the ring is where it says, unless refused.
299 const result = await next(e)
300 if (!result.deny) ringSlot = slot
301 return result
302 }
303 return inOrder(async () => {
304 const slug = (await read($, highlight)) || FALLBACK.slug
305 const from = ringSlot >= 0 ? ringSlot : slotOfTheme(slug)
306 const index = Math.max(0, LIST.findIndex(t => t.slug === slug))
307 // The engine wraps its ring past either end of the buttons it holds (a Down on the last slot lands on slot 0), and
308 // a burst can outrun a drawing that has fewer buttons than the new window: a jump of nearly a window's height
309 // is that wrap, one press in the other direction. (A click never comes here: it raises only ui.press.)
310 const wrap = Math.max(2, Math.max(6, bodyRows - PREVIEW_ROWS) - 4)
311 const travelled = slot - from <= -wrap ? 1 : slot - from >= wrap ? -1 : slot - from
312 const target = LIST[Math.max(0, Math.min(LIST.length - 1, index + travelled))]!
313 if (target.slug === slug) {
314 // Nothing to move (the end of the list, or the same slot): keep the ring where it was.
315 return next(from === slot ? e : { ...e, element: slotKey(from) })
316 }
317 const was = ringSlot
318 const to = await moveHighlight($, target.slug)
319 const result = await next({ ...e, element: slotKey(to) })
320 if (result.deny) {
321 // The engine's drawing has no such slot yet: the ring stayed. Ask again once the next drawing brings it.
322 ringSlot = was
323 void $.ui.focus({ requestId: PANE, key: slotKey(to) }).catch(() => undefined)
324 }
325 return result
326 })
327 })
328
329 // If the engine reads an arrow as a scroll (the list overflowed), move the highlight instead.
330 on('ui.scroll', { requestId: PANE }, async ($, e, next) => {
331 if (e.origin.kind !== 'person' || e.pointer !== undefined || e.by === 0) return next(e)
332 return inOrder(async () => {
333 const slug = (await read($, highlight)) || FALLBACK.slug
334 const index = Math.max(0, LIST.findIndex(t => t.slug === slug))
335 const target = LIST[Math.max(0, Math.min(LIST.length - 1, index + e.by))]!
336 const was = ringSlot
337 const to = await moveHighlight($, target.slug)
338 // Bring the ring along; a refusal leaves the highlight moved (Enter applies the highlight, not the ring).
339 // The ring then stays on its old slot: track that, so Enter there is not read as a click.
340 void $.ui
341 .focus({ requestId: PANE, key: slotKey(to) })
342 .then(result => {
343 if (result.deny && ringSlot === to) ringSlot = was
344 })
345 .catch(() => undefined)
346 return {}
347 })
348 })
349
350 on('ui.render', { component: 'Pane', requestId: PANE }, async ($, e) => {
351 const { Box, Text, Button } = $.ui.resolve(e)
352 const slug = await read($, highlight)
353 const chosen = await read($, current)
354 const theme = findTheme(slug) ?? FALLBACK
355 const c = theme.colors
356
357 let swatch = null
358 if (e.surface === 'terminal') {
359 const { Raster } = $.ui.resolve(e)
360 const strip = swatchCells(theme, 2)
361 swatch = <Raster key="swatch" columns={strip.columns} rows={strip.rows} cells={strip.cells} />
362 }
363
364 bodyRows = e.props.scroll.bodyRows
365 // One row is kept for a sticky group header, so DARK / LIGHT always shows above the window.
366 const { start, visible } = windowAround(theme.slug, bodyRows)
367 const top = visible[0]
368 const sticky = top && top.kind === 'theme' ? ROWS[HEADER_OF[start]!]! : null
369
370 let slotNumber = -1
371 return (
372 <Box flexDirection="column" paddingX={1}>
373 <Text color={c.accent} bold>
374 {sourceLabel(theme)} {theme.name} · {theme.dark ? 'dark' : 'light'}
375 {theme.slug === chosen ? ' · current' : ''}
376 </Text>
377 {swatch}
378 <Box key="mock" flexDirection="column" backgroundColor={c.bg} paddingX={1} marginTop={1}>
379 <Box flexDirection="row">
380 <Text color={c.fg} backgroundColor={c.bg}>
381 PS C:\projects>{' '}
382 </Text>
383 <Text color={c.accent} backgroundColor={c.bg}>
384 claude
385 </Text>
386 </Box>
387 <Text color={c.accent} backgroundColor={c.bg}>
388 ● Update(src/theme.ts)
389 </Text>
390 <Text color={c.red} backgroundColor={c.bg}>
391 - const theme = 'old'
392 </Text>
393 <Text color={c.green} backgroundColor={c.bg}>
394 + const theme = '{theme.slug}'
395 </Text>
396 <Text color={c.muted} backgroundColor={c.bg}>
397 ✻ Thinking…
398 </Text>
399 </Box>
400 <Text color={c.subtle}>Tab/↑↓ move · Enter/click apply · Esc close</Text>
401 <Text> </Text>
402 {sticky && sticky.kind === 'header' && (
403 <Text color={c.muted} bold>
404 {sticky.label}
405 </Text>
406 )}
407 {visible.map(row => {
408 if (row.kind !== 'header') slotNumber += 1
409 return row.kind === 'header' ? (
410 <Text color={c.muted} bold>
411 {row.label}
412 </Text>
413 ) : (
414 <Box key={`r-${slotKey(slotNumber)}`} flexDirection="row" gap={1}>
415 <Text color={row.theme.colors.accent}>██</Text>
416 <Button
417 key={slotKey(slotNumber)}
418 label={`${row.theme.slug === chosen ? '●' : ' '} ${row.theme.name}`}
419 plain
420 autoFocus={row.theme.slug === theme.slug ? true : undefined}
421 onPress={async press => {
422 // Enter presses the slot the ring is on: it applies the theme the header names (the highlight),
423 // because during a burst the row under the ring can be stale. A click raises only ui.press, for the
424 // slot clicked, with no ui.focus (observed 2026-10-06): a press off the ring is a click on this row.
425 const clicked = slotOfKey(press.element) !== ringSlot
426 const named = clicked ? row.theme : (findTheme(await read($, highlight)) ?? row.theme)
427 await apply($, named)
428 await $.ui.close({ id: PANE })
429 }}
430 />
431 </Box>
432 )
433 })}
434 </Box>
435 )
436 })
437}
438hooks/theme.ts 351 lines1// Pure conversion: a Doki theme -> Claude Code theme JSON, Windows Terminal scheme, shared accent record.
2import type { Accent, DokiTheme, TermcnRaw } from '../types'
3import { TERMCN_RAW } from './termcn-themes'
4import { THEMES as DOKI_THEMES } from './themes'
5
6export const WT_PROFILE_GUID = '{61c54bbd-c2c6-5271-96e7-009a87ff44bf}'
7
8// Doki "Ram": the default theme, and the fallback when the accent file is missing.
9export const RAM_ACCENT: Accent = {
10 name: 'Ram',
11 dark: true,
12 accent: '#e594bf',
13 accent2: '#a1e9ff',
14 muted: '#ab7b9d',
15 text: '#F8F8F2',
16 subtle: '#666879',
17}
18
19// Tokens that must stay with the daltonized (color-blind-safe) base: never overridden.
20export const PROTECTED_TOKEN = /^(diff|success$|error$)/
21
22type Rgb = [number, number, number]
23
24const parse = (hex: string): Rgb => [1, 3, 5].map(i => parseInt(hex.slice(i, i + 2), 16)) as Rgb
25const format = (rgb: readonly number[]): string =>
26 '#' + rgb.map(v => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, '0')).join('')
27
28/** Blend `a` toward `b` by `t` (0..1). */
29export function mix(a: string, b: string, t: number): string {
30 const A = parse(a)
31 const B = parse(b)
32 return format(A.map((v, i) => v + ((B[i] ?? v) - v) * t))
33}
34
35/** Shift HSL lightness by `delta` (-1..1), keeping hue and saturation. */
36export function lightness(hex: string, delta: number): string {
37 const [r, g, b] = parse(hex).map(v => v / 255) as Rgb
38 const max = Math.max(r, g, b)
39 const min = Math.min(r, g, b)
40 let h = 0
41 let s = 0
42 let l = (max + min) / 2
43 if (max !== min) {
44 const d = max - min
45 s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
46 h = max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4
47 h /= 6
48 }
49 l = Math.max(0, Math.min(1, l + delta))
50 if (s === 0) return format([l * 255, l * 255, l * 255])
51 const q = l < 0.5 ? l * (1 + s) : l + s - l * s
52 const p = 2 * l - q
53 const channel = (t: number) => {
54 if (t < 0) t += 1
55 if (t > 1) t -= 1
56 if (t < 1 / 6) return p + (q - p) * 6 * t
57 if (t < 1 / 2) return q
58 if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
59 return p
60 }
61 return format([channel(h + 1 / 3) * 255, channel(h) * 255, channel(h - 1 / 3) * 255])
62}
63
64/** Relative luminance (0..1) of a #rrggbb color. */
65export function luminance(hex: string): number {
66 const [r, g, b] = parse(hex).map(v => {
67 const s = v / 255
68 return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4
69 }) as Rgb
70 return 0.2126 * r + 0.7152 * g + 0.0722 * b
71}
72
73/** WCAG contrast ratio (1..21) between two #rrggbb colors. */
74export function contrast(a: string, b: string): number {
75 const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x) as [number, number]
76 return (hi + 0.05) / (lo + 0.05)
77}
78
79// The lowest contrast a termcn theme's subtle text gets against its background.
80// Doki themes' own subtle colors have a median of about 3.0.
81export const SUBTLE_CONTRAST = 2.5
82
83/** The first blend of bg toward fg that reaches SUBTLE_CONTRAST: dim, but still readable. */
84function readableSubtle(bg: string, fg: string): string {
85 for (let t = 0.05; t < 1; t += 0.05) {
86 const c = mix(bg, fg, t)
87 if (contrast(bg, c) >= SUBTLE_CONTRAST) return c
88 }
89 return fg
90}
91
92/** A termcn theme as the picker's theme: termcn has no ANSI palette, so the roles stand in for it. */
93export function toTermcnTheme(raw: TermcnRaw): DokiTheme {
94 const k = raw.colors
95 const dark = luminance(k.background) < 0.5
96 return {
97 name: raw.name,
98 slug: `termcn-${raw.slug}`,
99 dark,
100 source: 'termcn',
101 colors: {
102 bg: k.background,
103 fg: k.foreground,
104 accent: k.accent,
105 muted: k.mutedForeground,
106 // termcn `muted` is a background tint, not a text color: as subtle text it was near-invisible.
107 subtle: readableSubtle(k.background, k.foreground),
108 selection: k.selection,
109 widget: lightness(k.background, dark ? 0.04 : -0.04),
110 cursor: k.focusRing,
111 red: k.error,
112 green: k.success,
113 yellow: k.warning,
114 blue: k.info,
115 magenta: k.secondary,
116 cyan: k.info,
117 error: k.error,
118 interface: k.info,
119 purple: k.primary,
120 func: k.primary,
121 constant: k.success,
122 cls: k.warning,
123 bool: k.accent,
124 },
125 }
126}
127
128export const THEMES: readonly DokiTheme[] = [...DOKI_THEMES, ...TERMCN_RAW.map(toTermcnTheme)]
129
130/** The label a theme goes by in names and toasts: "Doki Ram", "termcn Dracula". */
131export const sourceLabel = (theme: DokiTheme): string => (theme.source === 'termcn' ? 'termcn' : 'Doki')
132
133/** The Claude Code theme preference for a theme: custom:doki-ram, custom:termcn-dracula. */
134export const preferenceOf = (theme: DokiTheme): string => (theme.source === 'termcn' ? `custom:${theme.slug}` : `custom:doki-${theme.slug}`)
135
136export type ClaudeTheme = { name: string; base: 'dark-daltonized' | 'light-daltonized'; overrides: Record<string, string> }
137
138/** The same tokens ~/.claude/themes/doki-ram.json sets, sourced from the theme's own colors. */
139export function toClaudeTheme(theme: DokiTheme): ClaudeTheme {
140 const c = theme.colors
141 // Dark themes lift message backgrounds toward light; light themes push them toward dark.
142 const lift = (d: number) => lightness(c.bg, theme.dark ? d : -d)
143 return {
144 name: `${sourceLabel(theme)} ${theme.name}`,
145 base: theme.dark ? 'dark-daltonized' : 'light-daltonized',
146 overrides: {
147 claude: c.accent,
148 text: c.fg,
149 inverseText: c.widget,
150 inactive: c.muted,
151 subtle: c.subtle,
152 suggestion: c.interface,
153 permission: c.purple,
154 remember: c.func,
155 warning: c.yellow,
156 merged: c.purple,
157 promptBorder: c.selection,
158 planMode: c.cyan,
159 autoAccept: c.func,
160 bashBorder: c.yellow,
161 ide: c.constant,
162 fastMode: c.cls,
163 effortUltra: c.bool,
164 userMessageBackground: lift(0.033),
165 userMessageBackgroundHover: lift(0.065),
166 bashMessageBackgroundColor: mix(c.bg, c.yellow, 0.03),
167 memoryBackgroundColor: mix(c.bg, c.purple, 0.065),
168 selectionBg: c.selection,
169 rate_limit_fill: c.accent,
170 rate_limit_empty: lift(0.08),
171 briefLabelYou: c.interface,
172 briefLabelClaude: c.accent,
173 },
174 }
175}
176
177export type WtScheme = Record<string, string>
178
179/**
180 * Windows Terminal color scheme. Doki ships 6 terminal.ansi* colors (red..cyan); the rest
181 * come from the same keys the hand-made "Doki Ram" scheme used.
182 */
183export function toWtScheme(theme: DokiTheme): WtScheme {
184 const c = theme.colors
185 const up = (hex: string) => hex.toUpperCase()
186 return {
187 name: `${sourceLabel(theme)} ${theme.name}`,
188 background: up(c.bg),
189 foreground: up(c.fg),
190 cursorColor: up(c.cursor),
191 selectionBackground: up(c.selection),
192 black: up(theme.dark ? c.widget : c.fg),
193 red: up(c.red),
194 green: up(c.green),
195 yellow: up(c.yellow),
196 blue: up(c.blue),
197 purple: up(c.func),
198 cyan: up(c.cyan),
199 white: up(theme.dark ? c.fg : c.widget),
200 brightBlack: up(c.subtle),
201 brightRed: up(c.error),
202 brightGreen: up(c.constant),
203 brightYellow: up(c.cls),
204 brightBlue: up(c.purple),
205 brightPurple: up(c.bool),
206 brightCyan: up(c.interface),
207 brightWhite: theme.dark ? '#FFFFFF' : up(c.bg),
208 }
209}
210
211export function toAccent(theme: DokiTheme): Accent {
212 const c = theme.colors
213 return { name: theme.name, dark: theme.dark, accent: c.accent, accent2: c.interface, muted: c.muted, text: c.fg, subtle: c.subtle }
214}
215
216/** Reads the accent file's text; anything missing or malformed falls back to Ram. */
217export function parseAccent(text: string | undefined): Accent {
218 try {
219 const raw = JSON.parse(text ?? '') as Partial<Accent>
220 const hex = (v: unknown, fallback: string) => (typeof v === 'string' && /^#[0-9a-fA-F]{6}$/.test(v) ? v : fallback)
221 return {
222 name: typeof raw.name === 'string' ? raw.name : RAM_ACCENT.name,
223 dark: typeof raw.dark === 'boolean' ? raw.dark : RAM_ACCENT.dark,
224 accent: hex(raw.accent, RAM_ACCENT.accent),
225 accent2: hex(raw.accent2, RAM_ACCENT.accent2),
226 muted: hex(raw.muted, RAM_ACCENT.muted),
227 text: hex(raw.text, RAM_ACCENT.text),
228 subtle: hex(raw.subtle, RAM_ACCENT.subtle),
229 }
230 } catch {
231 return RAM_ACCENT
232 }
233}
234
235/** "vanilla", "Doki Mai Dark", "mai dark", "termcn dracula", "custom:termcn-nord", or bare "nord" -> the theme. */
236export function findTheme(query: string, themes: readonly DokiTheme[] = THEMES): DokiTheme | undefined {
237 const key = query
238 .trim()
239 .toLowerCase()
240 .replace(/^custom:/, '')
241 .replace(/^doki[\s-]+/, '')
242 .replace(/[^a-z0-9]+/g, '-')
243 .replace(/^-|-$/g, '')
244 if (!key) return undefined
245 // Doki names win; a bare termcn name ("nord") is tried as "termcn-nord" after them.
246 const termcn = `termcn-${key}`
247 return (
248 themes.find(t => t.slug === key) ??
249 themes.find(t => t.slug === termcn) ??
250 themes.find(t => t.slug.startsWith(key)) ??
251 themes.find(t => t.slug.startsWith(termcn))
252 )
253}
254
255/** The slug in a theme preference ("custom:doki-ram" -> "ram", "custom:termcn-nord" -> "termcn-nord"), or "" for a built-in theme. */
256export function slugOfPreference(preference: unknown): string {
257 if (typeof preference !== 'string') return ''
258 if (preference.startsWith('custom:doki-')) return preference.slice('custom:doki-'.length)
259 return preference.startsWith('custom:termcn-') ? preference.slice('custom:'.length) : ''
260}
261
262/** Doki, then termcn; within each, dark first, then light, each by name: the order the picker lists them in. */
263export function ordered(themes: readonly DokiTheme[] = THEMES): DokiTheme[] {
264 const rank = (t: DokiTheme) => (t.source === 'termcn' ? 1 : 0)
265 return [...themes].sort((a, b) => rank(a) - rank(b) || Number(b.dark) - Number(a.dark) || a.name.localeCompare(b.name))
266}
267
268/** The first index of a `size`-row window over `count` rows that keeps `index` in its middle. */
269export function windowStart(index: number, count: number, size: number): number {
270 if (count <= size) return 0
271 const start = index - Math.floor(size / 2)
272 return Math.max(0, Math.min(count - size, start))
273}
274
275/** Gives freshly serialized `text` the line endings (CRLF or LF) and final newline (or none) of `original`. */
276export function matchStyle(original: string, text: string): string {
277 const eol = original.includes('\r\n') ? '\r\n' : '\n'
278 const body = text.replace(/\r?\n$/, '').replace(/\r?\n/g, eol)
279 return /\r?\n$/.test(original) ? body + eol : body
280}
281
282/**
283 * Adds or replaces `scheme` (by name) and points one profile at it. Returns the new file text.
284 * The profile: `current` (Windows Terminal's WT_PROFILE_ID, the tab Claude Code runs in), else the
285 * default profile (a guid or a name), else Windows PowerShell.
286 */
287export function updateWtSettings(text: string, scheme: WtScheme, current?: string | null): string {
288 const settings = JSON.parse(text) as {
289 defaultProfile?: unknown
290 schemes?: WtScheme[]
291 profiles?: { list?: Array<Record<string, unknown>> }
292 }
293 const list = settings.profiles?.list ?? []
294 const same = (a: unknown, b: unknown) => typeof a === 'string' && typeof b === 'string' && a.toLowerCase() === b.toLowerCase()
295 const profile = [current, settings.defaultProfile, WT_PROFILE_GUID]
296 .map(want => list.find(p => same(p.guid, want) || same(p.name, want)))
297 .find(p => p !== undefined)
298 if (!profile) throw new Error('Windows Terminal profile not found')
299 const schemes = (settings.schemes ?? []).filter(s => s.name !== scheme.name)
300 settings.schemes = [...schemes, scheme]
301 profile.colorScheme = scheme.name
302 return matchStyle(text, JSON.stringify(settings, null, 4))
303}
304
305/**
306 * Sets the top-level "theme" key of Claude Code's settings.json text. Edits that one line in place
307 * when it can (a one-line diff); otherwise re-serializes in the file's own line endings.
308 */
309export function updateClaudeSettings(text: string, preference: string): string {
310 const line = /^( {2}"theme"\s*:\s*)"(?:[^"\\\r\n]|\\.)*"/gm
311 if ((text.match(line) ?? []).length === 1) {
312 const edited = text.replace(line, (_all, head: string) => `${head}${JSON.stringify(preference)}`)
313 try {
314 if ((JSON.parse(edited) as { theme?: unknown }).theme === preference) return edited
315 } catch {
316 // fall through to a full rewrite
317 }
318 }
319 const settings = JSON.parse(text) as Record<string, unknown>
320 settings.theme = preference
321 return matchStyle(text, JSON.stringify(settings, null, 2))
322}
323
324/**
325 * A Raster strip of the theme's colors: row 1 the UI colors, row 2 the terminal colors.
326 * Each swatch is `width` full-block cells in that color.
327 */
328export function swatchCells(theme: DokiTheme, width = 2): { columns: number; rows: number; cells: string } {
329 const c = theme.colors
330 const rows = [
331 [c.bg, c.fg, c.accent, c.muted, c.subtle, c.selection, c.interface, c.purple],
332 [c.red, c.green, c.yellow, c.blue, c.func, c.cyan, c.constant, c.cls],
333 ]
334 const columns = rows[0]!.length * width
335 const words: number[] = []
336 for (const row of rows) {
337 for (const hex of row) {
338 const color = parseInt(hex.slice(1, 7), 16)
339 for (let i = 0; i < width; i++) words.push(0x2588, color, 0x01000000)
340 }
341 }
342 const bytes = new Uint8Array(new Uint32Array(words).buffer)
343 let binary = ''
344 for (const b of bytes) binary += String.fromCharCode(b)
345 return { columns, rows: rows.length, cells: btoa(binary) }
346}
347
348export function stamp(date: Date): string {
349 return date.toISOString().replace(/[:.]/g, '-')
350}
351hooks/termcn-themes.ts 47 lines1// Generated by scripts/build-termcn.mjs from the termcn registry (https://termcn.dev/r/registry.json).
2// Source: https://github.com/shadcn-labs/termcn - licence: MIT (Copyright (c) 2026 Aniket Pawar). Do not edit by hand.
3import type { TermcnRaw } from '../types'
4
5export const TERMCN_RAW: readonly TermcnRaw[] = [
6 {"name":"AMOLED","slug":"amoled","colors":{"accent":"#ff4081","background":"#000000","error":"#ff1744","focusRing":"#b388ff","foreground":"#ffffff","info":"#18ffff","muted":"#1a1a1a","mutedForeground":"#888888","primary":"#b388ff","secondary":"#333333","selection":"#b388ff","success":"#00ff88","warning":"#ffea00"}},
7 {"name":"Aura","slug":"aura","colors":{"accent":"#ff6767","background":"#15141b","error":"#ff6767","focusRing":"#a277ff","foreground":"#edecee","info":"#82e2ff","muted":"#242329","mutedForeground":"#6d6a7e","primary":"#a277ff","secondary":"#2a2834","selection":"#a277ff","success":"#61ffca","warning":"#ffca85"}},
8 {"name":"Ayu","slug":"ayu","colors":{"accent":"#f2856f","background":"#0f1419","error":"#f58572","focusRing":"#3fb7e3","foreground":"#d6dae0","info":"#66c6f1","muted":"#1e2229","mutedForeground":"#5a6673","primary":"#3fb7e3","secondary":"#242a33","selection":"#3fb7e3","success":"#78d05c","warning":"#e4a75c"}},
9 {"name":"Carbonfox","slug":"carbonfox","colors":{"accent":"#ff8389","background":"#393939","error":"#ff8389","focusRing":"#be95ff","foreground":"#f2f4f8","info":"#78a9ff","muted":"#2d2d2d","mutedForeground":"#6f6f6f","primary":"#33b1ff","secondary":"#454545","selection":"#33b1ff","success":"#42be65","warning":"#f1c21b"}},
10 {"name":"Catppuccin","slug":"catppuccin","colors":{"accent":"#F38BA8","background":"#1E1E2E","error":"#F38BA8","focusRing":"#CBA6F7","foreground":"#CDD6F4","info":"#89B4FA","muted":"#313244","mutedForeground":"#6C7086","primary":"#CBA6F7","secondary":"#89B4FA","selection":"#313244","success":"#A6E3A1","warning":"#F9E2AF"}},
11 {"name":"Catppuccin Frappe","slug":"catppuccin-frappe","colors":{"accent":"#f4b8e4","background":"#303446","error":"#e78284","focusRing":"#ca9ee6","foreground":"#c6d0f5","info":"#81c8be","muted":"#232330","mutedForeground":"#949cb8","primary":"#8da4e2","secondary":"#414559","selection":"#8da4e2","success":"#a6d189","warning":"#e5c890"}},
12 {"name":"Catppuccin Macchiato","slug":"catppuccin-macchiato","colors":{"accent":"#f5bde6","background":"#24273a","error":"#ed8796","focusRing":"#c6a0f6","foreground":"#cad3f5","info":"#8bd5ca","muted":"#1b1e2b","mutedForeground":"#939ab7","primary":"#8aadf4","secondary":"#363a4f","selection":"#8aadf4","success":"#a6da95","warning":"#eed49f"}},
13 {"name":"Cobalt2","slug":"cobalt2","colors":{"accent":"#2affdf","background":"#193549","error":"#ff0088","focusRing":"#2affdf","foreground":"#ffffff","info":"#ff9d00","muted":"#0d1b2a","mutedForeground":"#adb7c9","primary":"#0088ff","secondary":"#284156","selection":"#0088ff","success":"#9eff80","warning":"#ffc600"}},
14 {"name":"Cursor","slug":"cursor","colors":{"accent":"#88c0d0","background":"#181818","error":"#e34671","focusRing":"#82d2ce","foreground":"#e4e4e4","info":"#81a1c1","muted":"#0d0d0d","mutedForeground":"#636363","primary":"#88c0d0","secondary":"#242424","selection":"#88c0d0","success":"#3fa266","warning":"#f1b467"}},
15 {"name":"Default","slug":"default","colors":{"accent":"#8B5CF6","background":"#000000","error":"#EF4444","focusRing":"#8B5CF6","foreground":"#FFFFFF","info":"#3B82F6","muted":"#374151","mutedForeground":"#9CA3AF","primary":"#7C3AED","secondary":"#6B7280","selection":"#7C3AED","success":"#10B981","warning":"#F59E0B"}},
16 {"name":"Dracula","slug":"dracula","colors":{"accent":"#FF79C6","background":"#282A36","error":"#FF5555","focusRing":"#BD93F9","foreground":"#F8F8F2","info":"#8BE9FD","muted":"#44475A","mutedForeground":"#6272A4","primary":"#BD93F9","secondary":"#6272A4","selection":"#44475A","success":"#50FA7B","warning":"#F1FA8C"}},
17 {"name":"Everforest","slug":"everforest","colors":{"accent":"#d699b6","background":"#2d353b","error":"#e67e80","focusRing":"#d699b6","foreground":"#d3c6aa","info":"#83c092","muted":"#1f252a","mutedForeground":"#7a8478","primary":"#a7c080","secondary":"#373e44","selection":"#a7c080","success":"#a7c080","warning":"#e69875"}},
18 {"name":"Flexoki","slug":"flexoki","colors":{"accent":"#8b7ec8","background":"#100f0f","error":"#d14d41","focusRing":"#879a39","foreground":"#cecdc3","info":"#3aa99f","muted":"#0a0a0a","mutedForeground":"#6f6e69","primary":"#da702c","secondary":"#1a1916","selection":"#da702c","success":"#879a39","warning":"#da702c"}},
19 {"name":"GitHub","slug":"github","colors":{"accent":"#39c5cf","background":"#0d1117","error":"#f85149","focusRing":"#58a6ff","foreground":"#c9d1d9","info":"#d29922","muted":"#161b22","mutedForeground":"#8b949e","primary":"#58a6ff","secondary":"#21262d","selection":"#58a6ff","success":"#3fb950","warning":"#e3b341"}},
20 {"name":"Gruvbox","slug":"gruvbox","colors":{"accent":"#fb4934","background":"#282828","error":"#fb4934","focusRing":"#fb4934","foreground":"#ebdbb2","info":"#d3869b","muted":"#1d2021","mutedForeground":"#928374","primary":"#83a598","secondary":"#32302f","selection":"#83a598","success":"#b8bb26","warning":"#fabd2f"}},
21 {"name":"High Contrast","slug":"high-contrast","colors":{"accent":"#00FFFF","background":"#000000","error":"#FF4444","focusRing":"#FFFF00","foreground":"#FFFFFF","info":"#00CCFF","muted":"#1A1A1A","mutedForeground":"#CCCCCC","primary":"#FFFFFF","secondary":"#FFFF00","selection":"#FFFFFF","success":"#00FF00","warning":"#FFFF00"}},
22 {"name":"High Contrast Light","slug":"high-contrast-light","colors":{"accent":"#004499","background":"#FFFFFF","error":"#CC0000","focusRing":"#0000CC","foreground":"#000000","info":"#004499","muted":"#F0F0F0","mutedForeground":"#444444","primary":"#000000","secondary":"#6600CC","selection":"#000000","success":"#006600","warning":"#884400"}},
23 {"name":"Kanagawa","slug":"kanagawa","colors":{"accent":"#d27e99","background":"#1f1f28","error":"#e82424","focusRing":"#957fbb","foreground":"#dcd7ba","info":"#76946a","muted":"#16161f","mutedForeground":"#727169","primary":"#7e9cd8","secondary":"#292a3f","selection":"#7e9cd8","success":"#98bb6c","warning":"#d7a657"}},
24 {"name":"Lucent Orng","slug":"lucent-orng","colors":{"accent":"#fff7f1","background":"#2a1a15","error":"#e06c75","focusRing":"#ec5b2b","foreground":"#eeeeee","info":"#56b6c2","muted":"#1a100d","mutedForeground":"#808080","primary":"#ec5b2b","secondary":"#3d2521","selection":"#ec5b2b","success":"#6ba1e6","warning":"#ec5b2b"}},
25 {"name":"Material","slug":"material","colors":{"accent":"#89ddff","background":"#263238","error":"#f07178","focusRing":"#c792ea","foreground":"#eeffff","info":"#ffcb6b","muted":"#1a2327","mutedForeground":"#546e7a","primary":"#82aaff","secondary":"#37474f","selection":"#82aaff","success":"#c3e88d","warning":"#ffcb6b"}},
26 {"name":"Matrix","slug":"matrix","colors":{"accent":"#c770ff","background":"#0a0e0a","error":"#ff4b4b","focusRing":"#c770ff","foreground":"#62ff94","info":"#30b3ff","muted":"#050805","mutedForeground":"#8ca391","primary":"#2eff6a","secondary":"#0f140f","selection":"#2eff6a","success":"#62ff94","warning":"#e6ff57"}},
27 {"name":"Mercury","slug":"mercury","colors":{"accent":"#8da4f5","background":"#171721","error":"#fc92b4","focusRing":"#8da4f5","foreground":"#dddde5","info":"#77becf","muted":"#101018","mutedForeground":"#9d9da8","primary":"#8da4f5","secondary":"#1e1e28","selection":"#8da4f5","success":"#77c599","warning":"#fc9b6f"}},
28 {"name":"Monokai","slug":"monokai","colors":{"accent":"#FD971F","background":"#272822","error":"#F92672","focusRing":"#A6E22E","foreground":"#F8F8F2","info":"#66D9E8","muted":"#3E3D32","mutedForeground":"#75715E","primary":"#A6E22E","secondary":"#66D9E8","selection":"#49483E","success":"#A6E22E","warning":"#E6DB74"}},
29 {"name":"Night Owl","slug":"night-owl","colors":{"accent":"#f78c6c","background":"#011627","error":"#ef5350","focusRing":"#c792ea","foreground":"#d6deeb","info":"#82aaff","muted":"#010c15","mutedForeground":"#637777","primary":"#82aaff","secondary":"#021a2b","selection":"#82aaff","success":"#c5e478","warning":"#ecc48d"}},
30 {"name":"Nord","slug":"nord","colors":{"accent":"#81A1C1","background":"#2E3440","error":"#BF616A","focusRing":"#88C0D0","foreground":"#ECEFF4","info":"#5E81AC","muted":"#3B4252","mutedForeground":"#4C566A","primary":"#88C0D0","secondary":"#4C566A","selection":"#3B4252","success":"#A3BE8C","warning":"#EBCB8B"}},
31 {"name":"OC-2","slug":"oc-2","colors":{"accent":"#edb2f1","background":"#1f1f1f","error":"#fc533a","focusRing":"#edb2f1","foreground":"#f1ece8","info":"#edb2f1","muted":"#141414","mutedForeground":"#707070","primary":"#fab283","secondary":"#262626","selection":"#fab283","success":"#12c905","warning":"#fcd53a"}},
32 {"name":"One Dark","slug":"one-dark","colors":{"accent":"#C678DD","background":"#282C34","error":"#E06C75","focusRing":"#61AFEF","foreground":"#ABB2BF","info":"#56B6C2","muted":"#3E4451","mutedForeground":"#5C6370","primary":"#61AFEF","secondary":"#C678DD","selection":"#3E4451","success":"#98C379","warning":"#E5C07B"}},
33 {"name":"One Dark Pro","slug":"one-dark-pro","colors":{"accent":"#e06c75","background":"#1e222a","error":"#e06c75","focusRing":"#c678dd","foreground":"#abb2bf","info":"#56b6c2","muted":"#15181f","mutedForeground":"#5c6370","primary":"#61afef","secondary":"#2c313a","selection":"#61afef","success":"#98c379","warning":"#e5c07b"}},
34 {"name":"OpenCode","slug":"opencode","colors":{"accent":"#9d7cd8","background":"#0a0a0a","error":"#e06c75","focusRing":"#9d7cd8","foreground":"#eeeeee","info":"#56b6c2","muted":"#050505","mutedForeground":"#808080","primary":"#fab283","secondary":"#151515","selection":"#fab283","success":"#7fd88f","warning":"#f5a742"}},
35 {"name":"Orng","slug":"orng","colors":{"accent":"#fff7f1","background":"#0a0a0a","error":"#e06c75","focusRing":"#ec5b2b","foreground":"#eeeeee","info":"#56b6c2","muted":"#050505","mutedForeground":"#808080","primary":"#ec5b2b","secondary":"#151515","selection":"#ec5b2b","success":"#6ba1e6","warning":"#ec5b2b"}},
36 {"name":"Osaka Jade","slug":"osaka-jade","colors":{"accent":"#549e6a","background":"#111c18","error":"#ff5345","focusRing":"#2dd5b7","foreground":"#c1c497","info":"#2dd5b7","muted":"#0a110f","mutedForeground":"#53685b","primary":"#2dd5b7","secondary":"#1a2921","selection":"#2dd5b7","success":"#549e6a","warning":"#e5c736"}},
37 {"name":"Palenight","slug":"palenight","colors":{"accent":"#89ddff","background":"#292d3e","error":"#f07178","focusRing":"#c792ea","foreground":"#a6accd","info":"#f78c6c","muted":"#1e2130","mutedForeground":"#676e95","primary":"#82aaff","secondary":"#383d4f","selection":"#82aaff","success":"#c3e88d","warning":"#ffcb6b"}},
38 {"name":"Rose Pine","slug":"rose-pine","colors":{"accent":"#ebbcba","background":"#191724","error":"#eb6f92","focusRing":"#31748f","foreground":"#e0def4","info":"#9ccfd8","muted":"#100f18","mutedForeground":"#6e6a86","primary":"#9ccfd8","secondary":"#262330","selection":"#9ccfd8","success":"#31748f","warning":"#f6c177"}},
39 {"name":"Shades of Purple","slug":"shades-of-purple","colors":{"accent":"#FF628C","background":"#2D2B55","error":"#EC3A37","focusRing":"#4D21FC","foreground":"#A599E9","info":"#9EFFFF","muted":"#1E1E3F","mutedForeground":"#B362FF","primary":"#FB94FF","secondary":"#1E1E3F","selection":"#4D21FC","success":"#3AD900","warning":"#FF9D00"}},
40 {"name":"Solarized","slug":"solarized","colors":{"accent":"#CB4B16","background":"#002B36","error":"#DC322F","focusRing":"#268BD2","foreground":"#839496","info":"#2AA198","muted":"#073642","mutedForeground":"#586E75","primary":"#268BD2","secondary":"#2AA198","selection":"#073642","success":"#859900","warning":"#B58900"}},
41 {"name":"Synthwave '84","slug":"synthwave-84","colors":{"accent":"#b084eb","background":"#262335","error":"#fe4450","focusRing":"#ff7edb","foreground":"#ffffff","info":"#ff8b39","muted":"#1a1a24","mutedForeground":"#848bbd","primary":"#36f9f6","secondary":"#35334a","selection":"#36f9f6","success":"#72f1b8","warning":"#fede5d"}},
42 {"name":"Tokyo Night","slug":"tokyo-night","colors":{"accent":"#BB9AF7","background":"#24283B","error":"#F7768E","focusRing":"#7AA2F7","foreground":"#C0CAF5","info":"#7DCFFF","muted":"#1F2335","mutedForeground":"#565F89","primary":"#7AA2F7","secondary":"#BB9AF7","selection":"#364A82","success":"#9ECE6A","warning":"#E0AF68"}},
43 {"name":"Vercel","slug":"vercel","colors":{"accent":"#8e4ec6","background":"#000000","error":"#e5484d","focusRing":"#f75590","foreground":"#ededed","info":"#52a8ff","muted":"#0a0a0a","mutedForeground":"#878787","primary":"#0070f3","secondary":"#1a1a1a","selection":"#0070f3","success":"#46a758","warning":"#ffb224"}},
44 {"name":"Vesper","slug":"vesper","colors":{"accent":"#ff8080","background":"#101010","error":"#ff8080","focusRing":"#a0a0a0","foreground":"#ffffff","info":"#ffc799","muted":"#080808","mutedForeground":"#8b8b8b","primary":"#ffc799","secondary":"#181818","selection":"#ffc799","success":"#99ffe4","warning":"#ffc799"}},
45 {"name":"Zenburn","slug":"zenburn","colors":{"accent":"#93e0e3","background":"#3f3f3f","error":"#cc9393","focusRing":"#f0dfaf","foreground":"#dcdccc","info":"#dfaf8f","muted":"#2f2f2f","mutedForeground":"#9f9f9f","primary":"#8cd0d3","secondary":"#4f4f4f","selection":"#8cd0d3","success":"#7f9f7f","warning":"#f0dfaf"}},
46]
47hooks/themes.ts 94 lines1// Generated by scripts/build-themes.mjs from unthrottled.doki-theme-88.1.18. Do not edit by hand.
2import type { DokiTheme } from '../types'
3
4export const THEMES: readonly DokiTheme[] = [
5 {"name":"Aqua","slug":"aqua","dark":true,"colors":{"bg":"#262940","fg":"#F8F8F2","accent":"#578CDA","muted":"#7b8bab","subtle":"#61647b","selection":"#4C637A","widget":"#2a2d44","cursor":"#578CDA","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#f4fa8c","purple":"#6893f3","func":"#578CDA","constant":"#48ffd6","cls":"#8dc6ef","bool":"#988F9A"}},
6 {"name":"Astolfo","slug":"astolfo","dark":true,"colors":{"bg":"#1a1c19","fg":"#F8F8F2","accent":"#d58d9c","muted":"#957a4d","subtle":"#8e856e","selection":"#501C1C","widget":"#181917","cursor":"#d58d9c","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#cd5257","purple":"#f6ebb7","func":"#efa554","constant":"#a7a0d1","cls":"#f5c9fc","bool":"#d776ae"}},
7 {"name":"Asuna Dark","slug":"asuna-dark","dark":true,"colors":{"bg":"#1b1b1b","fg":"#F8F8F2","accent":"#99202c","muted":"#7a3f41","subtle":"#5d5051","selection":"#531616","widget":"#1e1e1e","cursor":"#99202c","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#FFD86E","purple":"#FCA57E","func":"#579DFA","constant":"#86dbfd","cls":"#7ECAFA","bool":"#e0474b"}},
8 {"name":"Azuki","slug":"azuki","dark":true,"colors":{"bg":"#2e221f","fg":"#F8F8F2","accent":"#e9b14e","muted":"#b0a17f","subtle":"#6c635a","selection":"#684e29","widget":"#2d221f","cursor":"#e9b14e","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#e0f6bf","purple":"#96f3fd","func":"#ffe845","constant":"#efacfc","cls":"#c4ff8d","bool":"#ffad46"}},
9 {"name":"Chocola","slug":"chocola","dark":true,"colors":{"bg":"#2c2729","fg":"#F8F8F2","accent":"#f771a3","muted":"#b0a17f","subtle":"#6c5a63","selection":"#6a3849","widget":"#2c2428","cursor":"#f771a3","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#F6E9CB","purple":"#48eae4","func":"#f689f6","constant":"#96b7fb","cls":"#f8835f","bool":"#FF357C"}},
10 {"name":"Christmas Chocola","slug":"christmas-chocola","dark":true,"colors":{"bg":"#3a141d","fg":"#F8F8F2","accent":"#FFFFFE","muted":"#56b36f","subtle":"#6d816c","selection":"#1f422d","widget":"#37131b","cursor":"#FFFFFE","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff1212","interface":"#ffe3cd","purple":"#ebc190","func":"#f16e7f","constant":"#96b7fb","cls":"#e3ecf8","bool":"#f06b7e"}},
11 {"name":"Cinnamon","slug":"cinnamon","dark":true,"colors":{"bg":"#343277","fg":"#F8F8F2","accent":"#54e255","muted":"#dfe19f","subtle":"#ffffff","selection":"#3a6c75","widget":"#37357f","cursor":"#54e255","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#b3a9ff","purple":"#FFD448","func":"#60ff62","constant":"#8bc1f8","cls":"#d0a2fa","bool":"#53dac7"}},
12 {"name":"Coconut","slug":"coconut","dark":true,"colors":{"bg":"#312b3a","fg":"#F8F8F2","accent":"#d2b503","muted":"#b0a17f","subtle":"#605a6c","selection":"#255b82","widget":"#312c3a","cursor":"#d2b503","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F6E9CB","purple":"#48eae4","func":"#9bf8ff","constant":"#50b5d1","cls":"#f689f6","bool":"#b897f6"}},
13 {"name":"Darkness Dark","slug":"darkness-dark","dark":true,"colors":{"bg":"#0a0904","fg":"#F8F8F2","accent":"#e99745","muted":"#7c7262","subtle":"#666879","selection":"#553919","widget":"#090802","cursor":"#e99745","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#4593f5","purple":"#3492b1","func":"#f4fa8c","constant":"#86dbfd","cls":"#d53a4a","bool":"#ffba2f"}},
14 {"name":"Echidna","slug":"echidna","dark":true,"colors":{"bg":"#121014","fg":"#F8F8F2","accent":"#ECECEC","muted":"#75aaab","subtle":"#6f7779","selection":"#274540","widget":"#171519","cursor":"#ECECEC","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#f4fa8c","purple":"#BD93F9","func":"#7ceec8","constant":"#86dbfd","cls":"#EFA554","bool":"#8b8b8b"}},
15 {"name":"Emilia Dark","slug":"emilia-dark","dark":true,"colors":{"bg":"#492d5a","fg":"#F8F8F2","accent":"#a53ba0","muted":"#a775ab","subtle":"#666879","selection":"#5C3378","widget":"#4c2e5c","cursor":"#a53ba0","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#FDEFA2","purple":"#C1A2F8","func":"#AE7BFF","constant":"#FFB9A7","cls":"#FF9CD6","bool":"#EF69C3"}},
16 {"name":"Essex","slug":"essex","dark":true,"colors":{"bg":"#001d39","fg":"#F8F8F2","accent":"#D53232","muted":"#ad9e6e","subtle":"#5d7685","selection":"#480F0F","widget":"#00203e","cursor":"#D53232","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff0505","interface":"#f3b085","purple":"#eec45e","func":"#2D96EA","constant":"#78DBEF","cls":"#B5AAEE","bool":"#EE4C4C"}},
17 {"name":"Gasai Yuno","slug":"gasai-yuno","dark":true,"colors":{"bg":"#150713","fg":"#F8F8F2","accent":"#ffa0b2","muted":"#ab5555","subtle":"#796675","selection":"#602b50","widget":"#1a0717","cursor":"#ffa0b2","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F6E3CC","purple":"#39e6a6","func":"#efa2da","constant":"#34a7d1","cls":"#EFA554","bool":"#e0474b"}},
18 {"name":"Genos","slug":"genos","dark":true,"colors":{"bg":"#313234","fg":"#F8F8F2","accent":"#ddc7a1","muted":"#ad9e6e","subtle":"#80755d","selection":"#605d51","widget":"#252627","cursor":"#ddc7a1","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#FF984B","purple":"#FFE35C","func":"#8dff4b","constant":"#EA7777","cls":"#B39CFF","bool":"#8ACAFF"}},
19 {"name":"Gray","slug":"gray","dark":true,"colors":{"bg":"#35393b","fg":"#F8F8F2","accent":"#4ed4b0","muted":"#b0a17f","subtle":"#556c6a","selection":"#295043","widget":"#363b3d","cursor":"#4ed4b0","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F6E9CB","purple":"#61ead9","func":"#84D0FF","constant":"#ec9cb2","cls":"#89acf6","bool":"#9f73ea"}},
20 {"name":"Hanekawa Tsubasa","slug":"hanekawa-tsubasa","dark":true,"colors":{"bg":"#100d11","fg":"#F8F8F2","accent":"#7660A4","muted":"#988ccb","subtle":"#777495","selection":"#5a3b5d","widget":"#0f0d10","cursor":"#7660A4","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F6E3CC","purple":"#7ceec8","func":"#9a97f4","constant":"#86dbfd","cls":"#e39656","bool":"#d55fde"}},
21 {"name":"Hatsune Miku","slug":"hatsune-miku","dark":true,"colors":{"bg":"#2f3635","fg":"#F8F8F2","accent":"#53b0b4","muted":"#73999b","subtle":"#666879","selection":"#4c7a76","widget":"#2c3333","cursor":"#53b0b4","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#B5F6BA","purple":"#95C8FA","func":"#FF9CEA","constant":"#86dbfd","cls":"#F6E9CB","bool":"#7BF8E1"}},
22 {"name":"Hayase Nagatoro","slug":"hayase-nagatoro","dark":true,"colors":{"bg":"#151515","fg":"#F8F8F2","accent":"#d2824e","muted":"#7e5b37","subtle":"#5d5550","selection":"#5d3e2f","widget":"#1a1a1a","cursor":"#d2824e","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#95acbd","purple":"#5cd7d7","func":"#E3A70E","constant":"#d776ae","cls":"#D233A2","bool":"#6d7fd4"}},
23 {"name":"Hinata Shoyo","slug":"hinata-shoyo","dark":true,"colors":{"bg":"#201c37","fg":"#F8F8F2","accent":"#f58d02","muted":"#ba804b","subtle":"#55596c","selection":"#6a473d","widget":"#24203c","cursor":"#f58d02","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#FFC32F","purple":"#84D0FF","func":"#49FF51","constant":"#ec9cb2","cls":"#61ead9","bool":"#ab77ff"}},
24 {"name":"Hiro","slug":"hiro","dark":true,"colors":{"bg":"#16171A","fg":"#F8F8F2","accent":"#3877d1","muted":"#8ad0bf","subtle":"#4F5D76","selection":"#1d4a88","widget":"#16171a","cursor":"#3877d1","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff0000","interface":"#FDB8EB","purple":"#89CCEC","func":"#61ead9","constant":"#83F57F","cls":"#EA517A","bool":"#6a96e9"}},
25 {"name":"Hiro x Zero Two","slug":"hiro-x-zero-two","dark":true,"colors":{"bg":"#150b24","fg":"#F8F8F2","accent":"#c93939","muted":"#5d89c2","subtle":"#5F4E65","selection":"#29466c","widget":"#0f071a","cursor":"#c93939","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#7EACF8","purple":"#FF96FD","func":"#b68cfd","constant":"#9CA2FF","cls":"#5FFF9F","bool":"#ec377e"}},
26 {"name":"Ishtar Dark","slug":"ishtar-dark","dark":true,"colors":{"bg":"#110F10","fg":"#F8F8F2","accent":"#f5c443","muted":"#866e45","subtle":"#6c6d5b","selection":"#553919","widget":"#0d0b0c","cursor":"#f5c443","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#a18649","purple":"#357fbf","func":"#f5c443","constant":"#86dbfd","cls":"#7C7C82","bool":"#db974d"}},
27 {"name":"Jabami Yumeko","slug":"jabami-yumeko","dark":true,"colors":{"bg":"#050000","fg":"#F8F8F2","accent":"#8a1820","muted":"#7e2a2a","subtle":"#97706f","selection":"#390c10","widget":"#0b0000","cursor":"#8a1820","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F6E3CC","purple":"#42E66C","func":"#b48fec","constant":"#e4ff10","cls":"#7092ea","bool":"#e0474b"}},
28 {"name":"Jahy","slug":"jahy","dark":true,"colors":{"bg":"#1b102e","fg":"#F8F8F2","accent":"#874488","muted":"#ad9e6e","subtle":"#656079","selection":"#452346","widget":"#1e1430","cursor":"#874488","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#f3b085","purple":"#eec45e","func":"#9581EC","constant":"#EA7797","cls":"#E77FD5","bool":"#D53232"}},
29 {"name":"Kanna","slug":"kanna","dark":true,"colors":{"bg":"#1a1426","fg":"#F8F8F2","accent":"#46459e","muted":"#9d79c2","subtle":"#6a6679","selection":"#492744","widget":"#1a1526","cursor":"#46459e","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#FAF7BA","purple":"#FF357C","func":"#69ecf5","constant":"#86dbfd","cls":"#6AADFF","bool":"#d285fd"}},
30 {"name":"Katsuragi Misato","slug":"katsuragi-misato","dark":true,"colors":{"bg":"#382536","fg":"#F8F8F2","accent":"#c2383e","muted":"#8c72a9","subtle":"#666879","selection":"#5a293f","widget":"#3d2536","cursor":"#c2383e","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#FAF7BA","purple":"#FF357C","func":"#42E66C","constant":"#86dbfd","cls":"#6AADFF","bool":"#BD84DD"}},
31 {"name":"Kirino","slug":"kirino","dark":true,"colors":{"bg":"#121e1c","fg":"#F8F8F2","accent":"#6cb3b5","muted":"#b0a17f","subtle":"#657978","selection":"#3d213e","widget":"#121e1c","cursor":"#6cb3b5","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#F6E9CB","purple":"#eec45e","func":"#8bd9ff","constant":"#EA7797","cls":"#E77FD5","bool":"#49e7d0"}},
32 {"name":"Konata","slug":"konata","dark":true,"colors":{"bg":"#355082","fg":"#F8F8F2","accent":"#4bcf4c","muted":"#addfa9","subtle":"#ffffff","selection":"#3a6c75","widget":"#314978","cursor":"#4bcf4c","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#fc9ee6","purple":"#fffd9b","func":"#60ff62","constant":"#f6be8b","cls":"#cda8fa","bool":"#ffc9d7"}},
33 {"name":"Mai Dark","slug":"mai-dark","dark":true,"colors":{"bg":"#242448","fg":"#F8F8F2","accent":"#fee3cf","muted":"#7cab9c","subtle":"#61647b","selection":"#235161","widget":"#25254e","cursor":"#fee3cf","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#EFA554","purple":"#F9B2FF","func":"#b772de","constant":"#FFEEA6","cls":"#61dba0","bool":"#50cefb"}},
34 {"name":"Maika","slug":"maika","dark":true,"colors":{"bg":"#24062f","fg":"#F8F8F2","accent":"#bc5d71","muted":"#79b7c1","subtle":"#70677b","selection":"#3d1535","widget":"#20052a","cursor":"#bc5d71","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#e09cf3","purple":"#f6e7ba","func":"#55daff","constant":"#86dbfd","cls":"#50cefb","bool":"#e42b54"}},
35 {"name":"Makise Kurisu","slug":"makise-kurisu","dark":true,"colors":{"bg":"#170a0b","fg":"#F8F8F2","accent":"#8F60B5","muted":"#843030","subtle":"#624849","selection":"#391717","widget":"#1a0e0e","cursor":"#8F60B5","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF0000","interface":"#4593f5","purple":"#FF8C74","func":"#DEC4AA","constant":"#86dbfd","cls":"#EC5D61","bool":"#BD93F9"}},
36 {"name":"Maple Dark","slug":"maple-dark","dark":true,"colors":{"bg":"#2d1d1d","fg":"#F8F8F2","accent":"#46ab79","muted":"#bfb38c","subtle":"#6c5b55","selection":"#295043","widget":"#2f1b1b","cursor":"#46ab79","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#F6E9CB","purple":"#4fe1a9","func":"#ad8cee","constant":"#ec93a1","cls":"#ee7fdc","bool":"#FFD448"}},
37 {"name":"Megumin","slug":"megumin","dark":true,"colors":{"bg":"#2c2126","fg":"#F8F8F2","accent":"#a73035","muted":"#75595d","subtle":"#7b7373","selection":"#563036","widget":"#2a1f24","cursor":"#a73035","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#ffd866","purple":"#BA6462","func":"#e4ff10","constant":"#FC79BB","cls":"#FF8A5F","bool":"#a28a92"}},
38 {"name":"Miia","slug":"miia","dark":true,"colors":{"bg":"#310e19","fg":"#F8F8F2","accent":"#d6a53e","muted":"#b19e78","subtle":"#a87975","selection":"#5b3225","widget":"#3a1020","cursor":"#d6a53e","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#e2d9bd","purple":"#c05388","func":"#efa2da","constant":"#34a7d1","cls":"#FFB86C","bool":"#39e6a6"}},
39 {"name":"Mioda Ibuki Dark","slug":"mioda-ibuki-dark","dark":true,"colors":{"bg":"#191b1d","fg":"#F8F8F2","accent":"#5395b4","muted":"#ab8d9f","subtle":"#666879","selection":"#452735","widget":"#17191b","cursor":"#5395b4","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#f4fa8c","purple":"#5ea7ff","func":"#ff69df","constant":"#86dbfd","cls":"#8daeef","bool":"#8b8b8b"}},
40 {"name":"Misaka Mikoto","slug":"misaka-mikoto","dark":true,"colors":{"bg":"#0b173a","fg":"#F8F8F2","accent":"#3eb7e5","muted":"#70bfbc","subtle":"#5d6680","selection":"#05649c","widget":"#0b1633","cursor":"#3eb7e5","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#A2EEFC","purple":"#FFE35C","func":"#f3b085","constant":"#EA7797","cls":"#8BEF85","bool":"#57e1ee"}},
41 {"name":"Monika Dark","slug":"monika-dark","dark":true,"colors":{"bg":"#1d2115","fg":"#F8F8F2","accent":"#388E3C","muted":"#3b753d","subtle":"#697966","selection":"#30432B","widget":"#1D2115","cursor":"#388E3C","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#94CFFF","purple":"#ABFFAF","func":"#60E769","constant":"#FF8FCA","cls":"#FFEA82","bool":"#3eae5d"}},
42 {"name":"Nadeshiko","slug":"nadeshiko","dark":true,"colors":{"bg":"#2c1f26","fg":"#F8F8F2","accent":"#78c6d0","muted":"#7ea5c1","subtle":"#6a5a6c","selection":"#553854","widget":"#2f2128","cursor":"#78c6d0","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F6E9CB","purple":"#61c1ea","func":"#ff8bfd","constant":"#AE9AFF","cls":"#61ead9","bool":"#ec9cb2"}},
43 {"name":"Nakano Miku","slug":"nakano-miku","dark":true,"colors":{"bg":"#244158","fg":"#F8F8F2","accent":"#A5F3FA","muted":"#addfa9","subtle":"#b9dfb6","selection":"#498192","widget":"#24445b","cursor":"#A5F3FA","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#fffeaf","purple":"#4BABFF","func":"#fc9ee6","constant":"#da8d97","cls":"#ba92f3","bool":"#60ff62"}},
44 {"name":"Nakano Nino","slug":"nakano-nino","dark":true,"colors":{"bg":"#1c191d","fg":"#F8F8F2","accent":"#d45575","muted":"#ab8d9f","subtle":"#666879","selection":"#452735","widget":"#1f1a1f","cursor":"#d45575","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#F6E3CC","purple":"#68c4ee","func":"#fc9ee6","constant":"#ff858c","cls":"#5ea7ff","bool":"#7ceec8"}},
45 {"name":"Nakano Yotsuba","slug":"nakano-yotsuba","dark":true,"colors":{"bg":"#200909","fg":"#F8F8F2","accent":"#e86a44","muted":"#c08865","subtle":"#F8E3D7","selection":"#622316","widget":"#110c15","cursor":"#e86a44","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#F6E3CC","purple":"#39e6a6","func":"#fc9ee6","constant":"#9DACF6","cls":"#ffba2f","bool":"#ff858c"}},
46 {"name":"Natsuki Dark","slug":"natsuki-dark","dark":true,"colors":{"bg":"#35102c","fg":"#F8F8F2","accent":"#E94686","muted":"#b74170","subtle":"#796675","selection":"#602b50","widget":"#2f0a27","cursor":"#E94686","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F6E9CB","purple":"#9DC0FF","func":"#E94686","constant":"#9286FD","cls":"#FF9CD6","bool":"#FF9CD6"}},
47 {"name":"Ram","slug":"ram","dark":true,"colors":{"bg":"#342c34","fg":"#F8F8F2","accent":"#e594bf","muted":"#ab7b9d","subtle":"#666879","selection":"#7a546f","widget":"#2b252b","cursor":"#e594bf","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#a1e9ff","purple":"#9d8df6","func":"#e88def","constant":"#85FFEF","cls":"#FBFF90","bool":"#ef57bf"}},
48 {"name":"Raphtalia","slug":"raphtalia","dark":true,"colors":{"bg":"#1e1710","fg":"#F8F8F2","accent":"#8a3c3d","muted":"#bfb38c","subtle":"#6c5f55","selection":"#5c3915","widget":"#1c140f","cursor":"#8a3c3d","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#FDC78C","purple":"#fd9144","func":"#4fe1a9","constant":"#8097e3","cls":"#FFD448","bool":"#f19992"}},
49 {"name":"Rei","slug":"rei","dark":true,"colors":{"bg":"#191b1f","fg":"#F8F8F2","accent":"#b53241","muted":"#7da1c2","subtle":"#666879","selection":"#25435a","widget":"#131514","cursor":"#b53241","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#f44747","interface":"#F6E3CC","purple":"#45e68a","func":"#ef596f","constant":"#86dbfd","cls":"#6AADFF","bool":"#788a8b"}},
50 {"name":"Rem","slug":"rem","dark":true,"colors":{"bg":"#2c2d34","fg":"#F8F8F2","accent":"#578CDA","muted":"#7b8bab","subtle":"#666879","selection":"#4C637A","widget":"#25262b","cursor":"#578CDA","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F0A1FF","purple":"#9d8df6","func":"#8dc6ef","constant":"#85FFEF","cls":"#FBFF90","bool":"#6893f3"}},
51 {"name":"Rias Crimson","slug":"rias-crimson","dark":true,"colors":{"bg":"#3E1010","fg":"#F8F8F2","accent":"#e03943","muted":"#cdacac","subtle":"#cdb0b0","selection":"#822e2e","widget":"#3d1313","cursor":"#e03943","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#9BBEE3","purple":"#eea367","func":"#fbf96e","constant":"#86dbfd","cls":"#e03392","bool":"#C04750"}},
52 {"name":"Rias Onyx","slug":"rias-onyx","dark":true,"colors":{"bg":"#100000","fg":"#F8F8F2","accent":"#7C171F","muted":"#6e2727","subtle":"#97706f","selection":"#390c10","widget":"#100000","cursor":"#7C171F","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F6E3CC","purple":"#b2dbe3","func":"#C04750","constant":"#E356A7","cls":"#5a84dd","bool":"#27c0b4"}},
53 {"name":"Rimuru Tempest","slug":"rimuru-tempest","dark":true,"colors":{"bg":"#1c171d","fg":"#F8F8F2","accent":"#d7cf8b","muted":"#b0a17f","subtle":"#675a6c","selection":"#29466c","widget":"#211c22","cursor":"#d7cf8b","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#77C2FF","purple":"#FF96FD","func":"#FDEA25","constant":"#9CA2FF","cls":"#FFA38F","bool":"#5FFF9F"}},
54 {"name":"Rory Mercury","slug":"rory-mercury","dark":true,"colors":{"bg":"#141417","fg":"#F8F8F2","accent":"#b53241","muted":"#843030","subtle":"#796666","selection":"#502121","widget":"#18181b","cursor":"#b53241","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF8484","interface":"#58A0F8","purple":"#7F8E90","func":"#FF4556","constant":"#86dbfd","cls":"#BD93F9","bool":"#e0474b"}},
55 {"name":"Ryuko Dark","slug":"ryuko-dark","dark":true,"colors":{"bg":"#2b3238","fg":"#F8F8F2","accent":"#a73035","muted":"#6e707a","subtle":"#666879","selection":"#563036","widget":"#2b3238","cursor":"#a73035","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#efa554","purple":"#99B6D5","func":"#e4ff10","constant":"#86dbfd","cls":"#6893f3","bool":"#e0474b"}},
56 {"name":"Sagiri","slug":"sagiri","dark":true,"colors":{"bg":"#0a3b36","fg":"#F8F8F2","accent":"#5eabb8","muted":"#eae99a","subtle":"#ffffff","selection":"#052421","widget":"#0a3f39","cursor":"#5eabb8","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#53dac7","purple":"#F1A4FA","func":"#42FA71","constant":"#82BAFF","cls":"#9FBBFF","bool":"#FFD448"}},
57 {"name":"Satsuki Dark","slug":"satsuki-dark","dark":true,"colors":{"bg":"#242729","fg":"#F8F8F2","accent":"#f03022","muted":"#af543f","subtle":"#596570","selection":"#5d2626","widget":"#212427","cursor":"#f03022","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#F6E9CB","purple":"#46F263","func":"#e4ff10","constant":"#96b7fb","cls":"#6893f3","bool":"#e24a3e"}},
58 {"name":"Sayori Dark","slug":"sayori-dark","dark":true,"colors":{"bg":"#111b2d","fg":"#F8F8F2","accent":"#00BCD4","muted":"#3a9fb1","subtle":"#666879","selection":"#234164","widget":"#0e1b2f","cursor":"#00BCD4","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff0000","interface":"#FF89BA","purple":"#FFF37C","func":"#01CFE7","constant":"#A486FD","cls":"#52FFA3","bool":"#3F77EF"}},
59 {"name":"Shima Rin","slug":"shima-rin","dark":true,"colors":{"bg":"#2b303b","fg":"#F8F8F2","accent":"#6688ad","muted":"#b0a17f","subtle":"#5a626c","selection":"#4f3a4e","widget":"#2e343e","cursor":"#6688ad","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F6E9CB","purple":"#61ead9","func":"#8bd9ff","constant":"#ec9cb2","cls":"#89acf6","bool":"#ea73d6"}},
60 {"name":"Sonoda Umi","slug":"sonoda-umi","dark":true,"colors":{"bg":"#15173c","fg":"#F8F8F2","accent":"#EFA554","muted":"#6878c2","subtle":"#5e5e79","selection":"#272A59","widget":"#191b44","cursor":"#EFA554","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#FFF6B3","purple":"#BD84DD","func":"#EFA554","constant":"#86dbfd","cls":"#78F5F0","bool":"#58b7ff"}},
61 {"name":"Takanashi Rikka","slug":"takanashi-rikka","dark":true,"colors":{"bg":"#1e1928","fg":"#F8F8F2","accent":"#dd2a62","muted":"#bd7e99","subtle":"#8e6e7b","selection":"#761d3a","widget":"#1d1926","cursor":"#dd2a62","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#FFB4F8","purple":"#8C92FC","func":"#65CDFA","constant":"#F9FC88","cls":"#67F5C4","bool":"#de4371"}},
62 {"name":"Tohsaka Rin","slug":"tohsaka-rin","dark":true,"colors":{"bg":"#161415","fg":"#F8F8F2","accent":"#4c9697","muted":"#86a4ab","subtle":"#847878","selection":"#501F1F","widget":"#1b191a","cursor":"#4c9697","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#C20000","interface":"#72F8B5","purple":"#e0474b","func":"#69e0f5","constant":"#86dbfd","cls":"#EFA554","bool":"#859395"}},
63 {"name":"Vanilla","slug":"vanilla","dark":true,"colors":{"bg":"#2b2c3d","fg":"#F8F8F2","accent":"#9debff","muted":"#b0a17f","subtle":"#5a5e6c","selection":"#374872","widget":"#292a3a","cursor":"#9debff","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F6E9CB","purple":"#6a96e9","func":"#9bf8ff","constant":"#5ddeda","cls":"#9d8df6","bool":"#FFD448"}},
64 {"name":"Yukihira Soma","slug":"yukihira-soma","dark":true,"colors":{"bg":"#09192b","fg":"#F8F8F2","accent":"#d13358","muted":"#6e89ad","subtle":"#5d6c80","selection":"#4f1d27","widget":"#0c1c2e","cursor":"#d13358","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff1717","interface":"#4BFF75","purple":"#8ACAFF","func":"#EA7777","constant":"#FFA6E1","cls":"#FF984B","bool":"#FFEF41"}},
65 {"name":"Yukinoshita Yukino","slug":"yukinoshita-yukino","dark":true,"colors":{"bg":"#1f2126","fg":"#F8F8F2","accent":"#2d6382","muted":"#456186","subtle":"#545e6d","selection":"#2d3b55","widget":"#282a2f","cursor":"#2d6382","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#F6E3CC","purple":"#ead979","func":"#84D0FF","constant":"#86dbfd","cls":"#9DACF6","bool":"#e0474b"}},
66 {"name":"Yuri Dark","slug":"yuri-dark","dark":true,"colors":{"bg":"#422D5A","fg":"#F8F8F2","accent":"#AB47BC","muted":"#9d52ab","subtle":"#6f6679","selection":"#663995","widget":"#442e5c","cursor":"#AB47BC","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#B6B3FF","purple":"#F1FF86","func":"#DC74FF","constant":"#86FDB6","cls":"#FF9CD6","bool":"#B17BFD"}},
67 {"name":"Zero Two Dark Obsidian","slug":"zero-two-dark-obsidian","dark":true,"colors":{"bg":"#17070e","fg":"#F8F8F2","accent":"#1ecd86","muted":"#5c9077","subtle":"#53615B","selection":"#174a2e","widget":"#150a0e","cursor":"#1ecd86","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF0000","interface":"#39e6a6","purple":"#B9F8BC","func":"#66FA36","constant":"#2FAAF6","cls":"#FFD448","bool":"#FDB8EB"}},
68 {"name":"Zero Two Dark Rose","slug":"zero-two-dark-rose","dark":true,"colors":{"bg":"#310f0f","fg":"#F8F8F2","accent":"#e4dad4","muted":"#b19e78","subtle":"#a87975","selection":"#531e1e","widget":"#300d0e","cursor":"#e4dad4","red":"#E356A7","green":"#42E66C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#e2d9bd","purple":"#C04750","func":"#efa2da","constant":"#34a7d1","cls":"#FFB86C","bool":"#39e6a6"}},
69 {"name":"Asuna Light","slug":"asuna-light","dark":false,"colors":{"bg":"#fcfcfc","fg":"#4D4D4A","accent":"#a61d0d","muted":"#a25252","subtle":"#aaaaaa","selection":"#e9b4b8","widget":"#fdfdfd","cursor":"#a61d0d","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#a61d0d","purple":"#0d5fa6","func":"#2527B1","constant":"#4C94D6","cls":"#C68741","bool":"#a61d0d"}},
70 {"name":"Beatrice","slug":"beatrice","dark":false,"colors":{"bg":"#FFE5F1","fg":"#4D4D4A","accent":"#78A5EB","muted":"#dd87a1","subtle":"#aaaaaa","selection":"#fcc9f2","widget":"#FFE0F0","cursor":"#78A5EB","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff5555","interface":"#DC872E","purple":"#7C75EF","func":"#5c84da","constant":"#4C94D6","cls":"#df81b8","bool":"#C869A3"}},
71 {"name":"C.C.","slug":"c-c","dark":false,"colors":{"bg":"#C4EA8A","fg":"#4D4D4A","accent":"#68ac17","muted":"#358969","subtle":"#507433","selection":"#92d564","widget":"#caec92","cursor":"#68ac17","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF0817","interface":"#CB5A29","purple":"#098776","func":"#009507","constant":"#2B57A7","cls":"#7748B7","bool":"#0803A5"}},
72 {"name":"Darkness Light","slug":"darkness-light","dark":false,"colors":{"bg":"#FFFEF9","fg":"#4D4D4A","accent":"#F5C83C","muted":"#aaaaaa","subtle":"#aaaaaa","selection":"#fff3b4","widget":"#FFFEF9","cursor":"#F5C83C","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#005CC5","purple":"#3492b1","func":"#b6323f","constant":"#005CC5","cls":"#c79c19","bool":"#E36207"}},
73 {"name":"Emilia Light","slug":"emilia-light","dark":false,"colors":{"bg":"#fbf0ff","fg":"#4D4D4A","accent":"#82357d","muted":"#8864ac","subtle":"#aaaaaa","selection":"#c7a0d2","widget":"#fbf0ff","cursor":"#82357d","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#0CA87E","purple":"#7C75EF","func":"#7D2DD2","constant":"#4C94D6","cls":"#cb70a5","bool":"#90468c"}},
74 {"name":"Ishtar Light","slug":"ishtar-light","dark":false,"colors":{"bg":"#fffefb","fg":"#4D4D4A","accent":"#f5a821","muted":"#5078a5","subtle":"#aaaaaa","selection":"#fff5c7","widget":"#fffefb","cursor":"#f5a821","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#a18649","purple":"#0d5fa6","func":"#9c3123","constant":"#4C94D6","cls":"#131f3b","bool":"#db974d"}},
75 {"name":"Mai Light","slug":"mai-light","dark":false,"colors":{"bg":"#FAF2F1","fg":"#4D4D4A","accent":"#4f5287","muted":"#6564ac","subtle":"#aaaaaa","selection":"#d3d5f1","widget":"#fff7f6","cursor":"#4f5287","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#d27f2d","purple":"#C869A3","func":"#BA2BB2","constant":"#4C94D6","cls":"#4f5287","bool":"#7C75EF"}},
76 {"name":"Maple Light","slug":"maple-light","dark":false,"colors":{"bg":"#ffd091","fg":"#4D4D4A","accent":"#923A4E","muted":"#763530","subtle":"#693434","selection":"#ec9e74","widget":"#fdcd8f","cursor":"#923A4E","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#208D3B","purple":"#007972","func":"#810808","constant":"#005CC5","cls":"#7748B7","bool":"#B03F0F"}},
77 {"name":"Mioda Ibuki Light","slug":"mioda-ibuki-light","dark":false,"colors":{"bg":"#ffeefd","fg":"#4D4D4A","accent":"#DA46A7","muted":"#5ca4d4","subtle":"#aaaaaa","selection":"#8EDBFF","widget":"#ffeefd","cursor":"#DA46A7","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#3193D7","purple":"#4174b3","func":"#DA46A7","constant":"#2F6AAD","cls":"#cb70a5","bool":"#C869A3"}},
78 {"name":"Monika Light","slug":"monika-light","dark":false,"colors":{"bg":"#f2fff0","fg":"#4D4D4A","accent":"#388E3C","muted":"#3b753d","subtle":"#8CAA8E","selection":"#a9ecac","widget":"#f2fff0","cursor":"#388E3C","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#da832e","purple":"#6D71DC","func":"#20AF6F","constant":"#4C94D6","cls":"#9A9E20","bool":"#2BBA37"}},
79 {"name":"Nakano Ichika","slug":"nakano-ichika","dark":false,"colors":{"bg":"#E3CCFD","fg":"#4D4D4A","accent":"#7F5EF5","muted":"#9160cd","subtle":"#8541b3","selection":"#f1b7d6","widget":"#e2c9fa","cursor":"#7F5EF5","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff000f","interface":"#8747CE","purple":"#3E6DE5","func":"#C95FC0","constant":"#251CDE","cls":"#BF1010","bool":"#5815CE"}},
80 {"name":"Nakano Itsuki","slug":"nakano-itsuki","dark":false,"colors":{"bg":"#FFBEBE","fg":"#4D4D4A","accent":"#4f52c4","muted":"#b1483d","subtle":"#D07E72","selection":"#f4665a","widget":"#fcc1c1","cursor":"#4f52c4","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff000f","interface":"#2D4DC2","purple":"#602C93","func":"#BF1010","constant":"#33618E","cls":"#8D2D1B","bool":"#B6159D"}},
81 {"name":"Natsuki Light","slug":"natsuki-light","dark":false,"colors":{"bg":"#FFE5F1","fg":"#4D4D4A","accent":"#E94686","muted":"#dd87a1","subtle":"#aaaaaa","selection":"#fcc9f2","widget":"#FFE0F0","cursor":"#E94686","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff5555","interface":"#DC872E","purple":"#7C75EF","func":"#EE5687","constant":"#4C94D6","cls":"#df81b8","bool":"#C869A3"}},
82 {"name":"Ryuko Light","slug":"ryuko-light","dark":false,"colors":{"bg":"#ffffff","fg":"#4D4D4A","accent":"#169ef2","muted":"#1f79a1","subtle":"#344f69","selection":"#74adec","widget":"#f5f6f7","cursor":"#169ef2","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#0F92E3","purple":"#007972","func":"#EE5C09","constant":"#005CC5","cls":"#7748B7","bool":"#B03F0F"}},
83 {"name":"Satsuki Light","slug":"satsuki-light","dark":false,"colors":{"bg":"#ffffff","fg":"#4D4D4A","accent":"#275AB3","muted":"#1f45a1","subtle":"#344f69","selection":"#748fec","widget":"#f5f6f7","cursor":"#275AB3","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff2525","interface":"#0F92E3","purple":"#79074c","func":"#1136b9","constant":"#005CC5","cls":"#7748B7","bool":"#13a78c"}},
84 {"name":"Sayori Light","slug":"sayori-light","dark":false,"colors":{"bg":"#f0faff","fg":"#4D4D4A","accent":"#00bcd4","muted":"#64a6ac","subtle":"#aaaaaa","selection":"#a9c8ec","widget":"#f0faff","cursor":"#00bcd4","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#E59584","purple":"#9f69dc","func":"#2e7093","constant":"#4C94D6","cls":"#EF5D99","bool":"#3F77EF"}},
85 {"name":"Senko","slug":"senko","dark":false,"colors":{"bg":"#FFE7CD","fg":"#4D4D4A","accent":"#cb3752","muted":"#b87157","subtle":"#CD9774","selection":"#f4ac96","widget":"#fce2c6","cursor":"#cb3752","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#ff000f","interface":"#3492b1","purple":"#4B72D7","func":"#D9732E","constant":"#E734A8","cls":"#3451b1","bool":"#BF1010"}},
86 {"name":"Shigure","slug":"shigure","dark":false,"colors":{"bg":"#e9e9ff","fg":"#4D4D4A","accent":"#5e1f7f","muted":"#584484","subtle":"#38336b","selection":"#5756a2","widget":"#dad9ff","cursor":"#5e1f7f","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF0707","interface":"#208D3B","purple":"#5E037E","func":"#C209A9","constant":"#005CC5","cls":"#7748B7","bool":"#410cb2"}},
87 {"name":"Tohru","slug":"tohru","dark":false,"colors":{"bg":"#ffe090","fg":"#4D4D4A","accent":"#d23c4b","muted":"#763530","subtle":"#693434","selection":"#ec9e74","widget":"#f6d988","cursor":"#d23c4b","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#005CC5","purple":"#176B82","func":"#aa2537","constant":"#005CC5","cls":"#0E8D61","bool":"#A74503"}},
88 {"name":"Tomori Nao","slug":"tomori-nao","dark":false,"colors":{"bg":"#efe7de","fg":"#4D4D4A","accent":"#276fd8","muted":"#608bcd","subtle":"#417db3","selection":"#b7c6ef","widget":"#f1e7de","cursor":"#276fd8","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF0817","interface":"#296FCB","purple":"#098776","func":"#A80675","constant":"#C26010","cls":"#7748B7","bool":"#030BA0"}},
89 {"name":"Yuri Light","slug":"yuri-light","dark":false,"colors":{"bg":"#f3f0ff","fg":"#4D4D4A","accent":"#ab74cb","muted":"#8864ac","subtle":"#aaaaaa","selection":"#ada0d2","widget":"#f5f0ff","cursor":"#ab74cb","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#2DA0D2","purple":"#D579D0","func":"#95348C","constant":"#4C94D6","cls":"#c26a9d","bool":"#7C75EF"}},
90 {"name":"Yuzuriha Inori","slug":"yuzuriha-inori","dark":false,"colors":{"bg":"#FFA772","fg":"#4D4D4A","accent":"#ba1515","muted":"#894935","subtle":"#743333","selection":"#EC7F54","widget":"#f8a56e","cursor":"#ba1515","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF0817","interface":"#413AC1","purple":"#0B6374","func":"#B11095","constant":"#2B57A7","cls":"#7748B7","bool":"#99101B"}},
91 {"name":"Zero Two Light Lily","slug":"zero-two-light-lily","dark":false,"colors":{"bg":"#fcfcfc","fg":"#4D4D4A","accent":"#A62210","muted":"#5282a2","subtle":"#aaaaaa","selection":"#e9b4b8","widget":"#fafafa","cursor":"#A62210","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#0EAAAF","purple":"#A62210","func":"#E356A7","constant":"#0d5fa6","cls":"#117aa6","bool":"#0da661"}},
92 {"name":"Zero Two Light Sakura","slug":"zero-two-light-sakura","dark":false,"colors":{"bg":"#ffe6ee","fg":"#4D4D4A","accent":"#A62210","muted":"#42a373","subtle":"#BB9BB1","selection":"#c1e9d4","widget":"#ffe5ef","cursor":"#A62210","red":"#E356A7","green":"#38B85C","yellow":"#EFA554","blue":"#9B6BDF","magenta":"#E64747","cyan":"#75D7EC","error":"#FF5555","interface":"#E356A7","purple":"#A62210","func":"#109757","constant":"#0d5fa6","cls":"#0F9497","bool":"#5236B4"}},
93]
94types/index.d.ts 58 lines1export type DokiColors = {
2 bg: string
3 fg: string
4 accent: string
5 muted: string
6 subtle: string
7 selection: string
8 widget: string
9 cursor: string
10 red: string
11 green: string
12 yellow: string
13 blue: string
14 magenta: string
15 cyan: string
16 error: string
17 interface: string
18 purple: string
19 func: string
20 constant: string
21 cls: string
22 bool: string
23}
24
25/** Where a theme comes from. Doki themes leave `source` off. termcn slugs carry a "termcn-" prefix. */
26export type ThemeSource = 'doki' | 'termcn'
27
28export type DokiTheme = { name: string; slug: string; dark: boolean; colors: DokiColors; source?: ThemeSource }
29
30/** The termcn color keys the picker maps from (hooks/termcn-themes.ts, generated). */
31export type TermcnColors = Record<
32 'accent' | 'background' | 'error' | 'focusRing' | 'foreground' | 'info' | 'muted' | 'mutedForeground' | 'primary' | 'secondary' | 'selection' | 'success' | 'warning',
33 string
34>
35
36export type TermcnRaw = { name: string; slug: string; colors: TermcnColors }
37
38/** The shared accent file (~/.claude/mods/theme-accent.json) that other mods can read. */
39export type Accent = {
40 name: string
41 dark: boolean
42 accent: string
43 accent2: string
44 muted: string
45 text: string
46 subtle: string
47}
48
49declare module 'claude-code' {
50 interface PluginState {
51 /**
52 * highlight: the slug under the focus ring; current: the slug last applied;
53 * followed: the slug whose Windows Terminal scheme and accent were last written.
54 */
55 'doki-theme-picker': { highlight: string; current: string; followed: string }
56 }
57}
58