DeepSeek Harness 插件

dsh-client-ui-custom

客制化DSH(Custom DSH): web-surface theming (wallpaper, frosted glass, accent, translucent surfaces), configurable keyboard shortcuts (new conversation / model / thinking effort / composer gestures /(英文原文)

跳到安装方式

来源信息

GitHub 仓库
yoli-mi/dsh-client-ui-custom
最近更新
2026年8月17日
分类
趣味扩展
GitHub stars
8
载体类型
plugin
目录证据
上游声明已找到 dsh.bundle
证据路径
package.json#dsh.bundle
核对版本
0.1.0-rc.8
上游核对日期
2026-08-20

该证据由上游目录提供。本站没有安装、运行或安全审核这个插件。

安装

默认先复制一段 Prompt,让 Agent 读 GitHub 仓库和源码;需要自己装时再切到命令。

复制这段 Prompt,发给 DSH、Codex 或其他 Agent,让它先读 GitHub 仓库和源码。

请先不要安装或执行任何命令。阅读这个插件的 GitHub 仓库、README 和关键源码,然后用清楚、直接的方式回答以下问题,帮助我判断它是否适合我的需求:

1. 这个插件是什么,解决什么问题;
2. 适合哪些用户和典型使用场景;
3. 安装后如何使用,并给出一个最小使用示例;
4. 有哪些已知限制,以及隐私、安全、兼容性或维护风险;
5. 给出“推荐 / 有条件推荐 / 不推荐”的明确建议和理由。

请区分仓库明确说明、根据源码推断和未知信息。证据不足时请明确说明,不要猜测或照抄 README。

GitHub:https://github.com/yoli-mi/dsh-client-ui-custom
插件名:dsh-client-ui-custom
作者:yoli-mi

检查来源文件

安装前先看这个插件目录里的 README 和其他文件。

文件资源管理器3 个文件
README.md来源说明 · 只读预览

Dsh-Client-UI-Custom

<div align="center">

![Awesome DSH Plugin](https://beancookie.github.io/awesome-dsh-plugin)

[中文](#中文) · [English](#english)

</div>

---

中文

简介

Dsh-client-ui-custom 是一个纯前端插件,它为用户提供了浮动历史记录条、用户消息md渲染、外观调试、插件市场、快捷键和用量统计功能。

  • 修改了通用设置项 —— 在「设置 → 通用」里新增了历史记录条(位置、数量)和用户消息 Markdown 渲染开关;
  • 修改了插件项 —— 在「设置 → 插件」里新增了「插件市场」;
  • 新增了三个设置页 —— 「外观」「快捷键」「用量统计」。

所有功能默认关闭,不配置时保持与原生界面一致,全程零 shell 改动。

宣传视频

▶ 点击观看插件宣传视频(B 站)

功能选择(按需安装)

插件由六个相互独立的功能模块组成:appearance(外观)、shortcuts(快捷键)、 usage(用量统计)、history(历史记录条)、markdown(用户消息 Markdown 渲染)、marketplace(插件市场)。可在插件配置里用 features 白名单选择要安装的 功能:

- id: ui-custom
  name: '@ha-na-bi/dsh-client-ui-custom'
  config:
    features: [shortcuts, usage]   # 只安装「快捷键」+「用量统计」

features 缺省或为空时,六个功能全部启用。

---

设置改动一览

位置类型内容
设置 → 外观新增页面主题定制,包括壁纸、玻璃、强调色、表面不透明度、字体与质感
设置 → 快捷键新增页面自定义快捷键,包括新建对话、切换模型、思考强度等
设置 → 应用用量新增页面用量统计,使用四窗口聚合、趋势图,展示会话用量排行
设置 → 通用修改原有页新增浮动历史条(可调节位置,数量)、用户消息 Markdown 渲染开关
设置 → 插件修改原有页新增「插件市场」,收录第三方插件目录

---

外观(设置 → 外观)

外观设置提供给用户极大的自定义空间,用户可根据自己需求选择背景、玻璃档位、强调色(可自动从 背景取色)、各表面不透明度、色调渐变、暗色遮罩、字体与字号、主题色滚动条 与内嵌晕影,并可把 ui-theme 的主题偏好(浅色 / 深色 / 跟随系统)合并进本 栏。改动通过 ui-custom settings 命名空间保存并即时生效(主题实时重渲染, 无需重启)。

预览—— 主题定制支持小窗预览。

<img src="https://cdn.jsdelivr.net/gh/yoli-mi/dsh-client-ui-custom@main/assets/preview-mini.png" width="720" alt="小窗预览">

也支持全屏预览,按 F2 即可退出。

<img src="https://cdn.jsdelivr.net/gh/yoli-mi/dsh-client-ui-custom@main/assets/preview-fullscreen.png" width="900" alt="全屏预览">

预设(Preset) —— 插件内置了六种预设,每个预设都有独立的风格(预设可独立生效,你自己的 wallpaper 仍会叠加在它之下):

id名称风格
ink-tealInk Teal 黛青青玉色渐变,静谧沉稳
ink-blueInk Blue 黛蓝黛蓝渐变,深邃克制的蓝
dusty-roseDusty Rose 藕荷藕荷色渐变,温润柔和的粉
apricot-goldApricot Gold 杏金杏金色渐变,温雅低调的金
mist-grayMist Gray 雾灰雾灰色渐变,清冷安静的灰蓝
ink-violetInk Violet 墨紫墨紫色渐变,沉静神秘

更多美术选择后续会扩展进这份列表 —— 见 src/client/presets.ts

玻璃档位 —— glass 是透明度的开关;显式设置 wallpaperBlur 时总是优先于档位的默认半径:

档位模糊饱和度气质
off0px1.0不透明,无玻璃
light6px1.15轻微玻璃
frosted14px1.25强毛玻璃(默认)
mica22px1.1柔和静态质感,保留壁纸色相

主题配置项 —— 所有字段均可选;显式配置永远优先于预设:

类型默认值含义
presetstring''预设 id(见上表);'' = 不使用预设
wallpaperstring''壁纸 URL/路径(Web 可访问);空字符串 = 插件保持关闭
wallpaperBlurnumber 0–60玻璃档位默认#root 模糊半径(px);显式值优先于玻璃档位
glassenumfrostedoff / light / frosted / mica(见玻璃档位表)
accentstring#4176e6强调色,整套 deepseek 色阶由它派生
autoAccentbooleanfalse从壁纸自动派生强调色(成功后覆盖 accent
surfaceOpacitynumber 0–100100主表面不透明度(聊天/细节列)
sidebarOpacitynumber 0–100100侧栏不透明度
chatSurfaceOpacitynumber 0–100100聊天列不透明度(经 --dsw-chat-surface
inputOpacitynumber 0–100100输入框不透明度
codeBlockOpacitynumber 0–100100代码块/行内代码不透明度
darkSurfaceOpacitynumber 0–100surfaceOpacity暗色模式表面不透明度(独立档位)
gradientstring''亮色模式下叠加在壁纸上的渐变;空 = 无
darkScrimnumber 0–1000暗色模式下壁纸上的遮罩强度
fontFamilystring''字体栈覆盖;空 = 主题默认
scrollbarAccentbooleanfalse滚动条使用强调色
vignettebooleanfalse应用根节点的柔和内嵌晕影
customCssstring''原样追加的自定义 CSS(逃生舱)
customVarsobject{}额外写到 <html> 上的 CSS 自定义属性(逃生舱)

完整示例:

config:
  preset: 'ink-teal'
  wallpaper: 'https://example.com/wall.jpg'
  glass: 'mica'              # 或 wallpaperBlur: 8 自定义半径
  autoAccent: true           # 强调色由壁纸自动派生
  chatSurfaceOpacity: 70
  customCss: |
    .some-hashed-class { border-radius: 16px; }
  customVars:
    '--my-accent-soft': 'rgb(255 127 178 / 0.3)'

---

快捷键(设置 → 快捷键)

新增的设置页,提供可自定义的键位绑定。值存在 ui-custom settings 命名空间里,运行时的修改无需重启即可生效(loader 配置作为组合层 base, 「恢复默认」会回到 loader 默认值)。

动作作用
newConversation新建对话(与侧栏「新建会话」按钮一致)
switchModel循环切换到会话目录中的下一个模型(循环;新模型使用自身默认思考强度)
cycleThinking循环切换当前模型的思考强度(off → … → max,循环)
sendMessage输入框发送手势(默认 Enter
newline输入框换行手势(默认 Shift+Enter
usagePanel呼出应用用量面板(默认未绑定,可在设置中开启,如 Mod+Alt+U
defaultWorkspacenewConversation 打开的目标工作区(空 = 当前/最近)
modelShortcuts一对一模型直达:每个组合键跳到指定模型(combo / provider / model)

<img src="https://cdn.jsdelivr.net/gh/yoli-mi/dsh-client-ui-custom@main/assets/shortcuts.png" width="720" alt="快捷键设置页">

实例:

config:
  shortcuts:
    newConversation: 'Mod+Alt+N'
    switchModel: 'Mod+Alt+M'
    cycleThinking: 'Mod+Alt+T'

习惯 Enter 换行?把发送改为 Mod+Enter、换行改为 Enter 即可(两个手势 同时命中时发送优先):

config:
  shortcuts:
    sendMessage: 'Mod+Enter'
    newline: 'Enter'

模型动作走与内置模型选择器相同的 session.models / session.selectModel RPC,输入区的模型显示会自动同步;被寻址的子代理会话会被跳过(与 UI 一致)。 不带 Mod 的组合键在输入框聚焦时不会触发,避免劫持正常打字。

---

用量统计(设置 → 应用用量)

用量统计页会统计展示各会话的用量总和(token-meter + session-stats),用户可自选时间跨度 (当前年内到最近三天)。页面展示 总 / 输入 / 输出 Token、 缓存命中、使用时长、会话数与步数,并带用量趋势图与会话排行。 会话列表行已携带 Host 计算好的投影基线,无需额外 RPC。

面板可通过快捷键在任何界面呼出。

---

通用设置项的改动

在「设置 → 通用设置」里新增内容:

浮动历史条(位置 / 数量) —— 记录某段会话的历史内容:

  • 位置left / right / off(默认 off,关闭时不显示);
  • 数量:显示最近多少回合(默认 10,0 = 全部);
  • 点击某段历史条目即可平滑滚动到对应消息,条目来自已挂载的会话快照,纯 DOM 跳转,无额外 RPC;
  • 支持悬挂:在消息操作行(复制/分支之间)可选择将某段会话悬挂到历史条上,

置顶回合忽略数量限制、始终显示并带有强调色边框)。

用户消息 Markdown 渲染 —— 默认关闭;开启后你自己的消息按 Markdown 渲染(标题、列表、代码块、@子代理 / @技能 引用等),关闭时与原生 纯文本外观一致。

<img src="https://cdn.jsdelivr.net/gh/yoli-mi/dsh-client-ui-custom@main/assets/general-settings.png" width="720" alt="通用设置">

---

插件项的改动

在「设置 → 插件」里新增第三个 tab 「插件市场」,通过调用Github API 发现带有dsh-plugin topic的项目, 为用户提供第三方 DSH 插件目录。

<img src="https://cdn.jsdelivr.net/gh/yoli-mi/dsh-client-ui-custom@main/assets/marketplace.png" width="720" alt="插件市场">

---

安装

1. 确保构建会包含该包(pnpm run build:lib:client)。 2. 在 Web profile 的补丁层加入浏览器 roster 行 —— ~/.dsh/profiles/web/cordis.patch.yml(或你 profile 中对应的 dsh.client roster):

- id: ui-custom
  name: '@ha-na-bi/dsh-client-ui-custom'
  config:
    preset: 'ink-teal'        # 选择预设;下面任意字段会覆盖它
    wallpaper: '/my-wall.jpg'
    wallpaperBlur: 14

3. 重启 dsh web

自行构建时需注意:设置页要能加载,ui-custom 命名空间必须在 Web 客户端的 设置暴露白名单里(packages/host/apiproxy/src/api-proxy.tsWEB_SETTINGS_NAMESPACES)——本检出已加入。

---

工作原理

  • 浏览器半区先解析 preset(presets.ts),按 DEFAULTS ← 预设 ← 配置

合并并对每个字段做钳制(config.ts),再把 --dsu-* 自定义属性写到 <html>(apply.ts)。runner 会把 roster 行的 config 作为 apply(ctx, config) 的第二个参数传入。

  • 样式表(custom.module.css)消费这些变量,用比主题表更高优先级的选择器

body / body[data-ds-dark-theme] 上重新声明主题 token,插件总是 赢得级联,且不修改任何插件或 shell 源码。

  • 毛玻璃给 #rootbackdrop-filter,半透明表面透过它显示壁纸。
  • 聊天列旋钮依赖 ConversationRoot 读取

var(--dsw-chat-surface, var(--dsw-alias-bg-base)) —— 一行完全向后兼容 的回退写法(没有该 token 的原生 Harness 行为与之前完全一致),见 packages/client/ui-conversation

  • 框架结构:
packages/client/ui-custom/
├── src/client/
│   ├── index.ts          # 插件入口:解析预设 → 规范化 → 应用
│   ├── config.ts         # CustomThemeConfig、DEFAULTS、normalizeConfig(类型收窄+钳制)
│   ├── presets.ts        # ThemePreset 注册表 —— 美术选择的扩展面
│   ├── apply.ts          # config → DOM:--dsu-* 变量、customCss、customVars
│   ├── custom.module.css # 消费 --dsu-* 变量的 token 覆盖
│   └── …                 # 其余功能子目录(appearance/ settings/ usage/ marketplace/ history/ pin/ markdown/)
├── tests/                # 配置管线单元测试
└── README.md             # 本文档(中文 / English 双语)

注意事项

  • profile 的 cordis.patch.yml 改动需要重启 dsh web 才生效。
  • 壁纸必须能被浏览器访问(例如放在 Web 服务静态根目录下,或外部 URL)。
  • 插件自带的设置页(外观、快捷键、用量统计等)修改实时生效、无需重启;

通过内置「插件配置」页直接编辑 loader 层配置暂不支持(待 ui-settings-plugins 的 schema)。

---

English

Overview

Dsh-client-ui-custom is a pure front-end plugin that provides a floating history strip, user-message Markdown rendering, appearance customization, a plugin marketplace, keyboard shortcuts, and usage statistics.

  • Adds to General settings — new rows under Settings → General for the

floating history strip (position / count) and the user-message Markdown rendering toggle;

  • Adds to Plugin settings — a new "Plugin Marketplace" under Settings → Plugins;
  • Adds three new settings pages — Appearance, Shortcuts, and Usage statistics.

All features are off by default; without configuration the UI stays identical to stock, with zero shell modifications.

Feature selection (install on demand)

The plugin is composed of six independent feature modules: appearance, shortcuts, usage (usage statistics), history (history strip), markdown (user-message Markdown rendering), and marketplace (plugin marketplace). Use the features whitelist in the plugin config to choose which to install:

- id: ui-custom
  name: '@ha-na-bi/dsh-client-ui-custom'
  config:
    features: [shortcuts, usage]   # install only shortcuts + usage stats

When features is absent or empty, all six features are enabled.

---

Settings at a glance

WhereKindWhat
Settings → Appearancenew pagecustom theming: wallpaper, glass, accent, surface opacity, fonts & texture
Settings → Shortcutsnew pagecustom keybindings: new conversation, model switch, thinking effort, direct model jumps, etc.
Settings → App Usagenew pageusage stats: aggregated over a selectable time span, with a trend chart and session ranking
Settings → Generaladded rowsfloating history strip (adjustable position / count), user-message Markdown toggle
Settings → Pluginsadded tab"Plugin Marketplace": third-party plugin catalog

---

Appearance (Settings → Appearance)

Appearance offers a large customization space: you can choose the wallpaper, glass level, accent color (optionally auto-derived from the wallpaper), per-surface opacities, tone gradient, dark scrim, fonts & scale, accent scrollbar and an inset vignette, and merge the ui-theme theme preference (light / dark / system) into this section. Changes save through the ui-custom settings namespace and apply immediately (the theme re-renders live, no restart).

Preview — the theme supports a mini-window preview.

<img src="https://cdn.jsdelivr.net/gh/yoli-mi/dsh-client-ui-custom@main/assets/preview-mini.png" width="720" alt="Mini preview">

Fullscreen preview is also supported — press F2 to exit.

<img src="https://cdn.jsdelivr.net/gh/yoli-mi/dsh-client-ui-custom@main/assets/preview-fullscreen.png" width="900" alt="Fullscreen preview">

Presets — the plugin ships six built-in presets, each with its own distinct style (a preset works standalone, and your own wallpaper still layers under it):

idnamelook
ink-tealInk Teal 黛青jade-green gradient, quiet and steady
ink-blueInk Blue 黛蓝deep blue gradient, restrained and profound
dusty-roseDusty Rose 藕荷dusty-rose gradient, warm and gentle pink
apricot-goldApricot Gold 杏金elegant, understated warm gold
mist-grayMist Gray 雾灰cool, quiet gray-blue mist
ink-violetInk Violet 墨紫deep violet, serene and mysterious

More art choices will extend this list — see src/client/presets.ts.

Glass levelsglass is the translucency switch; an explicit wallpaperBlur always overrides the level's default radius:

LevelBlurSaturationVibe
off0px1.0opaque, no glass
light6px1.15subtle glass
frosted14px1.25strong frosted glass (default)
mica22px1.1soft static texture, keeps the wallpaper's hues

Theme config keys — every field is optional; explicit values always win over the preset:

KeyTypeDefaultMeaning
presetstring''Preset id (see the table above); '' = no preset
wallpaperstring''Wallpaper URL/path (web-reachable); empty string keeps the plugin off
wallpaperBlurnumber 0–60glass defaultBlur radius (px) on #root; an explicit value overrides the glass level
glassenumfrostedoff / light / frosted / mica (see the glass-level table)
accentstring#4176e6Accent color; the whole deepseek ramp is derived from it
autoAccentbooleanfalseDerive the accent from the wallpaper automatically (overrides accent on success)
surfaceOpacitynumber 0–100100Main surface opacity (chat/details columns)
sidebarOpacitynumber 0–100100Sidebar opacity
chatSurfaceOpacitynumber 0–100100Chat column opacity (via --dsw-chat-surface)
inputOpacitynumber 0–100100Composer input opacity
codeBlockOpacitynumber 0–100100Code block / inline code opacity
darkSurfaceOpacitynumber 0–100surfaceOpacityDark-mode surface opacity (independent knob)
gradientstring''Light-theme gradient layered over the wallpaper; empty = none
darkScrimnumber 0–1000Dark-theme scrim strength over the wallpaper
fontFamilystring''Font stack override; empty = theme default
scrollbarAccentbooleanfalseTint the scrollbar with the accent color
vignettebooleanfalseSoft inset vignette on the app root
customCssstring''Raw custom CSS appended verbatim (escape hatch)
customVarsobject{}Extra CSS custom properties written onto <html> (escape hatch)

Full example:

config:
  preset: 'ink-teal'
  wallpaper: 'https://example.com/wall.jpg'
  glass: 'mica'              # or wallpaperBlur: 8 for a custom radius
  autoAccent: true           # accent derived from the wallpaper
  chatSurfaceOpacity: 70
  customCss: |
    .some-hashed-class { border-radius: 16px; }
  customVars:
    '--my-accent-soft': 'rgb(255 127 178 / 0.3)'

---

Shortcuts (Settings → Shortcuts)

A new settings page with customizable keybindings. Values live in the ui-custom settings namespace, so runtime changes apply immediately without a restart (the loader config acts as the composition base, and Reset reverts to the loader defaults).

ActionWhat it does
newConversationStart a new conversation (same as the sidebar's New Session button)
switchModelCycle to the next model in the session's catalog (wraps; the new model starts at its own default reasoning effort)
cycleThinkingCycle the current model's reasoning effort (off → … → max, wraps)
sendMessageComposer send gesture (default: Enter)
newlineComposer newline gesture (default: Shift+Enter)
usagePanelPop the app-usage panel (unbound by default — enable it in Settings, e.g. Mod+Alt+U)
defaultWorkspaceThe workspace where newConversation opens (empty = current/recent)
modelShortcutsOne-to-one model jumps: each combo goes straight to a specific model (combo / provider / model)

<img src="https://cdn.jsdelivr.net/gh/yoli-mi/dsh-client-ui-custom@main/assets/shortcuts.png" width="720" alt="Shortcuts settings page">

Example:

config:
  shortcuts:
    newConversation: 'Mod+Alt+N'
    switchModel: 'Mod+Alt+M'
    cycleThinking: 'Mod+Alt+T'

Used to Enter for newlines? Set send to Mod+Enter and newline to Enter (when both gestures hit at once, send wins):

config:
  shortcuts:
    sendMessage: 'Mod+Enter'
    newline: 'Enter'

Model actions go through the same session.models / session.selectModel RPCs as the built-in model selector, so the model shown in the composer stays in sync; addressed subagent sessions are skipped (same as the UI). Combos without Mod do not fire while an input is focused, so they never hijack normal typing.

---

Usage statistics (Settings → App Usage)

The usage-statistics page aggregates each session's total usage (token-meter + session-stats) over a user-selectable time span, from the current year down to the last three days. It shows total / input / output tokens, cache hits, usage time, and session & step counts, together with a usage trend chart and a session ranking. The session list rows already carry the host-computed projection baseline, so no extra RPCs are needed.

The panel can be popped up from any screen via a shortcut.

---

General settings additions

New additions under Settings → General:

Floating history strip (position / count) — records the history of a conversation:

  • Position: left / right / off (default off — hidden when off);
  • Count: how many recent turns to show (default 10, 0 = all);
  • Clicking an entry smooth-scrolls to the matching message; entries come from

the mounted session snapshot, so jumping is a pure DOM operation — no extra RPCs;

  • Pinning is supported: from the message action row (between copy and

branch) you can pin a turn onto the strip; pinned turns ignore the count limit, always show, and carry an accent-colored border.

User-message Markdown rendering — off by default; when enabled your own messages render as Markdown (headings, lists, code blocks, @subagent / @skill references, …); when off, they look the same as stock plain text.

<img src="https://cdn.jsdelivr.net/gh/yoli-mi/dsh-client-ui-custom@main/assets/general-settings.png" width="720" alt="General settings">

---

Plugin settings additions

A third tab, "Plugin Marketplace", is added under Settings → Plugins: it calls the GitHub API to discover projects tagged with the dsh-plugin topic, providing a catalog of third-party DSH plugins.

<img src="https://cdn.jsdelivr.net/gh/yoli-mi/dsh-client-ui-custom@main/assets/marketplace.png" width="720" alt="Plugin marketplace">

---

Install

1. Make sure the package is included in your build (pnpm run build:lib:client). 2. Add a browser-roster row to your web profile's patch layer — ~/.dsh/profiles/web/cordis.patch.yml (or the corresponding dsh.client roster in your profile):

- id: ui-custom
  name: '@ha-na-bi/dsh-client-ui-custom'
  config:
    preset: 'ink-teal'        # pick a preset; any field below overrides it
    wallpaper: '/my-wall.jpg'
    wallpaperBlur: 14

3. Restart dsh web.

Self-builders: for the settings pages to load, the ui-custom namespace must be in the web client's settings exposure allowlist (WEB_SETTINGS_NAMESPACES in packages/host/apiproxy/src/api-proxy.ts) — it is already in this checkout.

---

How it works

  • The browser half first resolves preset (presets.ts), merges

DEFAULTS ← preset ← config and clamps every field (config.ts), then writes the --dsu-* custom properties onto <html> (apply.ts). The runner passes the roster row's config to apply(ctx, config) as the second argument.

  • The stylesheet (custom.module.css) consumes these variables and re-declares

the theme tokens on body / body[data-ds-dark-theme] with selectors that out-specify the theme sheets, so the plugin always wins the cascade — no plugin or shell source is modified.

  • Frosted glass adds backdrop-filter to #root, and translucent surfaces

show the wallpaper through it.

  • The chat-column knob relies on ConversationRoot reading

var(--dsw-chat-surface, var(--dsw-alias-bg-base)) — a one-line, fully backwards-compatible fallback (stock Harness behavior without the token is exactly as before). See packages/client/ui-conversation.

  • Framework layout:
packages/client/ui-custom/
├── src/client/
│   ├── index.ts          # plugin entry: resolve preset → normalize → apply
│   ├── config.ts         # CustomThemeConfig, DEFAULTS, normalizeConfig (type narrowing + clamping)
│   ├── presets.ts        # Them

…