给 DSH Web GUI 换上 20 款 base16 配色

DeepSeek Harness(下面简称 dsh)的 Web GUI 能像换主题一样整站换配色。这个能力不是 dsh 核心自带的,而是社区插件 dsh-web 全家桶(@linxin666/dsh-web-all)里的「皮肤中心」提供的——皮肤依赖这个插件才能被加载。而皮肤中心自带方案不多,社区皮肤也大多是一套一套手搓的,想要”更多配色”就只能重复劳动。
于是我做了这个项目 dsh-base16-skins(仓库地址),把 base16 这个标准化配色体系里的 20 款方案,一次性喂给皮肤中心。
Github前置依赖:换肤能力来自 dsh-web 插件
先把依赖关系说清楚,免得装完发现设置里根本没有入口。
- 换肤功能的提供者是插件
@linxin666/dsh-web-all(DSH Web UI 全家桶聚合插件),皮肤中心本体是它依赖的子包@linxin666/dsh-client-ui-skin-center。 - 本仓库只产出皮肤资产,不含任何换肤代码。皮肤中心对自己的定位写得很明确:皮肤是纯资产目录(内置的 +
$DSH_HOME/skins),只由皮肤中心加载和渲染。 - 所以顺序是:先装 dsh-web(皮肤中心)→ 再把皮肤放进去。没装插件的话,
install.sh拷进去的皮肤没有任何东西会去读它,设置里也不会有「皮肤中心」这个入口。
安装插件(profile 侧,pnpm 由 dsh plugin 转发):
1 | dsh plugin --profile web add @linxin666/dsh-web-all@latest |
装完打开 设置 → 皮肤中心 就能看到入口。全家桶里还有 task-board、git-graph、pet、usage、remote-web-ui 等一堆插件,皮肤中心只是其中之一。
如果你在 Android / Termux 上装这个插件,还有一批额外的坑要处理(pnpm 11 只认 allowBuilds 布尔映射、node-pty 必须与 DSH 核心同版本、cloudflared 在 bionic 上不可用等)。这些我整理在另一篇里:让 DeepSeek Harness 在 Android / Termux 上跑起来。
为什么是 base16
base16 是一套已经约定好语义的 16 色体系,槽位含义固定:
| 槽位 | 含义 | 槽位 | 含义 |
|---|---|---|---|
base00 | 背景 | base08 | 红(错误、变量) |
base01 | 背景层次 1 | base09 | 橙(常量、数字) |
base02 | 背景层次 2 | base0A | 黄(警告、类) |
base03 | 注释、暗线 | base0B | 绿(字符串、成功) |
base04 | 暗前景 | base0C | 青(转义、链接) |
base05 | 默认前景 | base0D | 蓝(函数、强调) |
base06 | 亮前景 | base0E | 紫(关键字) |
base07 | 最亮前景 | base0F | 棕(弃用、内嵌) |
语义固定带来一个很舒服的结果:只要写一套映射公式,喂任何调色板都能自动得到正确的明暗极性,不需要为每个方案单独手调。上游 tinted-theming/schemes 已经积累了 300+ 款方案,加新配色就是加一个 YAML 文件的事。
项目做了什么
一句话:把 base16 的 16 个颜色,重映射到 dsh 的全部设计 token,并接管 Shiki 语法高亮。
每款皮肤输出一个目录,每个 skin.css 里有 259 条 CSS 自定义属性:
1 | skins/<id>/ |
覆盖的 token 家族:
--dsw-alias-*:官方设计 token 主体(表面/边框/品牌/按钮/交互态/文本/Markdown/滚动条/状态/浮层)--dsw-specific-*:侧栏、气泡、输入框、菜单、选择器--shiki-*:代码块语法高亮--aion-*:dsh-web 插件生态在用的另一套变量家族--dsh-scrollbar-*:滚动条
映射规则(generate.mjs 里的 tokens()):
1 | const accent = p.base0D // 强调色统一取 base0D |
注意 toward() 这个细节:所有”变淡/变暗”的派生色都朝背景混合,而不是朝黑或朝白混合。这样同一套公式在深色底和浅色底上,对比度的变化方向都是对的。
四个值得说的设计决策
1. 恒深 / 恒浅,而不是跟随模式
dsh 官方把深色的 token 声明在 body[data-ds-dark-theme] 上,而不是 :root。所以只写 :root 会被它压住。
同时 Shiki 的语法高亮颜色是按模式切换的——如果只覆盖一半,深色皮肤在浅色模式下就会出现”深底深字”,直接不可读。
于是每款皮肤在 :root 和 body[data-ds-dark-theme] 下写同一组值,也就是”恒深/恒浅”:
1 | :root { |
代价是:皮肤激活期间,界面的浅色/深色开关不再改变外观。这是刻意的取舍——换来的是”任何配色在任何模式下都不会糊成一团”。
2. 语法高亮同源
代码块是配色最容易露馅的地方。官方把 Shiki 的颜色放在 --shiki-token-* 变量里并按模式切换,本项目一并接管,用 base16 的经典映射:
| Shiki token | base16 | Shiki token | base16 |
|---|---|---|---|
constant | base09 | function | base0D |
string | base0B | string-expression | base0C |
comment | base03 | link | base0C |
keyword | base0E | punctuation | base04 |
parameter | base08 | foreground | base05 |
于是代码块和界面是同一套配色,而不是”界面换了皮、代码块还是原来那个”。
3. 用皮肤中心自己的校验器做离线校验
verify.mjs 不自己写校验逻辑,而是直接 import 皮肤中心安装好的实现:
1 | const { validateSkinManifestV2, transformSkinCss, loadSkinCatalog } = lib |
逐个皮肤跑三件事:
validateSkinManifestV2—— 清单是否符合 v2 契约(且skin.json的id必须等于目录名)transformSkinCss—— 皮肤中心自己的 CSS 安全管线能不能吃下去、有没有 warningloadSkinCatalog—— 目录册能否真的收录这 20 个用户来源皮肤
这样校验标准和运行时是同一个,不会出现”我的校验过了但皮肤中心不认”。
4. 对抗浏览器强制深色
Chrome / Edge 的「网站深色主题 / 强制深色」(Auto Dark Theme)会把浅色页面整体反转,看起来就像浅色皮肤失效了——面板发灰、背景不变亮。这跟皮肤本身无关,任何浅色网页都会中招。
皮肤按 MDN 记载的官方豁免写法声明”只支持单一配色”:
1 | color-scheme: light; /* 旧版浏览器回退 */ |
深色皮肤对应 only dark。
皮肤清单
| 暗色(恒深) | 亮色(恒浅) |
|---|---|
| One Dark · Gruvbox Dark · Nord · Tokyo Night | One Light · Gruvbox Light · Ayu Light · Tokyo Night Light |
| Catppuccin Mocha · Dracula · Solarized Dark | Catppuccin Latte · Solarized Light · Rosé Pine Dawn |
| Rosé Pine · Everforest Dark · GitHub Dark | Everforest Light · GitHub Light · Flexoki Light |
共 20 款,暗色 10 + 亮色 10。极性不是手写的,而是读上游调色板的 variant 字段自动判定。
预览图也不是截图,而是 generate.mjs 逐像素画出来的 UI 示意(640×400,sharp 编码成 JPEG)——不依赖系统字体,所以在任何机器上生成的结果都一致。
安装与使用
前提:先把插件装好(@linxin666/dsh-web-all,皮肤中心随它一起进来),见上文「前置依赖」。
1 | git clone https://github.com/clevebitr/dsh-base16-skins.git |
装完后打开 设置 → 皮肤中心,刷新页面即可看到新增的 20 款,先「试穿」再「应用」。安装新皮肤不需要重启,皮肤中心重新扫一遍 $DSH_HOME/skins 就行(刷新页面或重开卡片)。
install.sh 支持 --prune,用来清掉皮肤目录里已经不在本仓库的 base16-* 皮肤:
1 | bash install.sh --prune |
加一款新配色
上游还有 300+ 方案没搬(gruvbox-material-*、kanagawa、horizon-*、selenized-*、zenburn、danqing …):
1 | curl -fsSL -o palettes/<slug>.yaml \ |
只要 YAML 里的 16 个槽位齐全,映射、极性判定、预览图、语法高亮就都是自动的。
已知限制
必须先装 dsh-web 插件(
@linxin666/dsh-web-all)。dsh 核心没有皮肤系统,换肤完全是这个插件的能力;本仓库只是往皮肤中心里补资产,卸载插件这些皮肤就一起失效。皮肤激活期间,界面自带的浅色/深色开关不再改变外观。这是”恒深/恒浅”设计的必然代价,原因见上文。
如果你的浏览器版本仍会强制反转浅色页面,
color-scheme: only light也不生效,请在浏览器设置里关掉:- Edge for Android:设置 → 外观 → 深色模式 → 关闭(或「将深色模式应用于网站」设为从不)
- Chrome for Android:设置 → 主题 → 关闭「网站深色主题」
自查方法:切到「官方默认」皮肤并把界面切到浅色模式——若背景仍是深色,就说明是浏览器强制深色,而不是皮肤问题。
来源与许可
palettes/*.yaml 是 tinted-theming/schemes(MIT,分支 spec-0.11)的原样拷贝;每款方案的作者与出处都写在各皮肤的 skin.json(author / sourceUrl / attribution / license)。本仓库只做「base16 → dsh token」的映射与打包,脚本与文档同为 MIT。
- 标题: 给 DSH Web GUI 换上 20 款 base16 配色
- 作者: Clevebitr
- 创建于 : 2026-09-14 11:20:00
- 更新于 : 2026-09-14 11:25:50
- 链接: https://blog.clevebitr.dpdns.org/2026/09/14/给DSH-Web-GUI换上20款base16配色/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。