AgentBar がエージェントを起動せず、ファイルだけを読む理由
CodexBar は使用量を読むために Claude CLI を起動し、Mac を毎分フリーズさせました。AgentBar はエージェントが自分で書いたファイルだけを読みます。その保証はテストで強制されています。
執筆 tsuvic · 公開 2026/08/01 · 読了約5分
去年の7月、私の Mac は1分おきに、1分近く固まるようになりました。ポインタは動いて、止まって、まとめて追いつきます。キー入力は遅れて届くか、届きません。どこかの Chrome タブが暴れているのだろうと思っていました。違います。プロセツリーが指していたのは、エージェントの様子を見るために入れたメニューバーアプリでした。そしてそのアプリが60秒ごとに起動していたのは、エージェントの側でした。
アプリは CodexBar 0.43.0、Apple のノータリゼーション済み、更新間隔は1分に設定してありました。使用量の数値を1つ表示するために、このアプリは Claude CLI を起動します。問題は、その CLI が隔離環境で動かなかったことです。CLI は普段の Claude 設定をそのまま読み込みました。私の設定には Context7 と Serena という2つの MCP サーバーと Chrome 連携が入っていて、プローブのたびにそれらも初期化されます。Chrome は GPU プロセス、ネットワークサービス、ストレージサービス、タブと拡張機能を復元する多数の Renderer を引き連れて起動しました。
その午後の実測値は、時刻付きでリポジトリに残してあります。14:56:48 と 14:57:48、1分差で2回のプローブが起動し、どちらも CodexBar の watchdog の子プロセスでした。Renderer は個別に CPU の 30〜111% を消費し、空きメモリは約22万ページから約4千ページへ落ち、圧縮メモリはゼロから10万ページを超え、WindowServer は 33〜40% まで上がり、入力が画面に届かなくなりました。14:58:42 に CodexBar を終了させて、さらに2分監視しています。新しいプローブは一度も現れませんでした。
公平を期すなら、この Mac の負荷は CodexBar だけのものではありません。DisplayLink と InstantView という2つの USB 映像ソフトが常駐しており、これらは WindowServer への負荷を増幅します。ただし、60秒ごとに背景の重さをデスクトップ全体のフリーズへ変えていた周期的なきっかけは、使用量を重い方法で読んでいたメニューバーアプリでした。
使用量を読むのに、CLI は要らない
あとから CodexBar の GitHub issues を200件ほど調査しました。同じ設計がどこにでも出てきます。データソースが「CLI に聞く」で、その CLI がフルスタックのエージェント実行環境であるかぎり、更新の重さはあなたの設定全体を引き受けます。MCP サーバーや連携を増やすほど、メニューバーの定期更新は重くなる。罰が設定量に比例する設計です。
issue トラッカーは、このパターンを具体的な数字で示しています。
- #1844: 時間ごとの「delegated CLI refresh」回復パスが
/usr/bin/openを呼び、ユーザーの既定ブラウザを勝手に起動しました。高速リトライ中は20秒〜3分間隔で開き続けます。 - #2052: バックグラウンドの Claude プローブが CLI の自動更新ダウンロードを誘発しました。
DISABLE_AUTOUPDATER=1が設定されていなかったためです。3日間で 90.6 GiB の通信、1日あたり 257〜495 の Claude CLI プロセスが起動しています。 - #2251: 使用量プローブのたびに空の Claude セッションが新規作成され、数週間で36以上の幻影セッションがアカウントに蓄積しました。Anthropic のレート制限にも抵触し始めます。
- #2241: CLI プローブの成功率は 268回中23回、8.6%。失敗時にキャッシュ済みのスナップショットを破棄するため、表示データに最長110分の欠落が生まれました。
- #1999: CodexBarCLI の2プロセスが合計 75 GB まで膨張し、48 GB マシンをシステム全体の OOM に巻き込んでいます。
これらは不注意ではありません。受動的なモニターが能動的なエージェントを起動し続ける設計が、1プローブずつ生む帰結そのものです。
ファイルは、もうそこにある
代替手段は、最初からディスクの上にありました。コーディングエージェントは自分の仕事を自分で記録します。Claude Code は ~/.claude/projects/**/*.jsonl、Codex は ~/.codex/sessions/YYYY/MM/DD/*.jsonl、Qwen はチャット JSONL と usage_record.jsonl、Gemini はイベントソーシングのセッション JSONL を書きます。Cursor は SQLite データベース(state.vscdb)に状態を持つので、AgentBar は sqlite3 の C API で直接読み取ります。Cursor には何も問い合わせません。
AgentBar が表示するものは、すべてこれらのファイルから再構成されます。日別のトークン使用量、クォータ、モデル別内訳、60日分のセッション履歴、どのエージェントが誰を呼び出したかのグラフ、そして「承認待ち」の状態まで。承認待ちは推測ではありません。Claude については生 JSONL の末尾から読んでいます。未完了の tool_use レコードがあり、対応する result がなければ、そのエージェントは人間の承認で止まっている。AgentBar はそういう行を最上位に固定します。
Claude のクォータ数値は ~/.claude/usage-watch/rate-limits.json から来ます。Claude CLI 自身が毎回の応答のあとに書き出すファイルです。AgentBar はサーバーに聞かず、プロセスも起動せず、このファイルを読みます。
約束ではなく、強制
「読取専用」は主張するのは簡単で、守り続けるのは難しい。だから AgentBar は規律に頼りません。構造的に2つの仕組みで強制します。
実行時は ProcessGuard が、取得の前後で sysctl を使ってプロセステーブルの差分を監視します。更新処理が禁止された子プロセス(Node、Python、npm、uv、ブラウザ、MCP サーバー)を起動したら、モニターが自分の違反を自分で検出して報告します。テストスイートの NoProcessSpawnTests はさらに先へ進みます。Claude 設定に意図的に10個の MCP サーバーを登録した状態で100回の更新を回し、Node・Python・npm・uv・Chrome・MCP のプロセスが1つでも現れたらビルドを失敗させます。テストが領収書です。
設計の残りは、上の issue リストへの直接の回答になっています。自己監視は getrusage と task_info で AgentBar 自身の CPU と RSS を計測し、閾値を超えたら自動更新を止めます。取得に失敗しても UI は白くなりません。最後の正常値が時刻付きで画面に残り続けます(stale-while-revalidate)。issue #2241 の真逆です。更新間隔の最短は5分。1分の選択肢は設計として存在しません。更新はプロバイダーごとに単一飛行、数秒ずつずらして実行され、失敗が続いたプロバイダーはサーキットブレーカーが開いて15分止まります。
AgentBar がサブプロセスを起動する場所は1つだけです。ツールアップデーターが、あなたのクリックで、ハードタイムアウト付きでオンデマンド実行するとき。Diag タブは帳簿を公開します。直近取得の所要時間、CPU 時間、ピーク RSS、読取ファイル数、パースしたレコード数、そして起動した禁止プロセス数。最後のカウンターは常にゼロです。
代わりに手放すもの
ファイルを読むことにも代償はあります。その代償を正直に書くことが、モニターと広告の分かれ目です。
ファイル読取が見るのは、エージェントがすでにディスクへ書き出したものまでです。API の真実ではなく、ディスクの真実。クォータの数値は、それを書き出すファイルの新しさそのものでしかありません。実行状態の検出は、ログ末尾が状態を明示している Claude では正確で、Codex・Qwen・Gemini・Cursor では会話ターンからの最善推定になります。コストはモデル単価テーブルに基づく推定値で、サブスクリプションにカバーされている可能性があります。だから UI は毎回「推定」と表示します。キャッシュトークンは生成トークンと別建てで課金し、推定値が二重課金しないようにしています。CodexBar の issue #1796 はここが壊れていて、コストが 2.7〜4.6 倍に膨れていました。
そして、ローカルに記録を残さないエージェントは、この方法では監視できません。ここはきっぱりしています。例外的に、リモートにしかデータがないプロバイダー向けにリモート usage 照会を用意していますが、明示設定の opt-in で、プロバイダーごとの設定が必要で、読取専用原則の唯一の例外です。既定で外へ出るものは何もありません。
静かな部分
あの日の午後、解決策はアプリを終了させることでした。新しいアプリを書く理由になったのは、「監視する」と「起動する」が同じ動詞であるべきではなかった、という気づきです。使用量メーターは、エージェントが働くほど重くなるべきで、ツールを設定するほど重くなってはいけません。
それ以来、私の Mac は静かです。これは私の Mac についての観察であって、あなたの Mac への約束ではありません。約束はリポジトリの中にあります。ProcessGuard と NoProcessSpawnTests、そして要求があればいつでも領収書を印刷する Diag タブの中に。