DSH Plugins Marketplace

DSH Plugins

Plugins

/

UI & Experience

/

dsh-skin-rotation

l

dsh-skin-rotation

Manifest valid★ 1

Random skin rotation for DeepSeek Harness: a different installed skin on every launch, with an on/off switch inside Settings -> Skins.

UI (client)hasBundlePatch

dsh-skin-rotation
A different skin every launch — random skin rotation for DeepSeek Harness, with the switch where you expect it: inside Settings → Skins.

MIT test npm stars dsh-plugin

English | 中文


What it does

You have four skins installed. You like all of them. You use one of them.

dsh-skin-rotation picks a different one at random every time DeepSeek Harness starts, and puts a switch inside the Skins settings page to turn that off. It never shows the same skin twice in a row, it only picks skins the host can actually load, and it keeps its hands off everything else.

launch 1 → 深海女仆工坊      launch 2 → 虎鲸链路      launch 3 → 鲸鱼娘昼夜工坊

Install

From GitHub:

dsh plugin --profile web add github:luoyuejun9/dsh-skin-rotation

From npm:

dsh plugin --profile web add dsh-skin-rotation

Or from the prebuilt tarball attached to the latest release — no build step, no allowBuilds prompt:

dsh plugin --profile web add https://github.com/luoyuejun9/dsh-skin-rotation/releases/latest/download/dsh-skin-rotation.tgz

Restart once. Then open Settings → Skins: the rotation card sits at the bottom of that page.

Installing into the desktop app instead of the web profile? Use --profile desktop. The plugin works in both.

The switch

Settings → Skins
├── Installed skins            ← the skin manager's own page
│   ├── 官方默认
│   ├── 深海女仆工坊  …
│   └── …
└── 🎲 Skin rotation           ← this plugin
    ├── [switch] Rotate skins on launch      2 skins in the pool
    ├── Current skin: 虎鲸链路 · Picked this launch: 虎鲸链路
    ├── 深海女仆工坊   虎鲸链路   鲸鱼娘昼夜工坊   DeepSeek 云鲸纸面
    └── [Shuffle now]  [Refresh]
ControlWhat it does
Rotate skins on launchOn: every launch picks a random skin. Off: the launch leaves the current skin alone.
Shuffle nowPicks immediately and reloads the page. Works whether the switch is on or off.
Skin listWho is in the pool. Skins the running host would refuse are marked and excluded.

A manual switch in the skin manager still wins — until the next launch, which is the entire point.

How it works

flowchart LR
  A[host boots] --> B{rotation on?}
  B -- no --> Z[leave the current skin]
  B -- yes --> C[discover installed skins]
  C --> D[drop skins the host would deny]
  D --> E[random pick, never the previous one]
  E --> F[rewrite the dsh-skin managed block<br/>in profile patch + home patch]
  F --> G[DSH's HMR watcher recomposes the tree]
  G --> H[the page opens already wearing it]
  • Rotation is a host-side decision, made once per launch. A process-level boot key means a hot reload of the plugin re-runs apply without rotating again; a real restart does rotate. A browser refresh never re-rolls the dice.
  • It edits the patch layers, not the skins. The plugin rewrites the same # --- dsh-skin managed --- block the skin manager owns, in both the profile patch and the higher-priority home patch. Every line outside that block — hand-written rows, comments, DSH's own appended settings rows — is preserved byte for byte, and writes go through a temp file plus rename.
  • It only picks skins the host will load. DSH denies any plugin row whose @deepseek-ai/dsh* peer range excludes the running version: the patch still says disabled: false, the row simply never starts, and you get no skin at all. This plugin mirrors that admission check with its own SemVer range evaluator and honours the profile's compatibility.json grants, so a random pick cannot land on a dead skin.
  • The browser half is one card. It observes the DOM, appends one container to the skin manager's page root, and renders the card into it. It registers no settings page of its own, keeps no global state, and removes every observer, timer and style tag it created when it unloads.
  • It never touches a skin's files, skin.json, or the manager's own state.

Files it writes

PathContent
<profile>/cordis.patch.ymlthe shared dsh-skin managed mutual-exclusion block
<DSH_HOME>/cordis.patch.ymlthe same block — higher priority, so it must agree
<profile>/.dsh-skin-rotation.jsonthis plugin's preference: switch, last pick, launch key, client report

HTTP surface: GET/POST /api/dsh/skin-rotation — same-origin only, cross-site requests rejected.

Requirements

  • DeepSeek Harness web profile, >=0.2.0-rc.2 <0.3.0-0 (declared as engines.dsh).
  • At least two installed skins for rotation to mean anything. Skins are read the way the ecosystem defines them: a package shipping a valid skin.json (id, package, bodyAttr, wiring.id).
  • The card lives inside the skin manager's Skins page (settings.section id dsh-skins). Without that manager rotation still works — you drive it through the route instead of a card.
  • No @deepseek-ai/* runtime dependency: nothing to resolve, nothing to build, no install-time scripts.

Development

node --test                       # 29 tests
npm pack --pack-destination dist  # build the release tarball
SuiteWhat it covers
test/host.test.mjsmanaged-block rewrite (including foreign-row survival), discovery against a live profile, random-pick rules, the once-per-launch guard, the two-layer write with rollback, route guards
test/client-card.test.mjsthe whole card render tree, driven through a stub module loader and stub React — no browser needed
test/semver-oracle.test.mjsdifferential test against real node-semver over a generated matrix (skipped when node-semver is not installed)
tools/e2e-rotation.shboots a real host against an isolated DSH_HOME, repeatedly, and asserts the picked skin is what the browser is actually served

The end-to-end script is the interesting one: it does not test the plugin's own opinion of what it did. It fetches the boot graph the browser receives and checks that exactly one skin is in it.

FAQ

Will it fight the skin manager? No. Both write the same block using the same rules; the plugin rotates at launch and then stays out of the way.

Does a browser refresh re-roll? No — once per host process. Otherwise every page reload would be a new skin.

What if I only have one skin? Rotation is a no-op, and the block is still normalised.

Can I keep my current skin? Turn the switch off. The launch then leaves the skin alone, and manual switching is unaffected.

License

MIT © luoyuejun9

Comments

Loading…

From the same category

dsh-desktop

by anywhere-labs

为 DeepSeek Harness (DSH) 插件生态打造的现代化桌面端解决方案。万物皆「插件」,桌面本身也是「插件」。

UI & ExperienceManifest valid

★ 30.4k

↓ 108/wk

MIT

TypeScript

Oct 10, 2026

dsh plugin --profile web add dsh-plugin-desktop

by zhu1090093659

DeepSeek Harness (DSH) Web Plugin Aggregation Ecosystem · Everything is a plugin, distributed via the Creative Workshop

UI & ExperienceManifest valid

★ 8.6k

↓ 125/wk

Apache-2.0

TypeScript

Oct 10, 2026

dsh plugin --profile web add dsh-web

A collection of independent Web UI plugins and skins, including task boards, Git graphs, mobile access, and live token stats.

UI & ExperienceManifest valid

★ 7.6k

↓ 119/wk

Apache-2.0

TypeScript

dsh plugin --profile web add dsh-web

by omdsh-dev

开放的侧边栏底座,支持三方拓展注册新侧边栏页面。内置文件渲染编辑/终端/侧边对话/Git/子代理页面 | Open sidebar foundation, supports third-party extensions to register new sidebar pages. Built-in file rendering/editing, terminal, side chat, Git,

UI & ExperienceManifest valid

★ 4.1k

↓ 38.1k/wk

MIT

TypeScript

Oct 9, 2026

dsh plugin --profile web add dsh-better-sidebar

by bowenliang123

The best DeepSeek Harness plugin for context insight and management, with context dashboard / browser / sidebar and context command, for context statistics, composition, breakdown, evolution details,

Tools & CapabilitiesTerminal & ClientsUI & ExperienceManifest valid

★ 2k

↓ 34.4k/wk

Apache-2.0

TypeScript

Oct 11, 2026

dsh plugin --profile web add dsh-context

by shaobeichen

把 DeepSeek Harness 装进你的口袋:电脑上跑 dsh web,手机扫码即同步访问(局域网 + 公网,实时同屏)Put DeepSeek Harness in your pocket: run dsh web on your computer and access it synchronously by scanning a QR code on your phone (LAN +

UI & ExperienceManifest valid

★ 1.6k

↓ 3.2k/wk

GPL-2.0

JavaScript

Sep 16, 2026

dsh plugin --profile web add dsh-pocket