给 AI 编程工具换皮肤是什么体验?本文以我开发的
dsh-skin-alphacoders为例,完整拆解 DeepSeek Harness(DSH)的插件机制、一个壁纸皮肤插件的开发全流程,以及开发中踩过的坑。文末附 GitHub 仓库,欢迎 Star。
一、项目是什么
DeepSeek Harness 是 DeepSeek 推出的编码 Agent 运行平台(dsh web 启动一个 Web GUI,默认 http://127.0.0.1:3080)。它本身支持浅色/深色/跟随系统三种主题,但没有自定义背景的能力。
dsh-skin-alphacoders 是一个皮肤插件:把 Alphacoders 热门壁纸 变成 Web GUI 的背景,功能包括:
- 🖼️ 壁纸库:浏览热门壁纸(15 张/页、分页、懒加载)
- 🔍 搜索:关键词搜索(走 Alphacoders 官方搜索页)
- 📤 本地图片:上传自己的 PNG/JPEG/WebP/GIF 做壁纸,重启不丢
- 🎨 显示控制:四种填充方式 + 0~90% 遮罩强度
- 🌗 明暗联动:浅色白雾 / 深色黑雾遮罩自动切换
- 💾 偏好持久化:写入
settings.yaml,重启自动恢复


二、DSH 插件机制:一个插件是怎么跑起来的
这部分是干货,理解了它,你也能给 DSH 写任何插件。
1. profile 与组合层
DSH 用 profile 组织运行配置,位于 $DSH_HOME/profiles/<name>。web 是一个内置 profile,它的配置树由若干层按顺序叠加:
dsh.profile.bundles里声明的组合包 patch(@deepseek-ai/dsh-base、@deepseek-ai/dsh-web-app)- profile 自己的
cordis.patch.yml - home 级
$DSH_HOME/cordis.patch.yml
每个 patch 就是一堆插件行:id + name(包名)+ config。给 web 加第三方插件的官方方式是:
dsh plugin --profile web add <包名>
然后在 cordis.patch.yml 里登记一行:
- insert:
- id: skin-alphacoders
name: 'dsh-skin-alphacoders'
2. 双半插件包(Host + Client)
DSH 插件运行在 Cordis 运行时上。Web 场景下一个包有两个入口:
- node 半(
exports["."]):跑在 Host 进程,能访问文件、网络、settings 服务、HTTP 服务器; - 浏览器半(
exports["./client"]):跑在页面里,负责 UI 与 DOM。
package.json 里用 dsh.client 声明浏览器半:
"dsh": {
"client": {
"platform": "web",
"immediately": false,
"inject": [
"@deepseek-ai/dsh-client-runtime",
"@deepseek-ai/dsh-client-locale",
"@deepseek-ai/dsh-client-ui-slots"
]
}
}
3. 客户端模块系统:__DSH_BOOT__
Web 壳启动时,host 侧会扫描浏览器插件名录,把配置项图注入首页的 window.__DSH_BOOT__。浏览器半的产物不是普通 ESM——它必须是一个单文件 + CJS 工厂:
window.__ModuleLoader__.load({
id: "dsh-skin-alphacoders",
factory: (require) => {
var module = { exports: {} }
var exports = module.exports
// ……你的 CJS 代码……
return module.exports
}
})
工厂里的 require 由模块系统提供(react、react/jsx-runtime 在 seed 表里),所以外部依赖只能引用模块表里的包,其余依赖必须打进 bundle。这就是为什么我用 tsdown 单独构建 client 为 CJS、再写了个 wrap-client.mjs 脚本做包装。
4. 主题系统:Token + ThemeRuntime
DSH 的配色是一套两层 CSS 变量:--dsw-static-*(静态色板)+ --dsw-alias-*(语义别名,如 --dsw-alias-bg-base)。客户端有 ctx.theme(ThemeRuntime)服务:
register(theme):注册第三方主题overrideTokens(source, tokens):在活动主题上叠加一层 token 覆盖(每个 token 要给 light/dark 两套值)theme/change事件:主题切换、系统配色变化时触发
壁纸皮肤的"表面透出壁纸"就是通过 overrideTokens 把背景系 token 改成 rgba(..., 0.55) 实现的——走官方机制,不直接改 DOM。
5. settings 的白名单,与绕行方案
DSH 的 settings 有 wire 白名单:浏览器经 api-proxy 只能读写 locale、ui-theme 等内置 namespace,仓库外插件注册的 namespace 一律返回 settings-not-exposed(这是我踩的第一个大坑)。
解决方案:Host 半仍用 ctx.settings.register('ui-skin', schema) 注册并持有 owner scope(进程内读写不受白名单限制),浏览器侧则走插件自己的 HTTP route 完成读写——数据最终还是落在 settings.yaml 的 ui-skin 分节。这是 DSH 为第三方插件预留的正规扩展点:ctx.webServer.register({ kind: 'prefix', path: '/skin-alphacoders', handler })。
三、开发流程复盘
1. 需求先行
先写了需求文档:功能(壁纸库/应用/持久化/明暗联动)、非功能(性能/可读性/合规)、技术方案、验收标准。后续每一轮迭代都回填实现状态。
2. 调研:读文档 + 实测数据源
DSH 随包分发文档,各插件包都有 README(dsh-client-ui-theme、dsh-settings、dsh-host-webserver…),加上 cordis-plugin-development SKILL。Alphacoders 则是实测:发现热门页是服务端渲染的 schema.org ImageObject(15 条/页、?page=N 分页),图片 CDN 无鉴权直连,还挖出了 thumb-1920-<id> 中等尺寸变体——避免为背景下载 5K/8K 原图。
3. 架构:职责按平台切分
Host 半:抓取+解析 alphacoders(含搜索)+ TTL 缓存
+ settings 注册 + 本地图片存储 + HTTP route
Client 半:皮肤 store + 壁纸背景层 + 设置页 UI(React)
浏览器永远只跟同源的 /skin-alphacoders/* 打交道,没有 CORS 面。
4. 构建链
- Host 半:tsdown 输出 ESM 单文件;
- Client 半:tsdown 输出 CJS 单文件,
wrap-client.mjs再包成__ModuleLoader__工厂; schemastery等浏览器模块表里没有的依赖用deps.alwaysBundle打进 bundle。
5. 隔离测试 + E2E
用一个独立的 DSH_HOME + 3090 端口起测试实例(不动正式 3080),HTTP 层用脚本验证,UI 层用 puppeteer-core 驱动系统 Chrome 跑 23 项断言:画廊渲染、应用壁纸、明暗联动、持久化、搜索、本地上传、文件清理、卸载恢复……
6. 踩坑记录
| 坑 | 解法 |
|---|---|
settings 白名单 settings-not-exposed | Host 持 owner scope + 插件自有 route 读写 |
overrideTokens 会同步发布 theme/change,形成重入风暴(实测 500+ 层递归) | token 覆盖层按签名去重,输入不变绝不重建 |
pnpm file: 依赖是硬链接副本,改源码不生效 | 开发期用目录联接(Junction)直连源码 |
| 全表面半透明导致文字不清(用户反馈) | 迭代出最终方案:主表面透壁纸,但设置面板的 --dsw-alias-bg-layer-2 不覆盖,面板保持不透明、文字清晰 |
四、安装使用
# 1. 构建
npm install && npm run build
# 2. 安装进 web profile
dsh plugin --profile web add "file:<本包绝对路径>"
# 3. $DSH_HOME/profiles/web/cordis.patch.yml 登记插件行
# - insert:
# - id: skin-alphacoders
# name: 'dsh-skin-alphacoders'
重启 dsh web,打开「设置 → 壁纸」即可使用。
五、欢迎体验与共建
- 📦 GitHub 仓库:github.com/sakka6868/d…
- 🏷️ 话题页:github.com/topics/dsh-…
- 🧪 内置 23 项 E2E 验证(
e2e/verify.mjs),中英双语 README
如果你也在折腾 DeepSeek Harness,欢迎 Star、提 Issue 或 PR;后续计划:官方 API 通道、壁纸自动轮换、配套主题色。
壁纸版权归原作者与 Alphacoders 所有,本插件仅供个人使用。