Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🟠 Lore Buddy 🟣

A tiny physical teammate that watches your AI coding agents and looks up at you the moment they need a decision.

Stop babysitting the terminal. Stop leaving agents blocked for 20 minutes. Glance over — and you just know.

Claude needs you Codex needs you

What is this?

Lore Buddy turns a $20 ESP32 touch-display into an ambient presence on your desk that mirrors the live state of Claude Code and OpenAI Codex. It has expressive animated eyes that you can read from across the room:

  • It works when your agent works (calm, focused, an orange or purple comet sweeping the screen edge).
  • It looks right at you, lights up, and softly chimes the instant the agent needs a decision — a permission, a question, a finished task.
  • It otherwise lets you stay in flow.

Four channels of glanceable information, no reading required:

Channel Meaning
Color Who — Claude is orange, Codex is purple
Border motion How active — a comet sweeps while it works
Eyes Emotion — focused, wide-alert, happy, worried
Logo + text The specifics — which agent, and what it needs

It's a build-status light, a Tamagotchi, and a notification system — fused into something that feels like a teammate.


The states

Working — agent is running. Focused eyes looking down, a slow comet sweeping the border in the agent's color. "It's grinding — go do something else."
Needs you (the killer state) — agent logo, eyes go wide and look at you, the reason as text, a faster brighter border, and one soft chime. "Come back, I need a decision."
Done — a happy squint and a celebratory border sweep, then it settles to calm.
Error — worried, dimmed eyes and a red border + red reason text.

Plus an idle ambient state (calm white eyes that look around and blink), and touch interactivity: the eyes follow your finger, and a tap dismisses an alert.


How it works

You ⇄ Claude Code ──hooks───────▶ ┐
                                   ├─▶  buddyd  ──USB serial──▶  ESP32-S3  ──▶  expressive eyes
       Codex ──notify event──────▶ ┘   (Mac daemon)              (firmware)
  1. The firmware (firmware/eyes/eyes.ino) renders everything itself — anti-aliased eyes via a signed-distance field, a per-pixel light-trail border, tinted logos, and text — into a full framebuffer in PSRAM, ~30 fps. It listens on USB serial for STATE <mood> <agent> <reason> lines.
  2. buddyd (mac/buddyd.py) is a tiny always-light daemon that holds the serial port open and translates agent events into state.
  3. Claude Code hooks feed it precise events: a prompt → working, a notification → needs you (with the real message), a finished turn → done.
  4. Codex feeds it through Codex's own notify mechanism (a wrapper that also forwards to your existing notifier, so nothing breaks).

Full detail in docs/ARCHITECTURE.md.


Hardware

A single off-the-shelf board, no soldering:

  • Waveshare ESP32-S3-Touch-LCD-1.69 — ESP32-S3 (8 MB PSRAM, 16 MB flash), 1.69" 240×280 IPS LCD (ST7789V2), CST816T capacitive touch, buzzer, IMU, RTC, USB-C.
  • A USB-C cable. That's it.

Pinout and flashing notes: docs/HARDWARE.md.


Quick start

1 · Flash the firmware

Install arduino-cli + the ESP32 core

  • "GFX Library for Arduino", and an esptool 4.x venv (the core ships esptool 5, which fails the connect on this native-USB board):
python3 -m venv .esptool-venv && .esptool-venv/bin/pip install 'esptool<5'
arduino-cli core install esp32:esp32 --additional-urls https://espressif.github.io/arduino-esp32/package_esp32_index.json
arduino-cli lib install "GFX Library for Arduino"

FQBN="esp32:esp32:esp32s3:PSRAM=opi,FlashSize=16M,CDCOnBoot=cdc"
arduino-cli compile --fqbn "$FQBN" --export-binaries firmware/eyes

# First flash only: hold BOOT, tap RST, release BOOT (enters download mode).
.esptool-venv/bin/esptool.py --chip esp32s3 -p /dev/cu.usbmodem* -b 921600 \
  --before default_reset --after hard_reset write_flash \
  0x0     firmware/eyes/build/esp32.esp32.esp32s3/eyes.ino.bootloader.bin \
  0x8000  firmware/eyes/build/esp32.esp32.esp32s3/eyes.ino.partitions.bin \
  0xe000  firmware/eyes/build/esp32.esp32.esp32s3/boot_app0.bin \
  0x10000 firmware/eyes/build/esp32.esp32.esp32s3/eyes.ino.bin

After this, CDC is enabled and future flashes auto-reset — no button needed.

2 · Install the Mac side

./install.sh        # installs ~/.buddy, the `buddy` command, and the launchd agent
buddy status
buddy test          # fire a test alert at the device

3 · Wire Claude Code

Add these to the "hooks" object in ~/.claude/settings.json (merge — don't replace existing hooks):

"UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "/Users/YOU/.buddy/bin/buddyctl working claude" }] }],
"Notification":     [{ "hooks": [{ "type": "command", "command": "/Users/YOU/.buddy/bin/buddyctl-notify" }] }],
"Stop":             [{ "hooks": [{ "type": "command", "command": "/Users/YOU/.buddy/bin/buddyctl done claude" }] }]

4 · Wire Codex (optional)

In ~/.codex/config.toml, point notify at the wrapper (it forwards to your existing notifier, so Computer Use etc. keep working):

notify = ["/Users/YOU/.buddy/bin/codex-notify"]

Now just use your agents — Lore Buddy reacts on its own.


The buddy command

Runs from anywhere. off fully stops the process — zero CPU/RAM, serial port released.

buddy on        start now + at login          buddy status   on/off + device connected?
buddy off       fully stop (zero resources)   buddy logs     watch live events
buddy toggle    flip on/off                    buddy test     flash a test alert
buddy restart                                  buddy idle     reset device to calm
buddy doctor    diagnose the whole setup      buddy demo     cycle through every state

buddy doctor checks every link in the chain — daemon, socket, device, Claude hooks, Codex notify — and tells you exactly what's broken and how to fix it. Run it first whenever something isn't reacting. buddy demo walks the device through every mood (working → needs-you → done → error) for both agents, so you can show it off or eyeball the firmware visuals without wiring up a single agent.

Mute the chime with the BOOT button on the device — a speaker icon pops up, a corner indicator shows it's muted, and it persists across reboots.


Customize

  • Colors / moods — edit the PAL_* palettes and MOODS[] table near the top of firmware/eyes/eyes.ino. Prototype changes instantly in preview/eyes3.html (open it in a browser — it's the design source of truth, mouse = touch).
  • Logos — drop new SVGs in assets/ and run python tools/gen_logos.py to regenerate firmware/eyes/logos.h.
  • PerformanceBUDDY_HEARTBEAT and BUDDY_CODEX env vars tune the daemon (see mac/README.md).

Troubleshooting

Start with buddy doctor — it walks the whole chain and pinpoints most of the issues below automatically. The rest:

Symptom Fix
esptool "No serial data received" Firmware is holding USB — hold BOOT, tap RST, release BOOT, then flash.
Eyes show the wrong agent color Process-sniffing is off by design; Codex only reacts to real notify events. Make sure step 4 is done.
Eyes follow your finger the wrong way Flip the dx/dy mapping in tpRead() in the firmware.
Image shifted at the panel edges Adjust the ROW_OFFSET/offsets in the Arduino_ST7789 constructor.
Nothing reacts to Claude Code Restart the CLI once so it loads the new hooks.

Credits

Created by Dakshay Mehtax.com/dakshay.

Also worth checking out: lore.thepantheonai.com.

Logos via simple-icons (CC0). "Claude" and the Claude mark are trademarks of Anthropic; "OpenAI"/"Codex" and their marks are trademarks of OpenAI — used here nominatively to identify each agent. Text font: Adafruit GFX (FreeSansBold). Built on Arduino_GFX.

License

MIT © 2026 Dakshay Mehta

About

A tiny ESP32 desk companion that mirrors your Claude Code & Codex agents — expressive eyes that tell you when an agent needs you.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages