Skip to content

Repository files navigation

dsh-theme-plugin

Chinese traditional colors as a DeepSeek Harness theme pack. 49 anchor colors × light/dark = 98 themes, each writing the full --dsw-* token vocabulary (89 tokens) and clearing WCAG AA on all 2254 contrast assertions. The picker opens on a curated shortlist of twelve.

📖 中文文档

竹青 light: raw-silk paper, a green wash on the bubble, and a send button in the anchor green itself 朱红 dark: sized-xuan paper in warm ink, a deep maroon wash, and a vermilion send button
群青 light: violet-tinted silk paper, a blue wash, and a blue send button 藤黄 dark: ochre paper in olive ink, an olive wash, and a gold send button

竹青 · light(素绢)  |  朱红 · dark(熟宣)
群青 · light(雪青)  |  藤黄 · dark(赭纸)

One anchor per paper family, same conversation in each. The most saturated patch on screen is always the color you picked.

Install

npx -y @deepseek-ai/dsh plugin --profile web add dsh-theme-plugin@latest
npx -y @deepseek-ai/dsh --profile web          # boot → open http://127.0.0.1:3080/

This pulls the prebuilt bundle from npm — no clone, no build step. The web profile is created on first boot under ~/.dsh/profiles/web.

  • Verify — the browser console logs registered 98/98 themes (49 light / 49 dark), and dsh --profile web --dump-config shows a theme-zhongguo row.
  • Update — run the same add command again.
  • Uninstalldsh plugin --profile web remove dsh-theme-plugin

Usage

Open Settings → Traditional Colors and pick a theme; it applies immediately. Themes also have deep links:

http://127.0.0.1:3080/#theme=zhuqing-light      # 竹青 light
http://127.0.0.1:3080/#theme=qunqing-dark       # 群青 dark

Changing the hash switches themes live. When several sources disagree, the order is deep link → your remembered pick → defaultTheme. The remembered pick lives in localStorage, not in settings.yaml, so it does not follow you across devices.

Settings → Traditional Colors on 竹青 light: the curated shortlist first, then every anchor grouped by paper family The same panel on 藤黄 dark, themed by the pack itself

Each row's chip shows the theme's real paper, veil and focus — not the raw anchor swatch, which is what the picker used to show and tells you very little about the theme you would get. The line under the current theme names its seal and why that seal was chosen.

The panel references nothing but --dsw-* tokens, so it is themed by the pack itself and doubles as a preview of whatever you are about to pick.

Design: 纸 · 帘 · 印

Chinese painting does not start with color. It prepares the paper, washes over it, and signs last. These themes are built in that order, and the three characters name three layers.

纸 Paper — about 60% of the screen. The ground is not "the traditional color, lightened"; it is a different material. Four families — 素绢 raw silk, 熟宣 sized xuan, 雪青 violet-tinted silk, 赭纸 ochre paper — carry deliberately separated chroma (OKLab ≈ 0.010 / 0.019 / 0.015 / 0.024 respectively), so the four papers are told apart by eye and not only in the data. Light grounds sit at L ≈ 0.963–0.971: off-white rather than white, which is what leaves room for a raised surface above them.

帘 Veil — about 25%. The sidebar and message bubbles are the anchor color itself, undiluted by paper, held inside a band of 1.25–1.55 contrast against the paper so the wash can neither disappear nor harden into a slab. You recognize which traditional color you are in by the bubbles, not by the background.

印 Sealthe focus is the anchor itself. The primary button and the send button are the anchor pressed darker. This reverses the pack's original law, under which the primary button was filled by a curated relative of the anchor sitting a median 109° away in hue — so choosing 竹青 handed you a crimson call-to-action. That relative is still chosen, still recorded per theme as sealName / sealRel / sealWhy, and now appears only as the active-nav accent: a signature rather than a focus. The picker shows the reasoning ("茜红 · 策展印 · 冷暖对冲").

Ink — text, rules and secondary surfaces run down one ink ramp, the paper color pushed darker. Every nb-XX step of the base stylesheet becomes a tinted neutral of the same lightness, and hover offsets, elevation steps, borders and interaction alphas are copied verbatim: hue changes, relations do not. The ramp's two endpoints are the deliberate exception — those are set here rather than inherited, because the base stylesheet's are the extremes. Light and dark now share one shape: body 16.7–17.5, secondary 7.4–8.0, tertiary 4.6–5.5.

Gates — AA is a floor, and elegance lives at the ceiling, so most rules are two-sided. pnpm check re-derives every claim above from the emitted tokens: 2254 contrast rows, plus invariants for veil chroma, the single focus (both focus tokens must be the anchor's own hue and the most saturated patches on screen), elevation direction, and full token coverage. It trusts nothing the generator says about itself.

Curation — twelve of the 49 anchors carry a curated flag and lead the picker. The list is derived rather than hand-kept: the CURATED names that survive the gates, topped up by farthest-point sampling in OKLab so the shortlist spreads across the space instead of clustering.

Anchors per paper family: 素绢 12 · 熟宣 14 · 雪青 17 · 赭纸 6. Within one mode, the two closest themes still differ by ΔE 0.018 across the four signature dimensions (ground, brand, bubble, focus) against a 0.015 floor.

Theme roster

49 anchors × light/dark = 98 themes — click to expand

⭐ marks the twelve curated anchors the picker shows first. Display names are <name>·亮 / <name>·暗, e.g. 竹青·暗. Paper families: 素绢 raw silk, 熟宣 sized xuan paper, 雪青 violet-tinted silk, 赭纸 ochre paper. The seal column is the curated relative described above — a signature mark, not the button color.

Color 中文 Anchor Paper Seal Theme ids (light / dark)
Zhu Qing 竹青 ⭐ #00A86B 素绢 茜红 zhuqing-light / zhuqing-dark
Zhu Hong 朱红 ⭐ #ED5126 熟宣 赭石 zhuhong-light / zhuhong-dark
Qun Qing 群青 ⭐ #1772B4 雪青 枫叶红 qunqing-light / qunqing-dark
Teng Huang 藤黄 ⭐ #FFD111 赭纸 瑶碧 tenghuang-light / tenghuang-dark
Jiang Zi 绛紫 ⭐ #8E354A 熟宣 洋葱紫 jiangzi-light / jiangzi-dark
Zi Yun 紫云 ⭐ #A020F0 雪青 蜻蜓红 ziyun-light / ziyun-dark
Mei Hong Se 玫红色 ⭐ #FF007F 熟宣 品红 meihongse-light / meihongse-dark
Dan Shu Hong 淡曙红 #EE2746 熟宣 殷红 danshuhong-light / danshuhong-dark
Gan Qing 绀青 #4F84FF 雪青 落霞 ganqing-light / ganqing-dark
Mei Gui Zi 玫瑰紫 #BA2F7B 熟宣 高粱红 meiguizi-light / meiguizi-dark
Ying Wu Lü 鹦鹉绿 #5BAE23 素绢 猩红 yingwulv-light / yingwulv-dark
Bo Luo Hong 菠萝红 #FC7930 熟宣 芙蓉红 boluohong-light / boluohong-dark
Fu Pen Zi Hong 覆盆子红 #AC1F18 熟宣 苋菜红 fupenzihong-light / fupenzihong-dark
Cang Bi 苍碧 #2A52BE 雪青 猩红 cangbi-light / cangbi-dark
Xiong Huang 雄黄 #FF9900 赭纸 绀青 xionghuang-light / xionghuang-dark
Hu Po Huang 琥珀黄 #FEBA07 赭纸 绀青 hupohuang-light / hupohuang-dark
Wei Zi 魏紫 #7E1671 雪青 魏紫·深 weizi-light / weizi-dark
Gan Lan Huang Lü 橄榄黄绿 #BEC936 素绢 魏紫 ganlanhuanglv-light / ganlanhuanglv-dark
Huo Zhuan Hong 火砖红 #CD6227 熟宣 淡可可棕 huozhuanhong-light / huozhuanhong-dark
Xiang Ye Hong 香叶红 #F07C82 熟宣 鹅冠红 xiangyehong-light / xiangyehong-dark
Yan Ying Zi 烟萦紫 #8A4B9C 雪青 烟萦紫·深 yanyingzi-light / yanyingzi-dark
Mei Ge 韎韐 #A5441B 熟宣 蟹蝥红 meige-light / meige-dark
Li Shou 綟绶 #6B8E23 素绢 暗紫苑红 lishou-light / lishou-dark
Zi Teng Luo 紫藤萝 #9B8AE8 雪青 淡罂粟红 zitengluo-light / zitengluo-dark
Han Xiu Lü 汉绣绿 #2E7D32 素绢 绛紫 hanxiulv-light / hanxiulv-dark
An Zi Yuan Hong 暗紫苑红 #82202B 熟宣 殷红 anziyuanhong-light / anziyuanhong-dark
Xin Lü 新绿 #6CC788 素绢 茜裙 xinlv-light / xinlv-dark
Ling Meng Hong 菱锰红 ⭐ #D276A3 熟宣 苋菜紫 lingmenghong-light / lingmenghong-dark
Man Tian Xing Zi 满天星紫 #2E317C 雪青 栗紫 mantianxingzi-light / mantianxingzi-dark
Kong Que Lan 孔雀蓝 #0EB0C9 雪青 胭脂红 kongquelan-light / kongquelan-dark
Bao Shi Lan 宝石蓝 #2486B9 雪青 朱墙 baoshilan-light / baoshilan-dark
Mei Die Lü 美蝶绿 #12AA9C 素绢 枫叶红 meidielv-light / meidielv-dark
Bian Dou Zi 扁豆紫 #A35C8F 雪青 扁豆紫·深 biandouzi-light / biandouzi-dark
Qian Zi Teng Luo 浅紫藤萝 ⭐ #D1B3FF 雪青 杏子 qianzitengluo-light / qianzitengluo-dark
Qing Fan Lü 青矾绿 #2C9678 素绢 汉绣红 qingfanlv-light / qingfanlv-dark
Bi Luo Chun Lü 碧螺春绿 #867018 赭纸 苍碧 biluochunlv-light / biluochunlv-dark
Gan Lan Shi Lü 橄榄石绿 #B2CF87 素绢 酢酱草红 ganlanshilv-light / ganlanshilv-dark
Fen Tuan Hua Hong 粉团花红 #EC9BAD 熟宣 锦葵红 fentuanhuahong-light / fentuanhuahong-dark
He Ye Lü 荷叶绿 ⭐ #1A6840 素绢 栗紫 heyelv-light / heyelv-dark
Shi Lü 石绿 #57C3C2 素绢 银红 shilv-light / shilv-dark
Zha Ye Zong 柞叶棕 #692A1B 熟宣 栗棕 zhayezong-light / zhayezong-dark
Chang Chun Hua Lan 长春花蓝 #7EC0EE 雪青 香叶红 changchunhualan-light / changchunhualan-dark
Shan Geng Zi 山梗紫 #61649F 雪青 满江红 shangengzi-light / shangengzi-dark
Yan Lan 鷃蓝 #144A74 雪青 枣红 yanlan-light / yanlan-dark
Fen Lü 粉绿 ⭐ #83CBAC 素绢 梅红 fenlv-light / fenlv-dark
Yu Qin Lan 玉鈫蓝 #126E82 雪青 赭石 yuqinlan-light / yuqinlan-dark
Pi Bian 皮弁 #8B5D33 赭纸 石青 pibian-light / pibian-dark
Gan Lan Lü 橄榄绿 #5E5314 赭纸 满天星紫 ganlanlv-light / ganlanlv-dark
Dai Zi 黛紫 ⭐ #5D3A6F 雪青 黛紫·深 daizi-light / daizi-dark

The roster is whatever the generator emits; it is not maintained by hand.

Configuration

Under the plugin's row in cordis.yml:

config:
  defaultTheme: zhuqing-light   # theme applied at boot (optional)
  remember: true                # remember the pick in localStorage
  hashSelector: true            # honour #theme=<id> deep links
  settingsOrder: 40             # settings page position in the nav

A malformed value is dropped and falls back to its default rather than failing the load — one bad preference should not cost you the whole pack.

Development

Requirements: Node.js 20+ (pnpm test runs .ts directly and needs 23.6+) and pnpm.

git clone https://github.com/nevertoday/dsh-theme-plugin
cd dsh-theme-plugin
pnpm install && pnpm build          # builds lib/client.js, the browser bundle
dsh plugin --profile web add -w .   # register this directory
dsh --profile web
  • -w is required because the profile directory is a pnpm workspace root. add links the directory and appends the package to dsh.profile.bundles; the loader then reads lib/client.js from your working copy, so pnpm build is what makes changes visible.
  • The repo ships an .npmrc with auto-install-peers=false. Without it pnpm ≥ 9 cannot install: it tries to fetch the optional @deepseek-ai/* peers, and one of them depends on a package that was never published.
  • pnpm build needs tsdown; node scripts/build-esbuild.mjs is the fallback.
  • Committing lib/ is optional. It costs a 564 KB bundle plus an 820 KB sourcemap showing up as changes after every build.

Gatespnpm check (2254 contrast rows plus invariants) and pnpm test (46 tests, including a load-time lock on lib/client.js). Neither needs a running harness.

Regenerating the themespnpm generate reads the color data and OKLab math from the 中国传统色 repository. Point it there:

ZH_COLORS_REPO=/path/to/zhongguo-traditional-colors pnpm generate

It also looks one directory up and at a sibling checkout, so a conventional layout needs no environment variable. The generator is deterministic — no clock, no randomness — so an unchanged input must reproduce byte-identical output.

License

MIT — see LICENSE.

About

No description or website provided.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages