Tamagotchi + Claude — a virtual pet whose moods are your coding sessions.
🌐 English · ไทย
What the screen says · What you need · Getting started · Troubleshooting
Before you start
- macOS only. The app that talks to Claude Code is a Swift menu bar app for macOS 14 or newer. There is no Linux or Windows build, and the firmware alone does nothing without it.
- Unofficial. A personal hobby project, not affiliated with or endorsed by Anthropic. "Claude" and "Claude Code" belong to them.
- As-is. Flashing firmware overwrites whatever is on the board, and you do it at your own risk. No warranty — see LICENSE.
- Reading your quota from claude.ai is optional and needs an account credential. Read step 5 before you turn it on.
A desk device that shows what Claude Code is doing right now. A blocky orange mascot lives on a small screen next to your keyboard: it types when Claude types, waves when a session needs your answer, and celebrates when a build finishes. The bars at the bottom are your Claude usage quota.
The board, and the menu bar app that feeds it.
Nothing leaves your network. A menu bar app on your Mac reads Claude Code's hooks and pushes a small snapshot to the board over Bluetooth LE — and, if you set up Wi-Fi, over your own LAN as a sealed fallback when Bluetooth goes quiet. The board never talks to claude.ai.
While a session runs
| Busy | Waiting for you | Done |
|---|---|---|
![]() |
![]() |
![]() |
| Up to three sessions and the tool each one is using. | A session stopped and wants an answer. | The mascot celebrates a finished turn. |
When nothing is happening
| Idle | No sessions | Offline |
|---|---|---|
![]() |
![]() |
![]() |
| One session, sleeping. Night sky and clock. | The mascot strolls. Clock and date. | The Mac is out of range or the app is not running. |
Quota
| Normal | Running hot | Unknown |
|---|---|---|
![]() |
![]() |
![]() |
| The current 5-hour window and the weekly one. | Near the limit; the tick marks your pace against the clock. | --, never a guess, when no number has arrived. |
Over Wi-Fi
Hardware
- An ESP32-2432S028R board — the "Cheap Yellow Display", 2.8" 320x240, roughly 300 baht. Tested against ESP32-D0WD-V3 rev 3.1, 4 MB flash, no PSRAM.
- A USB data cable for the board's micro-USB port. Charge-only cables do not enumerate.
Mac
- macOS 14 or newer, with Bluetooth.
- Claude Code installed and logged in.
The Mac app is always built from source. The firmware you can either download or build — step 2 has both routes.
xcode-select --install
git clone https://github.com/thaitop/tamaclaude.git
cd tamaclaudePlug the board in and put its serial port into a variable, so the commands below work as written:
PORT=$(ls /dev/cu.usbserial-* | head -1)
echo "$PORT"That should print one path, something like /dev/cu.usbserial-1420 — the number differs
from board to board and from port to port, which is why nothing below spells it out. If
it prints nothing, see Troubleshooting.
PORT only exists in the terminal window you typed it in; if you open a new one, set it
again.
Download tamaclaude-esp32-*.bin from the
latest release. It is one file,
about 1 MB, containing the bootloader, the partition table and the app.
python3 -m pip install esptool
python3 -m esptool --chip esp32 --port "$PORT" \
write_flash 0x0 ~/Downloads/tamaclaude-esp32-1.0.4.binThat is the whole toolchain: about 10 MB of Python, no compiler. Skip to step 3.
Take this route if you want to change the firmware, or if your board turns out to need different panel settings.
Build tools:
brew install cmake ninja dfu-util python3ESP-IDF — this is the big one, roughly 2 GB. v5.5 is what this firmware is built and tested against; the component manifest accepts 5.4 and newer:
mkdir -p ~/esp && cd ~/esp
git clone -b v5.5 --recursive https://github.com/espressif/esp-idf.git
cd esp-idf && ./install.sh esp32Then, from the repository, load the toolchain into your shell and flash:
cd firmware
. $HOME/esp/esp-idf/export.sh
idf.py -p "$PORT" flash monitorThe export.sh line is per-shell and is not permanent; open a new terminal and you run
it again. The first build takes several minutes. If anything here goes wrong, Espressif's
own getting-started guide
is the authority.
The screen lights up and the board starts announcing itself over Bluetooth as
tamaclaude-3f7a — the last part comes from its MAC address, so you can tell two boards
apart. With idf.py monitor running you can watch it happen; press Ctrl+] to leave.
cd ../host
./Scripts/make-app.sh --installThis builds TamaClaude.app, copies it to /Applications, and launches it. macOS asks
for Bluetooth permission the first time — say yes, or the app can never see the board.
A small mascot icon appears in your menu bar. Click it for the quota panel; click the gear for settings. The foot of the panel tells you whether the board is connected and what each session is doing.
The badge next to the icon is your session usage, and it turns red when you are burning through the window faster than the clock is.
Everything below is in gear ▸ Settings… ▸ General:
- Install hooks in settings.json — this is the one that matters. It teaches Claude Code to tell the app what it is doing. Nothing appears on the board without it. Your existing settings are kept, and a backup is written beside the file.
- Board — pick your board by name, or leave it on Any board.
- Brightness — the slider drives the screen's backlight.
- Launch at login — so it is running before you start work.
Start a Claude Code session in any terminal. Within a second or two the mascot should start moving.
The bars at the bottom of the screen have two independent sources, both optional:
- Read quota from the statusline (Settings ▸ General) installs a Claude Code statusline that hands the app your current usage. It needs no password, but it only updates while Claude Code is running.
- Set session key… (Settings ▸ General) lets the app ask claude.ai directly, so the number keeps moving even with Claude Code closed. Refresh quota then chooses how often (Off / 60s / 5 min).
About the session key. It is the
sessionKeycookie of a logged-in claude.ai browser session, and it is a full-account credential — anyone holding it can act as your account. The app stores it in~/.tamaclaude/session-keywith mode 600 and never puts it in a command line, an environment variable, or a log. Take it out at any time by deleting that file, and revoke it by logging out of claude.ai in the browser you copied it from. If you would rather not, skip this — the statusline route above still shows a number.To get one: in your browser, open claude.ai while logged in → DevTools → Application → Cookies →
claude.ai→ copy the value ofsessionKey.
Taking over the statusline slot never changes what you see: your own statusline command is
handed the same input and its output is printed as is. If you never had one, the app draws
this instead — the same elements, colours, and ~/.claude/statusline-config.txt as the
statusline that ships with Claude Usage.
Bluetooth is the main path and always wins. It also drops — you walk past the board, the Mac half-sleeps — and until now that left a frozen screen. Put the board on your network and the app keeps feeding it when Bluetooth has been quiet for ten seconds.
gear ▸ Settings… ▸ Wi-Fi, with the board in Bluetooth range:
- The list fills in as the board scans — not your Mac, so what you see is what the board can actually reach. It is 2.4 GHz only; a 5 GHz-only network will not appear.
- Pick a network, type the password, Connect. macOS pairs with the board the first time; there is no six-digit code to enter.
- It says
Connected to <name>with the board's address. The board remembers up to five networks and comes back on its own after a power cut.
You do not have to configure anything on the Mac side. The snapshot is sealed with AES-256-GCM under a key the app generates and pushes to the board over the same encrypted channel as your Wi-Fi password, and the board is found over mDNS — the address box at the bottom of the tab is only for networks that filter it.
The board still never talks to claude.ai; your session key never leaves the Mac.
No /dev/cu.usbserial-* when the board is plugged in.
Usually the cable — many micro-USB cables carry power only. Failing that, the board's
USB-serial chip (CH340) may need a driver on older macOS releases.
Flashing stops at "Connecting........".
Hold the BOOT button on the board, start idf.py flash, and release it once the log
says Connecting. Also close any serial monitor still holding the port.
The screen is on but the colours are wrong, or the image is mirrored.
Some batches of this board ship a different panel than the one this firmware was measured
against. Run the probe project in firmware/probe/ to read out what your panel actually
reports, then change the two constants it disagrees with in firmware/main/ct_lcd.c:
the 0x36 (MADCTL) value for orientation and mirroring, and 0x20 (inversion off) versus
0x21 (inversion on) for inverted colours.
The board never shows up in the Board menu. Check that the app has Bluetooth permission in System Settings → Privacy & Security → Bluetooth, that the board is powered, and that nothing else is connected to it — the firmware accepts exactly one connection at a time.
macOS asks for Bluetooth permission again after every rebuild. Expected. The app is signed ad-hoc, so each build is a new identity as far as macOS is concerned. There is no way around it without an Apple Developer ID.
The mascot never moves. The hooks are probably not installed — Settings ▸ General → Install hooks in settings.json. Sessions already open when you install them keep the old settings; start a new one. Open log in the same tab shows what the app is receiving.
The Wi-Fi list stays empty, or the spinner never stops. Wi-Fi is set up over Bluetooth, so the board has to be connected first — the tab says so when it is not. The list only ever holds 2.4 GHz networks.
The board is on the network and pings, but the screen still freezes when Bluetooth goes. macOS 15 and newer ask for Local Network permission separately, and a refusal silences both mDNS and direct connections with no error at all. System Settings ▸ Privacy & Security ▸ Local Network.
- macOS only. The app that talks to Claude Code is a Swift menu bar app; there is no Linux or Windows build.
- No over-the-air updates. New firmware means plugging the USB cable back in.
- The touchscreen and speaker are unused. The panel is touch-capable and the board has a speaker pin; neither is wired up yet.
- Ad-hoc signing. The app is not notarised, so it is built per-machine rather than handed around.
MIT — see LICENSE.














