🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

鲸鱼娘皮肤系列 Small-tailqwq/dsh-deep-whale

DeepSeek Harness
Small-tailqwq0 天前有提交已提供中文文档扫描:含敏感能力

DeepSeek Harness 的鲸鱼娘系列皮肤。

69.9/100
综合分
3,011
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查未通过:仓库根目录无 package.json,浅层子目录有 3 份 dsh 插件清单(maid-atelier/package.json、orca-link/package.json、skin-manager/package.json),无法唯一定位安装名。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Small-tailqwq/dsh-deep-whale
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · ui
装得上吗
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 0 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

仓库根目录无 package.json,浅层子目录有 3 份 dsh 插件清单(maid-atelier/package.json、orca-link/package.json、skin-manager/package.json),无法唯一定位安装名

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-deep-whale(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/2 02:36:33

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 110 处,展示前 64 条)
  • 读取本地文件
    maid-atelier/build/tsdown.client.ts:217
    const source = await readFile(fileId)
  • 读取本地文件
    maid-atelier/build/tsdown.client.ts:263
    if (existsSync(emitted)) return emitted
  • 读取本地文件
    maid-atelier/lib/index.js:25
    bytes = await readFile(new URL(file, directory));
  • 读取本地文件
    orca-link/build/tsdown.client.ts:217
    const source = await readFile(fileId)
  • 读取本地文件
    orca-link/build/tsdown.client.ts:263
    if (existsSync(emitted)) return emitted
  • 读取本地文件
    orca-link/lib/index.js:25
    bytes = await readFile(new URL(file, directory));
  • 读取本地文件
    shared/skin-assets.ts:28
    bytes = await readFile(new URL(file, directory))
  • 写入剪贴板
    skin-manager/lib/client.js:1076
    await navigator.clipboard?.writeText(info.local.hash);
  • 发起网络请求
    skin-manager/lib/client.js:2120
    const response = await fetch(SKIN_MANAGER_ROUTE, { credentials: "same-origin" });
  • 发起网络请求
    skin-manager/lib/client.js:2134
    const response = await fetch(SKIN_MANAGER_ROUTE, {
  • 发起网络请求
    skin-manager/lib/client.js:2149
    const response = await fetch(SKIN_MANAGER_ROUTE, {
  • 发起网络请求
    skin-manager/lib/client.js:2161
    const response = await fetch(SKIN_MANAGER_ROUTE, {
  • 发起网络请求
    skin-manager/lib/client.js:2184
    const response = await fetch(SKIN_MANAGER_ROUTE, {
  • 读取本地文件
    skin-manager/lib/index.js:37
    if (!existsSync(join(skinRoot, manifest))) return;
  • 读取本地文件
    skin-manager/lib/index.js:38
    const text = readFileSync(join(skinRoot, manifest), "utf8").replaceAll("\r\n", "\n");
  • 读取本地文件
    skin-manager/lib/index.js:44
    const bytes = readFileSync(join(skinRoot, input));
  • 读取本地文件
    skin-manager/lib/index.js:913
    const value = JSON.parse(readFileSync(manifest, "utf8")).version;
  • 读取本地文件
    skin-manager/lib/index.js:926
    const value = JSON.parse(readFileSync(join(profileDir, PROFILE_COMPATIBILITY_FILENAME), "utf8"));
  • 读取本地文件
    skin-manager/lib/index.js:1080
    const stat = statSync(file);
  • 删除本地文件
    skin-manager/lib/index.js:1148
    rmSync(this.parkMarkerPath, { force: true });
  • 写入本地文件
    skin-manager/lib/index.js:1152
    mkdirSync(dirname(this.parkMarkerPath), { recursive: true });
  • 写入本地文件
    skin-manager/lib/index.js:1153
    writeFileSync(this.parkMarkerPath, "");
  • 删除本地文件
    skin-manager/lib/index.js:1155
    rmSync(this.parkMarkerPath, { force: true });
  • 写入本地文件
    skin-manager/lib/index.js:1193
    mkdirSync(this.managedDir, { recursive: true });
  • 写入本地文件
    skin-manager/lib/index.js:1195
    copyFileSync(source.file, temporary);
  • 写入本地文件
    skin-manager/lib/index.js:1196
    renameSync(temporary, target);
  • 删除本地文件
    skin-manager/lib/index.js:1212
    if (/ ico$/i.test(file) && !keep.has(pathKey(full))) rmSync(full, { force: true });
  • 写入本地文件
    skin-manager/lib/index.js:1233
    mkdirSync(dirname(this.statePath), { recursive: true });
  • 执行外部命令固定命令
    skin-manager/lib/index.js:1325
    execFile("powershell.exe", [
  • 执行外部命令固定命令
    skin-manager/lib/index.js:1444
    const child = spawn("powershell.exe", [
  • 发起网络请求
    skin-manager/lib/index.js:1853
    const response = await fetch(url, {
  • 删除本地文件
    skin-manager/lib/index.js:2129
    if (existsSync(temporary)) rmSync(temporary, { force: true });
  • 删除本地文件
    skin-manager/lib/index.js:2149
    else rmSync(original.path, { force: true });
  • 读取本地文件
    skin-manager/src/compatibility.ts:37
    const value = (JSON.parse(readFileSync(manifest, 'utf8')) as { version?: unknown }).version
  • 读取本地文件
    skin-manager/src/compatibility.ts:50
    const value = JSON.parse(readFileSync(join(profileDir, PROFILE_COMPATIBILITY_FILENAME), 'utf8')) as unknown
  • 读取本地文件
    skin-manager/src/desktop-icon.ts:190
    const stat = statSync(file)
  • 读取本地文件
    skin-manager/src/desktop-icon.ts:257
    if (!scan && file === null && Object.keys(state.shortcuts).length === 0 && !existsSync(this.parkMarkerPath) && !this.hasManagedIcons()) {
  • 删除本地文件
    skin-manager/src/desktop-icon.ts:263
    rmSync(this.parkMarkerPath, { force: true })
  • 写入本地文件
    skin-manager/src/desktop-icon.ts:267
    mkdirSync(dirname(this.parkMarkerPath), { recursive: true })
  • 写入本地文件
    skin-manager/src/desktop-icon.ts:268
    writeFileSync(this.parkMarkerPath, '')
  • 删除本地文件
    skin-manager/src/desktop-icon.ts:270
    rmSync(this.parkMarkerPath, { force: true })
  • 读取本地文件
    skin-manager/src/desktop-icon.ts:292
    return readdirSync(this.managedDir).some(file => /\.ico$/i.test(file))
  • 读取本地文件
    skin-manager/src/desktop-icon.ts:300
    const bytes = readFileSync(source.file)
  • 读取本地文件
    skin-manager/src/desktop-icon.ts:303
    if (!existsSync(target)) {
  • 写入本地文件
    skin-manager/src/desktop-icon.ts:304
    mkdirSync(this.managedDir, { recursive: true })
  • 写入本地文件
    skin-manager/src/desktop-icon.ts:306
    copyFileSync(source.file, temporary)
  • 写入本地文件
    skin-manager/src/desktop-icon.ts:307
    renameSync(temporary, target)
  • 读取本地文件
    skin-manager/src/desktop-icon.ts:318
    files = readdirSync(this.managedDir)
  • 删除本地文件
    skin-manager/src/desktop-icon.ts:324
    if (/ ico$/i.test(file) && !keep.has(pathKey(full))) rmSync(full, { force: true })
  • 写入本地文件
    skin-manager/src/desktop-icon.ts:342
    mkdirSync(dirname(this.statePath), { recursive: true })
  • 执行外部命令固定命令
    skin-manager/src/desktop-icon.ts:444
    execFile('powershell.exe', [
  • 执行外部命令固定命令
    skin-manager/src/desktop-icon.ts:566
    const child = spawn('powershell.exe', [
  • 读取本地文件
    skin-manager/src/index.ts:119
    const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as {
  • 读取本地文件
    skin-manager/src/index.ts:146
    const own = JSON.parse(readFileSync(joinPath(dirname(manifestPath), 'package.json'), 'utf8')) as { name?: unknown }
  • 读取本地文件
    skin-manager/src/index.ts:158
    return existsSync(candidate) ? located(candidate) : null
  • 读取本地文件
    skin-manager/src/index.ts:161
    return existsSync(candidate) ? located(candidate) : null
  • 读取本地文件
    skin-manager/src/index.ts:211
    const entry = catalogEntry(JSON.parse(readFileSync(skin.manifestPath, 'utf8')) as SkinManifest, skin.packageName)
  • 读取本地文件
    skin-manager/src/index.ts:218
    manifest = JSON.parse(readFileSync(joinPath(dirname(skin.manifestPath), 'package.json'), 'utf8'))
  • 发起网络请求
    skin-manager/src/index.ts:482
    const response = await fetch(url, {
  • 写入本地文件
    skin-manager/src/index.ts:804
    mkdirSync(dirname(path), { recursive: true })
  • 写入本地文件
    skin-manager/src/index.ts:809
    writeFileSync(fd, text, 'utf8')
  • 写入本地文件
    skin-manager/src/index.ts:813
    renameSync(temporary, path)
  • 删除本地文件
    skin-manager/src/index.ts:816
    if (existsSync(temporary)) rmSync(temporary, { force: true })
  • 删除本地文件
    skin-manager/src/index.ts:844
    else rmSync(original.path, { force: true })
扫描于 2026/11/2(1 天前) · 范围 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

4 张 · 点击查看大图

功能亮点

  • 鲸鱼娘系列皮肤

README

由 DeepSeek 最新模型翻译生成
dsh-deep-whale · 鲸鱼娘皮肤系列 简体中文 · English · Tiếng Việt 给 DeepSeek Harness(DSH)Web 界面换上鲸鱼娘主题的皮肤合集,附带一个管理面板,用来切换皮肤。 效果预览 点击图片可查看完整尺寸。 | 皮肤 | 亮色模式 | 暗色模式 | | maid-atelier | maid-atelier 亮色模式 | maid-atelier 暗色模式 | | orca-link | orca-link 亮色模式 | orca-link 暗色模式 | 住户 | 皮肤 | 包名 | 说明 | 许可 | | maid-atelier | @smalltailqwq/dsh-client-ui-skin-maid-atelier | 深海女仆工坊:两位鲸鱼娘女仆、深海蓝蕾丝与 Q 版侧栏,把 DSH 布置成女仆工坊 | MIT (code) / CC BY-NC-SA 4.0 (artwork) | | orca-link | @smalltailqwq/dsh-client-ui-skin-orca-link | 虎鲸链路:酷酷的小黑鲸操作员,全直角界面加用直线重绘的图标;亮色机能,暗色治愈 | MIT (code) / CC BY-NC-SA 4.0 (artwork) |
展开完整文档(README 剩余 1 节)
dsh-deep-whale · 鲸鱼娘皮肤系列

简体中文 · English · Tiếng Việt

给 DeepSeek Harness(DSH)Web 界面换上鲸鱼娘主题的皮肤合集,附带一个管理面板,用来切换皮肤。

效果预览

点击图片可查看完整尺寸。

| 皮肤 | 亮色模式 | 暗色模式 |
| maid-atelier | maid-atelier 亮色模式 | maid-atelier 暗色模式 |
| orca-link | orca-link 亮色模式 | orca-link 暗色模式 |

住户

| 皮肤 | 包名 | 说明 | 许可 |
| maid-atelier | @smalltailqwq/dsh-client-ui-skin-maid-atelier | 深海女仆工坊:两位鲸鱼娘女仆、深海蓝蕾丝与 Q 版侧栏,把 DSH 布置成女仆工坊 | MIT (code) / CC BY-NC-SA 4.0 (artwork) |
| orca-link | @smalltailqwq/dsh-client-ui-skin-orca-link | 虎鲸链路:酷酷的小黑鲸操作员,全直角界面加用直线重绘的图标;亮色机能,暗色治愈 | MIT (code) / CC BY-NC-SA 4.0 (artwork) |
| skin-manager | @smalltailqwq/dsh-client-ui-skin-deep-whale-manager | 皮肤管理器:切换已安装的皮肤,调整各皮肤自带的选项,在「设置 → 皮肤管理」中打开 | MIT |

版权所有人

| 版权所有人 | 版权所有内容 | 对应皮肤 | 个人主页 |
| 上善 | 鲸鱼娘角色形象原作 | maid-atelier / orca-link | Pixiv · Bilibili(上善无形) |
| ZipZipPipe | 加入 DeepSeek 元素的女仆鲸鱼娘二次设计 | maid-atelier | Pixiv · Bilibili(ZipZipPipe) |

\反馈问题尽可能在 issue 中发起,而不是跑去联系上面两位老师。但是,看鲸鱼娘二创可以去关注一下,谢谢喵

安装

[!NOTE]
如果你用的是 dsh-web(装过 @linxin666/dsh-web-all),请直接在 dsh-web 自带的皮肤中心里安装 maid-atelier 和 orca-link,不要再运行下面的命令。两边的皮肤是分别适配的,装在同一个 profile 里会让界面显示错乱。

官方桌面版

1. 按需选择一套或多套皮肤。打开侧栏「插件」,点击「添加插件」,逐个填入下面对应的 npm 包名并安装。

| 插件 | npm 包名 |
| maid-atelier | @smalltailqwq/dsh-client-ui-skin-maid-atelier |
| orca-link | @smalltailqwq/dsh-client-ui-skin-orca-link |
| 皮肤管理器 | @smalltailqwq/dsh-client-ui-skin-deep-whale-manager |

2. 只装一套皮肤时,管理器可选;不装就无法使用配置面板、图形化版本兼容放行和自动多皮肤互斥管理。同时装多套皮肤必须安装并保持管理器启用,否则皮肤同时启用会让界面错乱。管理器一旦安装,即使只用一套皮肤也应保持启用。安装完成后按提示启用插件,然后重启一次 DSH。
3. 如果安装了皮肤管理器,重启后打开「设置 → 皮肤管理」。首次启动若仍显示官方界面,到这里选择要启用的皮肤即可。

想用 main 上的最新代码,也可以按所选皮肤和管理器,在同一个安装框里逐个填入对应的 GitHub 地址(只填地址,不加 dsh plugin add):

github:Small-tailqwq/dsh-deep-whale#main&path:/skin-manager
github:Small-tailqwq/dsh-deep-whale#main&path:/maid-atelier
github:Small-tailqwq/dsh-deep-whale#main&path:/orca-link

在默认配置下,DSH 捆绑的 pnpm 11.7.0 优先选择发布满 24 小时的 npm 版本。想立即安装某个刚发布的新版,可以在同一个「添加插件」框里填入 包名@^版本号,例如 @smalltailqwq/dsh-client-ui-skin-orca-link@^0.1.9(不加命令前缀)。这次显式 add 会安装新版,并把具体版本写入 pnpm-workspace.yaml 的 minimumReleaseAgeExclude,依赖仍保持 caret 范围。此行为对应捆绑版本及默认配置,其他 pnpm 版本或自定义策略可能不同。GitHub 来源不受这项 npm 包龄检查影响。
桌面版通过应用管理自己的 desktop profile,不需要先配置 dsh 命令。下面的 web 命令不会给桌面版安装皮肤。

CLI 安装的 Web 版

本页命令以 web profile 为例;如果你启动的是其他 CLI profile,请把命令中的 web 换成对应名称。

皮肤可以从 npm 或 GitHub 安装,两种来源装的是同一套皮肤,区别在于更新节奏:

| | npm(推荐) | GitHub |
| 拿到的版本 | 正式发布的版本,有固定版本号 | main 分支上的最新代码 |
| 什么时候能用上修复 | 通常在发版约 24 小时后(DSH 内置 pnpm 的默认包龄策略) | 修复合并后马上就能装 |
| 网络 | 可以配置 npm 镜像源,国内一般更稳 | 需要能访问 GitHub |

拿不准就选 npm。复制对应系统的命令运行即可,不需要 clone 仓库。

从 npm 安装

Linux / macOS / WSL
dsh plugin --profile web add '@smalltailqwq/dsh-client-ui-skin-deep-whale-manager' && dsh plugin --profile web add '@smalltailqwq/dsh-client-ui-skin-maid-atelier' && dsh plugin --profile web add '@smalltailqwq/dsh-client-ui-skin-orca-link'

PowerShell
dsh plugin --profile web add '@smalltailqwq/dsh-client-ui-skin-deep-whale-manager'; dsh plugin --profile web add '@smalltailqwq/dsh-client-ui-skin-maid-atelier'; dsh plugin --profile web add '@smalltailqwq/dsh-client-ui-skin-orca-link'

从 GitHub 安装

Linux / macOS / WSL
dsh plugin --profile web add 'github:Small-tailqwq/dsh-deep-whale#main&path:/skin-manager' && dsh plugin --profile web add 'github:Small-tailqwq/dsh-deep-whale#main&path:/maid-atelier' && dsh plugin --profile web add 'github:Small-tailqwq/dsh-deep-whale#main&path:/orca-link'

PowerShell
dsh plugin --profile web add 'github:Small-tailqwq/dsh-deep-whale#main&path:/skin-manager'; dsh plugin --profile web add 'github:Small-tailqwq/dsh-deep-whale#main&path:/maid-atelier'; dsh plugin --profile web add 'github:Small-tailqwq/dsh-deep-whale#main&path:/orca-link'

两种来源用的是同一个包名,后装的会替换先装的。想从一种换到另一种,直接用另一组命令重新装一遍即可。

装好后重启一次 DSH。如果装了管理器,打开「设置 → 皮肤管理」,在想用的皮肤上点「切换」。之后换皮肤都是即时生效,不用再重启。

- 只装一套皮肤时,可以删掉另一套皮肤和管理器的 add;不装管理器就无法使用配置面板、图形化版本兼容放行和自动多皮肤互斥管理。管理器一旦安装就应保持启用;同时装多套皮肤必须安装并保持管理器启用,避免皮肤同时启用。
- 两套都装了的话,首次重启后界面还是官方默认的样子,这是正常的:两套皮肤同时启用会互相打架,管理器会先把它们都关掉,等你来选。
- 不想自己敲命令,可以把这句话发给任意 AI(或 DSH 本身),它会按 INSTALL.md 帮你装好:

读取 https://github.com/Small-tailqwq/dsh-deep-whale/INSTALL.md 并按其中的指引安装本仓库皮肤

更新

桌面版:截至 DSH 0.2.0-rc.2,插件页没有升级入口,也不会自动更新第三方插件。在「插件」列表卸载要更新的插件,再按上面的步骤重新安装并启用,完成后重启 DSH。

CLI Web 版:只保留你实际安装的包名。

Linux / macOS / WSL
dsh plugin --profile web update @smalltailqwq/dsh-client-ui-skin-deep-whale-manager @smalltailqwq/dsh-client-ui-skin-maid-atelier @smalltailqwq/dsh-client-ui-skin-orca-link

PowerShell
dsh plugin --profile web update '@smalltailqwq/dsh-client-ui-skin-deep-whale-manager' '@smalltailqwq/dsh-client-ui-skin-maid-atelier' '@smalltailqwq/dsh-client-ui-skin-orca-link'

这条命令对 npm 和 GitHub 两种来源都适用:npm 来源会更新到最新发布的版本,GitHub 来源会拉取 main 上的最新代码。更新后刷新页面即可,不需要重启 DSH。如果这个 profile 里只装了本仓库的皮肤,也可以直接运行 dsh plugin --profile web update 更新全部插件。
在默认配置下,DSH 内置的 pnpm 11.7.0 优先选择发布满 24 小时的 npm 版本,所以 update 可能仍停在旧版。要立即安装某个新版,可以显式 add 包名加 @^版本号:pnpm 会安装新版,并把具体版本写入 pnpm-workspace.yaml 的 minimumReleaseAgeExclude,依赖仍保持 caret 范围。其他 pnpm 版本或自定义策略可能不同。版本号见 Releases:

dsh plugin --profile web add '@smalltailqwq/dsh-client-ui-skin-orca-link@^0.1.9'

版本号前的 ^ 不要省:省掉后会固定在这个版本,以后的 update 就不会再升级了。

遇到问题

升级 DSH 后皮肤不见了

每套皮肤只声明支持自己适配过的 DSH 版本(目前是 0.2 系列,从 0.2.0-rc.2 起)。DSH 升级到更新的版本而皮肤还没跟上时,DSH 会自动停用皮肤、恢复官方界面,免得皮肤把输入框之类的控件挡住。

先按上面的更新说明更新皮肤。如果还没有新版,又想先用着旧皮肤,可以打开「设置 → 皮肤管理」:被停用的皮肤会显示「未声明支持当前的 DSH x.y.z,已被自动停用」,点「切换」并确认即可。这个放行只针对当前的皮肤版本和 DSH 版本,任意一方升级后会重新检查;用得不顺手随时切回「官方默认」。

用命令行放行

dsh plugin --profile web allow-version @smalltailqwq/dsh-client-ui-skin-orca-link@<皮肤版本> --dsh-version <DSH 版本> --accept-risk

界面乱了:设置按钮不见、侧栏宽度异常、装饰叠在一起

多半是两套皮肤同时在运行。打开「设置 → 皮肤管理」,点「官方默认」或任意一套皮肤,刷新页面即可恢复。如果连设置都打不开,展开下方的皮肤互斥原理,按其中的方法手动修复。

装了但页面没变化

先刷新浏览器;仍然没有的话,去「设置 → 皮肤管理」确认目标皮肤处于启用状态。

更多情况见下方的常见安装报错。

进阶说明

以下内容大多数用户用不到,按需展开。

从 0.1.3 之前的旧版本迁移

0.1.3 之前从 GitHub 安装的版本用的是 @dsh-external/ 这个旧包名。请先移除这三个旧包,再按安装重新装,否则 DSH 里会同时留着两份同样的插件:

dsh plugin --profile web remove '@dsh-external/dsh-client-ui-skin-orca-link'
dsh plugin --profile web remove '@dsh-external/dsh-client-ui-skin-maid-atelier'
dsh plugin --profile web remove '@dsh-external/dsh-client-ui-skin-deep-whale-manager'

装好后重启一次 DSH。你之前选的皮肤和设置会保留,不受包名变化影响。

从本地目录安装(开发 / 测试指定提交)

本地开发,或者想测试某个指定提交时,可以 clone 仓库后按目录安装:

git clone --depth 1 https://github.com/Small-tailqwq/dsh-deep-whale
node <clone 的绝对路径>/.agents/skills/dsh-skin-install/scripts/stage-mutual-exclusion.mjs --profile web --target maid-atelier
dsh plugin --profile web add <clone 的绝对路径>/skin-manager
dsh plugin --profile web add <clone 的绝对路径>/maid-atelier
dsh plugin --profile web add <clone 的绝对路径>/orca-link

- 第二行 node 命令可以跳过。它的作用是提前选好默认皮肤,让第一次启动直接就是这套皮肤;--target 可以写 maid-atelier、orca-link 或 official(官方默认)。跳过的话,首次启动是官方界面,再去皮肤管理里切换即可。
- 路径请尽量写绝对路径,Windows 下正斜杠、反斜杠都行,例如 C:/Users/<你>/code/dsh-deep-whale/maid-atelier。
- 不要只写目录名:dsh plugin --profile web add maid-atelier 会被当成 npm 包名去下载,结果 404。相对路径要以 ./ 或 ../ 开头,并且是相对于你运行 dsh 命令时所在的目录,不是皮肤仓库目录;路径算错时命令不会报错,但皮肤不会生效。
- 本地目录和 npm、GitHub 来源用的是同一个包名,以最后一次 add 为准。

皮肤互斥原理

同一时间只能启用一套皮肤;皮肤管理器本身不算皮肤,安装后需要一直开着。同时安装多套皮肤时,必须安装并保持管理器启用来管理互斥。

每套皮肤的开关记录在两个配置文件里:~/.dsh/profiles/<profile>/cordis.patch.yml(profile 层,<profile> 为 web 或桌面版的 desktop 等实际名称)和 ~/.dsh/cordis.patch.yml(home 层,优先级更高)。文件里没有写某套皮肤时,它默认是开启的,所以一次装两套又从没切换过,它们就会同时运行,导致界面错乱。

皮肤管理器会处理这件事:

- 每次启动时,如果发现有两套以上皮肤同时开着,会把它们全部关掉、回到官方默认,已经选好的单套皮肤不受影响;
- 在「设置 → 皮肤管理」里切换时,会自动把开关写进两个配置文件并即时生效。
管理器用不了时,可以手动修改。把下面的内容同时加到上面两个文件里,想启用哪套,就把哪套设为 false,另一套设为 true:

- id: ui-skin-maid-atelier
disabled: false
- id: ui-skin-orca-link
disabled: true
- id: ui-skin-deep-whale-manager
disabled: false

如果文件还是 DSH 的默认模板(几行注释加一行 []),请用上面的内容替换掉 [] 那一行,否则文件格式会出错。也可以运行上一节的 stage-mutual-exclusion.mjs 自动写好,或者用 dsh plugin --profile web remove <包名> 直接卸掉不用的皮肤。

皮肤的个性化设置(例如「不那么二次元模式」的生效时段)保存在当前浏览器里,由管理器统一应用。

确认安装是否成功

桌面版:在「插件」列表确认所装的包已出现,重启后查看皮肤效果;装了管理器的,再到「设置 → 皮肤管理」选择皮肤。桌面版的 desktop profile 不支持 CLI 的 --dump-config,无需运行下面的命令。

CLI Web 版:

dsh plugin --profile web list # 应该能看到你选择安装的包
dsh --profile web --dump-config # 所选皮肤应为 disabled: false;如装了管理器,也应为 false

刚装完、还没重启时,两套皮肤可能都显示为启用,这是正常的,重启后管理器会处理。

重启后还可以在浏览器控制台运行下面这行,确认页面确实加载了皮肤脚本:

document.documentElement.outerHTML.match(/\/plugins\/@smalltailqwq\/[^"'\s]+/g) ?? []

结果里应包含当前启用的皮肤,以及你安装并启用的管理器;停用的皮肤不出现是正常的。

常见安装报错

| 现象 | 原因 | 处理 |
| ERR_PNPM_FETCH_404 | 包名拼错、网络不通,或本地安装时只写了目录名 | 直接复制本页的包名;本地安装改用绝对路径 |
| The matching commit... / 无法解析 ref | pnpm 版本低于 9,不支持 #path: 写法 | 升级 pnpm:npm i -g pnpm@latest |
| ERR_PNPM_EXOTIC_SUBDEP | 试图安装一个会再拉取 Git 依赖的聚合包(pnpm 11 的安全限制,本仓库不提供这类包) | 按本页命令分别安装三个包 |
| pnpm not found on PATH | 没有安装 pnpm | npm i -g pnpm 后重试 |
| 包已安装但页面没变化 | 皮肤处于停用状态,或浏览器没刷新 | 在皮肤管理里启用它,然后刷新页面 |
| PowerShell 命令不完整或报错 | 包名没加引号,# 后面被当成注释截掉了 | 包名一律用单引号包住 |

贡献者

感谢以下开发者对 dsh-deep-whale 的贡献:

有价值但未合入的 PR

以下 PR 因与现有上游实现冲突未能合入,但其功能需求已在仓库中落地,特此致谢:

- @yaoyiqun — 按所选模型切换角色位置(#15)
- @Chartreuse310 — 对话区衬线字体(#22)
- @Vergemesh — 原版/鲸鱼娘皮肤即时切换(#27)
- @joejojoking-cloud — top-trim 装饰层级(#26)、字符舞台层级(#31)修复

许可

项目自有代码采用 MIT,许可范围见 LICENSE。美术资源保留原作者版权与既有授权:两套皮肤的全部美术(包括 AI 生成及加工的图片)按 CC BY-NC-SA 4.0 使用,禁止商业性使用,署名链见各自 NOTICE,许可正文见 LICENSE-ARTWORK。图片即使嵌入源码、CSS 或构建产物,也不属于 MIT 授权范围。第三方材料保留其适用许可;历史版本已授出的权限不因本说明而撤销。

皮肤工程脚手架来自 zhu1090093659/dsh-web-ui,本仓库仅分发皮肤成品,不包含脚手架。
预览分享卡片长什么样 ↓Small-tailqwq/dsh-deep-whale
分享 · DeepSeek Harness Hub
Small-tailqwq/dsh-deep-whale

DeepSeek Harness 的鲸鱼娘系列皮肤。

回到顶部