A Remielle(ZZZ) desktop pet for the dsh web GUI that switches animated sticker moods with the harness work state.
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-pet-remielle
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:Gin-7/dsh-pet-remielle
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
A multi-pet web desktop pet driven by real DSH session events — it tracks DeepSeek Harness task progress in real time and presents it with sticker animations + status bubbles.
- Multi-pet registry + status bubbles (project / phase / tasks / progress in real time)
- SSE live push + optional desktop floating window (bundled Electron, transparent & always-on-top)
- Double-click drawing: brush-reveal artwork (drawing → satisfied → fade-out)
- Built-in version check + one-click incremental update
- Settings panel: pet management (tabbed) + plugin config card
Compatible with DeepSeek Harness (and its forks) web profile; desktop mode is off by default and can be enabled anytime. Desktop mode requires DSH
>= 0.1.2-alpha.1to provide an authenticated root URL with a launch token.
Features
| Capability | Details |
|---|---|
| State source | DSH session/event real events — no DOM scraping |
| State machine | Pure-function PetReducer with mood mapping (unit-tested) |
| Message protocol | Typed protocol (protocol.js) |
| Configuration | schemastery persistence + settings card |
| Multi-session priority | Approval > plan review > waiting for an answer (ask_user_question) > completion reminder > waiting/error > current session > state priority > recency. Hysteresis only stabilizes the top two; third and later still rotate with recency |
| Live push | SSE stream (auto-reconnect + polling fallback) |
| Status bubble | Adaptive two-layer deck on both the in-page pet and the desktop window: top status card + +N summary backboard; message + detail (project · completed x/y · phase) |
| Session actions | Web and desktop match: card / ? / ! open the session, ✓ allows once; with no web client online, a card/icon click opens the DSH page in the system browser |
| Completion reminders | Persist until handled; a completion on the current session is auto-cleared only by a foreground browser tab (even while the desktop window is up), so background tabs never clear a reminder ahead of you; the desktop window only shows the reminder — opening that session (in-page jump, browser, or clicking the desktop completion card) also clears it. The already-open session has no unread dot (current Host lifetime only) |
| Error reminders | A failed turn (model-call error, etc.) keeps the pink attention mark until that conversation is opened; a failure in the current session never becomes a reminder. Opening the session (bubble jump or sidebar) dismisses it. Approvals and questions are unchanged |
| Balance | With both status and usage on, the left dot or a wheel on the bubble switches to the balance page (60s auto-refresh, rolling-number animation, stale fallback on network blips); stays on the current page, no auto-return |
| Today usage | Two modes: ledger (default, token-free, balance-delta) / real-time token (platform usage API + peak/off-peak pricing, exact) |
| Desktop float | Bundled Electron transparent always-on-top window (opt-in) |
| Multi-pet | Settings → Pet Management (registry + switch active pet) |
| Version update | Built-in check + one-click incremental update |
Sticker (mood) → State Mapping
| Sticker | Preview | Trigger |
|---|---|---|
| 01 Drawing | THINKING + streaming: streaming output / double-click drawing | |
| 02 Slacking | WORKING / ERROR: tool calls (search/edit/test/command) | |
| 03 Pleased | PULSE SUCCESS: turn completed / drawing finished / click interaction | |
| 04 Thinking | THINKING: turn/step start, reasoning, result compilation | |
| 05 Waiting | WAITING: question answer, approval pending, plan review, turn blocked | |
| 06 Idle | IDLE / DISCONNECTED: idle, after turn ends |
When multiple sessions run concurrently, the top task is selected by approval > plan review > waiting for an answer > completion reminder > waiting/error > current session > state priority > recency; every other session is represented by a clickable +N summary backboard. Sub-agents are ignored by default (configurable).
Pet Definition Convention
assets/pets/<id>/01.gif Drawing (output)
assets/pets/<id>/02.gif Slacking (tools/errors)
assets/pets/<id>/03.gif Pleased (completed/interaction)
assets/pets/<id>/04.gif Thinking
assets/pets/<id>/05.gif Waiting
assets/pets/<id>/06.gif Idle
Optional extensions (don't affect completeness validation):
assets/pets/<id>/07.gif Extra sticker slot
assets/pets/<id>/pet-manifest.json Per-sticker alignment offsets + artwork count
assets/pets/<id>/pics/<n>.png Artwork images (double-click to pop, n starts at 1)
id may contain only letters, numbers, underscores, and hyphens. Built-in pet: Remielle (see NOTICE for asset copyright).
Installation
For DSH / DeepSeek Harness (including Fairy and other DSH-based forks) web profile.
# Option 1: npm registry (recommended, one-click incremental update)
dsh plugin --profile web add dsh-pet-remielle
# Option 2: GitHub repository (build install, no version check)
dsh plugin --profile web add github:Gin-7/dsh-pet-remielle
# Option 3: Local directory (dev/debug, link install)
dsh plugin --profile web add D:\path\to\dsh-pet-remielle
# Option 4: GitHub Release tgz
dsh plugin --profile web add "C:\Users\you\Downloads\dsh-pet-remielle-<version>.tgz"
Plugin row id: dsh-pet-remielle. Uninstalling removes everything cleanly.
Updating
Built-in update check in Settings → Pet Management → Update + bottom-right update bubble: checks GitHub for the latest version and offers one-click update.
| Install type | Version | Update method |
|---|---|---|
| Local link | ≥ 0.3.0 | One-click git pull (incremental) |
| npm registry | ≥ 0.3.0 | One-click pnpm update dsh-pet-remielle (incremental) |
| Any type | < 0.3.0 | No auto-update: package/row-id changed since 0.3.0 — must fully uninstall then reinstall |
Why? Before 0.3.0 there were package/row-id renames (before 0.2.0 it was
@dsh-external/dsh-client-ui-pet-remielle, from 0.2.0–0.3.0 it wasdsh-pet-remielle).git pull/pnpm updatecan't cross that boundary, so versions below 0.3.0 must be uninstalled first (otherwise you getloaded without registering … via __ModuleLoader__.loaderrors):
# Uninstall by the actual old row id (whichever applies):
dsh plugin --profile web remove @dsh-external/dsh-client-ui-pet-remielle # <= 0.2.0
dsh plugin --profile web remove dsh-pet-remielle # > 0.2.0
# Reinstall latest:
dsh plugin --profile web add dsh-pet-remielle
# or: dsh plugin --profile web add github:Gin-7/dsh-pet-remielle
The same uninstall/reinstall guidance is shown in Settings → Pet Management → Update when the installed version is below 0.3.0.
Desktop Floating Mode (opt-in)
desktopMode is off by default. When enabled, a transparent, always-on-top, frameless Electron window displays the pet.
- Window supports dragging (position remembered), scroll-wheel zoom, double-click drawing, right-click menu.
- Status/balance bubbles match the web pet: stacked session cards, a single toggle dot, the same tooltips and click behavior;
✓still clicks Allow once. - Known limit: the sidebar “pending content” green-dot feed is synced only while a web client is online. Reminders that appear while the page is closed may be missing from the desktop bubble until the page is opened again.
- The desktop window compensates UI size from the system scale so it matches the in-page pet.
- Double-click drawing: artwork appears in a desktop top-right independent window, brush-reveal along the diagonal, then "Pleased → fade-out".
- Right-click menu: switch to web mode, lock, bubble toggle, size, drawing, etc.
- Closing/switching returns to the in-page pet automatically; the window closes when the DSH host exits (within 1 second).
- The desktop window's Electron data dir is pinned under the system application-data directory (
%APPDATA%\dsh-pet-remielleon Windows) instead of a temp dir, which disk-cleanup tools would wipe along with its cache. Only one desktop window may hold it at a time: on detecting another live instance (host restarted while the old window is still exiting) it falls back to a pid-suffixed sibling directory, so the two never share one Chromium cache.
Electron runtime sources (probed in order): DSH_PET_ELECTRON → vendor/electron-<platform>-<arch>/ (not in Git; downloaded for the current system) → system-installed Electron → none → in-page only.
First run: if desktop mode is enabled but no Electron runtime is found locally, a prompt will offer to download and install it (requires confirmation, about 100–220 MB). Download failure falls back to in-page display automatically. You can also manually extract the matching Electron release to
vendor/electron-<platform>-<arch>/or setDSH_PET_ELECTRONto an existing executable (electron.exeon Windows,Electron.app/Contents/MacOS/Electronon macOS,electronon Linux).
Platform support
| Platform | Desktop float | In-page pet |
|---|---|---|
| Windows x64 | ✓ (Electron transparent window) | Hidden when desktop mode is on |
| macOS (arm64 / x64) | ✓ (matching darwin runtime) | Hidden when desktop mode is on |
| Linux x64 | ✓ (matching linux runtime) | Hidden when desktop mode is on |
Usage
- Single-click pet: cycle through random sticker moods.
- Double-click pet: enter drawing animation; after completion a artwork pops up (screen top-right) and fades out.
- Right-click pet: the same menu in-page and in the desktop window (same width and order, sliders aligned) — character size / opacity / mirror / lock position / pause animation / show bubble / drawing / reset position / desktop float mode. "Reset position" clears both the in-page and the desktop-window position at once; "Pause animation" freezes on the currently displayed frame (not the first frame) — exact on secure contexts (
127.0.0.1/localhost/ https), falls back to the first frame over plain-HTTP LAN addresses; resuming replays the GIF from frame 0 (an inherent consequence of re-assigningsrc—<img>cannot seek to a given frame). - Settings-only: enable / hide pet, pet management, respond to sub-agents, usage mode and platform token, bubble sub-toggles and bubble-scaling details — these are either low-frequency or would remove their own entry point (hide pet), so they stay out of the right-click menu.
- Both ends share one theme source: the in-page menu/bubbles and the desktop window use the same colours and follow the same theme — the page reports the host theme (
body[data-ds-dark-theme]) and the desktop window colours itself from that report; with no web client online (or the report expired) it falls back to the system light/dark setting, which stays a sensible default for a standalone window. Rows, order and geometry match item by item as well (a toggle's check mark never changes its row height), and a cross-file assertion pins the colours. - Bubble paging: with both status and usage on, the left dot or a wheel on the bubble switches between the status card and the balance page; stays on the current page, no auto-return.
- Scroll wheel (pet): resize character.
- In-page pet menu can also launch the desktop window.
Balance & Today Usage
With both status and usage on, the left dot or a wheel on the bubble shows your DeepSeek account balance and today's spend (bubble shows "DeepSeek Balance ¥X" + "Today ¥X · Off-peak/Peak", the period is color-coded: green = off-peak, red = peak). Usage-only shows the balance page directly. Stays on the current page; does not auto-return to status.
- Balance: from the official API
api.deepseek.com/user/balance(credentialDEEPSEEK_API_KEY). Auto-refreshes every 60s; switching to the balance page fetches once; rolling-number animation on changes; transient network blips keep the last known balance instead of flashing errors. - Today usage · ledger (default, token-free): accumulates balance deltas into
$DSH_HOME/.dshp-usage.json(cross-day reset & archive). No extra token needed, but it is an estimate — usage while DSH is off is not recorded. - Today usage · real-time token (exact): after configuring the platform session token
DEEPSEEK_PLATFORM_TOKEN, it queries the platform cost API (platform.deepseek.com/api/v0/usage/by_api_key/cost) and reads the platform's own per-hour CNY amount — no local pricing table, so DeepSeek price changes are followed automatically:- The bubble also shows the current period (off-peak / peak): on workdays peak is 09:00–12:00 and 14:00–18:00 Beijing time, while Saturdays, Sundays and Chinese public holidays are off-peak all day (weekends that are adjusted workdays still count as off-peak, matching the official rule). The holiday calendar falls back to a built-in table and silently refreshes a public calendar in the background (cached at
$DSH_HOME/.dshp-holidays-<year>.json), issuing a year-only request on first use or after expiry - Falls back to ledger mode when the token is missing or invalid
- The bubble also shows the current period (off-peak / peak): on workdays peak is 09:00–12:00 and 14:00–18:00 Beijing time, while Saturdays, Sundays and Chinese public holidays are off-peak all day (weekends that are adjusted workdays still count as off-peak, matching the official rule). The holiday calendar falls back to a built-in table and silently refreshes a public calendar in the background (cached at
Switching usage mode: Settings → Pet Management → Behavior → "Usage Mode" (ledger / real-time token). It is a configuration choice rather than a live tweak, so it lives in Settings only.
To obtain
DEEPSEEK_PLATFORM_TOKEN: sign in to platform.deepseek.com → F12 DevTools → Network → open the "Usage" page → copy theAuthorizationheader value of theapi/v0/usage/...request → add it to the DSH credentials service.
Configuration (Settings → Plugin → Remielle Desktop Pet)
| Field | Default | Description |
|---|---|---|
| enabled | true | Enable the pet (disables immediately, re-enabling restores) |
All other appearance/behavior options (size, opacity, mirror, lock, bubble, usage mode, desktop float, pause, hide, etc.) live in Settings → Pet Management, not duplicated in the plugin config card. The few that are instantly visible and high-frequency also appear in the right-click menu (list under "Usage") — both ends share one skeleton and one set of labels, so changing one means changing the other.
Settings → Pet Management
Pet registry as its own tab, alongside Appearance / Pets / Behavior / Desktop Float / About (five tabs).
- Enable/disable pets, set as current, rename, add new pets; pets with a missing directory or incomplete stickers show the reason on the card (the enable switch is disabled alongside).
- Behavior page: enable / lock / pause / hide / respond to sub-agents / show bubble / usage mode.
- "Update": shows current version, check for updates, one-click update, upgrade guide.
- "Feedback": shows pet version, submit bug reports / feature requests.
Development
npm install
node scripts/build-client.mjs # Build lib/client.js (version injected from package.json)
npm test # node --test unit tests
npm run check # Syntax check
Directory Structure
src/
├── index.js # Host: config, event wiring, config/state/balance/pets/assets/desktop endpoints, self-update routes
├── balance.js # Balance service: fetch (retry/cache/stale fallback), today usage (ledger/token), peak pricing
├── holidays.js # Holiday calendar: peak/off-peak decision (weekends & public holidays are off-peak all day), builtin table + remote refresh + disk cache
├── self-update.js # Version check + one-click update (GitHub direct + HTTP proxy fallback; git pull / pnpm update)
├── pet-reducer.js # Pure state machine: session events → state/pulse/task (unit-tested)
├── protocol.js # Typed protocol: PetState / PetMood / PetMessageKind
├── pets.js # Pet registry: directory discovery/merge/validation (unit-tested)
├── status-copy.js # Remielle-flavored status copy (replaceable)
├── turn-watchdog.js # Turn-hang watchdog: recovers a session stuck in THINKING after a forced kill
├── desktop-window.js # Desktop mode: Electron discovery + window process management (unit-tested)
├── electron-fetch.mjs # On-demand cross-platform Electron runtime download and extraction
├── pet-window.cjs # Desktop mode: Electron main (transparent window + top-right artwork window)
├── pet-window-paths.cjs # Pet-window userData directory policy (isolated from the host's Electron)
├── pet-preload.cjs # Pet-window preload: page ↔ main bridge (click-through, drag, hit rects, menu expand)
├── pet-view.html # Desktop mode: pet window page (GIF + bubble + SSE + drawing + balance bubble)
├── balance-widget.js # Balance controller (client): fetch/rolling animation, rendered into the pet's own bubble
└── client.core.js # Browser side: pet UI + settings (wrapped at build time)
# Shared between both ends. The `.cjs` suffix is what lets the host ESM pick the
# exports up through createRequire; the served URL keeps the `.js` extension
# because a browser <script> doesn't treat `.cjs` specially. One implementation for
# both ends, so copy and geometry can't drift apart.
├── session-order.cjs # Deck ordering (approval > plan review > ask > completion > attention …)
├── pet-tip.cjs # Page-switch-dot hover copy, tip viewport clamp, bubble zoom resolution
├── gif-frame.cjs # The GIF frame currently on screen (right-click pause; canvas only ever paints frame 0)
├── bubble-title.cjs # Session-card presentation: title throttle, width measurement, approval/review/done copy & classes
└── markdown.cjs # Markdown rendering for release notes (escape first, then transform; only http(s)/mailto links)
lib/client.js # Build artifact (version injected, ready to use)
assets/pets/remielle/ # Remielle assets (GIFs + artwork)
scripts/build-client.mjs
test/ # node --test
When you add a shared module, wire it into both
scripts/build-client.mjs(web bundle) and the host's route registration (desktop window). Verify the actual script response intest/host-transport.test.js, and check the page's script src and shared-module calls intest/desktop-window-ui.test.js.
Publishing to npm
npm login
pnpm version patch # Bump version
pnpm pack --dry-run # Check what will be published (no node_modules / vendor)
pnpm publish
Published content is controlled by the
filesfield:src/,lib/client.js,assets/,scripts/,test/,cordis.patch.yml,NOTICE,README.md. Thevendor/(Electron runtime) is not published — desktop mode downloads it on demand.
License & Asset Copyright
Source code is distributed under MIT License; the Remielle character art and GIF/ artwork assets are copyrighted by miHooyoverse (HoYoverse),
commercial use and redistribution of assets is prohibited. See NOTICE for details.
Links
More in this category
PC2005-cloud/dsh-pet#dsh-pet★ 928
Desktop pet for the DSH Web UI with 25 transparent animations, screen wandering, click reactions and drag, plus a reproducible asset-generation pipeline.
Nagi-ovo/dsh-ads★ 641
Parody ads in 2005-Chinese-web style: sidebar banners, in-chat feeds, corner popups, and a close button whose hit area is smaller than it looks. All fictional.
vlln/whale-girl★ 340
Desktop pet (QQ-pet style): floats in the corner, draggable, feedable, playable.
a86582751/dsh-nexttavern★ 127
Roleplay workspace for DeepSeek Harness: import SillyTavern/TauriTavern character cards or author one from scratch through an interactive flow; turn a long TXT novel into a playable card with either an intensive or a coarse reading pass; the main agent consults worldbooks on demand, and prose is read in a dedicated tavern reader tab; explore multiple worldlines inside one conversation (regenerate, edit-and-send, explicit clone); scoped style presets with 16 built-in styles, a character agent cluster, a standalone decision card, and card or novel export; long stories hold together through a frozen settings prefix, a hard-cut context window, traceable director notes and keyword/semantic/hybrid recall, with embeddings either online or fully local. Targets Harness 0.1.2-alpha.3 and applies its documented compatibility patches.
yyh-001/dsh-meme★ 118
Chat meme stickers: text-only send, mood auto-send, QQ/WeChat-style picker, auto-learn, custom packs.
Sutera-Diffusus/dsh-whale-musume★ 100
A whale-girl desktop pet for the DeepSeek Harness Web UI: pat-to-raise growth, work-state poses per tool type, 494 dialogue lines, 30 achievements, a growth diary, drag physics, theme sync and an accessibility mode. Chat-keyword sensing and API-balance care ship off and are opt-in; an optional weather mood calls Open-Meteo only after you name a city. No telemetry.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.