musingfox/cc-plugins/tree/main/omp-quota
omp-quota
[Experimental] 各 omp provider の残りクォータをセッション内に表示します。プロンプト上の /quota バンド、/quota refresh、provider が ok から悪化したときの toast を提供します(Claude Mod。Claude Code 2.1.287+ が必要)。
この mod について
omp-quota
各 omp provider の残りクォータを Claude Code のセッション内に表示する Claude Mod です(function-hooks モジュール、hooks/register.ts)。
/quota:プロンプトの上に provider ごと 1 行のコンパクトな表を表示・非表示にします。/quota refresh:omp のキャッシュを破棄して最新のクォータを取得します。モデルターンは発生しません。- Toast:provider の状態が
okから悪化したとき、セッション内で 1 回 toast を表示します。
Claude Mods がデフォルトでオンになる Claude Code 2.1.287 以降が必要です。Claude Code 2.1.287 で構築・テストしています。
omp の実行方法
各取得では PI_CODING_AGENT_DIR を $HOME/.omp/agent に設定して omp usage --json を実行し、制限時間を 30 s とします(2026-09-25 に全 provider を対象にしたコールド取得は約 10 s でした)。この上書きは重要です。Claude Code が独自の PI_CODING_AGENT_DIR を渡すことがあり(pi-dispatch が設定します)、omp がその home を読むと exit 0 で provider なしと返すためです。omp は Claude Code の PATH から見つかります(通常は ~/.bun/bin にあります)。HOME が未設定なら omp は実行されず、バンドには Unavailable: HOME is unset、/quota refresh には omp quota refresh failed: HOME is unset と表示されます。
クォータはセッション開始時に 1 回取得し、その後 5 分ごとに取得します。取得に失敗してもポーリングは続き、ほかの再試行はありません。/quota の登録が拒否されても同様です。reload がセッション開始を再発火すると、まず前のポーリングをキャンセルするため、間隔が二重になることはありません。
omp の完了を待つ処理はありません。セッション開始(Claude Code は最初のプロンプト前にこれを await します)は取得を await なしで開始します。モジュールは tool-call や prompt のイベントにも hook しないため、遅い omp によって tool call や prompt が止まることはありません。
クォータの読み取り方
- 残りの割合:omp の
remainingFractionが数値ならそれを使い、そうでなければ1 − usedFraction、それもなければなしとします。0–100% に収めます。provider の割合は各 limit の割合の最小値です。四捨五入したパーセントで表示し、計算できない場合は—を表示します。 - 状態:provider の状態は各 limit の最悪の状態(
exhausted>warning>ok)です。状態のない limit は無視し、1 つもない provider には状態がありません。同じ provider 名のレポートは 1 つに統合し、名前のないレポートは(unnamed)とします。 - 悪化した provider:前回の成功した取得で
okだった状態が、今回warningまたはexhaustedになったものです。最初の成功取得には前回がありません。warning→exhausted、どちらか一方に状態がない provider、新しく現れた provider は対象外です。 - 取得失敗:omp が応答しなかった(起動できなかった、または 30 s 後も実行中だった)、ゼロ以外で終了した、JSON のレポート一覧でないものを出力した、または provider を報告しなかった場合です。最後は omp が間違った home を読んだときの返答なので、表示は消しません。omp のエラー出力は表示しません。
- アカウントデータ:provider 名、limit の id と label、割合、状態、リセット時刻だけを保持します。omp の
metadata(email、account id、endpoint)と各 limit のscopeは toast、トランスクリプト、バンドに届きません。
Toast
前回の成功取得から悪化した provider(上の 悪化した provider を参照)が見つかると、1 つのセッション内 toast で全てを示します:omp quota: openai-codex now warning, anthropic now exhausted。途中の取得失敗では比較をリセットしません。OS 通知はありません。別のウィンドウにいる間に悪化しても、戻ったときにバンドがオンなら表示されます。
コマンド
/quotaはプロンプト上のバンドをオン・オフにし、トランスクリプトには何も出しません。バンドを変えるのはこのコマンドだけで、ポーリングや悪化では変わりません。選択はプラグインストアのbandkey に保存され、セッション開始時に読み込まれるため、離れたときの状態が保たれます。保存がない場合や保存に失敗した場合はオフで開始します。切り替え時の保存に失敗しても、そのセッションでは切り替わります。/quota refreshはomp usage invalidateを実行してから取得します。どちらも同じ omp home を使い、1 行でomp quota refreshedまたはomp quota refresh failed: <reason>と返します(その後、バンドの通知行に失敗が表示されます)。invalidate に失敗しても取得は続き、返答の末尾に(cache not invalidated)が付きます。バンドは変えず、モデルターンも不要です。/quota <anything else>はusage: /quota [refresh]と返し、何も実行しません。
バンド
バンドはプロンプト入力のすぐ上にある帯です。/quota がオンの間、取得中は暗い通知行(Fetching omp usage)、まだ成功した取得がないときは(Unavailable: <reason>)、最新の取得が失敗したときは(Stale: <reason>; showing data from <age> ago)を表示します。その後、limit を報告した provider を、残りの割合が少ない順に 1 行ずつ表示します。例:
cursor Monthly 0% 11h 25m exhausted
openai-codex 5 hours 100% 4h 59m 7 days 6% 1d 11h warning
anthropic 5 Hour 86% 1h 44m 7 Day 94% 5d 15h
各行には各ウィンドウのセルを 1 つずつ置きます(omp の window label、なければ limit label)。リセットが早い順で、<window> <share> <time to reset> の形式です。ウィンドウの状態は warning または exhausted のときだけ追加します。ウィンドウの割合とリセットは、残りが最も少ない limit(割合がなければ最初のもの)から取り、antigravity の共有 Claude・GPT limit のような重複プールを 1 セルにまとめます。セルは provider 間でウィンドウが揃うようにパディングします。provider の順序は全 limit の最低割合で決まり、割合のない provider は最後に置き、limit を報告しない provider(ollama-cloud など)は除外します。リセットまでの時間は Xd Yh、Xh Ym、Ym のいずれかで、期限なら now、omp が値を返さなければ — です。割合は表示されたパーセントで色付けし、0–30% は赤、31–60% はオレンジ、61–100% は緑、— は無色です。
各行は折り返さず、バンドの幅で省略記号を使って切ります。survey がバンドを占有するときは場所を譲り、他の mod がそこにバンドを描く場合(例えば /cal)も隠さず空間を共有します。成功・失敗を問わず取得が確定するたびに再描画するため、常にモジュールが保持する最新データを表示します。ctrl+x ctrl+a(または [-] マーク)で折りたためますが、オフにはなりません。Box と Text だけで描画し、props は flexDirection、color、dimColor、wrap です。
Tests
claude plugin test omp-quota
テストキットは hermetic です。ファイルシステム、ネットワーク、プロセスを使わず、テストが行う $ 呼び出しはすべてプラグイン下の stub が返します。
tests/fixtures/snapshot.ts は 2026-09-18 に取得したライブ omp usage --json の編集済みコピーです。更新するには新しい snapshot を取得し、すべての metadata オブジェクト、すべての scope.projectId と scope.accountId、resetCredits を削除して貼り付けます。アカウント key または @ を含む文字列が 1 つでも残っている間は、tests/snapshot.test.ts の最初のテストが失敗します。
インストール
まず作者の README で marketplace とプラグイン名を確認してください。コマンドはリポジトリの構成によって変わる場合があります。
claude plugin marketplace add musingfox/cc-plugins claude plugin install omp-quota
原文 / README
omp-quota
Shows every omp provider's remaining quota inside a Claude Code session, as one Claude Mod
(a function-hooks module, hooks/register.ts).
/quota: toggles a compact table above the prompt, one line per provider./quota refresh: drops omp's cache and fetches fresh quota, without a model turn.- Toast: one in-session toast when a provider's status worsens from
ok.
Needs Claude Code 2.1.287 or later, where Claude Mods are on by default. Built and tested against Claude Code 2.1.287.
How omp is run
Each fetch runs omp usage --json with PI_CODING_AGENT_DIR set to $HOME/.omp/agent
and a 30 s limit (a cold fetch across all providers took about 10 s on 2026-09-25). The override matters: Claude Code may pass down a
PI_CODING_AGENT_DIR of its own (pi-dispatch sets one), and omp reading that home answers
with exit 0 and no providers. omp is found on Claude Code's PATH (it usually lives in
~/.bun/bin). With HOME unset, omp is not run, the band reads
Unavailable: HOME is unset, and /quota refresh answers
omp quota refresh failed: HOME is unset.
Quota is fetched once at session start and then every 5 minutes. A failed fetch leaves the
poll running; there is no other retry. A refused /quota registration leaves it running
too. When a reload re-fires session start, the previous poll is cancelled first, so the
cadence never doubles.
Nothing waits on omp. Session start (which Claude Code awaits before the first prompt) starts the fetch without awaiting it, and the module hooks no tool-call or prompt event, so no tool call or prompt is ever held up by a slow omp.
How quota is read
- Remaining share of a limit: omp's
remainingFractionwhen it is a number, else1 − usedFraction, else none; clamped to 0–100%. A provider's share is the lowest of its limits' shares. Shown as a rounded percentage, or—when none is computable. - Status of a provider: the worst status among its limits (
exhausted>warning>ok); limits without one are ignored, and a provider with none has no status. Reports with the same provider name merge into one provider; a report without one is listed as(unnamed). - Worsened provider: one whose status was
okin the previous good fetch and iswarningorexhaustednow. The first good fetch has no previous;warning→exhausted, a provider without a status on either side, and a newly appearing provider do not count. - Failed fetch: omp did not answer (could not start, or still running after 30 s), exited non-zero, printed something that is not a JSON report list, or reported no providers — the last is how omp answers when it reads the wrong home, so it never wipes the display. omp's error output is never shown.
- Account data: only provider names, limit ids and labels, shares, statuses, and reset
times are kept. omp's
metadata(email, account id, endpoint) and each limit'sscopenever reach a toast, the transcript, or the band.
The toast
When a good fetch finds providers that worsened since the previous good fetch (see
Worsened provider above), one in-session toast names them all:
omp quota: openai-codex now warning, anthropic now exhausted. Failed fetches in between
do not reset the comparison. There is no OS notification; a worsening that happens while
you are in another window shows in the band, if it is on, when you return.
Commands
/quotatoggles the band above the prompt on or off and prints nothing in the transcript. Only this command changes the band — a poll or a worsening never does. The choice is kept in the plugin's store (keyband) and read at session start, so the band stays as you left it; with nothing stored, or a store that fails, it starts off. A store that fails on the toggle still flips the band for this session./quota refreshrunsomp usage invalidate, then fetches, both against the same omp home, and answers one line:omp quota refreshedoromp quota refresh failed: <reason>(the band then shows the failure in its notice line). When the invalidate fails, the fetch still runs and the answer ends in(cache not invalidated). It does not change the band and needs no model turn./quota <anything else>answersusage: /quota [refresh]and runs nothing.
The band
The band is the strip directly above the prompt input. While /quota has it on, it shows
a dim notice line while fetching (Fetching omp usage), when no fetch has succeeded
(Unavailable: <reason>), or when the latest fetch failed
(Stale: <reason>; showing data from <age> ago). Then one line per provider that reports
limits, from the least share left to the most, for example:
cursor Monthly 0% 11h 25m exhausted
openai-codex 5 hours 100% 4h 59m 7 days 6% 1d 11h warning
anthropic 5 Hour 86% 1h 44m 7 Day 94% 5d 15h
Each line holds one cell per window (omp's window label, or the limit label when it has
none), soonest reset first: <window> <share> <time to reset>, plus the window's status
only when it is warning or exhausted. A window's share and reset come from its limit
with the least share left (the first one when none has a share), so repeated pools such as
antigravity's shared Claude & GPT limits collapse into one cell. Cells are padded so the
windows line up across providers. A provider's order uses its lowest share across all
limits; providers without a share go last, and one reporting no limits (such as
ollama-cloud) is left out. Time to reset reads Xd Yh, Xh Ym, or Ym, now when due,
and — when omp gives none. Each share is colored by the percentage shown: red for
0–30%, orange for 31–60%, green for 61–100%; — stays uncolored.
Every line is cut at the band's width with an ellipsis rather than wrapped. The band yields
to a survey while one holds it, shares its space with any band another mod draws there (/cal,
for one) instead of hiding it, and redraws after every settled fetch, failed ones
included, so it always shows the latest data the module holds. Collapse it with
ctrl+x ctrl+a (or its [-] mark) without turning it off. It is drawn from Box and Text
only, with the props flexDirection, color, dimColor, and wrap.
Tests
claude plugin test omp-quota
The test kit is hermetic: no filesystem, network, or process; every $ call a test makes
is answered by a stub beneath the plugin.
tests/fixtures/snapshot.ts is a redacted copy of a live omp usage --json taken on
2026-09-18. To refresh it, capture a new snapshot, remove every metadata object, every
scope.projectId and scope.accountId, and resetCredits, then paste it in. The first
test in tests/snapshot.test.ts fails while any account key or any string holding @
remains.
