Bundle
dsh-agent-whale-girl
An unofficial whale-girl companion for the DSH Web GUI: a sidebar brand mark plus a draggable, collapsible floating mascot that follows the cursor, reacts to pats and clicks, reads the agent state, and reports the current session's real token usage.
- Source
- Turanbuturan
- License
- MIT
- Updated
- Updated 7 days ago
Readme
# dsh-agent-whale-girl
An unofficial **whale-girl (鲸鱼娘) companion** for the DeepSeek Harness Web GUI.
She replaces the sidebar brand mark and floats over the page as a draggable,
collapsible mascot: her head follows your cursor, she reacts to pats and clicks,
she follows what the agent is doing, and her speech bubble reports the current
session's real token usage.

> The character is community fan art, not an official DeepSeek asset — see
> [Source & attribution](#source--attribution). Chinese docs: [README.zh.md](README.zh.md).
## What she does
| Area | Behaviour |
| --- | --- |
| Sidebar brand mark (`sidebar.brand.mark`) | Replaces the stock fish logo with a close-up of her face (`avatar-face.png`). Registered with `priority: -1` so it wins the single-value slot. |
| Floating companion (`shell.overlay`) | A 220×298 paper doll over the frame, with a token card above her and speech bubbles. Drag her anywhere inside the frame (position kept in `localStorage['whale-girl:position']`); double-click returns her to the bottom-right corner and forgets the position; when the window shrinks she is folded back into view. |
| Gaze | Her head turns towards the pointer (up to ±7°) and her tail counter-swings (±4.8°); both settle back to centre 0.22 s after the pointer leaves. The pivot is measured from the eyes/lashes in the art, not from the bounding box. |
| Pat | Press and hold ≥ 350 ms: a one-shot squash-and-return animation plus a dedicated line. She does **not** fold away. |
| Click and combo | A quick click (< 350 ms) folds or unfolds her, with an answering line; 3–4 fast clicks get a counted complaint; the 5th click fires a one-shot easter egg. |
| Mood | `data-mood` follows context occupancy: `<50%` `calm`, `≥50%` `tense`, `≥85%` `crit`. Each crossing drops a 💦 in her corner for 2.6 s. |
| Speech | Lines are triggered by state and filled with real numbers from DSH's own session projections (`tokenUsage`, `contextPressure`): a greeting on mount, an answer on click, live progress while the turn is producing output, a context warning at 80 %, and a "done" line 2.5 s after output stops. She never calls the network or the model. |
| Token card | Context occupancy (bar plus `tokens / window`) and output / input / cache-read counts for the current session — the same projections the composer's own indicator uses. Hidden when there is no session; it yields when the window is narrower than 900 px. |
| Three-layer puppet | Her body, head and tail are separate layers that are pixel-identical to the still illustration at rest, so they are invisible until she moves. |
Animations run only while she is being interacted with: exactly three one-shot
`@keyframes` (`wg-pat` / `wg-egg` / `wg-emote`), no `infinite`, no `alternate`,
no `will-change`; `getAnimations()` is empty when idle.
## Install
The package declares a `dsh.bundle` patch, so installing it mounts both halves —
no profile editing, no manual copy:
```sh
dsh plugin --profile desktop add github:Turanbuturan/dsh-agent-whale-girl
```
`--profile desktop` is the DSH desktop app; use `--profile web` for a plain web
profile. A release tarball or a local checkout works the same way:
```sh
dsh plugin --profile desktop add ./dsh-agent-whale-girl
```
Reload the page afterwards. Host-side changes need a full app restart (Node's ESM
cache pins the module path), but this plugin's host half is empty — a page
refresh is enough.
### Manual drop-in
Copy the folder into `<profile>/plugins/` and add the row to the profile's
`cordis.patch.yml`:
```yaml
- insert:
- id: whale-girl
name: "./plugins/dsh-agent-whale-girl/index.js"
```
The path resolves against the profile directory. Removing the `insert` row (and
refreshing) removes her; the folder may stay in place.
### Uninstall
```sh
dsh plugin --profile desktop remove dsh-agent-whale-girl
```
If you used the manual drop-in instead, delete the `insert` row and refresh.
## Build and verify
`lib/client.js` and `lib/client.css` are committed, so installing needs no build
step. To rebuild after changing the art or the skeleton:
```sh
node build.mjs # regenerates lib/client.js + lib/client.css from the PNGs and layers.json
node verify-bundle.cjs lib/client.js
```
`verify-bundle.cjs` is a structural and behavioural self-check (registrations,
injected CSS, layer geometry, gaze maths, click/pat/combo timing, mood values).
Use absolute paths — the script resolves the bundle relative to the working
directory.
## Files
| File | Purpose |
| --- | --- |
| `package.json` | Declares `dsh.bundle.patch` (installable bundle) and `dsh.client.platform = "web"` (browser half). |
| `index.js` | Host half: an intentionally empty `apply()` so the loader can mount the package. |
| `cordis.patch.yml` | The mount declaration read at install time. |
| `lib/client.js` / `lib/client.css` | Build output: the client bundle that registers both slots, and the stylesheet it injects. |
| `build.mjs` | Builds the two files above from the PNGs and `layers.json` (inlines the art, writes the skeleton geometry into CSS). |
| `layers.json` | Puppet skeleton: crop boxes, rotation origins in the 414×560 art space, amplitudes, measured pivots. |
| `verify-bundle.cjs` | Self-check. |
| `avatar-body.png` / `avatar-head.png` / `avatar-tail.png` | The three puppet layers. |
| `avatar-face.png` | 96×96 face crop used by the 24 px mark and the folded bubble. |
| `avatar.png` | The full-body illustration before cutting. |
| `assets/` | Source art. |
## Source & attribution
The code is MIT. The character art is community fan art and keeps the terms of
the repositories it came from:
- [`Neko3000/deepseek-whalechan`](https://github.com/Neko3000/deepseek-whalechan) — MIT — **the art used now**; cut into layers and background-removed here.
- [`TreapGoGo/deepseek-whale-girl`](https://github.com/TreapGoGo/deepseek-whale-girl) — MIT — the earlier chibi avatar (`assets/whale-girl-avatar-512.png`).
- [`fornarwhal/deepseek-whale-girl-icon`](https://github.com/fornarwhal/deepseek-whale-girl-icon) — custom terms — reviewed as a candidate icon source, not shipped.
See [NOTICE](NOTICE) for the file-by-file mapping. "DeepSeek" and the DeepSeek
whale logo belong to their respective owners; this plugin is an unofficial
community project.
## License
MIT — see [LICENSE](LICENSE).
Install
dsh plugin --profile web add github:Turanbuturan/dsh-agent-whale-girl
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-agent-whale-girl from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.