npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@badgie/cli

v1.1.1

Published

The official Badgie CLI — operate your sports school, club or academy from the terminal. A terminal harness for humans and AI agents, powered by the Badgie MCP.

Readme

Badgie CLI

Opera tu escuela, club o academia deportiva desde la terminal. Para humanos y para agentes.

npm version node license

Badgie CLI es el harness oficial de línea de comandos de Badgie, la plataforma de gestión deportiva. Es un cliente del Badgie MCP (el servidor MCP oficial de Badgie), así que reutiliza todo lo que ya conoces: tu cuenta, tu rol y el catálogo completo de acciones — alumnos, insignias, clases, finanzas, reservas, torneos, comunicaciones, golf y mucho más.

Un binario, dos modos:

  • Modo interactivo (REPL) — escribe badgie y opera tu escuela conversando con la terminal.
  • Modo comandobadgie run <accion> --json para scripts, CI y agentes IA.

Instalación

npm i -g @badgie/cli

Y arranca:

badgie

Requiere Node.js ≥ 18.

Quickstart

1. Inicia sesión (abre el navegador — OAuth 2.1 con tu cuenta Badgie):

badgie login

2. Comprueba quién eres (rol + escuela):

badgie whoami

3. Mira qué puedes hacer (el catálogo se filtra por tu rol):

badgie tools

4. Ejecuta acciones:

# Consulta genérica de datos de tu escuela (~346 tablas bajo tu RLS)
badgie run query_data table=badge limit=5

# Argumentos como pares key=value (con dot-notation para anidar)…
badgie run get_top_debtors limit=10

# …o el payload completo en JSON con --args (ideal para acciones anidadas)
badgie run students.set_avatar --args '{"action_type":"students.set_avatar","payload":{"student_id":"…","avatar":"adventurer"}}'

5. O simplemente entra al REPL y trabaja en conversación:

badgie
  ★ Badgie — tu escuela desde la terminal
  Escuela Ejemplo · owner · [email protected]

badgie> tools
badgie> run query_data table=student limit=10
badgie> run propose_action --args '{"action_type":"communications.send","payload":{…},"summary":"Recordatorio cuota julio"}'

Las escrituras sensibles no se ejecutan directamente: el CLI las propone y el humano las aprueba en el dashboard de Badgie (/dashboard/agent). Human-in-the-loop de serie.

Comandos

| Comando | Qué hace | |---------|----------| | badgie | REPL interactivo (banner + sesión conversacional) | | badgie login | Autoriza el CLI con tu cuenta Badgie (navegador, OAuth 2.1 + PKCE) | | badgie logout | Cierra la sesión local | | badgie whoami | Tu identidad: rol, escuela, email | | badgie tools | Lista las acciones disponibles para tu rol | | badgie run <accion> [k=v…] [--args '<json>'] [--json] | Ejecuta o propone una acción | | badgie update [--check] [--json] [--channel <tag>] | Actualiza el CLI a la última versión publicada |

Argumentos de run:

  • Pares key=value — se coercionan a number/boolean/null automáticamente y admiten dot-notation (payload.student_id=…).
  • --args '<json>' — payload base completo en JSON; los pares key=value se aplican encima.
  • --json — salida JSON pura (sin colores ni banner), pensada para máquinas.

Mantenerlo al día

El catálogo de acciones se lee del Badgie MCP en vivo, así que las herramientas nuevas aparecen solas. Lo que sí envejece es el harness: por eso el CLI se actualiza solo y avisa cuando se ha quedado atrás.

badgie update            # actualiza con el gestor con el que se instaló
badgie update --check    # solo mira si hay versión nueva

badgie update no pregunta nada. Detecta cómo está instalado —npm global, Homebrew, pnpm, yarn, bun, Volta, dependencia de un proyecto, npx, checkout de fuente— y usa el comando correcto. Cuando no puede hacerlo él (una copia efímera de npx, una dependencia de proyecto, un directorio sin permiso de escritura), imprime el comando exacto y por qué no lo lanza. Nunca ejecuta sudo por su cuenta.

Tres cosas que hace y que no se ven:

  • Uno cada vez. El instalador va dentro de un lock de fichero con dueño identificable, con la ruta de instalación como clave. Dos badgie update simultáneos no lanzan dos npm install -g sobre el mismo prefix: el segundo espera y, si el primero ya dejó puesta la versión buena y arrancando, lo dice y no instala nada. Un lock huérfano (proceso muerto) caduca solo, y robarlo es atómico. El fichero vive en un directorio de máquina (/var/tmp), no en el temporal del proceso: en macOS $TMPDIR es por usuario y cron/launchd no lo llevan puesto, así que un update programado y uno de la terminal se creaban dos locks distintos para el mismo prefix y lanzaban dos npm a la vez.
  • Se instala del mismo sitio del que se ha mirado. El registro consultado viaja en el comando de instalación (--registry y, para npm, además --@badgie:registry=, porque el registro por scope de un .npmrc gana a --registry). Sin eso, en una máquina con espejo privado se consulta un registro y se instala de otro.
  • El exit 0 del instalador no vale como prueba, y su package.json tampoco. Al terminar se ejecuta el CLI instalado (<prefix>/bin/badgie -v) y se compara lo que contesta con la versión perseguida. Si no arranca, o arranca y dice otra cosa —el instalador no tocó nada, bajó de versión, se llevó el dist/ o dejó el bin/ vacío—, el comando falla y lo dice. Una cadena en un fichero no demuestra que la instalación sirva; un binario que arranca, sí.

El aviso de versión

Cuando hay una versión nueva, el CLI lo dice al terminar:

  ▲  Badgie CLI 1.0.4 → 1.1.0
     Actualiza con: badgie update

Reglas del aviso, pensadas para que no moleste a un agente:

  • Va por stderr, nunca por stdout.
  • Con --json no se imprime nada en absoluto, ni siquiera por stderr — porque un agente puede estar corriendo con 2>&1.
  • No añade latencia: la consulta al registro la hace un proceso de fondo desacoplado, como mucho una vez al día, y el resultado se usa en la ejecución siguiente. Si no hay red, el CLI funciona igual y calla.
  • Solo aparece si stderr es un terminal. En CI no aparece nunca.
  • Se apaga con BADGIE_NO_UPDATE_NOTIFIER=1.

Para agentes

# ¿hay algo que actualizar? (sin parsear texto)
badgie update --check --json | jq -e '.updateAvailable == true' >/dev/null || exit 0

# actualizar: UNA sola vez. Si no llega, sale ≠ 0 y ahí se acaba.
badgie update --json | jq -e '.ok == true and .verified == true' >/dev/null

⚠️ No metas badgie update en un bucle «hasta que current == latest». No hace falta, y con una instalación que por lo que sea no puede llegar a latest el bucle gira para siempre. badgie update ya comprueba el resultado por ti: o llega y sale con 0, o no llega, sale con ≠ 0 y dice exactamente por qué. Un ok:false es terminal: se lee, no se reintenta.

badgie update --json escribe una línea de JSON por stdout:

{"ok":true,"current":"1.0.4","latest":"1.1.0","channel":"latest","updateAvailable":true,
 "performed":true,"installed":"1.1.0","verified":true,"install":{"manager":"npm","scope":"global",
 "kind":"npm-global","path":"/opt/homebrew/lib/node_modules/@badgie/cli","writable":true,
 "canSelfUpdate":true,"registryPinned":true},
 "command":"npm install -g --prefix /opt/homebrew --registry https://registry.npmjs.org --@badgie:registry=https://registry.npmjs.org @badgie/cli@latest",
 "registry":"https://registry.npmjs.org"}

installed es la versión que ha dicho el CLI instalado al ejecutarlo, no la que ponga su package.json: se lanza el ejecutable con -v y se lee lo que contesta. verified:true significa exactamente eso — que arrancó y dijo la versión que tocaba. Una instalación a medias deja un package.json mintiendo; un binario que arranca, no.

El contrato de esa línea se verifica antes de escribirla; si algo no cuadrara, la salida se degrada a fallo en vez de publicar una contradicción:

| Garantía | Qué significa | |---|---| | performed:trueok:true | jamás se declara «he actualizado» dentro de un fallo | | performed:trueinstalled == latest | installed sale de ejecutar el CLI instalado, no de leer su package.json. Nunca se supone | | performed:trueverified:true | no hay éxito sin haber arrancado el binario resultante | | reason:"already-installed"verified:true | «ya estaba puesta» también exige comprobarlo ejecutándola | | verified:falseok:false | una verificación fallida jamás convive con un éxito | | ok:falseperformed:false y hay reason y hay error | un fallo siempre viene explicado | | exit 0ok:true | el código de salida y el JSON dicen lo mismo |

reason cuando lo hay:

| reason | Cuándo | exit | |---|---|---| | updates-disabled | BADGIE_DISABLE_UPDATES=1 | 0 | | npx-ephemeral, source-checkout, project-dependency, not-writable, unknown-install | no podemos actualizarnos solos; command dice cómo hacerlo | 0 | | already-installed | otro badgie update simultáneo ya dejó puesta la versión buena; este proceso no instaló nada | 0 | | update-in-progress | hay otro instalador en curso y no lanzamos un npm encima. No se ha tocado nada: reintenta cuando termine | ≠ 0 | | version-mismatch | el instalador salió 0 pero el CLI que arranca no es latest (no tocó nada, o bajó de versión) | ≠ 0 | | installation-broken | el árbol dice una versión y el CLI no arranca. Con --check solo se informa; sin --check, badgie update reinstala para repararlo | ≠ 0 | | installer-failed | el instalador falló; error lleva su stderr | ≠ 0 | | internal-inconsistency | red de seguridad: la salida no cuadraba consigo misma | ≠ 0 |

Con --check nunca se instala nada: performed es siempre false y el exit es 0 (salvo que la instalación esté rota, que es un ok:false).

Reparación

«Al día» no es lo mismo que «funciona». Si el canal no trae nada nuevo pero el CLI instalado no arranca —el caso clásico: dos instalaciones a la vez se llevaron por delante <prefix>/bin/badgie y el package.json quedó con la versión subida—, badgie update no dice «ya estás al día»: reinstala. Esa salida se distingue por repaired:true con updateAvailable:false:

{"ok":true,"current":"1.1.0","latest":"1.1.0","updateAvailable":false,
 "repaired":true,"performed":true,"installed":"1.1.0","verified":true}

Cuando el binario ni siquiera arranca para poder ejecutar badgie update, el paquete sigue ahí: node "$(npm prefix -g)/lib/node_modules/@badgie/cli/dist/bin.js" update.

Por rol

El rol no se elige: se deriva de tu cuenta Badgie en el servidor. Cada rol ve un catálogo distinto.

🏫 Owner (cuenta de escuela)

Lectura universal del negocio + propuestas de acción:

badgie run get_school_profile
badgie run query_data table=fin_invoices limit=20
badgie run get_top_debtors
badgie run list_action_catalog          # ~24 tipos de acción proponibles
badgie run list_my_proposals            # estado de tus propuestas

~51 tools: asistencia, riesgo de abandono, MRR, deuda, ocupación de reservas, progreso de colecciones, nutrición, drills… cada una gated por el módulo correspondiente de tu escuela.

🧑‍🏫 Teacher (profesor)

Tu día a día, scoped a tus clases y alumnos:

badgie run my_classes_today
badgie run my_students
badgie run award_badge --args '{"student_id":"…","badge_id":"…"}'
badgie run record_attendance --args '{"event_id":"…","records":[…]}'

🎽 Student / familia

Tus datos y solo los tuyos:

badgie run my_badges
badgie run my_schedule
badgie run my_payments
badgie run my_golf_stats

Para agentes y scripts

El CLI está diseñado para que un agente (OpenClaw, Claude, ChatGPT, un cron de CI…) opere Badgie sin fricción:

  • --json en cualquier comando → salida JSON estable, sin decoración.
  • Exit codes limpios: 0 éxito, distinto de cero en error (con el error legible en stderr).
  • Mismo backend que un cliente MCP: es el Badgie MCP oficial, así que un agente que ya hable MCP puede conectarse directo a https://www.badgie.com/api/mcp/mcp; el CLI es la vía cómoda cuando el agente vive en una shell.
  • Sin estado sorpresa: la sesión vive en ~/.badgie, portable entre invocaciones.
  • Se mantiene al día solo: badgie update --check --json dice si hay versión nueva y badgie update --json la instala, las dos con salida parseable. El aviso de versión jamás contamina un --json.
# Ejemplo: informe diario en un script
badgie run my_classes_today --json | jq '.classes[] | {name, start, students}'

Seguridad

  • OAuth 2.1 + PKCE: badgie login abre el navegador y autorizas con tu cuenta Badgie. El CLI nunca ve tu contraseña.
  • Scoping por rol, en el servidor: owner / teacher / student se derivan de la base de datos, nunca del cliente. La RLS de Badgie aplica en cada llamada.
  • Nunca cross-tenant: jamás verás datos de otra escuela ni de otro alumno.
  • Human-in-the-loop: las escrituras sensibles se registran como propuestas que un humano aprueba en el dashboard. Los datos de menores siempre pasan por aprobación humana.
  • Tokens en local con permisos estrictos: ~/.badgie/auth.json se guarda con modo 0600.

Configuración

| Qué | Dónde | |-----|-------| | Sesión y tokens | ~/.badgie/auth.json | | Preferencias del CLI | ~/.badgie/cli-config.json | | BADGIE_MCP_URL | Override del endpoint MCP (dev/staging). Default: https://www.badgie.com/api/mcp/mcp | | BADGIE_ORIGIN | Override del origen OAuth. Default: https://www.badgie.com | | BADGIE_CONFIG_DIR | Reubica ~/.badgie entero (entornos aislados, contenedores) | | BADGIE_NO_UPDATE_NOTIFIER | 1 calla el aviso de versión y el chequeo de fondo. badgie update sigue funcionando | | NO_UPDATE_NOTIFIER | Igual que la anterior (convención del ecosistema) | | BADGIE_DISABLE_UPDATES | 1 calla el aviso y badgie update se niega. Para instalaciones gobernadas | | BADGIE_UPDATE_CHANNEL | dist-tag a seguir. Default: latest | | BADGIE_REGISTRY | Registro npm alternativo. Default: https://registry.npmjs.org |

Estado en disco relacionado con actualizaciones: ~/.badgie/cli-update.json (caché del aviso; borrarlo no rompe nada) y, solo mientras dura una instalación, un lock en un directorio de máquina —/var/tmp en POSIX (/tmp de reserva), %ProgramData%\Badgie en Windows— llamado badgie-cli-update-<hash de la ruta de instalación>.lock. No en el temporal del proceso: $TMPDIR es distinto por usuario y no lo lleva cron, y el lock tiene que ser función del prefix, no de quién lo toca. El lock caduca solo si el proceso que lo tenía muere (o a los 15 minutos).

# Apuntar el CLI a un entorno de desarrollo
BADGIE_MCP_URL=http://localhost:3000/api/mcp/mcp badgie whoami

Enlaces


Hecho con ⭐ por Badgie Sports App, S.L. · MIT