Voltar

Um dashboard de uso do Claude no M5Stack Basic — limites do plano e gastos de API na sua mesa

O M5Stack Basic sobre o teclado de um notebook mostrando o dashboard: uma conta Claude Max em 88% do limite semanal, a sessão de 5 horas em 30% e 142M de tokens hoje

Eu uso o Claude todos os dias, e a pergunta que faço com mais frequência não é sobre código. É “quanto da minha semana ainda resta?”. A tela /usage do Claude Code responde, mas só quando eu paro e digito o comando. Eu queria a resposta na minha mesa, do jeito que um relógio mostra as horas.

O M5Stack Basic é uma boa escolha. É um dispositivo pronto: uma tela de 2 polegadas 320×240, três botões, uma bateria e um ESP32 em uma carcaça de 54 mm. Sem protoboard, sem solda.

Este artigo descreve o dashboard: o que ele mostra, como os dados vão do Claude até a tela, como o dispositivo se conecta sem nenhuma configuração e os passos para construir o seu. A interface foi projetada no M5Stack Core no Velxio antes de tocar o hardware, e essa é a rota que recomendo se você quiser construir um. Você também pode executar este firmware no seu navegador, com dados de demonstração, sem o dispositivo.

O dashboard no dispositivo: assista no YouTube.

Todo o código, o firmware e a ponte no PC, está no GitHub sob a licença MIT: velxio/m5claude. A seção “O código, parte por parte” abaixo percorre o que cada arquivo faz.

O hardware

O M5Stack Basic v2.7: um ESP32 com tela IPS de 2 polegadas 320x240, três botões, USB-C, slot microSD e uma bateria de 110 mAh

A placa é o M5Stack Basic Core IoT Development Kit v2.7:

Nada mais é necessário: o dashboard usa apenas o que está na carcaça. A placa não tem IMU, microfone, LEDs nem relógio de tempo real, então o dashboard usa todo o resto: a tela e os botões, o alto-falante para alertas, o backlight para economizar bateria e o chip de energia para mostrar a carga.

O que a tela mostra

O dashboard funciona com dois tipos de conta do Claude, e com várias de cada:

Para ambos, mostra tokens por dia na última semana, divididos em entrada, saída, leituras de cache e escritas de cache, e por modelo.

São quatro telas. B passa para a próxima, A e C alternam entre contas, segurar B pede dados novos ao PC, e segurar C abre as configurações. Estas são todas as telas, com a animação que cada uma reproduz ao abrir:

Um tour animado por todas as telas: a visão geral com três contas, as telas de limites, tokens e detalhamento, uma organização de API, a visão geral de conta única, a bateria carregando, as configurações em inglês e espanhol, o pedido de aprovação e a tela de espera

Visão geral. Um cartão por conta. O layout se adapta à quantidade de contas: uma conta ocupa a tela, duas ganham cartões mais altos com uma linha para o uso de hoje, e três ou mais viram uma lista rolável.

A visão geral com uma conta Claude Max: o limite semanal como um anel, a sessão de 5 horas e os limites por modelo à direita, e os tokens de hoje com um gráfico de sete dias

A visão geral com duas contas Max e uma organização de API: porcentagem semanal, barras de 5 horas e 7 dias, horários de reset e gasto de sete dias da conta de API

Limites. O limite semanal como um anel, com a sessão e os limites por modelo ao lado. Os nomes dos modelos vêm do próprio Claude, então as linhas acompanham os limites que o seu plano tiver. As cores mudam em 60% (âmbar) e 85% (vermelho).

A tela de limites: um anel semanal de 67%, a sessão de 5 horas em 42%, e os limites semanais de Opus e Sonnet

Tokens. Hoje, os últimos sete dias e o valor em dólares, depois tokens por dia com uma linha tracejada na média. Para uma assinatura, o valor em dólares é quanto os mesmos tokens custariam pelos preços de tabela da API. Não é uma cobrança, mas é uma forma útil de ver com que intensidade você usa o plano.

A tela de tokens: 2,84M de tokens hoje, 20,8M em sete dias, um valor de API de US$ 84,20 e um gráfico de barras de tokens por dia

A tela de tokens no dispositivo, com 142M de tokens hoje e 296M em sete dias

Detalhamento. Os tokens da semana por tipo e por modelo. Com o Claude Code, as leituras de cache costumam ser a maior parte do total.

A tela de detalhamento: uma barra empilhada de tokens de entrada, saída, leitura de cache e escrita de cache, e a participação de cada modelo

A tela de detalhamento no dispositivo: quase todos os 296M de tokens de uma semana são leituras de cache, divididas entre Opus e Fable

O ponto ao lado do relógio mostra a conexão: verde enquanto os dados estão atualizados, âmbar quando estão defasados, vermelho quando nenhum PC está conectado. As fotos mostram a minha própria conta. As capturas de tela usam contas de demonstração.

Bateria, som e configurações

Ao lado do relógio está a bateria, desenhada como os celulares desenham: o nível, e um raio com um preenchimento que sobe enquanto carrega. O chip de energia IP5306 reporta apenas quatro degraus (25, 50, 75 e 100%), então o número muda em passos de 25.

O cabeçalho durante o carregamento: 75% com um raio e uma bateria verde, ao lado do ponto de conexão e do relógio

O alto-falante é usado para alertas. Quando uma sessão ou um limite semanal passa de 90% (ou 80%, se você escolher), o dispositivo toca um bipe duplo curto e mostra qual conta e qual limite. Quando um limite é resetado, toca um bipe ascendente. Pedidos de aprovação de um computador novo também emitem som. Os cliques dos botões são opcionais.

Segurar C abre as configurações. A e C navegam, B altera um valor, e segurar B fecha a tela. As configurações são salvas no dispositivo.

A tela de configurações: idioma, brilho, sons, limite de alerta, tela desligada na bateria, escurecer à noite, computadores pareados e a versão do firmware

As mesmas telas em espanhol: as configurações e a visão geral

A visão geral em espanhol

Fazendo 110 mAh durarem

O primeiro firmware drenava a bateria em bem menos de uma hora. A CPU rodava a 240 MHz, a tela se repintava a cada segundo, e o rádio transmitia na potência máxima com um intervalo de conexão de 15–30 ms. Nada disso é necessário para mostrar um número que muda uma vez por minuto. Na bateria, o firmware agora faz o seguinte:

Para uso o dia todo longe da mesa, o Battery Module 13.2 se encaixa embaixo do Basic e adiciona 1500 mAh.

Como funciona

Os dados fluem do login e dos transcripts do Claude Code e da Admin API para a ponte em Python, depois por USB ou Bluetooth LE até o M5Stack, que apenas desenha o que recebe

A regra de projeto é que o dispositivo não sabe nada. Ele não guarda credenciais do Claude nem configurações de Wi-Fi. Um pequeno programa no PC, a ponte, coleta tudo e envia ao dispositivo um snapshot para desenhar. Isso mantém os segredos fora de um aparelho que fica em cima da mesa, e significa que trocar de computador ou de rede não exige nenhuma reconfiguração.

De onde vêm os dados

A ponte tem cerca de 1.100 linhas de Python com duas dependências (pyserial e bleak). Ela lê três fontes:

  1. Limites do plano, a partir do login do Claude Code. Cada diretório de configuração do Claude Code (~/.claude, ~/.claude-work, …) guarda o login de uma conta. A ponte encontra todos e usa cada token para ler os mesmos limites que a tela /usage do Claude Code mostra. Ela apenas lê o token e nunca o renova, porque renovar rotacionaria o token e desconectaria o Claude Code.
  2. Tokens, a partir dos transcripts do Claude Code. Toda resposta que o Claude Code recebe é gravada em um arquivo JSONL em projects/, com o uso de tokens e o modelo. A ponte soma esses valores por dia, remove duplicatas (uma sessão retomada copia mensagens anteriores para um novo arquivo) e os precifica com a tabela de preços da API.
  3. Gastos das organizações de API, a partir da Usage and Cost Admin API. usage_report/messages fornece tokens por dia e por modelo. cost_report fornece o gasto real. Ambos exigem uma chave da Admin API (sk-ant-admin01-...).

Duas lições de rodar isso contra contas reais:

O snapshot

Cada atualização produz uma linha JSON de cerca de 600 bytes:

{"v":1,"ts":1792770195,"tz":3600,"acc":[
 {"n":"Personal","p":"Max 20x","k":"sub","ok":1,
  "s":[42,1792778235],"w":[67,1793037195],"x":[["Opus",54,1793037195],["Sonnet",31,1793037195]],
  "td":2840000,"tk":[2310000,1480000,15900000,1120000],"c":84.2,"ct":11.35,
  "d":[1900000,3400000,2600000,4100000,3300000,2670000,2840000],"m":[["Opus",61],["Sonnet",34],["Haiku",5]]}]}

s, w e x são os limites de sessão, semanal e por modelo como [percentual, horário de reset]. d é tokens por dia. ts e tz são o relógio do PC e o deslocamento UTC. O M5Stack Basic não tem relógio de tempo real nem banco de dados de fusos horários, então o dispositivo pega ambos do snapshot e conta os segundos a partir dali. Isso basta para “reinicia em 2h 14m” e “Ter 04:00”.

Conectando sem configuração

Eu não queria nenhuma configuração. Digitar uma senha de Wi-Fi em um dispositivo com três botões é desagradável. Salvar o endereço IP do PC no dispositivo quebra assim que você troca de computador. Então o dispositivo suporta dois links, e nenhum deles precisa de ajustes.

USB. Conecte o cabo. A ponte procura portas seriais cujo chip USB seja de um M5Stack (CH9102 ou CP2104). Ela abre a porta sem alternar DTR e RTS, para que o ESP32 não reinicie, e espera por uma saudação. O firmware envia {"hello":"m5claude",...} a cada dois segundos até os dados chegarem. Se nenhuma saudação chegar em alguns segundos, a ponte libera a porta e a deixa em paz por um tempo, para que outras placas ESP32 e ferramentas de gravação não sejam afetadas.

Bluetooth LE. O firmware anuncia um serviço GATT com duas características: uma na qual o PC escreve linhas, e outra na qual o dispositivo envia notificações. A ponte procura pelo UUID do serviço e se conecta. Não há diálogo de pareamento do Windows, e nada para escolher de uma lista.

Como qualquer computador ao alcance poderia encontrar o dispositivo, cada novo PC é aprovado uma vez, no próprio dispositivo:

O prompt de aprovação: "New computer, DESKTOP-STUDIO. Allow it to send usage data?" com Deny no botão A e Allow no botão C

A troca de pareamento: hello do dispositivo, o nome e o id estável do PC vindos da ponte, uma resposta pendente, o prompt na tela, depois ok, uma solicitação de atualização e os snapshots

A ponte mantém um id aleatório em ~/.m5claude/pc_id. O dispositivo guarda os ids de até quatro PCs aprovados na NVS. Um PC conhecido é aceito na hora, e segurar A ao ligar esquece todos eles. Um dispositivo que já está conectado por USB é ignorado no Bluetooth, para não pedir a aprovação do mesmo PC duas vezes.

Até a ponte estar rodando, o dispositivo mostra o que fazer:

A tela de espera: "Waiting for your PC. Run m5claude-bridge on your computer. It connects over USB or Bluetooth automatically."

O firmware

O firmware é um sketch Arduino compilado com arduino-cli no core arduino-esp32 2.0. Ele usa três bibliotecas:

O código da UI não depende do hardware. Ele desenha em um alvo LovyanGFX e lê os três botões. Tudo o que é específico da placa (o painel, USB, BLE, NVS) fica no sketch.

Alguns detalhes que fazem parecer um produto em vez de uma demo:

Desenhando sem PSRAM, e os riscos diagonais

Um quadro completo de 320×240 em cores de 16 bits tem 150 KB. O maior bloco de memória livre do ESP32, com o Bluetooth rodando, é menor que isso. Então a UI é desenhada quatro vezes por quadro em uma faixa de 320×60 (38 KB). Cada passada desenha tudo deslocado pelo offset da faixa, e as partes que caem fora da faixa são recortadas.

A primeira vez que isso rodou na placa, a tela mostrou riscos diagonais, e os botões do prompt de aprovação apareceram duas vezes, no topo e na parte de baixo. A configuração do painel foi meu primeiro suspeito. Reescrevi à mão a partir da documentação da M5Stack, e nada mudou. A causa estava em outro lugar:

Com um buffer, a próxima faixa é desenhada no buffer enquanto o DMA ainda o está enviando. Com dois buffers, um é desenhado enquanto o outro é enviado, e a CPU espera a transferência antes de reutilizar um buffer

O LovyanGFX envia um sprite para o painel com DMA, em segundo plano. Meu loop começava a desenhar a próxima faixa no mesmo buffer enquanto a anterior ainda estava sendo enviada, então o painel recebia metade de uma faixa e metade da seguinte. A correção usa dois buffers alternadamente e espera a transferência anterior antes de enviar:

for (int y = 0, k = 0; y < 240; y += 60, k ^= 1) {
  LGFX_Sprite& band = bands[k];
  band.fillScreen(BG);
  draw_ui(band, /*offset_y=*/y);   // runs while the other buffer is still being sent
  lcd.waitDMA();                    // the other buffer's transfer has finished
  band.pushSprite(&lcd, 0, y);      // starts this buffer's transfer
}
lcd.waitDMA();

Custa um buffer de 38 KB a mais, de cerca de 275 KB de RAM livre.

O código, parte por parte

Baixe o código com git clone https://github.com/velxio/m5claude.git, ou como ZIP pelo botão Code do repositório. Ele tem duas metades que não compartilham nada além do protocolo: bridge/ roda no PC, e firmware/ mais src/ rodam no M5Stack.

No M5Stack

firmware/m5claude/m5claude.ino: tudo o que é específico da placa.

src/app/app.cpp: o protocolo, independente do link.

src/model/: os dados.

src/ui/: as telas.

No PC

A ponte fica em bridge/m5claude_bridge/. Suas únicas dependências são pyserial e bleak. As chamadas HTTPS usam a biblioteca padrão.

__main__.py: a linha de comando e o loop principal.

autostart.py registra a ponte para iniciar no login sem janela: a chave de registro Run com pythonw no Windows, um LaunchAgent no macOS, uma unit de usuário do systemd no Linux.

config.py: as contas.

sources/: um arquivo por fonte de dados.

pricing.py guarda os preços de tabela da API por família de modelo. Ele estima o valor do uso da assinatura.

snapshot.py: monta o snapshot.

hub.py guarda o snapshot mais recente e o entrega a cada dispositivo conectado. Um link lento recebe apenas o mais recente, nunca um acúmulo.

transports/: um arquivo por link.

O README do repositório tem o mesmo tour em tabelas, além de solução de problemas.

Monte o seu

A ordem que eu recomendo: desenhe as telas no Velxio, depois grave o firmware na placa, depois conecte a ponte.

1. Execute e altere no M5Stack Core no Velxio

O Velxio simula o M5Stack Core com sua tela de 320×240, os botões A, B e C e o chip da bateria. Montar o layout de uma tela de 2 polegadas envolve muitos ajustes pequenos (um rótulo dois pixels abaixo demais, um número que não cabe no seu cartão), e cada um leva segundos no navegador em vez de um ciclo de gravação.

O dashboard está na galeria de exemplos do Velxio, com os mesmos arquivos-fonte do repositório:

  1. Abra M5Stack Core: Claude usage dashboard (m5claude) e clique no botão de play. Não é preciso cadastro. Ele começa com as contas de demonstração deste artigo.
  2. Clique em A e C para escolher uma conta e em B para percorrer as visualizações. O simulador executa o firmware mais devagar que a placa, então para abrir as configurações, segure C por alguns segundos.
  3. Para ver seus próprios números, execute m5claude-bridge snapshot no seu PC e cole a linha que ele imprime no monitor serial. O primeiro comentário do sketch tem uma linha de exemplo que você pode editar.
  4. Altere as telas em ui.cpp e execute de novo. Quando estiverem boas, grave na placa.

Duas coisas diferem da placa: o Velxio não tem Bluetooth, então esse link fica de fora e o monitor serial é o único link, e o código do alto-falante usa as chamadas do core ESP32 Arduino mais recente. Cada alteração está marcada no sketch.

Para começar um dashboard seu a partir de uma tela vazia, M5Stack Core: Hello LCD + Buttons é o menor exemplo. Ele usa o M5GFX da M5Stack, que é construído sobre o LovyanGFX e compartilha sua API de desenho, então o código transita entre os dois.

2. Grave o firmware

git clone https://github.com/velxio/m5claude.git && cd m5claude
arduino-cli core install esp32:esp32
arduino-cli lib install LovyanGFX NimBLE-Arduino ArduinoJson

./firmware/build.sh /dev/ttyUSB0      # Linux / macOS
.\firmware\build.ps1 -Upload          # Windows, finds the COM port by itself

Os scripts compilam para o M5Stack Core com um esquema de partições que deixa espaço para um app grande (PartitionScheme=no_ota). O firmware tem cerca de 820 KB. Duas configurações me pegaram de surpresa:

3. Execute a ponte

pip install -e bridge                # from the repository root; installs pyserial and bleak
m5claude-bridge accounts             # which accounts it found
m5claude-bridge autostart on         # start now, and at every login

autostart on registra a ponte para iniciar quando você faz login, sem janela. No Windows ele adiciona um valor sob a chave de registro Run do usuário que inicia o pythonw. No macOS ele instala um LaunchAgent, e no Linux um serviço de usuário do systemd. autostart status mostra se ela está em execução e as últimas linhas do seu log, em ~/.m5claude/bridge.log. Apenas uma ponte roda por vez: uma segunda competiria pela porta USB e pela conexão Bluetooth, então ela encerra com uma mensagem. Executar m5claude-bridge sozinho a mantém em primeiro plano, com o log no terminal.

Contas Pro e Max são encontradas a partir dos diretórios de configuração do Claude Code. Para adicionar uma segunda assinatura, faça login dela em seu próprio diretório:

$env:CLAUDE_CONFIG_DIR = "$HOME\.claude-work"; claude    # then /login

Organizações de API precisam de uma chave de Admin API, do Claude Console em Settings → Admin keys:

m5claude-bridge add-api "Acme API" --key-env ACME_ADMIN_KEY

4. Conecte

Conecte o cabo USB, ou deixe o dispositivo na mesa e deixe o Bluetooth encontrá-lo. Na primeira vez via Bluetooth, pressione C no dispositivo para aprovar o PC. Os dados aparecem em alguns segundos.

Ressalvas

Próximos passos

O código está em github.com/velxio/m5claude. Issues e pull requests são bem-vindos.

Agradecimentos à M5Stack por uma placa pronta para usar logo de cara, e aos autores do LovyanGFX, NimBLE-Arduino, ArduinoJson e bleak.

Os links para a loja da M5Stack nesta página são links de afiliado: se você comprar por eles, o Velxio ganha uma pequena comissão sem custo extra para você, e isso ajuda a manter o simulador gratuito.


Compartilhar em:
David Montero

Escrito por

David Montero

Creator of Velxio, the open-source circuit and Arduino simulator.

GitHub velxio.dev

Artigos relacionados


Artigo anterior
Robô de mesa fofo: um rosto que escuta no ESP-VoCat, com seu emulador no navegador
Próximo artigo
Raspberry Pi 4 e 5 no navegador: modo básico e modo Linux, passo a passo