quartermaster

skill
Guvenlik Denetimi
Basarisiz
Health Uyari
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Basarisiz
  • spawnSync — Synchronous process spawning in bin/qm.mjs
  • process.env — Environment variable access in bin/qm.mjs
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

Cuánta cuota te queda, en todas tus cuentas de agentes: cada perfil de Claude Code de la máquina —no sólo el de por defecto— más Codex y los proveedores de opencode. Sin red y sin credenciales.

README.md

quartermaster

How much quota you have left — in every agent account on the machine.
Every Claude Code profile, not just the default one, plus Codex and the
providers stored by opencode.

Landing ·
Install ·
Releases ·
Security ·
En castellano ·
MIT

An instrument by




Legios

The GNOME top bar with one meter per account
brew install legiosai/tap/quartermaster        # macOS and Linux
npm install -g @legios/quartermaster           # anywhere
Then run qm. Details, the bar item and Windows: Install.

Mission. Nobody should find out their quota is gone by hitting the wall.

The problem

Claude Code supports several profiles through CLAUDE_CONFIG_DIR, and each one
has its own account and its own credential. A work seat and a personal
subscription on the same laptop is ordinary.

Every monitor out there reads one credential: the default directory's. On
the machine this was written on, that means reading ~/.claude — which is
empty — while the two real accounts live in ~/.claude-personal and
~/.claude-teams. The observed result was a monitor polling every 120 seconds
for hours, logging credential expired — gating poll, and displaying nothing.

quartermaster finds every account, and reads the number from disk.

Install

brew install legiosai/tap/quartermaster        # macOS and Linux
npm install -g @legios/quartermaster           # anywhere

The bar item, on all three: the first time you run qm in a terminal, it
asks once whether to put it in the bar and start it at every login — the menu
bar on macOS, the top bar on GNOME, the notification area on Windows. The
install itself can't: brew can't start anything from a formula, the .deb drops
the files and leaves, npm's postinstall won't register anything either, and a
tool that reads OAuth tokens shouldn't register login agents nobody asked for.
Without the question: brew services start quartermaster on macOS, and

qm-indicator --instalar-extension   # Linux: the item that opens the panel on click
qm-indicator --instalar-arranque    # and start it once: qm-indicator &
bin/qm-tray --instalar-arranque     # Windows, from WSL: then run bin/qm-tray

Saying yes on Linux also installs the GNOME extension, which is what makes a
click open the panel: without it the item is hosted by AppIndicator and the click
falls through to the GTK menu — the one that does not hold the grab and closes
the moment you touch it. GNOME does not load a freshly installed extension on
Wayland, so when it had to be installed the closing line says so and you have to
log out once.

The question only appears when there is somewhere to show it: a graphical
session, python3-gi with AyatanaAppIndicator3, and a host for the item — an
extension already in place, or a GNOME Shell to install ours into. Without those
the process would start anyway and nothing would appear up there, which is worse
than not offering. qm --diagnostico says which one is missing.

Windows: npm install -g @legios/quartermaster inside WSL works too, and
the first qm asks the same question — the tray ships in the package. For a
native install without WSL, the installer from the latest
release
. Per-user
and no UAC: it puts qm on your PATH, the tray in the Start menu, and — if
you leave the box ticked — the tray in startup.

Debian and Ubuntu: the .deb from the same release, or the signed apt repo
(two lines).

Arch: a PKGBUILD in paquetes/aur/.
Nix: nix run github:legiosai/quartermaster.

Needs Node >= 22.6: qm reads its own TypeScript with no build step, and
type stripping starts there. The launcher looks for a usable Node on the PATH
and in nvm, fnm and volta; if it cannot find one it says so and explains how to
get one, rather than dying with a syntax error.

Use

qm                  # quota and usage for every account
qm --breve          # one line — this is what goes in a statusline
qm --json           # the same, for scripts and panels
qm --refrescar      # also ask the endpoint (needs a live token)
qm --watch 60       # redraw every N seconds
qm --umbral=80      # exit 3 if any bar is over N%
qm --esperar        # block until quota drops:  qm --esperar && codex ...
qm --diagnostico    # everything a bug report needs, already redacted

In Claude Code's settings.json:

{ "statusLine": { "type": "command", "command": "qm --breve" } }
personal 23/75%! · teams 9/42% · codex 49/59%

Two numbers per account, on purpose. The first is the session; the second is
the bar that stops you first. They answer different questions — "can I keep
going right now?" and "do I make it to the end of the week?" — and either one
alone is half an answer.

When something is wrong

qm --diagnostico

One command, and you can paste the output straight into an issue: home paths
become ~, and no e-mail, token or account id is ever printed.

It gathers what otherwise takes five commands nobody should have to know —
gnome-extensions info, gdbus … GetExtensionErrors, journalctl --user -b,
the cache directory, and ps for when the graphical session started — and it
states the conclusion rather than leaving you the data. The case that
prompted it:

  ⚠ extension.js es 12.9 h MÁS NUEVO que la sesión gráfica.
    El shell carga el módulo una vez y lo deja en memoria: lo que está
    corriendo es el archivo viejo …
      → cerrá sesión y volvé a entrar. Es el único paso que falta.

Anything it cannot find out it says so — it never omits and never guesses. It
works with none of those commands installed.

The GNOME item also writes what it does to stderr, which systemd's journal
picks up when it starts from the autostart entry:

journalctl --user -b | grep qm-indicator
qm-indicator: pedido accion=actualizar
qm-indicator: calentar cuentas=.claude,.claude-teams,codex
qm-indicator: panel.abierto donde=arriba-derecha alto=1032
qm-indicator: panel.cerrado vivio_ms=3999
qm-indicator: panel.agarre-roto
qm-indicator: aviso clave=teams|weekly_all|2026-09-13T11:00|80 urgente=False
qm-indicator: qm.sin-datos motivo=qm salió 2: opción desconocida

The events, and the question each one answers:

event answers
pedido did the click reach the indicator at all?
calentar / calentar.fallo which accounts were re-read, and why a refresh did not happen
panel.abierto / panel.cerrado vivio_ms — a panel that lived 40 ms was not closed by you
panel.agarre-roto the compositor took the grab away
aviso / aviso.repetido / aviso.fallo it fired, it was suppressed as a duplicate, or the notification server refused it
qm.sin-datos why there is no number, instead of only a phrase on screen
reinicio the process replaced itself because the source changed
suspension.duerme / .vuelve the machine slept, and the quota was re-read on resume
calentar.colgado a warm never called back and its flag was released after the deadline

vivio_ms is the one that matters for "the panel closes on its own": a panel
that lives 40 ms was not closed by you. QM_SILENCIO=1 turns it off.

The macOS menu bar writes a log too, timestamped and capped at 1 MB. With
brew it is $(brew --prefix)/var/log/quartermaster.log:

2026-09-14T11:40:02-03:00 [qm-barra] arranca · qm=/opt/homebrew/opt/quartermaster/libexec/bin/qm · pid 812
2026-09-14T11:40:03-03:00 [qm-barra] posición: ancho=125.0 x=985.0..1110.0 muescaDerechaMinX=825.0 pantalla=1470.0 escondido=false
2026-09-14T11:40:04-03:00 [qm-barra] calentar · .claude: sin credencial — corré: …
2026-09-14T12:02:10-03:00 [qm-barra] aviso: quartermaster · teams — …
2026-09-14T13:15:40-03:00 [qm-barra] calentado (--calentar) falló: salió 1
2026-09-14T13:21:41-03:00 [qm-barra] calentado volvió a andar

It writes changes, not repeats: the item's position once per screen when it
moves, a refresh or a read the first time it fails and again when it recovers,
why an account was not refreshed (once per reason), and every notification —
with a line if osascript did not show it.
escondido=true is the one to look for when the item does not appear: macOS
put it under the notch or ran out of room.

Where you can see it

Terminal qm, and qm --breve for a statusline — it skips transcripts, so it takes milliseconds
GNOME an item in the top bar, panel on the first click. Ships its own Shell extension, because the AppIndicator one eats the left click
macOS the menu bar, with live text next to the icon
Windows the notification area, with the percentage drawn inside the icon like a battery meter
Browser qm-web — a local dashboard on 127.0.0.1 only. Works everywhere
waybar paquetes/waybar/ — for Hyprland, Sway and river

All of them only draw. The CLI resolves which bar wins and emits the resolved
answer in qm --json (mostrar, frena, sesion, semanal); no renderer
reimplements a rule. That is a design rule with a scar behind it: the same
function once lived in Python, JavaScript and Swift at the same time.

What it reads, and what leaves the machine

The number needs no network and no credential. Claude Code stores the last
quota response it got in each profile's .claude.json, so quartermaster reads
it from disk — which means it still works on a profile whose token expired,
the exact state the motivating monitor died in.

The only thing that ever leaves is one request per vendor, and only when you ask
for it (--refrescar, or --calentar, which is what the panels run):

GET https://api.anthropic.com/api/oauth/usage
GET https://api.z.ai/api/monitor/usage/quota/limit     # only if you use z.ai

Each one is the same host that vendor's own tool already talks to, with the
credential it already stored, asking about your own account, with a 60-second
floor. No account, no cloud, no telemetry, and zero runtime dependencies. It
never refreshes a token
— a locked non-goal, with a test.

The z.ai one is the exception to "no credential", and it is worth knowing which
direction it runs: opencode stores GLM, MiniMax and Kimi plans as API keys, and
those plans leave no percentage anywhere on disk. The opencode rows therefore
show what disk can prove — tokens spent, and the reset time a 429 already told
you — and the percentage only after you ask for it once. It is cached like every
other number, so the panels get a bar without ever touching the key themselves.

The full table, and the straight paragraph about both endpoints being
undocumented, are in SECURITY.md.

Package managers

One tag publishes everywhere. git push origin v0.1.7 runs the release
workflow, which builds every artifact and pushes it to each channel that has its
secret configured — and says in the log which ones it skipped and why.

Install What it gets Published by
npm npm install -g @legios/quartermaster the tarball with dist/, with provenance the tag, automatically
Homebrew brew install legiosai/tap/quartermaster the formula, from the tag's tarball the tag, automatically
apt sudo apt install quartermaster a signed repo, so apt upgrade brings new versions by itself the tag, automatically
.deb sudo apt install ./quartermaster_*.deb the same package, standalone attached to the release
Windows installer quartermaster-<v>-setup.exe per-user, no UAC: qm on PATH, tray in the Start menu attached to the release
scoop scoop install quartermaster the portable zip, no installer the tag, automatically
winget winget install Legios.Quartermaster the installer, declaring Node as a dependency the tag opens the PR
AUR yay -S quartermaster PKGBUILD, with a real nodejs>=22.6 the tag, automatically
Nix nix run github:legiosai/quartermaster the flake, with its own Node in the closure nothing to publish
GNOME Extensions from the Extensions app the Shell extension by hand — no upload API
waybar copy paquetes/waybar/ a module for Hyprland, Sway, river copied by hand

The one exception is extensions.gnome.org, which has no API for uploading. The
release reminds you, with a link to the artifact.

Cutting a version is one command:

./scripts/cortar-release.sh patch     # moves the version in all seven places,
                                      # runs the gates, commits and tags
git push origin main && git push origin v0.1.7

What each channel needs configured is in
paquetes/README.md.

Design

src/core/         profiles, types. Knows nothing about keychains or HTTP.
src/adapters/     credentials (keychain / file), transcripts (JSONL), quota
                  from the cache (.claude.json) and from the endpoint (HTTP),
                  Codex (JSON-RPC), opencode (SQLite) and z.ai (HTTP — the
                  only file that opens opencode's auth.json).
src/cli/          qm, and one demo per milestone.
src/render/       bars and formatting for the terminal, and the dashboard.
bin/              the launchers — qm (POSIX), qm.cmd + buscar-node.cmd
                  (Windows), qm.mjs (npm's entry, which has to work on both) —
                  and the four surfaces. They draw and nothing else.
extension/        the GNOME Shell extension that keeps the click.
paquetes/         how it reaches a machine that never clones the repo.
numeros/          one file per milestone: measured output, and an explicit
                  list of what could NOT be measured and why.

If a vendor name or an OS-specific path shows up outside src/adapters/, that
is a design bug.

The rest of it

  • SOUL.md — the mission, the metric, and the locked non-goals.
    Short, and the only file you need before proposing a change.
  • BITACORA.md — the engineering log, in Spanish: how each
    decision was reached, mistakes included. Three architectures for the GNOME
    panel before one held; an assumption about the macOS menu bar that turned out
    to be false; a CI gate that watched one function out of 1500 lines; an npm
    package that installed and then refused to run.
  • CONTRIBUTING.md — the three unusual rules:
    everything is measured, renderers only draw, gates are proven red.
  • docs/esquema-json.md — the qm --json
    contract, if you are writing a consumer.
  • numeros/ — the measurements themselves, one per milestone.

The code and its comments are in Spanish; what faces outward is in English.
That is deliberate, and CONTRIBUTING.md says why.

License

MIT. The deliberate exception: the core of Legios — cartographer, healer,
pipeline — is proprietary, and what gets published is what stands on its own.
This stands on its own.





Legios

Built by Valentín Torassa and Sol Soletti.

Yorumlar (0)

Sonuc bulunamadi