ruegg114514/dsh-colorlab

dsh-colorlab

对话界面配色引擎:内置 Mariana 配色作为默认预设,提供 18 个颜色槽位与 9 个 Markdown 正文角色色,最多可保存 12 套预设;LaTeX 代码块通过移植 Sublime 自身的语法来上色。

Uncategorizedcolorschemedeepseek-harnesstheme

dsh-colorlab

EN · 中文

A colour theme plugin for the DeepSeek Harness chat UI. It ships Sublime Text's Mariana palette as its default preset, and adds a colour engine on top: 18 adjustable colour slots, 9 Markdown prose roles, saved presets, live WCAG contrast warnings and light/dark modes — all from a settings panel, persisted to your profile.

Process rows are colour-coded (green for tool calls, amber for summaries),
headings and inline code are tinted, and the surface sits on Mariana's
cool blue-grey rather than pure black.

Glass UI (opt-in)

With Glass interface on, the three columns become translucent panels over a background layer — your Windows wallpaper, a generated gradient, or a procedural topographic contour sheet. Blur is applied once, to the background itself, so every surface sees the same frosted world underneath; each layer paints only the *difference* between its tier and the one below, so cards stay legibly above the columns and the columns stay tinted with the theme instead of washing out.

Screenshot: glass on over a wallpaper; title bar, sidebar and conversation
read as one continuous sheet of tinted glass; the composer card is lifted out
of the scroll flow, so streamed text clips cleanly at its top edge instead of
sliding underneath.

Background ground: glow / bands / blend

The generated-gradient background is a small compositor of its own. Pick glow (soft coloured fog, no edges), bands (angular colour strips) or blend (both), then colour every element yourself:

  • Glow — 2–6 light sources, each with its own colour, strength and X/Y

position, plus overall density (0–100%) and spread (40–140%).

  • Bands — 2–6 strips, each its own colour, plus a cutting angle anywhere

from 0° to 360° and an edge-softness slider (0 = hard cut).

Screenshot: the generated gradient background in glow mode — several soft
coloured lights composited over the theme base, no wallpaper involved.

Contour background

The third background source is procedural: a topographic contour sheet rendered in a worker thread. Speed, ink density, line width, terrain density, elevation steps, drift amplitude and optional elevation labels are all adjustable, and the whole thing costs nothing when the speed is set to still (one frame, then no repaint).

Screenshot: contour mode. Terrain lines are tinted from the accent colour and
the panels stay translucent above them.

It does not patch app.asar, and it does not fork the host. It uses DSH's official theme extension point (ctx.theme.overrideTokens) and layers its tokens on top of whatever theme is active.

Install

dsh plugin add ruegg114514/dsh-colorlab

This installs from source, so DSH will ask you to approve the package's build step (allowBuilds) on first run. Restart DSH afterwards — the plugin is picked up by the loader at boot.

Uninstall

dsh plugin remove ruegg114514/dsh-colorlab

Or just turn Enable off in the plugin's settings panel: the theme reverts to the host default immediately, no restart needed, and your saved colours are kept.

Versions

Releases are tagged and documented on the releases page; the per-version detail lives in CHANGELOG.md.

The command above always installs the tip of main. To pin a specific release:

dsh plugin add ruegg114514/dsh-colorlab#v1.1.0

Version numbers follow SemVer. While the plugin is pre-2.0, a minor bump may still change how a setting looks — the CHANGELOG says so explicitly under Changed when it does.

What it changes

Mariana is the default colour scheme of Sublime Text 3.0 (2017) and Sublime Text 4. Its background is a cool blue-grey (#343D46) rather than pure black, and its foreground is a soft grey (#D8DEE9) rather than pure white — which is why it stays readable for long sessions on bright displays.

Area · Effect Surfaces / cards / sidebar / menus · #343D46 / #2F3841 / #23292E Body / secondary / tertiary text · #D8DEE9 / #A7ADBA / #8792A2 Borders and dividers · low-opacity overlays of #D8DEE9 Bubbles / input / code blocks · #3B454F / #2E363F Status colours · success #99C794, error #EC5F67, warning #F9AE58 Code syntax highlighting · keywords #C594C5, strings #99C794, functions #5FB3B3, numbers #F9AE58, comments #8792A2 Sidebar terminal · background and cursor follow the theme

The colour engine

Settings panel

Settings → ColorLab:

Option · What it does Enable · Off reverts to the host palette immediately; your settings are kept Apply to · Dark appearance only (default) / both dark and light Surface variant · Standard #343D46 / Deep #252B32 (the early ST3 tmTheme) / Dim #2B3336 Accent · Teal #5FB3B3 / Orange #F9AE58 / Blue #6699CC — affects business-state highlights only Custom accent · Any #RRGGBB via colour picker, hex input or random; overrides the presets. Light mode auto-darkens for contrast Code palette · Overrides Shiki's --shiki-* tokens used inside fenced code blocks Prose highlight · Adds colour hierarchy to Markdown body text (headings, bold, inline code, list markers, quote rules) Prose brightness · Original / Boosted (default) / Brighter — interpolates toward white without shifting hue Prose preview · Shows both states side by side, right under the toggle Prose colours · 9 independent slots: heading, bold, italic, inline code, list marker, quote text, quote rule, link, strikethrough Process row highlight · Colours process rows — tool rows one colour, summary rows another File card colour · Recolours the header band of "edited N files" cards and the whole card body of "delivered files" cards Custom colours · 18 slots (8 surfaces / 3 text / 7 syntax), each adjustable Presets · Save the current palette and load it back later, up to 12 Glass interface · Translucent panels over a background layer (off by default) Background source · Windows wallpaper / image URL / generated gradient / procedural contour lines (ported from dsh-theme-endfield, MIT) Surface tint · Column opacity 0–100 (65 default; lower = wallpaper shows through more) Float tint · How much more solid cards/menus/input sit above the columns (0–40) Blur radius · Background pre-blur 0–80 px Tier tint (fold) · Three independent "how much more solid than the columns" knobs: float +0–40, code block +0–40, hover +0–20 Region tiers (fold) · Sidebar / panel / preview / composer opacity (0–100) and overlay blur (0–80 px), each independently or "follow" Ambient palette · Aurora / Ocean / Sunset / Mono, or follow the surface colours (gradient background only) Background brightness · 0–100, 50 = neutral. Left darkens, right brightens; the ground fades out as it leaves neutral Ground (fold) · Glow / Bands / Blend mode. Glow: 2–6 light sources, each with its own colour, strength and X/Y position; overall density 0–100%. Bands: 2–6 colour strips, each its own colour, plus direction (165°/135°/90°/0°) and edge softness Solid floats · Pin history-message and hover-preview popovers to opaque (off by default) Solid diff · Pin diff line backgrounds to opaque — line colours only, cards untouched (off by default) Background fit · Fill / Fit / Stretch / Tile / Center / Blur fill — same names as Windows personalisation Crop & text guard (fold) · Crop the wallpaper by ratio (left/top/width/height) + text guard (halo, no background tint) Auto tone · Follow the wallpaper's average brightness to switch light/dark theme Advanced (fold) · Background dimming (auto/fixed/off), saturation 0–200%, haze, custom wallpaper path, image URL Contour speed · static / 1x / 2x / 4x; renders in a Web Worker when CSP allows, with a visible backend note Hand-drawn shape · Uneven corner radii, paper shadows, hover lift and a glowing sidebar divider (off by default; mechanism borrowed from dsh-maid-whale-UI, no art assets)

Tier tint: three readability budgets instead of one

Glass has two very different jobs. The columns are decoration — they can be as transparent as you like. Cards, code blocks and file previews are where you read, and they need a separate budget: pull the surface tint down to see your wallpaper and your code should still be legible.

Before, those three levels were hard-coded constants (0.10 / 0.14 / 0.05). Now they are sliders, and the layering algorithm is unchanged: each layer paints only the *difference* between its tier and the one below, so every position on screen converges on its target instead of compounding (1-(1-a)² is what you get from naive stacking — at 20% that reads as 36%).

Knob · Range · Default · What it moves Float tint · 0–40 · 10 · Cards, bubbles, composer, menus Code block tint · 0–40 · 14 · Fenced code — read character by character, so it stays the most solid Hover tint · 0–20 · 5 · Hover feedback; active state is 1.8× this

Region tiers: the same idea, one level down

Tier tint asks *how far above the columns* a layer sits. Region tiers ask a different question: does this piece of UI need to be read?

Pull the surface tint down to admire your wallpaper and the file diff, the stats popover and the composer all fade with it. Raise the surface tint to read them and the whole interface goes solid. The two needs fight, so these four get their own values:

Setting · Range · Default · Covers Panel opacity · 0-100 · *follow* · Popovers, menus, modals, stats and cost panels Preview opacity · 0-100 · *follow* · File diffs, edited-files card, document preview Overlay blur · 0-80 px · *follow* · Behind popovers, menus, modals Composer opacity · 0-100 · *follow* · Composer, approval cards, task cards

"Follow" (-1) is the default for all four, so upgrading changes nothing until you open the fold and set one. Previously overlay blur was derived as glassBlur + 10 and could not be adjusted.

Composer is opacity here, not blur - deliberately different from the
reference plugin. We do *seat lift* (see DESIGN.md): the composer is hoisted
out of the scroll flow so content physically clips at its top edge. Nothing
live sits behind it, so a backdrop-filter there would only buy the
containing-block side effect (fixed-positioned tooltips drifting) with zero
visual gain. That filter was removed on purpose on 2026-10-22, and a test
now locks it out.

Ambient palette

glassAmbientAccent picks the colour family of the gradient backdrop - Aurora / Ocean / Sunset / Mono, or *follow the surface colours* (default). It is separate from Accent, which drives buttons, links and status highlights: you can keep a Mariana-teal interface over a sunset backdrop. Only applies when the background source is *gradient* - a photo or contour sheet has no ambient light to tint.

Wallpaper fit and crop

background-size: cover was hard-coded. It is now five options matching Windows' own wallpaper settings — Fill, Fit, Stretch, Tile, Center. Tile matters: a 512 px texture wallpaper under cover gets blown up 8× on a 4K display.

Crop is expressed as ratios, not pixels ({x, y, w, h}, whole image = 0,0,1,1), so changing resolution or window size never needs a recompute. Out-of-bounds boxes keep their width/height and push the top-left corner back instead of squashing — the box stops at the edge, like a desktop crop tool. The crop is a real re-render via canvas, not a background-position trick: percentage offsets only work for Fill, and Tile/Center would reveal the whole original image.

Text guard: halo only, never a background

With a photo behind the UI, the tempting fix is "make the surface more solid" — but that silently overrides the transparency the user chose. Someone may deliberately run 5% surface tint with blur at 0 to *see* the wallpaper.

So text guard touches not one pixel of background. It does two things:

  1. A text-shadow halo in the same direction as the theme (white in light,

black in dark). It is an inherited property, so putting it on body covers the sidebar, title bar, composer and any portal-rendered popovers. 1 px solid + 2 px soft + 3 px softer is a *stroke*, not a *glow* — any larger and text looks blurred, which is worse.

  1. Darkens the secondary text tokens one step (label-secondary /

tertiary / caption). This is not optional: a halo on pale grey text makes contrast worse (grey on white halo), so the text itself has to move. Only lightness changes — no font size or weight, so nothing reflows. Inline SVG icons use currentColor and follow along.

Auto tone: follow the wallpaper's brightness

Text colour follows the theme mode (dark theme = light text), but the wallpaper's brightness has nothing to do with the mode. Switch to a dark wallpaper while in light theme and dark text lands on a dark photo — the halo and the darkened tokens cannot fix a problem of the wrong direction.

So the plugin measures the cropped region's mean relative luminance (0.2126R + 0.7152G + 0.0722B, sRGB-linearised) on a 32×32 sample:

Mean luminance · Action 0.58 · switch to light 0.42–0.58 · leave alone (a mixed image flipping back and forth is jarring)

Three rules it follows:

  • It calls the official themeService.setTheme(), never writes

data-ds-dark-theme — changing the attribute leaves the host's internal palette and component state untouched, and the next theme change overwrites it.

  • It only touches built-in `light` / `dark` / `system`. If you have selected

a third-party theme id, it will not switch (setTheme('dark') would displace your theme).