--- name: skin-developer description: Build a new skin for the dsh-web-ui skin collection (DSH Web GUI) and publish it into the skin-center plugin — scaffold with scripts/dsh-skin-new, author skin.json plus the apply/dispose + scoped-CSS contract, build and test with the official standalone bundle standard (turtle-ui shape), regenerate the skin-center registry and gallery, and submit the PR. Use when the user asks to create, add, develop, scaffold, or publish a new skin for the dsh web GUI skin collection. whenToUse: The user wants a new skin (新建/新增/开发一个皮肤), or wants to publish/发 skin-center, or asks how skins are built and shipped in the dsh-web-ui repo. Not for switching skins (scripts/dsh-skin) or gallery-only edits. --- # 皮肤开发者(dsh-web-ui 皮肤集合) 本技能指导在 `/Users/zcl/code/dsh-web-ui`(或任何 dsh-web-ui 克隆)里从零构建一个新皮肤, 并把它发布进 **skin-center 插件**(GUI 设置页 Skins 分区)与 gallery。每个皮肤是符合 DSH 官方插件标准(turtle-ui 式 setup)的自包含包,可被 `dsh plugin add` 安装。 ## 仓库与标准速览 - `packages/skins//` — 一个皮肤 = 一个自包含插件包;`packages/skins/qq98/` 是成熟样例,遇到疑问先读它。 - 官方标准四件套(对照 DSH `docs/user/develop/basic/publish.md`,turtle-ui 为范例): 1. `package.json` 声明 `dsh.bundle.patch` → `cordis.patch.yml`(安装时自动插入 `ui-skin-*` dshClient 行); 2. `cordis.patch.yml` — bundle patch 层; 3. `prepare` 脚本 = `tsdown`(pnpm 在 git 安装后自动运行,自包含构建 `lib/`,无项目引用、无类型检查); 4. devDependencies 只用真实发布版本(tsdown / lightningcss / cordis / vitest / jsdom)—— `@deepseek-ai/dsh-*` 未发布到 npm,运行时由宿主 shell 的 module table 提供,构建时作 external。 - 构建预设:`packages/skins/tsdown.client.ts`(官方 `packages/client/tsdown.client.ts` 的 standalone 移植)。 - 仓库是 pnpm workspace:根目录 `pnpm install` 一次即可构建/测试全部皮肤。 ## 0. 前置 ```sh cd pnpm install # 首次;顺带跑每个皮肤的 prepare ``` 先读 `packages/skins/qq98/` 的 `src/client/index.ts` 与 `skin.json`,理解 apply 契约与元数据契约。 ## 1. 脚手架 ```sh node scripts/dsh-skin-new # 如 matrix、coffee-break ``` 生成 `packages/skins//`:package.json(官方标准)、cordis.patch.yml、tsdown.config.ts、 tsconfig.json、skin.json(order 自动取最大值+1)、src/index.ts(无操作 host 入口)、 src/client/index.ts(最小 apply 模板)、`.module.css`(作用域样式)、tests/apply.spec.ts (契约测试)、README.md。随后按脚本打印的 next steps 填写。 ## 2. 皮肤契约(硬性约束,违反会挂评审) - **纯呈现层**:不注入服务、不发 cordis 事件、不触及模型请求(与既有皮肤一致)。 - `apply(ctx)` 只写自己会收回的东西:body 属性、注入的 chrome DOM、favicon、document.title; 所有写面在 `ctx.effect(() => () => {...}, 'ui-skin-: …')` 的 disposer 里**全部收回** (包括 body 属性、每个注入元素、favicon;标题仅在仍是皮肤自己的标题时才还原,不覆盖会话标题)。 - 样式全部挂在**自己的 body 属性**下:`body[data-dsh-]`;暗色变体 `body[data-dsh-][data-ds-dark-theme]`。不得用裸类名/全局选择器污染其它皮肤与官方 UI。 - CSS Modules:`import css from './.module.css'`,类名经 `css[name]` 取值; CSS 文本由 bundle 的 CSS-modules 自动注入(`