DeepSeek Harness Plugin

hansomgar/dsh-settings-resize

Stars ★ 0 Category UI Enhancements Added 2026-10-22

Resize the Settings dialog and set its transparency from three sliders in General settings; the choice persists across restarts.

Install

# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)

dsh plugin --profile web add github:hansomgar/dsh-settings-resize

Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).

README

Adds three sliders to Settings → General in DeepSeek Harness that resize the Settings dialog and adjust its transparency. Changes apply immediately and are remembered across restarts.

The UI is bilingual and follows the active DSH language (Chinese or English).

中文 | English

在 DeepSeek Harness 的设置 → 通用设置里加三个滑动条,用来调节设置弹窗的宽度、高度和透明度。拖动即刻生效,选择会被记住。

Features

  • Width / Height / Transparency, three sliders: width 640–2400 px, height 480–2160 px, transparency 0–100%.
  • Live: the open Settings dialog resizes while you drag. No save button, no restart.
  • Persistent: stored in localStorage under dsh.settingsResize.v1, so a full quit and relaunch keeps your settings.
  • Bilingual: text comes from the plugin's own zh / en dictionaries and switches instantly in Settings → General → Language.
  • Reset to default: one click returns to the shipped 800 × 800, fully opaque.
  • Never overflows the screen: width is capped at 100vw - 48px and height at 100vh - 2 * max(24px, var(--dsh-frame-overlay-top, 24px)), so shrinking the window clamps the dialog instead of spilling it off-screen.
  • Scoped to the Settings dialog: every rule is keyed on [data-shortcut-modal="settings"]; other dialogs, panels and pages are untouched.
  • Cleanly removable: the <style> element, all four CSS custom properties, the slot registration and the locale dictionaries are created inside ctx.effect cleanups, so disabling or uninstalling restores the shipped dialog exactly.

Layout

File Role
package.json Manifest: dsh.bundle.patch points at the bundle patch, dsh.client declares the Web client half
cordis.patch.yml Inserts one row, dsh-settings-resize
lib/index.js Host half, intentionally empty; its presence is what makes the Web GUI load ./client
client/client.js The whole feature: stylesheet, CSS custom properties, the settings.general.item registration, three sliders
locale/{en,zh}.json Title and description shown on the plugin page
icon.svg Plugin icon
test/*.cjs Test suites, run with node test/<name>.cjs
需求.txt Full implementation spec (Chinese), including both locale bugs and their fixes

Why transparency fades the surface only

Transparency targets the panel surface, not the panel element. The surface token is diluted toward transparent with color-mix, so text and controls keep full opacity and stay readable:

background: color-mix(
  in srgb,
  var(--dsw-alias-bg-layer-2) var(--dsh-settings-alpha, 100%),
  transparent
) !important;

Applying opacity to the panel instead would fade the text, icons, navigation and buttons along with the background — unusable past about 50%.

The slider measures transparency; the custom property stores the complementary opacity (100% - transparency).

At 100% the surface is fully clear. So that the dialog can still be located and its close button found, a 0.5px outline fades in as the surface fades out, reaching full strength at 100%:

outline: .5px solid
  color-mix(in srgb, var(--dsw-alias-border-l2) var(--dsh-settings-edge, 0%), transparent) !important;
outline-offset: -1px !important;

It is an outline, not a border, because an outline takes no space in the layout box — the width and height you set are exactly the dimensions you get.

The stored record looks like this:

{"width":1200,"height":900,"heightUnit":"px","transparency":20}

Implementation notes

The Settings dialog's class is generated by CSS Modules (currently wCInkW_panel) and its hash changes between releases, so the plugin selects on the stable data-shortcut-modal="settings" attribute only.

Two custom properties drive the size and two more drive the surface:

html {
  --dsh-settings-w: 800px;
  --dsh-settings-h: 800px;
  --dsh-settings-alpha: 100%;  /* surface opacity = 100% - transparency */
  --dsh-settings-edge: 0%;     /* outline strength = transparency */
}
[data-shortcut-modal="settings"] {
  width: var(--dsh-settings-w) !important;
  height: var(--dsh-settings-h) !important;
  max-width: calc(100vw - 48px) !important;
  max-height: calc(100vh - 2 * max(24px, var(--dsh-frame-overlay-top, 24px))) !important;
  background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) var(--dsh-settings-alpha), transparent) !important;
  outline: .5px solid color-mix(in srgb, var(--dsw-alias-border-l2) var(--dsh-settings-edge), transparent) !important;
  outline-offset: -1px !important;
}

!important is required: the shipped rules come from a CSS Modules class of the same specificity. The properties live in the inline style of document.documentElement and are removed one by one with removeProperty.

Locale wiring

locale is declared as a hard dependency:

export.inject = ['slots', 'locale']

A cold page has no ordering guarantee between this plugin and the locale plugin. Probing with ctx.get('locale') and skipping registration when it was absent left the namespace without its dictionaries while the slot still declared locale: NS — the row then fell through to the en fallback and could never display Chinese. Declaring the dependency makes the loader hold this plugin inactive until the service exists, so apply always sees a live service.

Dictionaries are registered once, both languages in one call, and the returning disposer is parked on globalThis so a reload can release the previous claim before re-registering. The service keeps one occupant per (namespace, language) and throws on a duplicate, so releasing first is what allows the plugin to survive an HMR pass.

Install

From GitHub (recommended):

dsh plugin add https://github.com/hansomgar/dsh-settings-resize

You can also paste that repository URL into the Settings → Plugins page in DSH.

For local development, install from your working directory:

pnpm add "file:E:\Data\data_dsh\2026\dsh-settings-resize"

Or add this directory to the profile's dependencies and dsh.profile.bundles, then run npm install.

Tests

node test/lifecycle.cjs        # 48 checks: registration, effects, clamping, disposal
node test/i18n.cjs            # 15 checks: both locales render, no leakage
node test/repro-hmr.cjs       # 11 checks: HMR reload against the real LocaleRuntime
node test/repro-coldstart.cjs #  9 checks: the locale dependency contract
node test/spec-sync.cjs       # 27 checks: 需求.txt embeds the sources verbatim

The two repro-* suites extract the real LocaleRuntime class from the shipped app.asar rather than re-implementing it, so they fail on the same conditions the running app does. Both were verified to catch their bug by reverting the fix and watching them fail.

Disable

Turn the plugin off on the Plugins page, or override it in the profile's cordis.patch.yml:

- id: dsh-settings-resize
  disabled: true

The Settings dialog returns to the shipped size; the localStorage record is kept, so re-enabling picks the settings back up.

Content from the project README on GitHub ↗

Links

More in this category

View the whole category →

Community comments

Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.