Purro Stick: A Desk Pet for Claude Code
Purro Stick
Purro Stick is a desk pet for Claude Code. A small orange cat lives on an M5StickC Plus next to my keyboard and shows what my coding agent is doing: it looks busy while tools are running, perks up when the agent needs my attention, and falls asleep when the session ends. When Claude Code asks for permission to run something, I can approve or deny it by pressing a button on the stick. In the video above, Claude Code is waiting for approval to run a command; I press the front button and the terminal carries on.
Why I Built It
The idea comes from Anthropic’s open-source claude-desktop-buddy and Felix Rieseberg’s demo of a physical pet that reacts to Claude. In that setup the Claude desktop app is the Bluetooth bridge to the device. I work in the Claude Code CLI, so I did not want a desktop app running in the background just to keep a pet alive.
The firmware’s Bluetooth protocol is fully documented, so I wrote the host side myself: a small Python daemon that listens to Claude Code and talks to the stick directly.
How It Works
Any number of terminal windows. HTTP hooks fire on session start, tool use, notifications, stop, and permission requests.
Runs in the background and restarts on login. Merges events from every session into one state, counts output tokens from the session transcripts, and holds a permission request open until a button is pressed.
Official firmware with a custom character pack. Shows the pet's mood, recent activity, and a prompt when approval is needed.
Every state change is sent to the device as a small JSON heartbeat:
{
"total": 1, "running": 1, "waiting": 0,
"msg": "approve: Bash",
"entries": ["10:42 git push"],
"tokens": 184502, "tokens_today": 31200,
"prompt": {"id": "perm_xxx", "tool": "Bash", "hint": "rm -rf /tmp/foo"}
}
When I press a button, the answer travels back the same way and becomes the response to Claude Code’s permission request.
The stick has an info screen that shows the same state the bridge is sending: how many sessions are open, how many are running or waiting, and how long ago the last message arrived.

What It Does
- Mood follows the agent. Idle, busy, needs attention, celebrating, asleep.
- Buttons answer permission requests. The front button approves, the side button denies.
- Tokens are food. The bridge counts output tokens, and the pet fills up and levels as the agent works.
- It reacts to being handled. Shake it and it gets dizzy. Lay it face down and it naps.
- It tracks every session. Several Claude Code windows feed the same pet.
Drawing Purro
The character is generated by a Python script instead of drawn by hand. The script composes each face from small parts (eyes, mouth, extras like hearts or sparkles) on a pixel grid, exports the frames as GIFs, and packs them for the device. Changing the palette or adding an expression is a few lines of code and one flash over USB. The animations come from the same parts: a blink is two frames with different eyes, a bounce is the same cat drawn a few pixels higher.
M5StickC Plus (ESP32), Python (bleak, aiohttp, Pillow), Claude Code hooks