原生皮肤市场与生命周期管理器,发现社区皮肤、展示预览与兼容状态,并提供已验证的一键安装或手动安装入口。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-skin-market
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:kingOfSoySauce/dsh-skin-market
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
一个嵌入 DSH 设置页的皮肤市场,可以浏览、安装、使用、停用、更新和卸载社区皮肤。
在线预览
近期收录
安装
命令安装:
安装前请确保已关闭其他皮肤插件,避免冲突
# Web 版
dsh plugin --profile web add "dsh-skin-market@latest"
# 官方桌面版:不要在终端执行;在桌面应用「插件 → 添加插件」中输入并启用
dsh-skin-market@latest
提示词安装:
复制以下给 DSH Agent;它会先判断宿主,再选择安装方式。
请安装 dsh-skin-market。先运行 dsh --version,并根据当前宿主和实际 profile 的 package.json/bundles 判断是 Web 版还是官方 Desktop;无法判断就先问我。
- Web 版:先检查冲突,再执行 dsh plugin --profile web add "dsh-skin-market@latest"。
- 官方 Desktop:不要执行 dsh plugin --profile desktop;在桌面应用「插件 → 添加插件」中输入 dsh-skin-market@latest 并启用。
安装前只读检查当前宿主实际 profile,发现其他皮肤插件就列出并停下;没有冲突才安装。安装后验证同一 profile 中有 dsh-skin-market 的依赖和 bundle,并告诉我重启哪个宿主、从哪里打开「皮肤市场」。不要替我安装其他皮肤。
安装失败时,可以让 DSH 自己排查
皮肤市场的安装、更新和卸载会调用 DSH 的 profile 插件管理器;当前 DSH 使用
pnpm管理 profile 依赖。如果出现pnpm is not recognized、package manifest missing或allowBuilds相关报错,不必手动猜测 profile 状态。含子目录路径的 GitHub 目标(
github:…#commit&path:/…)请优先用市场页一键安装。市场安装结束后会校验node_modules中的包名是否与目录一致,避免&path:被截断时误把仓库根包装成成功。Windows 上不要把这段 spec 交给dsh plugin add:cmd.exe 会在&处截断。下面的手动命令仅适用于 Web profile;官方 Desktop 请使用桌面插件管理器:pnpm add "github:owner/repo#<commit>&path:/subdir" --dir $env:USERPROFILE\.dsh\profiles\web如果报错含
ERR_PNPM_UNEXPECTED_STORE,是 profile 的node_modules与当前 pnpm store 代际不一致(常见于本机同时装了 pnpm 10 / store v10 和 pnpm 11 / store v11)。在 profile 目录内 查看node_modules/.modules.yaml的packageManager和storeDir,再对比同一目录下的pnpm --version与pnpm store path;不要用 DSH 源码仓库目录里的结果来判断。用.modules.yaml记录的同一版 pnpm 重试,或用当前 pnpm 重建该 profile 的node_modules。Windows 上dsh plugin add走 PATH 上的 pnpm,不会因为源码仓库写了"packageManager": "pnpm@11"就自动切换。
把完整原始报错填入后复制给你的 DSH Agent。它会先判断当前是 Web 还是官方 Desktop;无法判断时先询问你:
请帮我排查 DSH 皮肤市场的安装或启用失败。先运行 dsh --version,并根据当前宿主和实际 profile 判断是 Web 版还是官方 Desktop;无法判断就先问我。下面是完整原始报错:
<把完整报错粘贴到这里>
如果是官方 Desktop:只读检查桌面应用插件管理器中的 dsh-skin-market 状态和完整原始错误;不要执行 dsh plugin --profile desktop,也不要手动修改 profile。若错误是 same-origin request required,请报告该错误并停止,不要猜测或重写 profile。
如果是 Web 版,请严格按以下 3 步处理,并报告每一步的结果:
1. 确认当前使用的 profile 名称和实际目录,并检查 DSH 进程自身是否能找到 pnpm(Windows 同时检查 pnpm.cmd)。如果 pnpm 不在 PATH,先说明如何安装或修复 pnpm,并停止把问题误判为 allowBuilds 配置问题。如果报错含 ERR_PNPM_UNEXPECTED_STORE,再比较 profile 的 node_modules/.modules.yaml(packageManager、storeDir)与「在 profile 目录内」执行的 pnpm --version / pnpm store path;不要用 DSH 源码仓库目录里的 pnpm 版本来判断。用同一版 pnpm 重试,或用当前 pnpm 重建该 profile 的 node_modules。
2. 只有确认 pnpm 可用且 store 一致后,才检查 profile 的 pnpm-workspace.yaml。若 pnpm 输出了构建审批 key,只把报错中完整、精确的 key 合并到 allowBuilds,对应值设为 true;不要启用 dangerouslyAllowAllBuilds,也不要放宽其他包。不要读取 .env、凭据或聊天记录。
3. 重新执行原来的皮肤安装命令。完成后验证 profile package.json 依赖、node_modules 中目标包的 package.json、dsh.client/dsh.bundle 声明和 loader 注册项;如果仍失败,请指出具体失败阶段和完整错误,不要把 package manifest missing 当作根因。
安装来源与长时间等待
Web 市场优先使用目录中已经核验的 npm 精确版本;没有合格 npm 来源时,继续使用原来的 GitHub 固定 commit。npm 来源须与目录的包名、版本、仓库、完整 commit 一致,并通过安装包完整性与已构建客户端入口检查。已有的 GitHub 安装仍然有效,不会仅因目录补充 npm 来源而要求重装。
安装横幅显示当前步骤、尝试次数和 pnpm 阶段;连续 30 秒没有输出时会提示,运行中也能复制诊断日志。Web 安装和更新的准备、下载、重试共用 15 分钟预算,达到时限后结束当前任务;已修改 profile 的失败操作只做一次、独立限时 60 秒的依赖恢复。市场会等待执行进程结束后再允许下一次操作,恢复未完成时会明确提示。Desktop 的安装失败恢复由宿主插件服务处理。
遇到长时间等待时,请提供皮肤名、DSH/市场版本、操作系统及市场横幅中的“复制日志”。浏览器能够访问 GitHub,不能单独证明实际运行 DSH 的进程和 pnpm 已使用相同代理;也可能卡在依赖解析或构建阶段。
更新本插件
方式一,页面更新(推荐):
在「设置 → 皮肤市场」标题右侧点击“更新”,完成后按界面提示重启 DSH Web 或官方 Desktop。
方式二,命令更新:
# Web 版
dsh plugin --profile web add "dsh-skin-market@latest"
# 官方桌面版:不要在终端执行;在桌面应用「插件 → 添加插件」中输入并启用
dsh-skin-market@latest
完成后按界面提示重启对应宿主。
方式三,提示词更新:
复制以下内容给 DSH Agent;它会先判断宿主,再选择更新方式:
请更新已安装的 dsh-skin-market。先运行 dsh --version,并根据当前宿主和实际 profile 判断是 Web 版还是官方 Desktop;无法判断就先问我。
- Web 版:只读确认 web profile 已安装 dsh-skin-market,再执行 dsh plugin --profile web add "dsh-skin-market@latest"。
- 官方 Desktop:不要执行 dsh plugin --profile desktop;在桌面应用「插件 → 添加插件」中输入 dsh-skin-market@latest 并启用。
更新后验证同一宿主的 dsh-skin-market 依赖和 bundle,告诉我更新前后版本及需要重启哪个宿主。不要替我更新或卸载其他皮肤。
收录你的皮肤
如果你开发了 DSH 皮肤,准备一个公开 GitHub 仓库后,向本仓库提 一个 registry/skins/<owner>__<repo>.yml 即可。YAML 只允许 url、subpath、name、author、description、screenshots;不要写 package、rowId、install 等字段。CI 会补全 package、commit、loader id 和预览图:
url: https://github.com/<owner>/<repo>
monorepo 子包加上 subpath:。也可以继续让 Agent 代为开 PR,复制下面提示词并把 <你的皮肤仓库地址> 换成真实地址。
这不是终端命令,而是交给 Agent 的任务说明:
复制以下整段提示词给你的 Agent:
请把我的 DSH 皮肤提交到 DSH 皮肤市场。
皮肤仓库:<你的皮肤仓库地址>
目标目录仓库:https://github.com/kingOfSoySauce/dsh-skin-market
目录路径:registry/skins
请自主完成以下工作:
1. 只用只读方式确认皮肤仓库是公开的 GitHub 仓库(或 monorepo 子目录),且确实是可安装的 DSH Web 皮肤。不要读取 .env、凭据或聊天记录。
2. fork 或 clone 目标目录仓库并新建分支。在 registry/skins 下只新增一个 YAML,不要覆盖已有条目,不要修改 data/catalog.json。
3. YAML 必须写成薄条目。只允许 url、subpath、name、author、description、screenshots。多写 package、rowId、category、tags、modes、compatibility、install 等字段会失败;CI 会从皮肤仓库补全其余字段:
url: https://github.com/<owner>/<repo>
# subpath: packages/my-skin # 仅 monorepo 子包需要
4. 预览图放在皮肤仓库的 screenshots.json 或 README 内;不要使用 SVG、data URI 或第三方图床。
5. 不要写完整 schema。若 registry:check 报缺少 id/install,删掉多余字段再跑,不要补全 schema。
6. 在目标目录仓库根目录运行 npm run registry:check。不得安装到我的真实 DSH profile。
7. git diff --name-only 应只有 registry/skins/<条目文件>.yml。提交并向目标目录仓库创建 PR,标题 feat(registry): add <皮肤名>。
8. 返回 PR 链接;没有 GitHub 权限时只准备好分支和可复制的 PR 内容。
收录不等于安全认证。不要声称该皮肤已被 DSH 官方、安全团队或市场背书。
皮肤市场里的「提交皮肤」也可以根据仓库地址生成这段提示词。
registry/skins/ 是社区提交的唯一事实来源,每个皮肤一个 YAML 文件。data/catalog.json 是生成文件,不需要在社区 PR 中维护;PR 合并到 main 后会由仓库自动重生成。这样新增皮肤之间不会因为共同编辑一个目录文件而反复冲突。
收录要求
皮肤市场同时支持带 dsh.bundle 的完整插件和只有 dsh.client 的纯前端皮肤。对于后者,市场会在安装后自动、幂等地写入该皮肤已审核的 rowId 和 package 注册项;卸载时一并移除。维护者不必为了进入市场而额外复制一份 cordis.patch.yml,但仍须在 package 或 README 中提供明确的 row ID 和 DSH 兼容范围。
- 必须是公开、可安装的 DSH Web 皮肤仓库或 monorepo 子包
- 安装来源必须固定到完整 40 位 commit SHA
- 必须提供明确的 package、row ID、许可证和兼容范围
- 预览图必须是仓库中的真实界面截图
- Topic、仓库名称和 Stars 只用于发现与排序,不代表安全审核或官方背书
仓库健康建议
市场在同步已收录仓库时会检查三项便于用户理解和安装的基础规范,并在皮肤详情页展示结果:
- README 是否展示仓库内、可固定到版本的真实界面截图
- README 或 package 元数据是否明确声明支持的 DSH Web 版本范围
- package 名称、
dsh.clientWeb 声明、row ID 和已构建客户端入口是否满足市场的一键安装要求
检查结果用于给维护者提供改进建议,不代表安全认证。暂未满足某项规范时,页面会说明如何完善,而不会把仓库描述为“不可用”。
“兼容性待验证”和“市场能否安装”是两个独立维度:
- 兼容性表示维护者是否明确声明并验证了支持的 DSH Web 版本;缺少声明时会提示风险,但不会单独阻止市场安装。
- 市场安装表示目录是否具备固定安装目标、package、
dsh.clientWeb 声明、row ID 和可解析的已构建客户端入口。符合这些条件时,市场会调用 DSH 的plugin add命令完成安装;不要求插件仓库自行实现名为add的命令。
兼容性验证
当前面向 DSH Web 0.1.0-rc.6。目录中的安装目标固定到收录时的完整 commit。
截至 2026-08-17,npm 的 DSH latest 与 next 均为 0.1.0-rc.6。本项目使用重新安装的该版本完成了以下验证:
- 皮肤市场
0.1.15:132 条目录校验、70 项自动化测试、类型检查、Host/Client 构建、站点构建和 package preflight 全部通过 - DSH Web 实机启动:市场 Host 路由、客户端设置入口、在线目录和 5 分钟静默更新正常加载
- Liang Intensity
0.1.4联合冒烟:8 项测试和客户端 bundle 构建通过,并可在同一 DSH Web profile 中保持 active
这组结果证明上述版本组合可以启动和运行,不代表市场内所有第三方皮肤都已完成同等级别的人工兼容或安全审核。
在线目录更新
已安装的皮肤市场不需要升级插件才能看到新收录或更新后的皮肤:
- 打开市场时由 DSH Host 从 GitHub Pages 拉取最新
catalog.json - 页面保持打开时每 5 分钟静默检查一次;窗口重新获得焦点时也会立即静默检查
- npm 上出现更高的市场插件版本时,标题右侧会显示下载按钮;悬停后显示“更新”,安装完成后提示重启生效
- 浏览器会用 IndexedDB 保留最近一次有效目录;再次打开时先展示缓存,再在后台校验在线目录
- 列表首批只渲染 20 个皮肤,接近底部时每次无感追加 20 个;搜索和排序仍覆盖完整目录
- 首次无缓存时显示结构化骨架屏,预览图延迟加载并保留固定尺寸,避免页面跳动
- 远程目录通过 schema、唯一 ID/package/rowId、GitHub 仓库地址和固定 commit 安装目标校验后,才会进入可安装生命周期
- 验证成功的目录会缓存到当前 profile;离线、超时或远程数据不合法时自动回退到缓存,再回退到插件内置目录
- 每日抓取任务在完整测试通过后直接部署在线目录,同时继续创建 registry PR 留下可审查记录
本地开发
需要 Node.js 22 或更高版本。
git clone https://github.com/kingOfSoySauce/dsh-skin-market.git
cd dsh-skin-market
npm install
npm run dev
npm run dev 只启动使用 Mock Host 数据的预览页面,不会修改任何 DSH profile。
本地目录调试
本地开发 DSH 皮肤时,市场默认仍会从 GitHub Pages 请求远程 catalog.json,因此刚写入本地 registry/skins 的条目可能被远程目录覆盖。启动 DSH Web 前设置下面的开发环境变量,市场会固定使用当前构建包内的 data/catalog.json,不发起远程目录请求:
DSH_SKIN_MARKET_LOCAL_CATALOG=1 dsh web
该开关只影响当前进程的目录读取;安装、激活、停用、更新和卸载仍然经过本地市场的完整生命周期。未设置时保持线上行为:优先读取远程目录,并在失败时回退到缓存和内置目录。
本地条目验证完成后,再删除该环境变量运行 DSH,确认远程目录行为没有被改变。
本地验证生成的 WebP
WebP 是独立的市场静态资源,catalog 中的 media 字段会让插件和在线页默认直接请求 GitHub Pages 上的 preview/full;没有对应 WebP 或请求失败时,继续使用原始 PNG/JPG。需要重新生成资源时,先安装 cwebp(macOS 可用 brew install webp),然后运行:
npm run registry
npm run media:build
本地调试默认也请求线上 WebP。只有需要关闭 WebP 对比原图时,才在地址后追加:
?dsh-media=0
对应仓库图片更新后,媒体脚本会重新下载并更新同一内容键;图片资源先发布到 ops 和 public market,插件代码可以单独发布。
常用检查命令:
npm run registry
npm test
npm run typecheck
npm run build
npm run release -- 0.1.31 --dry-run
正式发布时去掉 --dry-run;脚本会校验工作区、同步 npm 版本、提交并推送 Git tag,再发布 npm。需要同时创建 GitHub Release 时追加 --github-release。
完整的本地安装和回滚验证步骤见 TESTING.md。
目录维护
目录继续使用原来的 data/catalog.json URL 和 schemaVersion: 1。registry YAML 的 install.npm 在生成时移到顶层 npmSources[skinId],旧版市场忽略这个字段并继续使用 GitHub;新版验证包名、版本、仓库、commit/gitHead 和完整性信息后读取 npm 来源,Host 缓存也保存同一兼容格式。
新版 Web 市场首次安装优先使用已验证的 npm 包,没有匹配包时仍使用固定 commit 的 GitHub 源。普通“更新”保留已有安装来源;通过 GitHub 安装且与目录版本及 commit 一致的皮肤,会单独显示“换用 npm”,确认后换成同版本 npm 包并保留启用、常驻状态。正在使用的皮肤完成后提示重启;迁移失败走现有恢复流程。旧版本、分支、自定义本地源及手动安装条目不自动迁移。
公共仓库保留 registry Schema、目录生成和社区提交校验。候选发现、全量收录、实机截图补录和运营报告属于维护者内部流程,不随市场运行时发布;正式目录条目仍位于 registry/skins/,data/catalog.json 是生成文件。
市场截图会作为 marketScreenshots 与上游截图合并展示;公共构建只负责校验和合并,不包含截图采集或提升工具。
安全说明
- 浏览器只能提交 registry 中的
skinId,不能提交任意命令或安装地址 - 安装、更新和激活失败时会恢复 profile manifest 快照并清理半安装状态
- GitHub Stars 由定时收录任务写入带更新时间的目录快照,页面和 Host 都不在浏览时请求 GitHub API
- 市场不会代替开发者登录 GitHub,也不会静默创建 PR
页面异常时重置皮肤
如果皮肤冲突导致 DSH 页面无法操作,先停止当前 DSH 进程,再执行:
~/.dsh/profiles/web/node_modules/.bin/dsh-skin-market-reset --profile web
该命令会关闭皮肤市场管理的所有皮肤并恢复默认外观,但保留已经安装的皮肤包和皮肤市场。随后重新启动 DSH 即可。命令使用原子写入;任何一步失败都会恢复执行前的 profile 文件。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。