Desktop Pet
approvedby xiaosong8584
A cute 3D cartoon robot inside your note-taking editor. - This plugin has not been manually reviewed by Obsidian staff.
Desktop Pet for Obsidian
Project: https://github.com/xiaosong8584/obsidian-desktoppet
A cute 3D cartoon robot desktop pet floating inside your Obsidian window. Built with parametric geometry (Sphere / Cylinder / Capsule / Torus), zero external assets, install and play.
โจ Features
- ๐จ 3D Cartoon Robot โ Rounded head + dot eyes (with highlights) + antenna + chest core + blush, all parametric, no external assets
- ๐ฑ๏ธ Drag & Click โ Drag with mouse, touch or stylus to reposition; click triggers scale pulse + happy eyes + speech bubble
- ๐ค Idle Animations โ Breathing float, gentle sway, random blinks (2.5โ6s), arm swing, antenna wiggle
- ๐ญ 5 Color Schemes โ Soft Blue, Mint, Coral Pink, Lavender, Warm Orange
- ๐ Size Slider โ 0.5x to 2.0x
- ๐ Theme Aware โ Bubble & shadow use Obsidian CSS variables (
--background-secondary,--background-modifier-box-shadow), auto-follow theme - ๐๏ธ Status Bar Toggle โ One-click show/hide, also via
Ctrl+Pcommand palette (status bar is desktop-only) - ๐ Fully Transparent โ Doesn't block Obsidian content (outer
pointer-events: none, only pet is interactive) - โป๏ธ Full Lifecycle โ
onunloadreleases renderer / geometry / material / rAF / listeners
๐ธ Screenshots

Settings panel โ visibility toggle, size slider (1.25x), primary color, position X/Y and reset. The pet itself is visible in the bottom-right corner, showing a speech bubble.
โ๏ธ Development Setup
- Install Node.js 18+ (20 LTS recommended)
- Clone or open the project:
cd obsidian-desktoppet npm install - Build commands:
npm run dev # watch mode: rebuild on save (non-minified, inline sourcemap) npm run build # production build: tsc type-check + minified main.js npm run build:dev # one-off development build (non-minified, inline sourcemap; exits when done)
๐ฆ Install to Obsidian
- Run
npm run buildto generatemain.js - Open Obsidian โ Settings โ Third-party plugins โ Disable Restricted Mode
- Copy the build artifacts only into
.obsidian/plugins/desktoppet/:
Source<your-vault>/.obsidian/plugins/desktoppet/ โโโ main.js # required (build artifact) โโโ manifest.json # required โโโ styles.css # required.tsfiles are not needed in the plugin directory. - Restart Obsidian (or refresh the plugin list)
- Search "Desktop Pet" in the plugin list and enable
Note: Works on both desktop and mobile (
isDesktopOnly: false). Interaction is built on Pointer Events, so mouse, touch and stylus all drive the same drag / click logic.
๐ฎ Usage
- Command palette โ
Ctrl+Pโ search "Show/Hide Pet" - Status bar โ Robot icon in the bottom-right corner, click to toggle (desktop only)
- Drag โ Press and drag the pet (mouse, touch or stylus) to any position
- Click โ Click the pet body โ scale pulse + happy eyes + speech bubble
- Settings โ Settings โ Community plugins โ Desktop Pet
- Visibility toggle
- Pet size (0.5x โ 2.0x)
- Primary color (5 soft schemes)
- Position X / Y (pixels)
- Reset to default
๐ Documentation
๐๏ธ Project Structure
desktoppet/
โโโ main.ts # Plugin entry (Plugin class + lifecycle + commands + status bar)
โโโ pet/
โ โโโ PetScene.ts # Three.js scene (renderer / scene / camera / lights / rAF loop)
โ โโโ PetModel.ts # Parametric 3D robot model (geometry composition)
โ โโโ PetAnimator.ts # Animation controller (idle / blink / click / drag tilt)
โ โโโ PetInteraction.ts # Interaction layer (Pointer Events drag + click)
โโโ settings/
โ โโโ SettingsTab.ts # Settings panel + DEFAULT_SETTINGS
โโโ styles.css # Floating container / bubble / status bar styles (theme aware)
โโโ manifest.json # Obsidian plugin manifest
โโโ package.json # npm dependencies
โโโ tsconfig.json # TypeScript config
โโโ esbuild.config.mjs # Build script
โโโ images/ # README screenshots
โโโ README.md # This file
๐ ๏ธ Tech Stack
- Language โ TypeScript (strict mode, no
any) - 3D Rendering โ Three.js
0.160.x - Build โ esbuild + Obsidian standard plugin template
- Dependencies โ Only
threeat runtime; everything else is dev-only
๐ Key Implementation Details
Primary Color Replacement
PetModel tags the material it builds for the body/antenna/limbs with material.userData.isPrimary = true. PetScene.applyColor() walks the model and swaps exactly those materials to the target color โ nothing else is touched.
No color-value heuristics ("white/dark/blush are not primary"): a heuristic both under-matches (the primary color could never be changed back if it happened to equal the detail color) and over-matches (any new auxiliary material of an unexpected shade would be repainted as primary).
Click Pulse
Click feedback (scale pulse + happy eyes + antenna bounce) is driven entirely by the animation loop's elapsed clock:
scalePulse = 1 + Math.sin(t * Math.PI) * 0.3;
group.scale.setScalar(scalePulse);
PetAnimator.triggerClickFeedback() reads the cached lastElapsed written by update(). It must not query performance.now() โ that clock counts from page load while the loop's elapsed counts from scene creation, so mixing the two made elapsed - clickStartAt permanently negative and the feedback never converged.
The pet's visual size is controlled solely by the container / canvas size; the model itself always stays at 1:1 inside it.
Speed-Aware Drag Tilt
During drag, compute a tilt target from the X velocity (-0.3 ~ +0.3 rad), then smooth it with a first-order low-pass filter:
tiltCurrent += (tiltTarget - tiltCurrent) * Math.min(1, delta * 8);
The filter runs every frame (not only while dragging), so releasing the pointer lets the tilt decay back to zero instead of staying frozen at its last angle.
Transparent Background
WebGLRenderer({ alpha: true })+setClearColor(0x000000, 0)- CSS container
pointer-events: none, only inner canvaspointer-events: auto - Outer layer doesn't block Obsidian content interaction
- While hidden, the canvas gets an explicit
pointer-events: noneโopacity: 0alone still receives hits
โ ๏ธ Known Limitations
- On touch devices the pet area captures the pointer (
touch-action: none), so scrolling / zooming gestures that start on the pet itself are suppressed by design โ drag it from elsewhere if you need to scroll - Position is clamped to the viewport, so the pet can never be dragged (or configured) off-screen; on a very small window a large pet will sit pinned to the top-left corner
- Speech bubble appears at the top of the container; may be clipped if the pet is near the window top edge
- No hover effect yet (could add slight scale + highlight boost)
๐ Future Directions
- Hover effects
- Multiple robot shapes (sphere / block / humanoid)
- Emotion system (fall asleep after idle)
- Custom keyboard shortcuts
- Multi-touch gestures (e.g. pinch to resize)
- More phrases, multi-language
- Obsidian note integration (e.g. open new note on click, show last-modified time)
๐ License
MIT ยฉ xiaosong8584
For plugin developers
Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.