Bundle
dsh-plugin-custom-css
Custom CSS injection for DeepSeek Harness — a Settings section with an on/off toggle and a CSS textarea injected live into the Web GUI
- Source
- nguyenduclong-ict
- License
- MIT
- Updated
- Updated 9 hours ago
Readme
# dsh-plugin-custom-css
[English](README.md) | [Tiếng Việt](README.vi.md)
Custom CSS injection for **DeepSeek Harness (DSH / DSH Desktop)**.
It adds one row to the Settings modal — **Custom CSS** — which opens a page with:
- an **on/off toggle** that enables or disables injection, and
- a **CSS textarea** whose contents are injected into the Web GUI live, as you type.
---
## 1. What it does
| Piece | Behavior |
|---|---|
| Settings entry | Registers a `settings.section` row (order `40`) labelled **Custom CSS** in the Settings modal nav rail. |
| Toggle | Injects or stops injecting the snippet. Turning it off **keeps** the saved code. |
| Textarea | Injected on every keystroke (debounced host write, `500 ms`). Flushed to the host on blur. |
| Injection target | A single `<style id="dsh-custom-css-style">` element, re-appended to the end of `<head>` on every write so it wins the cascade against styles the Harness appends while booting. |
| Storage | `~/.dsh/plugins/dsh-plugin-custom-css/config.json` (`$DSH_HOME` wins when set), served over `GET/POST /api/custom-css/config`, mirrored into `localStorage` so the snippet is applied before the first paint of the next launch. |
| Locales | `zh`, `en`, `vi` dictionaries are registered under the `custom-css` namespace (falls back to `en`). |
Nothing else is touched: styles injected by other sources are never removed, and the plugin does not modify the Harness installation.
---
## 2. Installation (DSH Desktop, Windows)
```powershell
# 1. From this repository's parent directory, install the package into the web profile
cd "$env:APPDATA\dsh-desktop\harness\profiles\web"
& "$env:APPDATA\dsh-desktop\harness\.desktop-bin\pnpm.cmd" add <path-to-this-package>
# e.g. pnpm add C:\Users\you\Desktop\Code\dsh-plugins\dsh-plugin-custom-css
# or pnpm add https://github.com/<user>/dsh-plugin-custom-css
```
Then add the package name to the profile's bundle list — edit
`%APPDATA%\dsh-desktop\harness\profiles\web\package.json`:
```json
{
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-plugin-custom-css"
]
}
}
}
```
Restart **DSH Desktop**. The plugin must be in `dsh.profile.bundles`, otherwise the
Harness never loads it.
> **Note** — any entry in `dsh.profile.bundles` must activate during boot. If the
> plugin cannot activate, the whole Web UI fails to boot with
> `web boot: N entries did not activate`.
### macOS / Linux
```bash
cd "$HOME/Library/Application Support/dsh-desktop/harness/profiles/web" # macOS
"$HOME/Library/Application Support/dsh-desktop/harness/.desktop-bin/pnpm" add <path-to-this-package>
# Linux: ~/.config/dsh-desktop/harness/profiles/web
```
### DSH CLI
```bash
dsh plugin --profile web add <path-to-this-package>
```
---
## 3. Usage
1. Open **Settings** (sidebar foot) → the **Custom CSS** row in the left nav.
2. Flip **Enable custom CSS** on.
3. Paste or write CSS into the textarea. It is injected immediately.
4. Close the modal — the styles stay applied and are restored on the next launch.
### Example snippets
```css
/* Recolor the brand accent */
:root {
--dsw-alias-brand-primary: #22d3ee;
}
/* Wider, calmer conversation column */
[data-conversation-scroll] {
font-size: 15px;
line-height: 1.7;
}
```
Design tokens available to a snippet are the Harness CSS custom properties
(`--dsw-alias-*`, `--dsw-font-*`), so a theme can stay consistent with whatever
light/dark variant DSH is using.
---
## 4. Files
| File | Role |
|---|---|
| `package.json` | Manifest: `dsh.bundle.patch` + `dsh.client` (`platform: web`, `immediately`, `inject`). |
| `cordis.patch.yml` | Bundle patch that inserts this package into the loader tree. |
| `index.js` | Host half: `GET/POST /api/custom-css/config` and the `$DSH_HOME`-based JSON store. |
| `client.js` | Browser half: style injection, Settings section, toggle + textarea. |
| `install.ps1` | Windows installer (pnpm add + register the bundle entry). |
| `config.json` | Created at runtime under `~/.dsh/plugins/dsh-plugin-custom-css/`. |
| `smoke-test.mjs` | Browser-half test: runs `client.js` against a DOM/React stub and asserts the injection, toggle, and persistence behavior. |
| `host-test.mjs` | Host-half test: mounts the real route on `node:http` and asserts GET/POST/OPTIONS, merge semantics, and restart recovery. |
| `LICENSE` | MIT. |
| `.gitignore` | Keeps runtime state (`config.json`, `plugins/`) out of the repository. |
### Tests
```bash
node smoke-test.mjs # browser half
node host-test.mjs # host half
```
## 5. HTTP API
| Method | Path | Body | Response |
|---|---|---|---|
| `GET` | `/api/custom-css/config` | — | `{ "enabled": boolean, "css": string }` |
| `POST` | `/api/custom-css/config` | `{ "enabled"?: boolean, "css"?: string }` | current config plus `saved: boolean` |
## 6. Development notes
- The browser bundle is hand-written framework-form CJS (`window.__ModuleLoader__.load`)
and requires only platform **seed** modules — `react`, `react/jsx-runtime` — so it
declares no `dsh.client.external` edges.
- Edit `client.js` and restart the app (or let the Harness HMR reload the plugin
bundle if your setup watches it).
- To reset everything, delete `~/.dsh/plugins/dsh-plugin-custom-css/config.json`.
## License
MIT © [nguyenduclong-ict](https://github.com/nguyenduclong-ict)
Install
dsh plugin --profile web add github:nguyenduclong-ict/dsh-plugin-custom-css#cdbee9bd8c7f41bb2eac2fc37eb05d8d7de231f0
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-plugin-custom-css from the hub