packages/desktop/.agents/skills/desktop-pet/SKILL.md
Create pixel-art chibi desktop pet companions for OpenWork's floating pet window.
Given any character name, generate a complete pet package with animated spritesheet
and place it in ~/.qwen/pets/ where OpenWork auto-discovers it.
Ask the user who they want as their desktop pet if not already specified. Then research the character's visual appearance:
Use web search if needed to gather visual reference. For well-known characters (F1 drivers, popular anime, etc.), rely on training knowledge.
Define 8-12 colors for the character:
| Color Role | Example (F1 Driver) | Example (Anime Character) |
|---|---|---|
| Primary outfit | Team color (papaya) | Uniform color (navy) |
| Outfit dark | Darker shade | Darker shade |
| Outfit light | Lighter shade | Lighter shade |
| Skin | Warm skin tone | Skin tone |
| Skin dark | Shadow skin | Shadow skin |
| Hair | Character hair color | Character hair color |
| Accent | Number/logo color | Eye color / accessory |
| Shoe | Dark grey/black | Character shoe color |
Important: All colors must be distinct and work at small pixel scale (3x = 9px details).
Use the template script at scripts/gen_spritesheet.py as a starting point.
The script generates a 1536×1872 pixel RGBA spritesheet (8 columns × 9 rows,
192×208 px cells) — the exact format OpenWork expects.
Run it like this:
python3 <skill_dir>/scripts/gen_spritesheet.py \
--output ~/.qwen/pets/<character_id>/spritesheet.webp \
--config '{"name":"...","colors":{...},"features":{...}}'
Or copy and customize the script for characters that need unique visual elements not covered by the parameterized version.
The 9 animation rows are:
| Row | State | Description |
|---|---|---|
| 0 | idle | Breathing + blinking (8 frames) |
| 1 | running-right | Running to the right (8 frames) |
| 2 | running-left | Running to the left (8 frames) |
| 3 | waving | Waving at user (8 frames) |
| 4 | jumping | Jumping celebration (8 frames) |
| 5 | failed | Sad/collapsed on error (8 frames) |
| 6 | waiting | Idle tapping (8 frames) |
| 7 | running | Generic running (8 frames) |
| 8 | review | Thinking/examining (8 frames) |
Write the manifest to ~/.qwen/pets/<character_id>/pet.json:
{
"id": "<character_id>",
"displayName": "<Display Name>",
"description": "<Short description — who is this character?>",
"spritesheetPath": "spritesheet.webp"
}
Rules:
id: lowercase, no spaces, URL-safe (e.g., piastri, satoru, goku)displayName: The name shown in the UI (e.g., "Piastri", "五条悟", "悟空")description: One short sentence describing the characterConfirm the files exist:
ls -lh ~/.qwen/pets/<character_id>/
Open the spritesheet in Preview for the user to check:
open ~/.qwen/pets/<character_id>/spritesheet.webp
Tell the user to activate:
Open OpenWork → Settings → Appearance → Pet Companion, click Refresh, then select <Display Name>.
The template supports several headgear types. Set via features.headgear:
cap — baseball cap with brim (default for F1 drivers)helmet — full racing helmet with visornone — no headgear (just hair)hat — generic hathood — hooded outfitcrown — royal crownhorns — devil/dragon hornsears — animal ears (cat, dog, etc.)halo — angel haloheadband — ninja/sports headbandSet via features.extras (list):
glasses — round or rectangular glassesscarf — neck scarftail — animal tailwings — small wings on backnumber — chest number (set features.number to the number string)logo — chest badge/logo areasweat_drop — anime sweat drop (in waiting/failed states){
"colors": {
"outfit": [255, 135, 32],
"outfit_dark": [220, 110, 20],
"outfit_light": [255, 170, 80],
"hair": [120, 80, 40],
"number": [30, 30, 30]
},
"features": {
"headgear": "cap",
"number": "81",
"extras": ["logo"]
}
}
{
"colors": {
"outfit": [30, 30, 50],
"outfit_dark": [20, 20, 35],
"outfit_light": [60, 60, 80],
"hair": [230, 230, 250],
"accent": [100, 180, 255]
},
"features": {
"headgear": "none",
"extras": ["glasses"]
}
}
{
"colors": {
"outfit": [220, 170, 100],
"outfit_dark": [180, 130, 70],
"outfit_light": [240, 200, 140],
"hair": [220, 170, 100],
"accent": [255, 255, 255]
},
"features": {
"headgear": "ears",
"extras": ["tail"]
}
}