Importing an animated pet required a file that was exactly 1536x2288, laid out as 88 seamless cells, with the last two rows holding sixteen distinct gaze angles. No image model emits that. Whatever a user got back from Jimeng or ChatGPT was some fixed size like 1024x1536, so the path ended at "the animation atlas must be exactly 1536x2288 pixels" every time. The third card was worse: "AI-generate full animation" was hardcoded `disabled`, so the one entry point named after what people actually wanted to do was dead. The fix was already in the tree. `scripts/assemble-generated-pet-atlas.py` landed in the same commit as the four built-in pets, which is to say the built-ins were produced this way — it takes an action sheet at any size, slices it on an 8x9 grid, fits each cell to 192x208, mirrors the run row to make run-left, and reuses rows to reach eleven. That capability was never wired to anything a user could reach. `petAtlasNormalize.ts` reimplements it on a canvas in the renderer, so an author draws nine rows and the app derives the rest. Verified against the reference assembler by reversing dada-code's atlas into a nine-row sheet and re-normalizing it: every difference lands on semi-transparent antialiased edges (2314 pixels, max channel delta 14/255) and opaque regions are identical. That residue is canvas premultiplied-alpha round-tripping, not a slicing bug. Three contract details worth stating. Row frame counts are now derived from `PET_ANIMATION_DEFINITIONS` rather than typed out a fourth time; they come out equal to the assembler's `(6,8,8,4,5,8,6,6,6,8,8)`. A sheet already at 1536x2288 passes through byte-for-byte instead of being resliced, because resampling finished artwork buys nothing. And since the validator never inspects the alpha channel, a flattened white background used to import happily and render as a rectangle on the desktop — the renderer now rejects sheets whose atlas is under 5% transparent (the built-ins sit near 78%) with a message that names the actual problem. The copy stops describing the implementation. "Animate one image" and "Import professional animation atlas / exact 1536x2288 v2 PNG" become "use a picture you already have" and "I already have an action sheet"; the dead AI card becomes a three-step walkthrough carrying a copyable prompt, a labelled 8x9 reference grid that can be saved locally, and the checks that catch the common failures. Reference images are generated by a script rather than hand- placed, in both languages. All five locales move together. Caught while reviewing the real dialog in Electron: after finishing the walkthrough the form heading fell through to the atlas branch and announced "I already have an action sheet" to someone who had just been walked through drawing one. Covered by a test now. Not done: docs/images/desktop_ui/15_pet_create_methods.png still shows the old dialog and needs a fresh capture from a running app to match the styling of the shots around it.
11 KiB
Desktop Pets
Desktop Pets are optional companions that live in a small transparent window outside the main app. They reflect a few useful session states, provide a quick way back to active sessions, and can be replaced with your own local artwork.
Pets are an Electron Desktop feature. They do not appear in H5 or the browser-only Web UI.
Enable a pet
- Open Settings → Pets.
- Turn on Show desktop pet.
- Choose one of the four built-in companions:
- Dada, the coding companion;
- Huhu, the planning companion;
- Bubu, the fixing companion;
- Huihui, the building companion.
- Adjust the size between
96pxand192px. - Choose whether to play animations and show the active-task panel.
The selected pet, size, window position, animation preference, and task-panel preference are restored between launches.
Interact with the floating pet
| Action | Result |
|---|---|
| Move the pointer near an idle pet | Its gaze follows the pointer; entering the pet also triggers a short jump |
| Click the pet | Bring the main Claude Code Haha window forward and play a wave |
| Drag the pet | Move the floating window; the pet runs in the drag direction |
| Right-click the pet | Open the menu for closing the pet window |
| Click the numbered task badge | Expand the active-session panel |
| Click a session in the panel | Return to that session in the main window |
| Click the arrow below the task list | Collapse the panel back to the numbered badge |
The pet can visibly distinguish working, waiting for you, failed, and idle states. The panel is a navigator, not an approval surface: return to the main app to handle any pending interaction, approve or deny a tool, stop work, or inspect full output.
When there are no active sessions, the task panel stays hidden. Disabling Show active task panel keeps active work behind the numbered badge instead of removing or stopping it.
The animation switch affects the pet only. Turning it off does not stop sessions. Claude Code Haha also respects the operating system’s reduced-motion preference.
Create a custom pet
Select Add pet under Your pets. The dialog offers three ways to make one. Images are processed entirely on your own computer: nothing is uploaded, and no chat quota is used.
Before choosing a file, enter:
- a Pet ID of at most 73 characters, containing only lowercase letters, numbers, and single hyphens, such as
docs-helper; - a display name;
- a short description.
The ID must be unique among your custom pets.
Option 1: use a picture you already have
The quickest route, about a minute. Pick a static image with a transparent background and the app adds breathing, floating and status motion locally.
The image must have:
- PNG or WebP format (APNG and animated WebP are rejected);
- width and height between
32pxand4096px; - no more than
16,777,216total pixels; - a file size no larger than
8MB.
This kind of pet only sways gently. It will not run, and it will not track your cursor. For full motion, use option 2.
Option 2: draw one with AI that runs and jumps
About ten minutes, and you need an AI that can draw. The dialog walks you through the prompt, the reference template and the checks.
Step 1: have an AI draw an action sheet
Open any AI that can draw (Nano Banana, ChatGPT image generation, Midjourney, Stable Diffusion and Jimeng all work — these are examples, not endorsements) and send it the whole block below, replacing the two "Character" lines with what you want:
Draw me a game character action sheet (sprite sheet).
[Character]
A round-headed orange kitten wearing a small blue scarf, chibi
three-heads-tall proportions, 3D cartoon render, soft glossy
surface, bright cheerful colours.
(Replace these lines with your own character - the more specific the better)
[Whole image]
- Fully transparent background: no backdrop colour, no grid lines, no text, no drop shadow
- Divide the image evenly into 8 columns x 9 rows, 72 equally sized cells
- One action frame per cell, character centred with a little margin around it
- Every cell must show the same character with identical proportions, colours and art style
- Leave unused cells fully transparent
[What to draw in each row]
Row 1, first 6 cells: standing still with a gentle breathing bob
Row 2, all 8 cells: a full run cycle facing right, always facing right
Row 3, first 4 cells: raising a hand and waving hello
Row 4, first 5 cells: crouch, leap, land
Row 5, all 8 cells: dejected and downcast, head lowered, sighing
Row 6, first 6 cells: waiting in place, glancing around
Row 7, first 6 cells: head down, busy working
Row 8, all 8 cells: head and gaze starting straight up, turning slowly to the right through upper-right, right and lower-right, ending near straight down
Row 9, all 8 cells: continuing from straight down, turning left through lower-left, left and upper-left, back to near straight up
Getting it wrong on the first try is normal. Ask for a redraw, or say "keep the character, redraw row 2 only".
Step 2: check it against the template
When the picture is ready, check three things before importing:
- The background is see-through, not white. A white backdrop becomes a square on your desktop; this is the most common mistake.
- 8 cells across, 9 rows down, one action per cell.
- The same character throughout, with no change of face, colours or proportions.
Save the template in the dialog writes this reference image to disk so you can lay out frames against it.
Step 3: pick the file
Fill in the ID, name and description, then select the picture. You do not need to resize anything — see "Sizes are aligned for you" below.
Option 3: I already have an action sheet
If you have drawn a sheet already, or hold a finished atlas, this path skips the walkthrough and goes straight to the form. Validation is identical to option 2.
What to draw in each row
You only draw nine rows; the app derives the rest:
| Row | Content | Frames needed |
|---|---|---|
| 1 | Idle: standing still with a gentle breathing bob | 6 |
| 2 | Run right: full run cycle, always facing right | 8 |
| 3 | Wave: raise a hand and greet | 4 |
| 4 | Jump: crouch, leap, land | 5 |
| 5 | Fail: discouraged, head down, sighing | 8 |
| 6 | Wait: looking around, shifting in place | 6 |
| 7 | Work: head down, busy | 6 |
| 8 | Gaze, upper half: straight up turning clockwise to near straight down | 8 |
| 9 | Gaze, lower half: continuing from straight down back to near straight up | 8 |
Notes:
- You do not draw "run left". The app mirrors row 2 horizontally to produce it.
- The last two rows are optional in practice. Repeat the first idle frame and the pet simply will not track your cursor; everything else still works.
- Leave unused cells at the right of each row fully transparent.
Sizes are aligned for you
After you pick the file, the app assembles the runtime atlas locally: it slices the sheet on an 8 × 9 grid, rescales each cell to 192 × 208, centres the character, mirrors the run row, and fills in the remaining runtime rows to reach 1536 × 2288.
That means:
- Exact dimensions are not required. Common AI output sizes such as
1024 × 1152work; a ratio close to 8:9 gives the best result. The reference size is1536 × 1872. - A finished
1536 × 2288atlas is kept byte-for-byte and is never resampled. - The assembled file stays under
8MB; WebP encoding is used automatically if a lossless PNG would exceed it.
Common problems
| Message | Cause and fix |
|---|---|
| This image has no transparent background… | The sheet was exported on a white or coloured backdrop. Ask for a transparent PNG, or remove the background with an editor. |
| This image cannot be sliced into 8 columns by 9 rows | The row or column count is off. Confirm 8 across and 9 down, or use a finished 1536 × 2288 atlas. |
| That image could not be read | An animated file (APNG / animated WebP) or a corrupt one. Use a static PNG or WebP. |
| That image is too big | The source exceeds 8 MB. Compress it, or ask for smaller output. |
| A pet with this ID already exists | Choose a different Pet ID, or remove the existing one (see "Storage and removal"). |
When the size, format, or image content does not meet these rules, the app refuses to create the pet and shows the matching error instead of adding an invalid entry.
After a successful import, the new pet is selected automatically and appears under Your pets.
Storage and removal
Custom pet packages are stored under:
${CLAUDE_CONFIG_DIR:-~/.claude}/cc-haha/pets
Use Open folder in Pet settings to open the resolved directory. This is also the current removal path:
- Select a built-in pet first if the package you are removing is active.
- Open the custom pet folder.
- Remove only the custom pet’s own package directory.
- Return to Pet settings and select Refresh.
Closing or disabling the floating window does not delete a custom pet. If a selected package goes missing, the app falls back to a built-in pet.
The loader skips invalid or unsafe packages and reports how many folders could not be loaded. Do not replace package files while an import is still running, and avoid symbolic links or unsupported animated image formats.
Privacy, safety, and boundaries
- Image selection, validation, copying, and lightweight animation are local operations.
- Importing a pet does not send the image to the selected chat model.
- A pet can show summarized task state and navigate to a session, but it cannot approve permissions, answer model questions, or control a task directly.
- Pets do not run in H5, IM integrations, or a browser-only deployment.
- The pet observes the local Desktop service; it is not a cloud monitor and does not stay active after the Desktop app exits.
- Always-on-top behavior, dragging across displays, and window placement can vary by operating system and desktop environment.
- A successful application build does not by itself prove pet-window behavior on every supported operating system.
If the pet does not move, check both Play animations and the operating system’s reduced-motion setting. If it does not appear at all, turn Show desktop pet off and on once, then restart the Desktop app before editing stored files manually.



