Introduction

The DSH (DeepSeek Harness) web version has several interface elements written into the host build artifacts: the brand Logo in the top-left corner of the sidebar, the welcome area when the conversation is empty, and the background color of the conversation area. To switch to your own logo or background image in an internal deployment, the conventional method is to modify the host build, but you have to redo it every time the host updates.

dsh-customui-plugin changes the approach: instead of modifying the host build, it injects a script into the browser via the plugin mechanism to overlay at the DOM layer, while also providing a formal entry point for these changes in the settings page. Below is an introduction to its functions, principles, and installation steps.

What is this

dsh-customui-plugin is a DSH web platform plugin, repository address is https://github.com/nexsjournal/dsh-customui-plugin, license is MIT. It does one thing: add a “Personalization” navigation item in the DSH web version’s settings page, through which three interface elements can be customized—the sidebar top-left Logo, the empty conversation welcome area (Logo + copy), and the conversation area background image. All modifications take effect in real-time, no need to restart DSH.

The plugin has no build steps: lib/index.js (host side, registers settings + whitelist patch) and lib/client.js (browser side, settings page + real-time application engine) are both pure JS, so you can read the source code directly before installation.

Core Features

Setting Item Description
Top-left Logo Replace the brand identity in the top-left corner of the sidebar (effective when sidebar is expanded). Suggest horizontal SVG, display height 24px.
Welcome Area Logo Replace the small fish icon in the empty conversation welcome area, display height 34px.
Welcome Area Copy Leave empty to keep the original welcome message; fill in to only show that copy (Logo can be shown together).
Conversation Background Image Placed behind the conversation area (messages + input box), supports “Cover / Fit” and 0-100% opacity. Suggest 1600x900 (16:9 horizontal).

Each image item supports two sources:

  1. Upload local image. The client auto-compresses: bitmaps are scaled to no more than 1920px and converted to JPEG/PNG; SVGs are kept as is.
  2. Paste https image link.

Other capabilities:

  • Real-time modification: Pure browser DOM overlay + MutationObserver monitoring; custom content is automatically restored after React re-renders, switching sessions, or sidebar collapse; application logic is idempotent.
  • Configuration is written to the DSH settings namespace customui, persisted with the profile, falling into the customui section of ~/.dsh/settings.yaml.
  • Supports one-click “Restore Defaults” to clear stored configuration.

Principle of Real-time Application

The plugin does not modify the host build, relying on two layers of mechanisms.

The first layer is anchor point selection. The client script does not bind hash class names that change with the build, but uses three stable design constants as anchors:

Brand Lettermark   svg[viewBox="0 0 182 24"]
Welcome Area Fish svg[viewBox="0 0 23.16 17.04"]
Conversation Area [data-conversation-scroll]

The second layer is continuous monitoring. The MutationObserver watches the DOM; custom content is automatically restored after React re-renders, switching sessions, or sidebar collapse; application logic is idempotent, so there is no infinite loop. Configuration is stored in the customui namespace; whenever the namespace changes, it is immediately reapplied—so changing it on the settings page makes the interface change immediately.

The specific placement of the background image: placed on the [data-conversation-scroll] container, via the ::before pseudo-element, z-index:-1, and real CSS opacity control. When the opacity is below 100%, the conversation area background color will show through, blending with light and dark backgrounds.

Installation and Enablement

Prerequisites: You need an existing DSH web deployment (dsh web or desktop version); plugin engines require Node >= 20.

Execute the installation script:

# Method 1: Current repository directory (dev link: soft link install, changes take effect immediately)
bash scripts/install.sh

# Method 2: npm / GitHub
bash scripts/install.sh dsh-customui-plugin@1.0.0
bash scripts/install.sh git+https://github.com/<owner>/dsh-customui-plugin.git

Two notes:

  1. The version numbers in the npm examples follow the style in the plugin README (@1.0.0), which is inconsistent with 0.1.0 in the repo’s package.json; the actual published version takes precedence during installation.
  2. <owner> in the GitHub example is a placeholder in the README and needs to be replaced with the actual repository owner; the repository address for this plugin is mentioned above.

If you don’t use the script, the equivalent manual steps are:

dsh plugin --profile web add -w /path/to/dsh-customui-plugin

-w is required because the profile is the pnpm workspace root.

After installation, you need to restart DSH once. Reason: When the plugin starts, it idempotently adds the customui namespace to the api-proxy whitelist of the Web settings page (WEB_SETTINGS_NAMESPACES of dsh-host-apiproxy), so the “Personalization” navigation item and settings writing only appear after the next startup. After that, all configuration modifications are hot-applied, no restart needed.

Additionally, desktop version updates (overwrite install) will reset the api-proxy whitelist file; after restart, the plugin will automatically patch again, no manual handling needed.

Typical Usage

After the steps above, restart DSH and open the settings page; a “Personalization” item will appear in the side navigation (parallel with General Settings, Model, Plugins, Agent Presets, etc.). The following flow:

  1. Enter the “Personalization” settings page.
  2. Set the top-left Logo, welcome Logo & copy, and conversation background image item by item; images can be uploaded local files or pasted https links.
  3. Each change reflects on the interface immediately, no refresh or restart needed.

To return to the original interface, click “Restore Defaults” to clear stored configuration.

Uninstall the plugin:

dsh plugin --profile web rm dsh-customui-plugin

Execute a restart of DSH after uninstalling, and click “Restore Defaults” once more to clear the configurations that have already been written to the profile.

Developer Perspective

For developers who want to study the writing of DSH plugins, the packaging method of this plugin is worth looking at. package.json declares two blocks:

  • dsh.bundle.patch points to ./cordis.patch.yml, responsible for host bundle tree insertion;
  • dsh.client.inject injects four client packages: @deepseek-ai/dsh-client-runtime, @deepseek-ai/dsh-client-locale, dsh-client-ui-slots, dsh-client-ui-settings, with platform as web.

@deepseek-ai/dsh-settings and @deepseek-ai/schemastery in peerDependencies are both optional.

After modifying the source code, you can do syntax checking:

node --check lib/index.js && node --check lib/client.js

The file structure is as follows:

├── package.json          # dsh.bundle.patch + dsh.client.inject declaration
├── cordis.patch.yml      # Host bundle tree insertion
├── dsh.plugin.json       # Plugin manifest
├── lib/
│   ├── index.js          # Server side: customui settings namespace + api-proxy whitelist self-patch
│   └── client.js         # Browser side: personalization settings page + real-time DOM application engine
├── scripts/install.sh
├── LICENSE
└── README.md

Suitable Scenarios and Notes

Suitable scenarios:

  • Team internal deployment of DSH, wanting to switch to own brand Logo, welcome message or unified background image;
  • Individuals wanting to match a background image for the conversation area, or replace the default welcome message;
  • Plugin developers wanting to reference the “Settings Namespace + Client Injection + API-proxy Whitelist Self-patch” approach.

Known boundaries, confirm before use:

  • In the sidebar collapse (rail) state, only icons are shown and the lettermark is not rendered; the top-left Logo does not work in this state and restores after expanding;
  • The welcome area only shows in empty conversations; it disappears after messages appear (background image is not affected);
  • If a certain version of DSH’s message bubble has an opaque background, the background image will be blocked; you can lower the opacity or change the image;
  • Images are saved as data URLs in the customui section of ~/.dsh/settings.yaml; although automatically compressed during upload, it is still recommended to use images in the tens of KB to hundreds of KB range.

Regarding security: DSH plugins run with the permissions of the current dsh process; you should check the source code and license before installing any third-party plugin. As for this plugin: no build steps, the two files under lib are pure JS, and the license is MIT, making the review cost relatively low.

Conclusion

dsh-customui-plugin uses the plugin mechanism to fill the interface personalization capability for the DSH web version: changes take effect in real-time, persisted with the profile, and do not require modifying the host build. For teams wanting to change branding for internal deployment, or developers wanting to learn the writing of DSH plugins, you can first read through the source code.

DSH’s philosophy is “Everything is a plugin”; such personalization plugins are the normal usage of this mechanism.

  • Plugin directory page: https://www.skillhub.cn/plugins/nexsjournal/dsh-customui-plugin
  • GitHub repository: https://github.com/nexsjournal/dsh-customui-plugin

skillhub.cn is an independent community plugin directory with no official affiliation with DeepSeek or Fangfang.