戻る

M5Stack Basic で作る Claude 使用状況ダッシュボード — プランの上限と API の支出を机の上に

ノート PC のキーボードの上に置かれた M5Stack Basic がダッシュボードを表示している。Claude Max アカウントの週間上限が 88%、5 時間セッションが 30%、今日のトークン数が 142M

私は毎日 Claude を使っていますが、最もよく口にする疑問はコードのことではありません。「今週はあとどれくらい残っているんだろう?」です。Claude Code の /usage 画面がその答えを出してくれますが、手を止めて入力したときだけです。私は時計が時刻を示すように、その答えを机の上に置きたかったのです。

M5Stack Basic はうってつけです。完成されたデバイスで、2 インチの 320×240 画面、3 つのボタン、バッテリー、そして ESP32 が 54 mm のケースに収まっています。ブレッドボードもはんだ付けも不要です。

この記事ではこのダッシュボードについて説明します。何を表示するのか、データがどうやって Claude から画面へ届くのか、デバイスが設定なしでどう接続するのか、そして自分で作るための手順です。UI はハードウェアに触れる前に Velxio 上の M5Stack Core で設計しました。作ってみたいなら、この方法をおすすめします。このファームウェアをブラウザで実行することもでき、デモデータで動くのでデバイスは不要です。

デバイス上のダッシュボードはこちらから。YouTube で見る。

コード、ファームウェア、PC ブリッジはすべて MIT ライセンスで GitHub に公開しています。velxio/m5claude。以下の「コードをパートごとに」のセクションで、各ファイルが何をするのかを順に説明します。

ハードウェア

M5Stack Basic v2.7 — 2 インチ 320x240 IPS 画面、3 つのボタン、USB-C、microSD スロット、110 mAh バッテリーを備えた ESP32

ボードは M5Stack Basic Core IoT Development Kit v2.7 です。

他には何も必要ありません。ダッシュボードはケースに入っているものだけを使います。このボードには IMU、マイク、LED、リアルタイムクロックがないので、ダッシュボードはそれ以外のすべて、つまり画面とボタン、アラート用のスピーカー、バッテリー節約用のバックライト、充電量表示用の電源チップを使います。

画面に表示されるもの

このダッシュボードは 2 種類の Claude アカウントに対応しており、それぞれ複数のアカウントを扱えます。

どちらの場合も、過去 1 週間の 1 日あたりのトークン数を、入力・出力・キャッシュ読み取り・キャッシュ書き込みに分けて、さらにモデル別にも表示します。

ビューは 4 つあります。B で次のビューに進み、A と C でアカウントを切り替え、B を長押しすると PC に最新データを要求し、C を長押しすると設定を開きます。以下がすべての画面で、各ビューが開くときに再生されるアニメーションも含まれています。

すべての画面のアニメーションツアー — 3 アカウントの概要、上限・トークン・内訳の各ビュー、API 組織、単一アカウントの概要、バッテリー充電中、英語とスペイン語の設定、承認プロンプト、待機画面

概要。 アカウントごとに 1 枚のカードを表示します。レイアウトはアカウント数に応じて変わります。1 アカウントなら画面全体を使い、2 アカウントなら今日の使用量の行を加えた背の高いカードになり、3 つ以上ならスクロールするリストになります。

Claude Max アカウント 1 つの概要 — 週次上限をリングで、5 時間セッションとモデル別上限を右側に、今日のトークン数と 7 日間のグラフを表示

Max アカウント 2 つと API 組織 1 つの概要 — 週次のパーセンテージ、5 時間と 7 日間のバー、リセット時刻、API アカウントの 7 日間の利用額

上限。 週次上限をリングで表示し、その横にセッションとモデル別の上限を並べます。モデル名は Claude 自身から取得するので、行はプランにある上限にそのまま従います。色は 60%(アンバー)と 85%(赤)で変わります。

上限ビュー — 67% の週次リング、42% の 5 時間セッション、Opus と Sonnet の週次上限

トークン。 今日、過去 7 日間、そしてドル換算額を表示し、その後に 1 日あたりのトークン数を平均値の破線付きで表示します。サブスクリプションの場合、ドル換算額は同じトークンを API の定価で使った場合の金額です。請求額ではありませんが、プランをどれだけ使っているかを知るのに便利な指標です。

トークンビュー — 今日 2.84M トークン、7 日間で 20.8M、API 換算額 $84.20、1 日あたりのトークンの棒グラフ

デバイス上のトークンビュー — 今日 142M トークン、7 日間で 296M

内訳。 1 週間のトークンを種類別とモデル別に表示します。Claude Code では、通常キャッシュ読み取りが合計の大部分を占めます。

内訳ビュー — 入力・出力・キャッシュ読み取り・キャッシュ書き込みの積み上げバーと、各モデルの割合

デバイス上の内訳ビュー — 1 週間の 296M トークンのほぼすべてがキャッシュ読み取りで、Opus と Fable に分かれている

時計の横のドットは接続状態を示します。データが新しいときは緑、古いときはアンバー、PC が接続されていないときは赤です。写真は私自身のアカウントです。スクリーンショットはデモアカウントを使用しています。

バッテリー、サウンド、設定

時計の横にはバッテリーをスマートフォンと同じように描画します。残量と、充電中に満ちていく稲妻マークです。IP5306 電源チップは 4 段階(25、50、75、100%)しか報告しないため、数値は 25 刻みで動きます。

充電中のヘッダー — 稲妻マークと緑のバッテリーで 75%、その横に接続ドットと時計

スピーカーはアラートに使います。セッションまたは週次上限が 90%(設定で 80% を選んだ場合は 80%)を超えると、デバイスは短い 2 回のチャイムを鳴らし、どのアカウントのどの上限かを表示します。上限がリセットされると、上昇するチャイムを鳴らします。新しいコンピューターからの承認リクエストも音を鳴らします。ボタンクリック音は任意です。

C を長押しすると設定が開きます。A と C で移動し、B で値を変更し、B を長押しすると画面を閉じます。設定はデバイスに保存されます。

設定画面 — 言語、明るさ、サウンド、アラートしきい値、バッテリー時の画面オフ、夜間の減光、ペアリング済みコンピューター、ファームウェアバージョン

スペイン語の同じ画面 — 設定と概要

スペイン語の概要

110 mAh を長持ちさせる

最初のファームウェアは 1 時間ももたずにバッテリーを使い切りました。CPU は 240 MHz で動作し、画面は毎秒再描画され、無線は 15〜30 ms の接続間隔で最大出力で送信していました。1 分に 1 回変わる数値を表示するのに、そのどれも必要ありません。バッテリー動作時、ファームウェアは次のようにしています。

机を離れて一日中使うなら、Battery Module 13.2 を Basic の下に重ねれば 1500 mAh を追加できます。

仕組み

データは Claude Code のログイン情報とトランスクリプト、および Admin API から Python ブリッジへ流れ、USB または Bluetooth LE 経由で M5Stack に届きます。M5Stack は送られてきた内容を描画するだけです

設計方針は デバイスは何も知らない ことです。Claude の認証情報も Wi-Fi 設定も持ちません。PC 上の小さなプログラムであるブリッジがすべてを収集し、デバイスには描画用のスナップショットを送ります。これにより、机の上に置かれたデバイスに秘密情報を残さずに済み、PC やネットワークを変えても再設定が不要になります。

データの取得元

ブリッジは約 1,100 行の Python で、依存関係は 2 つだけです(pyserial と bleak)。3 つのソースから読み取ります。

  1. プラン上限 — Claude Code のログイン情報から。 各 Claude Code の設定ディレクトリ(~/.claude、~/.claude-work など)には 1 アカウントのログイン情報が入っています。ブリッジはそれらをすべて見つけ、各トークンを使って Claude Code の /usage 画面に表示されるのと同じ上限を読み取ります。トークンは読むだけで、リフレッシュはしません。リフレッシュするとトークンがローテーションされ、Claude Code がログアウトしてしまうからです。
  2. トークン数 — Claude Code のトランスクリプトから。 Claude Code が受け取るすべての応答は、トークン使用量とモデルとともに projects/ 配下の JSONL ファイルに書き込まれます。ブリッジはこれを日ごとに集計し、重複を除去し(セッションを再開すると以前のメッセージが新しいファイルにコピーされます)、API の価格表で金額を計算します。
  3. API 組織の利用額 — Usage and Cost Admin API から。 usage_report/messages は日ごと・モデルごとのトークン数を返します。cost_report は実際の利用額を返します。どちらも Admin API キー(sk-ant-admin01-...)が必要です。

実際のアカウントで動かして分かった 2 つの教訓:

スナップショット

更新のたびに、約 600 バイトの JSON が 1 行生成されます。

{"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、x はそれぞれセッション、週間、モデル別の上限を [パーセント, リセット時刻] で表します。d は 1 日あたりのトークン数です。ts と tz は PC の時計と UTC オフセットです。M5Stack Basic にはリアルタイムクロックもタイムゾーンデータベースもないため、デバイスはスナップショットから両方を受け取り、そこから秒を数えます。「あと 2 時間 14 分でリセット」や「火 04:00」を表示するにはこれで十分です。

設定なしで接続する

セットアップは一切不要にしたかったのです。ボタンが 3 つしかないデバイスに Wi-Fi パスワードを入力するのは不快です。PC の IP アドレスをデバイスに保存すると、PC を変えた途端に壊れます。そこでデバイスは 2 つの接続方式に対応し、どちらも設定を必要としません。

USB。 ケーブルを挿すだけです。ブリッジは USB チップが M5Stack のもの(CH9102 または CP2104)であるシリアルポートを探します。DTR と RTS をトグルせずにポートを開くので ESP32 はリセットされず、挨拶を待ちます。ファームウェアはデータが届くまで 2 秒ごとに {"hello":"m5claude",...} を送信します。数秒以内に挨拶が届かなければ、ブリッジはポートを解放し、しばらくそのままにします。これにより他の ESP32 ボードや書き込みツールに影響しません。

Bluetooth LE。 ファームウェアは 2 つのキャラクタリスティックを持つ GATT サービスをアドバタイズします。1 つは PC が行を書き込むもの、もう 1 つはデバイスが通知を送るものです。ブリッジはサービス UUID をスキャンして接続します。Windows のペアリングダイアログは出ず、リストから選ぶものもありません。

範囲内のどの PC からでもデバイスを見つけられるため、新しい PC はデバイス上で一度だけ承認します。

承認プロンプト — 「新しいコンピューター、DESKTOP-STUDIO。使用状況データの送信を許可しますか?」ボタン A が拒否、ボタン C が許可

ペアリングのやり取り — デバイスからの hello、ブリッジからの PC 名と固定 ID、保留中の応答、画面のプロンプト、そして ok、更新リクエスト、スナップショット

ブリッジは ~/.m5claude/pc_id にランダムな ID を保持します。デバイスは最大 4 台の承認済み PC の ID を NVS に保存します。既知の PC は即座に受け入れられ、電源投入時に A を押し続けるとすべて忘れます。すでに USB で接続されているデバイスは Bluetooth ではスキップされるため、同じ PC を 2 回承認するよう求められることはありません。

ブリッジが起動するまでの間、デバイスは何をすべきかを表示します。

待機画面 — 「PC を待っています。コンピューターで m5claude-bridge を実行してください。USB または Bluetooth で自動的に接続します。」

ファームウェア

ファームウェアは arduino-esp32 2.0 コア上で arduino-cli を使ってビルドする Arduino スケッチです。3 つのライブラリを使用します。

UI コードはハードウェアに依存しません。LovyanGFX のターゲットに描画し、3 つのボタンを読み取ります。ボード固有のもの(パネル、USB、BLE、NVS)はすべてスケッチ側にあります。

デモではなく製品のように見せるためのいくつかの工夫:

PSRAM なしで描画する、そして斜めの筋

16 ビットカラーの 320×240 のフルフレームは 150 KB です。Bluetooth が動作している状態での ESP32 の最大空きメモリブロックはそれより小さくなります。そこで UI はフレームごとに 320×60 のバンド(38 KB)へ 4 回に分けて描画されます。各パスはすべてをバンドのオフセット分だけ上にずらして描画し、バンドの外にはみ出した部分はクリップされます。

これをボードで初めて動かしたとき、画面には斜めの筋が現れ、承認プロンプトのボタンが上部と下部の 2 回表示されました。最初はパネル設定を疑いました。M5Stack のドキュメントを見ながら手書きで書き直しましたが、何も変わりませんでした。原因は別のところにありました。

バッファが 1 つの場合、DMA がまだ送信中なのに次のバンドがそのバッファに描画されます。バッファが 2 つの場合、一方を描画している間にもう一方が送信され、CPU はバッファを再利用する前に転送の完了を待ちます

LovyanGFX はスプライトを DMA でバックグラウンドでパネルに送信します。私のループは前のバンドがまだ送信されている間に、次のバンドを同じバッファに描画し始めていました。そのためパネルはあるバンドの半分と次のバンドの半分を受け取っていました。修正は 2 つのバッファを交互に使い、プッシュする前に前の転送を待つことです。

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();

追加コストは 38 KB のバッファがもう 1 つだけで、空き RAM 約 275 KB のうちの一部です。

コードをパートごとに

コードは git clone https://github.com/velxio/m5claude.git でダウンロードするか、リポジトリの Code ボタンから ZIP で取得できます。プロトコル以外に共通点のない 2 つの半分で構成されています。bridge/ は PC 上で動作し、firmware/ と src/ は M5Stack 上で動作します。

M5Stack 側

firmware/m5claude/m5claude.ino: ボード固有のすべて。

src/app/app.cpp: リンクに依存しないプロトコル。

src/model/: データ。

src/ui/: 画面。

PC 側

ブリッジは bridge/m5claude_bridge/ にあります。依存関係は pyserial と bleak だけです。HTTPS 呼び出しは標準ライブラリを使います。

__main__.py: コマンドラインとメインループ。

autostart.py はブリッジをウィンドウなしでログイン時に起動するよう登録します。Windows では pythonw を使った Run レジストリキー、macOS では LaunchAgent、Linux では systemd ユーザーユニットです。

config.py: アカウント。

sources/: データソースごとに 1 ファイル。

pricing.py はモデルファミリーごとの API 定価を保持します。サブスクリプション利用の価値を推定します。

snapshot.py: スナップショットを構築。

hub.py は最新のスナップショットを保持し、接続中のすべてのデバイスに渡します。遅いリンクには最新のものだけが渡され、たまることはありません。

transports/: リンクごとに 1 ファイル。

リポジトリの README には、同じ内容を表形式でまとめたツアーとトラブルシューティングがあります。

自分で作る

おすすめの順番は、Velxio で画面を設計し、次にボードへ書き込み、最後にブリッジを接続する、という流れです。

1. Velxio で M5Stack Core 上で動かして変更する

Velxio は M5Stack Core を 320×240 の画面、A・B・C ボタン、バッテリーチップとともにシミュレートします。2 インチの画面のレイアウトは細かい調整の連続です(ラベルが 2 ピクセル低すぎる、数値がカードに収まらない、など)。Velxio ならその 1 つ 1 つが書き込みサイクルではなくブラウザ上で数秒で済みます。

このダッシュボードは Velxio のサンプルギャラリーにあり、リポジトリと同じソースファイルを使っています。

  1. M5Stack Core: Claude usage dashboard (m5claude) を開いて再生ボタンをクリックします。サインアップは不要です。この記事で紹介しているデモアカウントで起動します。
  2. A と C でアカウントを選び、B でビューを切り替えます。シミュレーターはボードより遅くファームウェアを実行するので、設定を開くには C を数秒間押し続けてください。
  3. 自分の数値を見るには、PC で m5claude-bridge snapshot を実行し、出力された行をシリアルモニターに貼り付けます。スケッチの先頭のコメントに、編集して使えるサンプル行があります。
  4. ui.cpp で画面を変更して再実行します。見た目が良くなったらボードへ書き込みます。

ボードとの違いは 2 点あります。Velxio には Bluetooth がないためその接続は省かれ、シリアルモニターが唯一の接続になります。またスピーカーのコードは新しい ESP32 Arduino コアの呼び出しを使っています。それぞれの変更はスケッチ内に印を付けてあります。

空の画面から自分のダッシュボードを作り始めるなら、M5Stack Core: Hello LCD + Buttons が最小のサンプルです。M5Stack の M5GFX を使っており、これは LovyanGFX を基にしていて描画 API を共有しているので、コードは両者の間で移行できます。

2. ファームウェアを書き込む

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

スクリプトは M5Stack Core 向けに、大きなアプリのための余裕を残すパーティション構成(PartitionScheme=no_ota)でビルドします。ファームウェアは約 820 KB です。私がつまずいた設定は 2 つあります。

3. ブリッジを実行する

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 はログイン時にウィンドウなしでブリッジが起動するよう登録します。Windows ではユーザーの Run レジストリキーに pythonw を起動する値を追加します。macOS では LaunchAgent を、Linux では systemd ユーザーサービスをインストールします。autostart status は実行中かどうかと、ログ(~/.m5claude/bridge.log)の最後の数行を表示します。同時に実行できるブリッジは 1 つだけです。2 つ目は USB ポートと Bluetooth 接続を取り合ってしまうため、メッセージを出して終了します。m5claude-bridge を単体で実行するとフォアグラウンドで動作し、ログはターミナルに表示されます。

Pro と Max アカウントは Claude Code の設定ディレクトリから検出されます。2 つ目のサブスクリプションを追加するには、専用のディレクトリでログインします。

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

API 組織には Admin API キーが必要です。Claude Console の Settings → Admin keys から取得します。

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

4. 接続する

USB ケーブルを挿すか、デバイスを机に置いたまま Bluetooth で見つけさせます。Bluetooth で初めて接続するときは、デバイスの C を押して PC を承認します。数秒以内にデータが表示されます。

注意点

今後の予定

コードは github.com/velxio/m5claude にあります。Issue とプルリクエストを歓迎します。

すぐに使えるボードを提供してくれた M5Stack に、そして LovyanGFX、NimBLE-Arduino、ArduinoJson、bleak の作者の皆さんに感謝します。

このページの M5Stack ストアへのリンクはアフィリエイトリンクです。リンク経由で購入いただくと、追加費用なしで Velxio に少額の手数料が入り、シミュレーターを無料で提供し続ける助けになります。


共有:
David Montero

執筆者

David Montero

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

GitHub velxio.dev

関連記事


前の記事
かわいいデスクトップロボット — ESP-VoCatで声に耳を傾ける顔と、ブラウザで動くエミュレータ
次の記事
ブラウザ上のRaspberry Pi 4と5 — 基本モードとLinuxモードを順を追って解説