わたしのダッシュボードには、Claude CodeとCodex CLIの使用量(枠の消費率とリセット時刻)を並べて表示する欄がある。そこのCodex側の「最終取得」が、9月18日で止まっていた。数字が出ていないのではなく、古い数字が、止まっていると分からない顔をして出ていた。これがいちばん悪い壊れ方だと思う。
2026-10-03の19:49から19:50にかけて、取得の仕組みを作り直した。やったことは一行で言うと、自前のログ解析をやめて、公式の取得口に切り替えた。その記録を残しておく。
壊れていた原因:使用量をログファイルから推測していた
修正前の処理は、ダッシュボード更新スクリプトの中の readCodexUsage() にあった。やっていたのは、ローカルに溜まる .codex/sessions のログを漁り、その中に過去に記録されていた rate limits らしき値を拾ってくる、というものだった。
この作りには、致命的な性質がある。
- ログは「最後にそのツールを対話で使った時」にしか増えない
- したがって、しばらく対話で使わなければ、値も取得日時も止まったまま
- 画面に出ていた「最終取得日」は、実際にはログの最終記録日だった
つまり、最新の値を誰にも問い合わせていなかった。これは「取得に失敗していた」のではなく、最初から取得していなかったという話で、ダッシュボードの数字として成立していなかった。
さらに悪いことに、当時のコードには「リセット予定時刻を過ぎていたら残り100%とみなす」という推測の分岐が入っていた。実測していない値を実測の顔で出していたことになるので、これは今回まとめて削除した。
切り替え先:Codexのapp-serverに rate limits だけを聞く
インストール済みのCodex CLIには、エディタなどの外部クライアントから話しかけるための app-server モードがある(公式ドキュメント: https://learn.chatgpt.com/docs/app-server )。ここに account/rateLimits/read という読み取り専用の口がある。
新設したのが Read-CodexUsage.js で、やっていることはこれだけ。
initialize ← クライアント名を名乗る
initialized ← 初期化完了を通知
account/rateLimits/read ← 使用量だけ読む
(結果を受け取ったら即終了)
推論のターンは一度も起動しない。 プロンプトも投げないし、モデルも呼ばない。表示用の数値を読むためだけにサーバーを立てて、読んだら落とす。使用量を見るために使用量を消費する、という本末転倒を避けたかった。
実装で決めたのは次の点。
app-server --stdioを非表示(windowsHide: true)で起動する- 45秒で打ち切り、タイムアウト時はプロセスを確実に終了させる
- 標準エラー出力は読み捨てる。認証まわりの情報が混ざる可能性があるため、転送も保存もしない
- 保存するのは画面に出す表示値だけ。アカウント識別子や認証情報、生のレスポンスは一切ローカルに残さない
- 枠は
rateLimitsByLimitId.codexを優先して選ぶ。同じレスポンスに別系統の枠が入っていても取り違えないようにする - 消費率が数値でない、0未満、100超のときは「取れなかった」として扱い、値を作らない
詰まったところ
1. プロセスが死なない。 最初はNode側のCLIラッパー経由で起動していたが、Windowsではラッパーを終了させても実体のapp-serverが残ることがあった。インストール先の実行ファイルを直接起動する形に変えて解決した。パスの組み立てはアーキテクチャ(x64 / arm64)で分岐させている。ここはCLIの配置が変わったら壊れる箇所なので、弱点として自覚している。
2. 取得できなかった時に何を出すか。 空欄にすると「壊れた」と見えるし、新しい時刻で古い値を出すのは嘘になる。採ったのは、前回取得できた値を、前回の取得時刻のまま返すという形。画面上では取得時刻が進まないので、見れば止まっていると分かる。有効な前回値すら無い場合は、何も作らずnullを返す。
今回の修正でわたしが一般化したのは、ここだけだと思っている。
自前のログ解析に依存した使用量表示は壊れる。公式の取得口を使い、取得に失敗したら前回値と前回の取得時刻をそのまま保持する。
結果の数字
Read-CodexUsage.test.cjsのテスト7件すべて合格(正常読取/codex枠の選択/不正値の拒否/RPCの順序とプロセス終了/キャッシュに秘匿情報が混ざらないことと取得時刻の保持/初回失敗/タイムアウト)- ダッシュボード更新スクリプト側の構文チェック合格
- 本番への送信は HTTP 200 /
ok:true - 既存のWindowsタスク(使用量同期)は5分間隔のまま変更なし。スクリプトを差し替えただけで、タスクは作り直していない
- サーバー側(GAS)の再デプロイは不要だった。送る中身の作り方を変えただけで、受け口の仕様は変えていないため
- 本番画面で 19:48 時点の取得を確認し、その後の定期同期で取得時刻が19:51へ自動で進むことを確認した
残りの枠の実数は、わたしの契約状況が分かる情報なので書かない。確認したのは「値が更新され続けること」であって、値そのものではない。
未確認の点も書いておく。Windows以外の環境では試していない。CLIの配布構成が変わった場合に実行ファイルのパス解決が追随できるかも未確認で、そのときは取得失敗として前回値保持に落ちる想定でいる。
次にやること
読んでいる方に1つだけ勧めるなら、自分のダッシュボードに出ている使用量が「いつ取得した値か」を画面に表示させること。わたしの場合、値の正しさより先に、取得時刻を出していなかったことが問題の発見を半月遅らせた。取得時刻さえ出ていれば、数字を疑う前に止まっていることに気づける。


コメント