用 dsh-skin 给 DeepSeek Harness 网页界面换肤并自定义壁纸

前言

DeepSeek Harness(命令是 dsh)把模型、工具、会话和界面都做成插件。网页端自带一套基于 --dsw-* 设计令牌的主题运行时,内置外观大致是跟随系统、浅色、深色。日常用下来,很多人还是希望再往前一步:像 Codex 那样点一下换一套配色,或者给主画布垫一张自己的壁纸,而不是去改 Harness 源码。

社区里已经出现多款主题类插件。本文只写其中一款:dsh-skin。它由 KinGao294 维护,社区目录归在「主题与外观」。核对过社区目录页、GitHub 仓库 README、package.jsonLICENSE 和客户端源码 lib/client.js 之后,可以把它理解成:在官方主题运行时上注册一套精选配色,并在设置页加一行壁纸控制,主画布和侧栏半透明,消息气泡保持不透明。

需要先说清边界:DeepSeek Harness 官方仓库的口号是「Everything is a Plugin」。社区插件目录 deepseek-harness-plugin.com 是独立站点,用来检索带 dsh-plugin 话题的仓库,和 DeepSeek / 幻方没有官方从属关系,也不是官方应用商店。

这是什么

dsh-skin 是面向 DeepSeek Harness 网页界面 的换肤插件。GitHub 仓库是 KinGao294/dsh-skin,许可证 MIT,作者栏写的是 KinGao294。package.json 里当前版本是 0.3.1,主语言是 JavaScript。截至 2026-08-17,GitHub API 显示该仓库有 18 颗星;社区目录页同一天仍显示 11 颗星,星标以仓库本身为准。

它要解决的问题很具体:

  • 不想只在系统浅色 / 深色之间切换,希望有几套现成的语义配色
  • 想给网页垫一张本地图片或远程图 / 视频,并调节界面遮罩和模糊
  • 换肤和壁纸刷新后还在,但不走 Host 设置里尚未对第三方开放的命名空间

仓库 README 把它写成双面插件,结构和官方自带的 ui-* 包类似:

  • Host 半边lib/index.js + cordis.patch.yml):声明 dsh.bundle,往 profile 的 loader 里插入一条 id: skinname: 'dsh-skin' 的条目;apply 是空操作
  • 浏览器半边lib/client.js):声明 dsh.client,由网页在 /plugins/dsh-skin/client.js 加载,负责注册皮肤、恢复上次选择、画壁纸层、往设置页挂两行控件

package.jsondsh.client.platform"web",并声明对 @deepseek-ai/dsh-client-runtime@deepseek-ai/dsh-client-ui-theme 等包 ^0.1.0-rc.6 的 peer 依赖。它走的是官方主题服务的第三方扩展点(ctx.theme.register / setTheme / overrideTokens),不是给 headless 或终端 TUI 换皮肤。

核心功能

装好并重启网页之后,设置页 Settings → General(通用)里、内置「外观」那一行下面,会多出两行:

  • 皮肤 / Skins
  • 背景图片 / Wallpaper

七套精选配色

皮肤不是另写一套 CSS,而是向 DSH 自带的 ThemeRuntime 注册主题。每个皮肤带一个 colorSchemelightdark),用来驱动 body[data-ds-dark-theme],再覆盖一层 --dsw-alias-*(以及少量 --dsw-specific-*)令牌。ThemePresenter 把这些值写成 body 上的内联自定义属性,卡片、输入框、气泡仍然走原来的令牌体系。

仓库 README 和 lib/client.js 里的目录一致,共 7 套,外加「默认」:

id 中文名 明暗 README 里的气质
skin-ocean 深海蓝 暗色 DeepSeek 蓝的深海
skin-graphite 石墨灰 暗色 中性单色
skin-forest 森林绿 暗色 绿色偏静
skin-sunset 落日紫 暗色 暖紫
skin-midnight 午夜黑 暗色 纯黑,偏 OLED
skin-paper 纸感暖 浅色 暖纸
skin-sakura 樱花粉 浅色 粉色点缀

id 带 skin- 前缀,避免和官方 @deepseek-ai/dsh-client-ui-console 里已有的 sakuragraphite 撞名。源码在读取时会把旧的无前缀 id 迁到 skin-*

默认 / Default 会回到内置外观(跟随系统),并清掉已保存的皮肤 id。

自定义壁纸:半透明画布 + 遮罩 / 模糊

壁纸不是铺满整个窗口的一张图。实现上是一层 z-index: -1 的固定背景;同时用 ctx.theme.overrideTokens 把主画布(--dsw-alias-bg-base)和侧栏(--dsw-specific-sidebar-fill)做成半透明,图从这两块透出来。消息气泡、卡片、输入框仍是实底,源码和界面提示都写了这一点:保证字还能读。

Settings → General → 背景图片 里可以做这些事(以 README 和客户端文案为准):

  • 选择图片:选本地图片,转成 data URL 存在当前浏览器。README 写软上限约 2MB;源码里 data URL 长度上限是 1800000 字符,超出会先压缩再存,仍超则提示存不下。本地视频文件不会被上传,界面会提示改用网址。
  • 网址:粘贴 http(s)data: 的图片 / 视频地址。视频扩展名按源码识别 mp4 / webm / ogv / movblob: 会被拒绝,因为刷新后失效。没有额外的媒体服务器。
  • 显示方式:铺满(cover)、完整显示(contain)、拉伸(stretch)、平铺(tile),默认铺满。
  • 界面遮罩模糊:两个滑块。遮罩越高,界面越实、壁纸越弱。滑块改动用 requestAnimationFrame 合并,避免拖动时把页面拖崩。默认遮罩 0.8,默认模糊 0
  • 移除:清掉壁纸。

换皮肤或切换浅色 / 深色时,半透明表面会按当前皮肤重新着色,壁纸仍在下面。

只存在当前浏览器里

选择存在 localStorage,键名是:

  • dsh-skin:skin
  • dsh-skin:wallpaper
  • dsh-skin:wallpaper-opacity
  • dsh-skin:wallpaper-blur
  • dsh-skin:wallpaper-fit

README 解释了原因:Host 设置通道只向浏览器暴露白名单里的命名空间(WEB_SETTINGS_NAMESPACES)。第三方命名空间会得到 settings-not-exposed。视觉偏好用 localStorage 能跨刷新保留,范围是同一个浏览器、同一来源,不会同步到另一台机器或另一个浏览器配置。第三方皮肤在启动时会再应用一次,因为 DSH 本身只持久化系统 / 浅色 / 深色。

安装与启用

社区目录页给出的安装命令如下,在 DeepSeek Harness 终端里运行:

dsh plugin add github:KinGao294/dsh-skin

需要可复现安装时,目录页要求固定 commit 哈希:

dsh plugin add github:KinGao294/dsh-skin#<commit>

<commit> 换成仓库里某个具体提交。不要长期跟踪浮动的默认分支。

官方 CLI 的插件命令形态是 dsh plugin --profile <profile> add <规格>,会在对应 profile 目录里转发给 pnpm。这个插件只声明了 web 平台。仓库 README 用本地 checkout 举例,并且强调必须加 -w:每个 profile 都带 pnpm-workspace.yaml,pnpm 9 把 profile 目录当成 workspace 根,裸 add 会报 ERR_PNPM_ADDING_TO_ROOT

dsh plugin --profile web add -w /path/to/dsh-skin

官方 CLI 文档里从 GitHub 安装的形态是 dsh plugin --profile <profile> add github:owner/repo。把目录页的规格装进 web profile,可以写成:

dsh plugin --profile web add github:KinGao294/dsh-skin

如果 pnpm 报 ERR_PNPM_ADDING_TO_ROOT,再按 README 的说明补上 -w。安装会把包装进 ~/.dsh/profiles/web,并追加到 dsh.profile.bundles。新的 bundle 层要重启正在跑的网页服务才生效:

# 先停掉当前实例,再启动:
dsh web

打开网页后进入 Settings → General,就能看到皮肤和背景图片两行。

目录页和官方文档都提醒:插件以当前 dsh 进程的权限运行,安装时可能执行代码。装之前应阅读仓库源码和 MIT 许可证。Git 依赖若带 prepare 脚本,pnpm 10 及以上可能先拒绝构建,需要按 CLI 提示把包名写进该 profile 的 pnpm-workspace.yamlallowBuilds 后再装一次。

典型用法

下面步骤都来自 README 和设置页文案,不涉及未公开的配置项。

  1. 确认本机已经能打开 DSH 网页(官方文档里常见入口是 npx @deepseek-ai/dsh web,默认 http://127.0.0.1:3080)。
  2. 按上一节把 dsh-skin 装进 web profile,重启 dsh web
  3. 打开 设置 → 通用。在「外观」下方找到 皮肤
  4. 点一套配色,例如「深海蓝」或「纸感暖」。页面应立刻切到对应明暗和令牌色;刷新后应仍是这一套。
  5. 若要恢复内置外观,选 默认
  6. 背景图片 一行点 选择图片,挑一张不太大的本地图;或在输入框粘贴 https://... 的图片 / 视频地址后点应用。
  7. 界面遮罩模糊,看主画布和侧栏的透出程度。消息气泡应保持实底。
  8. 显示方式按桌面壁纸习惯选:铺满适合照片,完整显示适合不想裁切的图,平铺适合纹理。
  9. 不要用 blob: 地址;刷新后会失效,插件会直接拒绝。

开发者如果在改 lib/client.js:这份客户端是按 __ModuleLoader__ 的 bundle 格式手写的,没有单独构建步骤。require 只能点到模块表里已有的实体(例如 react@deepseek-ai/dsh-client-ui-theme/client)。改完同样需要重启 web 服务,loader 会按新的内容哈希重新提供文件。

适用场景与注意事项

适合这些情况:

  • 已经在用 DSH 网页,只想换配色、加壁纸,不想碰 Harness 源码
  • 希望皮肤走官方 ThemeService 的 alias 令牌,而不是整页覆盖一张大 CSS
  • 壁纸可以只存在当前浏览器,不需要多设备同步

使用前注意下面几条,均能在目录页、README 或源码里对上:

  1. 只覆盖网页。 dsh.client.platformweb。headless、自己做的 TUI profile 装了也不会出现这两行设置。
  2. 偏好不跨浏览器。 清站点数据、换浏览器或换设备,皮肤和壁纸都要重设。这是当前 Host 设置白名单的限制,不是漏做的云同步。
  3. 本地图片有体积上限。 过大存不进 localStorage。本地视频请改用网址,插件不会把视频文件上传到本机服务。
  4. 可读性优先于「全透明」。 半透明只作用在主画布和侧栏;把遮罩拖到很低,字仍应落在实底气泡上。若和其他改全局 CSS 的外观插件叠用,后挂载的令牌覆盖可能互相打架,需要自己看效果。
  5. 和官方主题 id 刻意错开。 本插件用 skin-sakuraskin-graphite 这类带前缀的 id。社区里还有 dsh-deep-whaledsh-xiaoyao-skins 等其它主题插件,职责不同,不要按名字混装、混改同一套 token。
  6. 权限模型。 插件与当前 dsh 进程同权。即使许可证是 MIT、源码公开,安装前仍应自己看 lib/index.jslib/client.jscordis.patch.yml
  7. API 仍在预览期。 Harness 官方说明核心插件和 API 还会变。本包 peer 依赖写的是 0.1.0-rc.6 一带的客户端包,升级 DSH 后若设置行消失或换肤不生效,应对照当时的 theme / client 插件接口再查仓库。

小结

dsh-skin 把「换一套配色」和「垫一张壁纸」接到 DeepSeek Harness 已有的令牌主题运行时上:七套 skin-* 精选色板,加上半透明主画布、可调遮罩和模糊的壁纸层,选择存在当前浏览器的 localStorage。它不改 Harness 源码,安装后重启 dsh web,在设置页通用一栏就能用。

目录页与源码:

  • 社区目录:https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-skin/
  • GitHub:https://github.com/KinGao294/dsh-skin
  • DeepSeek Harness 官方仓库:https://github.com/deepseek-ai/deepseek-harness
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜