Install
Inside DeepSeek Harness, with dsh-market
dsh plugin --profile web add dshmarket
Or from the command line
dsh plugin --profile web add dsh-pet-remielle
Installing runs third-party code with your own permissions — it can read your files, use your credentials and reach the network. Review the source first, and pin a commit (github:owner/repo#sha) when you can.
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.
Comments
Comments live in GitHub Discussions. Sign in with GitHub to post or react.