c-ling/dsh-plugin-pet3

dsh-plugin-pet

A virtual pet companion for the DeepSeek Harness web GUI: mood animations driven by live agent state, built-in sprites, custom image upload, and Codex-style multi-frame spritesheet import.

AI Analysis

核心用途是提供一个能根据 AI 思考、报错等状态做出动画反馈的桌面宠物。适合想要增加界面趣味性和陪伴感的用户。

Package
dsh-plugin-pet
Version
1.0.2
License
MIT
Last updated
Aug 15, 2026

Install

This plugin has no verified bundle, or compatibility checks failed. Read the repository notes first. Read the full README ↗

dsh-plugin-pet

A virtual pet companion for the DeepSeek Harness web GUI: built-in, custom, and Codex-style sprites with mood animations driven by live agent state.

中文

dsh-plugin topic license

A desktop pet for DeepSeek Harness Web GUI, inspired by the Codex companion and Claude Code Buddy. The pet lives in the bottom-right corner and reacts in real time to the agent state (thinking / tool calls / errors / turn completed / waiting for you), with rename, scale, visibility, and full reskinning support:

  • 6 built-in sprites (blob / cat / duck / robot / axolotl / ghost; inline SVG, pure CSS animation)
  • Custom image upload (PNG / JPEG / GIF / WebP; animated images play as-is)
  • Codex-style multi-frame spritesheets — import a Codex pet pack (pet.json + spritesheet.webp, V1 1536×1872 and V2 1536×2288; see the Codex pet package spec), or configure a generic grid (columns / rows / fps / per-mood state rows)

All state is stored under $DSH_HOME/storages/dsh-plugin-pet/ and survives dsh web restarts.

Structure

FilePurpose
lib/index.jsHost plugin: pet persistence + HTTP routes mounted on the harness webServer service
lib/client.jsBrowser bundle (hand-written factory-CJS, no build step): pet overlay and settings panel
test/node --test suite covering host routes and the zero-dependency image sniffer

This is a dual-face package: the host half is a plain Cordis plugin; the client half is declared through "dsh": { "client": { "platform": "web", "inject": [], "immediately": true } } plus the "./client" export, so the harness client-modules system serves it at /plugins/dsh-plugin-pet/client.js and loads it immediately at boot.

Install

Install into the web profile from GitHub (requires pnpm on PATH; otherwise use the corepack fallback below):

npx @deepseek-ai/dsh plugin --profile web add "github:c-ling/dsh-plugin-pet#v1.0.2"

Or with an existing dsh binary:

dsh plugin --profile web add "github:c-ling/dsh-plugin-pet#v1.0.2"

When pnpm is not on PATH:

cd ~/.dsh/profiles/web
corepack pnpm add "github:c-ling/dsh-plugin-pet#v1.0.2"

dsh plugin forwards its arguments to pnpm and fetches the package from this repo (pnpm 9+, git required). The warning declares no dsh.bundle — installed as a plain dependency is expected: this plugin is not a profile bundle layer; it is activated by the loader row below.

Then add a loader row to ~/.dsh/profiles/web/cordis.patch.yml:

- insert:
    - id: dsh-plugin-pet
      name: 'dsh-plugin-pet'
      config:
        maxImageBytes: 5242880   # optional: single-image upload limit (default 5 MB)
        maxSheetBytes: 10485760  # optional: spritesheet upload limit (default 10 MB)

Restart dsh web (client-modules caches package verdicts per process; new packages require a host restart), then hard-refresh the page. The pet appears in the bottom-right corner; its settings live under Settings → Pet.

Verify

curl -s http://127.0.0.1:3080/plugins/dsh-plugin-pet/client.js | head -c 60

It should print a factory bundle starting with window.__ModuleLoader__.load({; the pet should be visible in the bottom-right corner.

Update

dsh plugin --profile web add "github:c-ling/dsh-plugin-pet#v1.0.2"
# or: npx @deepseek-ai/dsh plugin --profile web add "github:c-ling/dsh-plugin-pet#v1.0.2"
# or: cd ~/.dsh/profiles/web && corepack pnpm add "github:c-ling/dsh-plugin-pet#v1.0.2"

Re-running the install command with the new #v1.0.2 pin upgrades the dependency; the loader row in cordis.patch.yml stays unchanged. Restart dsh web, then hard-refresh.

Uninstall

cd ~/.dsh/profiles/web
corepack pnpm remove dsh-plugin-pet   # or: dsh plugin --profile web remove dsh-plugin-pet

Remove the matching insert row from cordis.patch.yml, then restart dsh web. Uploaded data remains under $DSH_HOME/storages/dsh-plugin-pet/ until you delete that directory manually.

Using the pet

  • Drag the pet anywhere; the position is remembered per browser.
  • Single-click pets it (hearts pop out). Double-click hides it; click the paw button to bring it back.
  • Mood is derived from the live session state: idle, thinking, working (the bubble shows the current tool name), sad (prompt error), waiting (pending confirmation), plus a celebratory hop when a turn finishes.

Codex spritesheet import

  1. Go to Settings → Pet → Spritesheet → Import a Codex pet pack.
  2. Upload spritesheet.webp / spritesheet.png first. It must be 1536×1872 (V1, 9 rows) or 1536×2288 (V2, 11 rows) — an 8-column grid with 192×208 cells. The version is auto-detected.
  3. Optionally import pet.json — it applies displayName and verifies spriteVersionNumber against the uploaded spritesheet.

Codex rows map to DSH moods as: idle→0, thinking→8 (review), working→7 (running), happy→4 (jumping), sad→5 (failed), waiting→6, petting→3 (waving). Direction rows (1/2) and V2 facing rows (9/10) are unused by this plugin.

Generic spritesheet

Under Spritesheet → Generic spritesheet, any PNG/WebP whose width and height divide evenly into the grid works: set columns, rows, and fps, upload the image, then assign a row and frame count to each mood. A live preview player animates the draft before saving.

HTTP API

MethodPathPurpose
GET/dsh-plugin-pet/configCurrent effective pet configuration
POST/dsh-plugin-pet/configUpdate name / size / visibility / builtin sprite / sheet fps, state rows, frame counts
GET/POST/DELETE/dsh-plugin-pet/imageRead / upload (raw bytes) / delete the custom image
GET/POST/DELETE/dsh-plugin-pet/sheetRead / upload (raw bytes; ?source=codex&version=1|2|auto or ?source=custom&cols=&rows=&fps=) / delete the spritesheet
POST/dsh-plugin-pet/petjsonImport a Codex pet.json (requires a matching spritesheet already uploaded)

All uploads are validated server-side: magic-byte sniffing (PNG/JPEG/GIF/WebP), size limits, exact Codex dimensions, and even cell splitting for generic grids. Config writes are atomic.

Development

node --check lib/index.js lib/client.js
node --test test/sniff.test.mjs test/host.test.mjs

The client bundle is pure JavaScript in the harness factory-CJS format (window.__ModuleLoader__.load({ id: "dsh-plugin-pet", factory })); require("react") resolves through the shell static module table. All UI contributions are registered via the shell.overlay and settings.section slots and managed by disposers held through ctx.effect.

Known limitations

  • One global pet per page (root-scope overlay), not per session.
  • Codex “trailing empty frames” auto-detection is not implemented; frame counts come from the spec defaults or your explicit configuration.
  • The pet position is stored per browser (localStorage) and is not synced across devices.
  • Activating the plugin requires restarting the dsh web host process (the web profile disables Cordis HMR for host rows by default).

License

MIT