Proyecto · M5StickC Plus2 · Claude Code

Arma tu personita: una IA de bolsillo que te avisa cuando Claude termina

Es una mascota virtual en pixel art que vive en un M5StickC Plus2, un computador del tamaño de un encendedor. Cuando Claude Code termina de trabajar en uno de tus proyectos, se pone feliz, suena y te muestra el nombre del proyecto. Y como las mascotas virtuales de antes, hay que cuidarla: come en sus horarios, duerme de noche y juega si la agitas. Te dejo el prompt completo para que Claude te la arme paso a paso, aunque nunca hayas programado.

La personita en pixel art: pelo morado tomado en un moño con elástico coral, audífonos, polerón coral, saludando con la mano

Qué hace

Claude Code puede trabajar largo rato solo en un proyecto mientras tú haces otra cosa. El problema es saber cuándo terminó. La personita te lo dice desde tu escritorio, y entre aviso y aviso, te pide que la cuides.

CuandoLo que hace la personita
Claude termina un proyectoSe pone feliz, suena dos veces y muestra el nombre de la carpeta, por ejemplo «qrescueid terminó». Si terminan varios, quedan en fila
Es la hora de almuerzo o de cenaTe avisa a las 13:00 y a las 18:00. Solo puede comer de 13:00 a 14:00 y de 18:00 a 19:00, como una persona
Llega la nocheSe acuesta entre las 21:00 y las 22:00 y despierta sola a las 7:00, con la energía cargada
Tiene sedPuedes darle agua a cualquier hora
Agitas el M5Juega contigo y sube su ánimo
La descuidasSi dos de sus necesidades quedan en cero por 3 horas, se enferma y se pone verde
El M5StickC Plus2 con la personita a la izquierda, la batería abajo y las barras de comida, agua, energía y ánimo a la derecha, con el menú Comer
Sus necesidades y el menú para cuidarla
El M5StickC Plus2 avisando que el proyecto diseno terminó, con la personita feliz
El aviso cuando Claude Code termina un proyecto
Las 7 caras de la personita: normal, feliz, hambre, sed, sueño, triste y enferma
Ojo con esto

Claude Code avisa cada vez que termina de responder y te está esperando, no solo cuando el proyecto entero está listo. Por eso la personita te avisa justo cuando te toca a ti.

Qué necesitas

Un M5StickC Plus2

Tiene pantalla a color, botones, batería, WiFi, parlante y un sensor de movimiento. Yo lo compré en la tienda oficial de M5Stack en AliExpress por unos 21 mil pesos; el precio va cambiando. También está en la tienda de M5Stack.

Claude Code

Es el que escribe el programa y lo sube al M5 por ti. Si todavía no lo tienes, en esta guía te explico cómo instalarlo.

WiFi de 2,4 GHz y un cable

El M5 solo se conecta a redes de 2,4 GHz: si tu router tiene una red que dice 5G, usa la otra. Y un cable USB-C que sirva para datos, no solo para cargar.

Cómo armarla

  1. Conecta el M5 al computador con el cable USB-C.
  2. Abre Claude Code en una carpeta vacía.
  3. Copia el prompt de abajo y pégalo en Claude Code.
  4. Claude va a avanzar de a un paso: te explica qué hace, lo hace, lo prueba y te espera. Cuando te diga que terminó un paso, escribe sigue.
  5. En el paso del WiFi, escribe tú el nombre y la clave de tu red en el archivo que te indique. Nunca la pegues en el chat.

Son 6 pasos: preparar el computador, dibujar a la personita, una primera prueba en el M5, la mascota con sus horarios, los avisos por WiFi y conectarla a Claude Code.

El prompt

Cópialo completo, tal cual. Trae el dibujo exacto de la personita, sus 7 caras, los horarios y todas las protecciones de seguridad.

Prompt para Claude Code
Quiero armar "la personita": una mascota virtual en pixel art para mi M5StickC Plus2 que hay que cuidar (comida, agua, energía y ánimo) y que además me avisa en la pantalla cuando termina una sesión de Claude Code, con el nombre de la carpeta del proyecto. No sé programar: guíame en español, explícame en 2 o 3 líneas qué vas a hacer en cada paso antes de hacerlo, y avanza de a un paso.

<reglas>
- Trabaja SOLO dentro de la carpeta `~/personita` (créala). La única excepción son los pasos 5 y 6, que guardan la clave de los avisos y el aviso de Claude Code en `~/.claude`.
- Haz SOLO lo que pide este documento. No agregues funciones, librerías, archivos ni servicios extra.
- NUNCA me pidas que escriba la clave de mi WiFi en el chat. Yo la escribo directamente en `secretos.h`.
- NUNCA abras puertos del router ni uses servicios en internet para los avisos: todo pasa dentro de mi red de la casa.
- Detén el trabajo y pregúntame antes de: instalar algo que no esté en este documento, reemplazar o borrar un archivo fuera de `~/personita`, o subir un programa al M5 por primera vez (reemplaza el programa de fábrica).
- Al terminar cada paso, escribe "✅ Paso N: [qué quedó hecho y cómo lo verificaste]" y espera a que yo diga "sigue".
- Si un mismo error se repite 3 veces, detente, explícame qué intentaste y pregúntame cómo seguir.
</reglas>

<paso n="1" titulo="Preparar el computador">
- Detecta mi sistema operativo. Con el M5 conectado por USB, encuentra su puerto serial (`arduino-cli board list` o `ls /dev/cu.*` en Mac). Si no aparece en Windows, dime que instale el driver CH9102 desde la página oficial de M5Stack y espera.
- Instala `arduino-cli` (Mac: Homebrew; Windows: winget).
- Agrega el catálogo de placas `https://static-cdn.m5stack.com/resource/arduino/package_m5stack_index.json`, instala la plataforma `m5stack:esp32` y la librería oficial `M5StickCPlus2` (autor M5Stack). La placa es `m5stack:esp32:m5stack_stickc_plus2`.
- Solo en Mac con chip Apple: el `ctags` que trae Arduino es para Intel y pediría Rosetta. Pregúntame antes, y si acepto, instala `universal-ctags` con Homebrew, respalda el original como `ctags.intel-original` y reemplázalo por un enlace al nativo.
- Verificación: `arduino-cli board listall` muestra `M5StickCPlus2`.
</paso>

<paso n="2" titulo="Dibujar a la personita">
Cada letra es un píxel. Colores:
K #1b1630 contorno · H #4b2a6b pelo · h #7a4aa8 brillo del pelo · P #2f2f3d audífonos · p #ee6c4d detalle coral (también el elástico del moño) · S #f4c7a1 piel · s #e2a882 sombra de piel · E #1b1630 ojos · W #ffffff brillo de ojos · M #c0504d boca · C #ee6c4d polerón · c #c9553b sombra del polerón · N #2e4460 pantalón · B #f2f2f2 zapatillas · G #c9dfae piel enferma · g #a9c78c sombra enferma · D #5ab0e6 gota y lágrima · Z #ffffff zetas de sueño. El punto es transparente.

Dibujo base (24 × 33):
```
..........KKKK..........
.........KHhhHK.........
........KHHhHHHK........
........KHhHHHHK........
........KHHHHHHK........
........KppppppK........
......KKHHHHHHHHKK......
.....KHHhhHHHHHHHHK.....
....KHHhhHHHHHHHHHHK....
...KPKHHHHHHHHHHHHKPK...
..KPpKHHSSSSSSSSHHKpPK..
..KPpKHSSSSSSSSSSHKpPK..
..KPpKSSEESSSSEESSKpPK..
..KPpKSSEWSSSSEWSSKpPK..
..KPPKSsSSSSSSSSsSKPPK..
...KKKSSSSSMMSSSSSKKK...
.....KSSSSSSSSSSSSK.KSK.
......KKSSSSSSSSKK..KSSK
........KKSSSSKK....KSSK
..........KSSK......KCCK
........KKCCCCKK...KCCK.
.......KCCCCCCCCK.KCCK..
......KCCCCCCCCCCKCCK...
.....KCCKCCCCCCCCCCK....
.....KCCKCCCCCCCCK......
.....KCCKCCCCCCCCK......
.....KSSKccccccccK......
......KK.KNNNNNNK.......
.........KNNKKNNK.......
.........KNNK.KNNK......
.........KNNK.KNNK......
........KBBBK.KBBBK.....
........KKKKK.KKKKK.....
```

Las 7 caras cambian las columnas 6 a 17 de algunas filas (fila: texto nuevo):
- Normal: el dibujo base.
- Feliz: 15 `SSSSMSSMSSSS`, 16 `SSSSSMMSSSSS`.
- Hambre: 15 `SSSSSMMSSSSS`, 16 `SSSSSMMSSSSS`.
- Sed: 15 `SSSSSSSSSSSS`, 16 `SSSSSMMSSSSS`, y una gota D arriba a la derecha (fila 1 col 20; filas 2 y 3 cols 19–21; fila 4 col 20).
- Sueño: 12 `SSSSSSSSSSSS`, 13 `SSEESSSSEESS`, 15 `SSSSSSSSSSSS`, 16 `SSSSSMSSSSSS`, y una Z (fila 0 cols 19–23; fila 1 col 22; fila 2 col 21; fila 3 col 20; fila 4 cols 19–23).
- Triste: 14 `SDSSSSSSSSsS`, 15 `SSSSSMMSSSSS`, 16 `SSSSMSSMSSSS`.
- Enferma: 12 `SSSSSSSSSSSS`, 13 `SSEESSSSEESS`, 15 `SSSSMSMSSSSS`, 16 `SSSSSMSMSSSS`, y en las filas 10 a 18, columnas 6 a 17, S pasa a G y s pasa a g.

Escribe un script en Python que convierta esto a `firmware/personita/sprites.h` (paleta en RGB565 con índice 0 transparente, y una matriz por cara) y otro que genere una imagen PNG con las 7 caras para que yo la revise. Verificación: muéstrame la imagen y espera mi visto bueno. Si quiero otros colores, cambia solo la paleta.
</paso>

<paso n="3" titulo="Primera prueba en el M5">
Programa que muestre a la personita (escala 3) sobre fondo #0d1b2a y que el botón grande (A) cambie de cara. Pon todo el código en `app.cpp` y deja `personita.ino` vacío con un comentario (así no depende de ctags). Compila, pídeme permiso para subirlo y súbelo. Verificación: te confirmo que veo las 7 caras.
</paso>

<paso n="4" titulo="La mascota">
- Pantalla horizontal (240 × 135). Dibuja todo en un `M5Canvas` y mándalo de una vez, sin parpadeo. Personita a la izquierda; debajo, una pila chica con el porcentaje de batería (verde > 50, amarillo 20–50, rojo < 20). A la derecha, 4 barras: Comida, Agua, Energía, Ánimo. Abajo, el menú `< Comer >`. Usa la fuente `efontJA_12/16` para que salgan tildes y ñ.
- Vive con los horarios de una persona, según la hora local:
  - **Almuerzo de 13:00 a 14:00 y cena de 18:00 a 19:00.** Comer solo funciona dentro de esos horarios y deja la comida en 100. Fuera de horario, Comer muestra "Todavía no es hora" y no hace nada. Si se salta una comida, sigue con hambre hasta la siguiente.
  - **Se acuesta entre 21:00 y 22:00 y despierta sola a las 7:00.** En ese horario, Dormir la acuesta. Si a las 22:00 sigue despierta, se duerme sola, pero baja el ánimo 20 por acostarse tarde.
  - **Siesta**: de día solo puede dormir si la energía está bajo 25, y despierta sola cuando llega a 100 o cuando la despiertas.
  - Si no hay hora válida (sin reloj ni internet), no aplica los horarios y deja comer y dormir en cualquier momento.
- Cada necesidad va de 100 a 0 y baja con el tiempo:
  - Comida: se vacía en 17 h despierta y a la mitad de velocidad durmiendo. Así, después de cenar a las 19:00 llega con hambre al almuerzo del día siguiente, sin quedar en 0.
  - Agua: se vacía en 6 h despierta, a la mitad durmiendo. Se puede beber a cualquier hora.
  - Energía: baja de 100 a 0 en 16 h despierta. **Durmiendo SUBE de 0 a 100 en 6 h**: súmala en cada actualización mientras duerme, nunca la restes, y guárdala.
  - Ánimo: se vacía en 10 h despierta y no baja durmiendo.
- Mientras duerme, la pantalla baja el brillo pero muestra "Durmiendo" y el porcentaje de energía subiendo, para que se vea que está cargando. Al despertar a las 7:00, vuelve el brillo normal.
- Botón lateral (B): recorre Comer, Beber, Dormir/Despertar, Jugar. Botón A: ejecuta. Beber +50. Al comer o beber queda feliz 1 minuto. Jugar: muestra "¡Agítame!" 8 segundos. Agitar el M5 (aceleración > 2 g, máximo una vez cada 10 segundos, solo despierta) sube ánimo +25 y baja energía −5. Si una acción no está permitida por el horario, explícalo en la línea del menú por 3 segundos.
- Cerca de cada comida y de la hora de dormir, te avisa con un pitido corto al empezar el horario (13:00, 18:00 y 21:00).
- La cara muestra lo más urgente: enferma, después durmiendo, después feliz, y si algo baja de 25, la cara de esa necesidad.
- Se enferma si dos necesidades quedan en 0 por 3 horas; se mejora cuando todas superan 50. Enferma no puede jugar.
- Te llama con 3 pitidos si algo está urgente: máximo una vez por hora y NUNCA entre las 22:00 y las 8:00.
- Guarda el estado con `Preferences` cada minuto y después de cada acción. Al encender, descuenta el tiempo que estuvo apagado (máximo 7 días) usando el reloj interno (RTC, guardado en UTC) y la hora de internet (NTP); cuando llega la hora de internet, corrige el RTC. Pregúntame mi zona horaria y usa su cadena POSIX (Chile continental: `<-04>4<-03>,M9.1.6/24,M4.1.6/24`).
- Antes de subirlo, prueba la lógica de los horarios y de la energía con un modo de prueba que acelere el tiempo (1 minuto real = 1 hora) y una hora simulada: comer a las 12:00 no funciona, a las 13:30 sí; acostarla a las 21:30 y ver que la energía sube hasta 100 y despierta a las 7:00. Después quita el modo de prueba.
- Verificación: compila, súbelo y yo te confirmo que las barras y el menú funcionan.
</paso>

<paso n="5" titulo="Avisos por WiFi">
- Crea `firmware/personita/secretos.h` con `WIFI_NOMBRE`, `WIFI_CLAVE` y `CLAVE_AVISOS`, más un `secretos.h.ejemplo` y un `.gitignore` que excluya `secretos.h`. Genera `CLAVE_AVISOS` al azar (24 bytes, base64 url) sin mostrarla en el chat, y guárdala también en `~/.claude/personita-clave` con permisos solo para mi usuario.
- Pídeme que escriba yo mi WiFi en `secretos.h` y avísame que el M5 solo usa redes de 2,4 GHz. Revisa que ya no tenga los datos de ejemplo, sin mostrar su contenido.
- En el M5: conectar al WiFi sin bloquear la pantalla, reintentar cada 30 segundos y anunciarse como `personita.local` (mDNS) cada vez que conecta. Servidor HTTP en el puerto 80 con una sola ruta, `POST /aviso`, con parámetro `proyecto` y cabecera `X-Clave`:
  - clave comparada en tiempo constante; si no calza, 401;
  - máximo 20 avisos por minuto (si se pasa, 429);
  - nombre limpiado: solo letras, números, `- _ .` y espacio, máximo 24 caracteres; si queda vacío, 400;
  - fila de máximo 5 avisos, sin repetir un proyecto que ya está esperando.
- Mientras haya avisos, tapan las barras: nombre del proyecto en coral (cortado con ".." si no cabe), "terminó", "+N más" y "A: visto"; suena un doble pitido y el botón A marca el primero como visto.
- Verificación: prueba con `curl -4` (sin el -4 se cuelga por IPv6) sin clave (401), con clave mala (401), con la clave buena (200) y con un nombre con `<script>` (se limpia). Si el computador no llega a la red local, dime que puede faltar el permiso de "Red local" para la terminal en los ajustes del sistema.
</paso>

<paso n="6" titulo="Conectar Claude Code">
- Crea `~/.claude/hooks/aviso-personita.sh` (en Windows, el equivalente en PowerShell): lee el JSON que llega por la entrada estándar, toma el nombre de la carpeta de `cwd` y lo manda con `curl -4 -s -m 3` a `http://personita.local/aviso` con la clave de `~/.claude/personita-clave`. Si algo falla, termina en silencio y con código 0: NUNCA puede frenar a Claude Code.
- Muéstrame el cambio antes de hacerlo y, si acepto, agrega en `~/.claude/settings.json` un hook `Stop` con `"async": true` que ejecute ese script, sin borrar los hooks que ya tenga.
- Verificación: al terminar tu respuesta, me tiene que llegar al M5 el nombre de esta carpeta. Si no llega, dime que cierre y vuelva a abrir Claude Code.
</paso>

<fin>
Cuando todo funcione, dame un resumen corto: qué hace cada botón, cómo cambiar de WiFi (editar `secretos.h` y volver a subir) y dónde quedó cada archivo. Agrega en el README del proyecto: "Personita original de Álvaro Cofré · Desarrollado por SICS · alvarocofre.dev".
</fin>

Cómo quedó blindada

El M5 va a estar conectado a tu WiFi y a Claude Code, así que el prompt trae estos cuidados desde el primer paso.

Tu WiFi no pasa por el chat

La clave la escribes tú en un archivo que queda solo en tu computador y que nunca se sube a GitHub.

Solo tu computador le habla

Los avisos llevan una clave secreta. Una visita conectada a tu WiFi no puede llenarle la pantalla de mensajes falsos.

Nada sale de tu casa

Todo pasa dentro de tu red: no abre puertos del router ni usa servicios externos. Solo viaja el nombre de la carpeta del proyecto.

Claude te pide permiso

Antes de instalar algo, borrar un archivo fuera de la carpeta, subir el programa al M5 o tocar la configuración de Claude Code, se detiene y te pregunta. Subir el programa reemplaza el que trae el M5 de fábrica.

De quién es

La personita la diseñé yo y la armé con Claude Code en mi propio M5StickC Plus2: el dibujo, las caras y el prompt son míos y los comparto gratis. El M5StickC Plus2 es de M5Stack. Ver la documentación oficial ↗

Si te sirvió esto, en recursos tengo más cosas del mismo estilo, todas gratis y explicadas para gente que no programa.