ClaudeMods
☰
KO
● 0 명 접속 중 · 조회 0 회
후원프로젝트 제출
GitHub 저장소 · 작성자 musingfox

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마다 한 줄씩 나오는 간결한 표를 켜고 끕니다.
  • /quota refresh: omp 캐시를 버리고 최신 할당량을 가져옵니다. 모델 턴은 발생하지 않습니다.
  • Toast: provider 상태가 ok에서 나빠지면 세션 안에서 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을 읽으면 종료 코드 0과 provider 없음으로 응답하기 때문입니다. omp는 Claude Code의 PATH에서 찾습니다(대개 ~/.bun/bin에 있습니다). HOME이 설정되지 않으면 omp를 실행하지 않고 밴드에는 Unavailable: HOME is unset, /quota refresh에는 omp quota refresh failed: HOME is unset을 표시합니다.

할당량은 세션 시작 시 한 번 가져온 뒤 5분마다 가져옵니다. 가져오기에 실패해도 폴링은 계속되고 다른 재시도는 없습니다. /quota 등록이 거부되어도 계속 실행합니다. reload로 세션 시작이 다시 실행되면 먼저 이전 폴링을 취소하므로 주기가 중복되지 않습니다.

omp를 기다리는 작업은 없습니다. 세션 시작(Claude Code는 첫 프롬프트 전에 이를 await함)은 기다리지 않고 가져오기를 시작합니다. 모듈은 tool-call이나 prompt 이벤트에도 hook하지 않으므로 느린 omp 때문에 도구 호출이나 프롬프트가 멈추지 않습니다.

할당량 읽기

  • 남은 비율: omp의 remainingFraction이 숫자면 사용하고, 아니면 1 − usedFraction, 그것도 아니면 없음으로 처리합니다. 0–100%으로 제한합니다. provider의 비율은 해당 limit 비율 중 가장 낮은 값입니다. 반올림한 백분율로 표시하며 계산할 수 없으면 —입니다.
  • 상태: provider의 상태는 limit 중 가장 나쁜 상태(exhausted > warning > ok)입니다. 상태가 없는 limit은 무시하고, 아무 상태도 없는 provider에는 상태가 없습니다. 같은 provider 이름의 보고서는 하나로 합치며, 이름이 없는 보고서는 (unnamed)으로 표시합니다.
  • 나빠진 provider: 이전 정상 가져오기에서 상태가 ok였고 이번에는 warning 또는 exhausted가 된 provider입니다. 첫 정상 가져오기에는 이전 상태가 없습니다. warning → exhausted, 어느 한쪽에 상태가 없는 provider, 새로 나타난 provider는 포함하지 않습니다.
  • 가져오기 실패: omp가 응답하지 않았거나(시작하지 못했거나 30 s 뒤에도 실행 중), 0이 아닌 상태로 끝났거나, JSON 보고서 목록이 아닌 내용을 출력했거나, provider를 보고하지 않은 경우입니다. 마지막 경우는 omp가 잘못된 home을 읽을 때의 응답이므로 표시를 지우지 않습니다. omp의 오류 출력은 표시하지 않습니다.
  • 계정 데이터: provider 이름, limit id와 label, 비율, 상태, 재설정 시간만 보관합니다. omp의 metadata(email, account id, endpoint)와 각 limit의 scope는 toast, 기록, 밴드에 절대 도달하지 않습니다.

Toast

정상 가져오기에서 이전 정상 가져오기 이후 나빠진 provider(위의 나빠진 provider 참조)를 찾으면 세션 안의 toast 하나에 모두 표시합니다: omp quota: openai-codex now warning, anthropic now exhausted. 그 사이의 가져오기 실패는 비교를 초기화하지 않습니다. OS 알림은 없습니다. 다른 창에 있을 때 나빠져도 돌아왔을 때 밴드가 켜져 있으면 밴드에서 확인할 수 있습니다.

명령

  • /quota는 프롬프트 위 밴드를 켜거나 끄며 기록에는 아무것도 출력하지 않습니다. 밴드를 바꾸는 것은 이 명령뿐이고 폴링이나 악화는 바꾸지 않습니다. 선택은 플러그인 저장소의 band key에 보관하고 세션 시작 시 읽으므로 떠날 때의 상태가 유지됩니다. 저장된 값이 없거나 저장소가 실패하면 꺼진 상태로 시작합니다. 전환할 때 저장에 실패해도 해당 세션에서는 밴드를 전환합니다.
  • /quota refresh는 omp usage invalidate를 실행한 뒤 가져오며 둘 다 같은 omp home을 사용합니다. 한 줄로 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를 남은 비율이 낮은 순서부터 한 줄씩 표시합니다. 예:

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

각 줄에는 각 window마다 셀 하나를 둡니다(omp의 window label을 쓰고, 없으면 limit label을 사용). 가장 빠른 재설정 순서로 <window> <share> <time to reset>을 표시하며 window 상태는 warning 또는 exhausted일 때만 덧붙입니다. window의 비율과 재설정 시간은 남은 비율이 가장 낮은 limit(비율이 없으면 첫 번째)에서 가져오므로 antigravity의 공유 Claude·GPT limit처럼 반복되는 풀은 한 셀로 합칩니다. provider 사이에서 window가 맞도록 셀에 여백을 채웁니다. 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나 @가 들어간 문자열이 하나라도 남아 있으면 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 remainingFraction when it is a number, else 1 − 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 ok in the previous good fetch and is warning or exhausted now. 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's scope never 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

  • /quota toggles 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 (key band) 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 refresh runs omp usage invalidate, then fetches, both against the same omp home, and answers one line: omp quota refreshed or omp 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> answers usage: /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.

비슷한 프로젝트