跪拜 Guibai
← Back to the summary

A Wallpaper Skin Plugin for DeepSeek Harness, Built from Scratch

1. What is the project

DeepSeek Harness is a coding Agent runtime platform launched by DeepSeek (dsh web starts a Web GUI, defaulting to http://127.0.0.1:3080). It supports three themes — light, dark, and follow system — but has no ability for custom backgrounds.

dsh-skin-alphacoders is a skin plugin: it turns Alphacoders popular wallpapers into the Web GUI's background, with features including:

Wallpaper effect

Settings panel


2. DSH plugin mechanism: how a plugin runs

This section is the meat — once you understand it, you can write any plugin for DSH.

1. Profiles and the composition layer

DSH organizes runtime configuration with profiles, located at $DSH_HOME/profiles/<name>. web is a built-in profile whose configuration tree is composed of several layers stacked in order:

  1. Composition bundle patches declared in dsh.profile.bundles (@deepseek-ai/dsh-base, @deepseek-ai/dsh-web-app)
  2. The profile's own cordis.patch.yml
  3. The home-level $DSH_HOME/cordis.patch.yml

Each patch is a bunch of plugin lines: id + name (package name) + config. The official way to add a third-party plugin to web is:

dsh plugin --profile web add <package-name>

Then register a line in cordis.patch.yml:

- insert:
    - id: skin-alphacoders
      name: 'dsh-skin-alphacoders'

2. Dual-half plugin package (Host + Client)

DSH plugins run on the Cordis runtime. In a web scenario, a package has two entry points:

package.json declares the browser half with dsh.client:

"dsh": {
  "client": {
    "platform": "web",
    "immediately": false,
    "inject": [
      "@deepseek-ai/dsh-client-runtime",
      "@deepseek-ai/dsh-client-locale",
      "@deepseek-ai/dsh-client-ui-slots"
    ]
  }
}

3. Client module system: __DSH_BOOT__

When the web shell starts, the host side scans the browser plugin registry and injects the configuration map into the page's window.__DSH_BOOT__. The browser half's output is not ordinary ESM — it must be a single file + CJS factory:

window.__ModuleLoader__.load({
  id: "dsh-skin-alphacoders",
  factory: (require) => {
    var module = { exports: {} }
    var exports = module.exports
    // ……your CJS code……
    return module.exports
  }
})

The require inside the factory is provided by the module system (react, react/jsx-runtime are in the seed table), so external dependencies can only reference packages in the module table; all other dependencies must be bundled in. That's why tsdown is used to separately build the client as CJS, with an additional wrap-client.mjs script to do the wrapping.

4. Theme system: Token + ThemeRuntime

DSH's color scheme is a two-layer CSS variable system: --dsw-static-* (static palette) + --dsw-alias-* (semantic aliases, e.g. --dsw-alias-bg-base). The client has a ctx.theme (ThemeRuntime) service:

The wallpaper skin's "surface reveals wallpaper" effect is achieved by using overrideTokens to change background tokens to rgba(..., 0.55) — using the official mechanism, not directly modifying the DOM.

5. Settings whitelist, and the workaround

DSH's settings have a wire whitelist: the browser, via api-proxy, can only read/write built-in namespaces like locale and ui-theme. Namespaces registered by plugins outside the repo always return settings-not-exposed (this was the first big pitfall).

The solution: the Host half still uses ctx.settings.register('ui-skin', schema) to register and hold the owner scope (in-process reads/writes are not restricted by the whitelist), while the browser side goes through the plugin's own HTTP route for reads and writes — the data ultimately lands in the ui-skin section of settings.yaml. This is the official extension point DSH reserves for third-party plugins: ctx.webServer.register({ kind: 'prefix', path: '/skin-alphacoders', handler }).


3. Development process review

1. Requirements first

A requirements document was written first: features (wallpaper library / apply / persistence / light-dark linkage), non-functional requirements (performance / readability / compliance), technical approach, acceptance criteria. Each subsequent iteration backfilled the implementation status.

2. Research: reading docs + testing the data source

DSH ships with documentation; each plugin package has a README (dsh-client-ui-theme, dsh-settings, dsh-host-webserver…), plus the cordis-plugin-development SKILL. Alphacoders was tested empirically: the popular page turned out to be server-rendered schema.org ImageObject (15 items per page, ?page=N pagination), image CDN has no auth and is directly accessible, and a thumb-1920-<id> medium-size variant was discovered — avoiding downloading 5K/8K originals for backgrounds.

3. Architecture: responsibilities split by platform

Host half: fetch + parse alphacoders (including search) + TTL cache
           + settings registration + local image storage + HTTP route
Client half: skin store + wallpaper background layer + settings page UI (React)

The browser only ever talks to same-origin /skin-alphacoders/*, with no CORS surface.

4. Build chain

5. Isolated testing + E2E

A separate DSH_HOME + port 3090 was used to start a test instance (leaving the real 3080 untouched). The HTTP layer was verified with scripts, and the UI layer used puppeteer-core driving the system Chrome to run 23 assertions: gallery rendering, wallpaper application, light-dark linkage, persistence, search, local upload, file cleanup, uninstall recovery…

6. Pitfalls log

Pitfall Solution
Settings whitelist settings-not-exposed Host holds owner scope + plugin's own route for reads/writes
overrideTokens synchronously publishes theme/change, causing a re-entry storm (measured 500+ layers of recursion) Token override layer deduplicates by signature; no rebuild when input is unchanged
pnpm file: dependencies are hardlink copies, source changes don't take effect Use directory junctions during development to link directly to source
Full-surface translucency makes text unreadable (user feedback) Iterated to final solution: main surfaces reveal wallpaper, but --dsw-alias-bg-layer-2 on the settings panel is not overridden, keeping the panel opaque and text clear

4. Installation and usage

# 1. Build
npm install && npm run build

# 2. Install into web profile
dsh plugin --profile web add "file:<absolute-path-to-this-package>"

# 3. Register the plugin line in $DSH_HOME/profiles/web/cordis.patch.yml
# - insert:
#     - id: skin-alphacoders
#       name: 'dsh-skin-alphacoders'

Restart dsh web, then open "Settings → Wallpaper" to use.


5. Welcome to try and contribute

If you're also tinkering with DeepSeek Harness, Star, open an Issue, or send a PR is welcome; future plans: official API channel, automatic wallpaper rotation, matching theme colors.

Wallpaper copyright belongs to the original authors and Alphacoders. This plugin is for personal use only.