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

@saezbaldo/mumaps

v0.1.3

Published

Agent-friendly CLI for creating MuMaps playlists from Kantplanedo 100k

Downloads

247

Readme

MuMaps CLI

CLI y librería para crear playlists de Spotify a partir de una canción semilla en Kantplanedo 100k, el layout musical de MuMaps. Tiene distribuciones equivalentes en npm y PyPI, salida JSON estable y un flujo seguro para agentes.

La regla central es deliberada: una coincidencia aproximada nunca crea una playlist. Si el nombre está mal escrito o es ambiguo, el CLI devuelve como máximo cinco canciones similares con sus IDs. Un humano o agente debe confirmar el seed mediante --seed-id.

Instalación

Elegí una sola distribución. Ambas instalan el comando mumaps.

# npm / Node.js 20+
npm install --global @saezbaldo/mumaps

# PyPI / Python 3.10+
pipx install mumaps
# o: python -m pip install mumaps

Sin instalar globalmente:

npx --package @saezbaldo/mumaps mumaps --help
pipx run mumaps --help

Inicio rápido para agentes

mumaps search "Bille Jean" --json

Respuesta aproximada (máximo cinco elementos):

{
  "query": "Bille Jean",
  "artist": null,
  "layout": "kantplanedo-preview-100k-r1",
  "exact": false,
  "matches": [
    {
      "id": 30089,
      "title": "Billie Jean",
      "artist": "Michael Jackson",
      "album": "Thriller",
      "spotify_id": "7J1uxwnxfQLu4APicE5Rnj",
      "popularity": 80,
      "score": 0.9091,
      "exact": false
    }
  ]
}

Cuando exact es false, mostrá matches al usuario y pedile que elija un id. No adivines. Una vez confirmado:

mumaps create --seed-id 30089 --method camelot --duration 45 --json

Si se pasa un nombre exacto y solo existe una coincidencia inequívoca, también se puede crear directamente:

mumaps create "Billie Jean" --artist "Michael Jackson" --method similarity

Si el nombre es aproximado o hay varias versiones exactas, create no realiza cambios, devuelve confirmation_required: true y termina con exit code 2.

Autenticación

Buscar y resolver seeds es público. Crear una playlist requiere una cuenta MuMaps activa, porque la API protege la creación contra abuso. Podés crear la cuenta en mumaps.net.

El password nunca se acepta como argumento de línea de comandos, para evitar que aparezca en el historial o en la lista de procesos.

# Humano/CI: password por stdin
printf '%s' "$MUMAPS_PASSWORD" | \
  mumaps auth login --email [email protected] --password-stdin --json

# Agente/CI: variable de entorno (MUMAPS_PASSWORD por defecto)
mumaps auth login --email [email protected] --json

mumaps auth status --json
mumaps auth logout --json

El login guarda solamente el token de sesión de 30 días en ~/.config/mumaps/credentials.json, con permisos 0600 donde el sistema los soporta. Alternativas sin persistencia:

MUMAPS_TOKEN="..." mumaps create --seed-id 30089 --json
mumaps create --seed-id 30089 --token "..." --json

Preferí MUMAPS_TOKEN: un token pasado por --token puede quedar visible en el historial o la lista de procesos. MUMAPS_CONFIG permite cambiar el archivo de credenciales y --api-url/MUMAPS_API_URL permiten apuntar a otra API (el flag tiene prioridad; la URL predeterminada es https://api.mumaps.net).

Comandos

search <song>

Resuelve el título dentro de kantplanedo-preview-100k-r1.

mumaps search "Around the World" --artist "Daft Punk" --limit 5 --json

Opciones:

  • --artist <name>: exige artista exacto para declarar un match exacto.
  • --limit <1..5>: cantidad máxima de resultados; nunca supera cinco.
  • --json: contrato estable para agentes y scripts.

La búsqueda normaliza mayúsculas, acentos y puntuación; consulta prefijos progresivos para recuperar errores comunes; elimina duplicados; valida cada candidato contra Kantplanedo 100k; y ordena con similitud Damerau-Levenshtein, popularidad e ID como desempates deterministas.

Un título aproximado nunca se marca como exacto. Dos canciones con el mismo título siguen siendo ambiguas salvo que --artist deje una sola coincidencia.

create [song]

Crea o recupera una playlist compartida de Spotify administrada por MuMaps.

mumaps create --seed-id 30089 \
  --method bpm \
  --duration 30 \
  --age 1990 \
  --json

Opciones:

  • --seed-id <id>: seed confirmado; es el flujo recomendado para agentes.
  • --artist <name>: desambigua un [song] exacto.
  • --method <method>: estrategia de armado; default similarity.
  • --duration <minutes>: duración objetivo; 0 solicita hasta 100 tracks.
  • --age <year>: año de nacimiento usado por MuMaps; default año actual.

El CLI fija siempre:

{
  "mapMode": "kantplanedo",
  "layoutKey": "kantplanedo-preview-100k-r1"
}

No existe un flag para cambiar de mapa accidentalmente.

methods

mumaps methods --json

Métodos de playlist

Todos parten del seed confirmado y seleccionan tracks existentes en Kantplanedo 100k:

| Método | Comportamiento | | --- | --- | | similarity | Recorre los vecinos más cercanos del seed en el layout Kantplanedo. Es el default general. | | bpm | Prioriza BPM cercanos sin superar el BPM del seed, en orden descendente. | | camelot | Ordena transiciones armónicamente compatibles en la rueda Camelot y prioriza tempo mezclable; usa fallbacks cuando hacen falta para completar la duración. | | key | Conserva la tonalidad/pitch class de Spotify del seed y desempata por distancia en el layout. | | danceability | Prioriza danceability cercana sin superar la del seed. | | popularity | Prioriza popularidad cercana sin superar la del seed. |

La API puede devolver una playlist ya existente con el mismo seed, método y duración; esto hace que los reintentos sean idempotentes desde la perspectiva del consumidor.

Contrato para agentes

Usá siempre --json y respetá estos estados:

  1. Ejecutá search o create [song].
  2. Si exact=false, confirmation_required=true o el proceso sale con 2, presentá matches y solicitá un ID.
  3. No transformes score en consentimiento. Solo el ID confirmado habilita create --seed-id.
  4. Exit code 4 implica login/token; no repitas automáticamente credenciales.
  5. Exit code 5 implica red/API; el error se emite por stderr como JSON.

Exit codes:

| Código | Significado | | ---: | --- | | 0 | Operación exitosa. | | 2 | Hace falta confirmar un seed o no hubo candidatos. | | 3 | Argumentos, método o entrada inválidos. | | 4 | Falta autenticación o el token expiró. | | 5 | Error de red o de la API MuMaps. |

Los errores con --json se escriben en stderr:

{
  "error": {
    "code": "AUTH_REQUIRED",
    "message": "Authentication is required...",
    "status": null
  }
}

API programática

JavaScript:

import { MuMapsClient } from "@saezbaldo/mumaps";

const client = new MuMapsClient({ token: process.env.MUMAPS_TOKEN });
const result = await client.search("Bille Jean", { artist: "Michael Jackson" });
const playlist = await client.create({
  seedId: result.matches[0].id,
  method: "camelot",
  duration: 45,
  age: 1990,
});

Python:

import os
from mumaps import MuMapsClient

client = MuMapsClient(token=os.environ["MUMAPS_TOKEN"])
result = client.search("Bille Jean", artist="Michael Jackson")
playlist = client.create(
    result["matches"][0]["id"],
    method="camelot",
    duration=45,
    age=1990,
)

La librería no crea automáticamente desde un resultado aproximado; esa regla la aplica el comando create. Si integrás la API programática, verificá result["exact"] o pedí confirmación explícita del ID.

Desarrollo y releases

npm ci
npm test

python -m unittest discover -s python/tests
python -m build python

ci.yml prueba Node 20/22/24 y Python 3.10–3.13. publish.yml se ejecuta al publicar un GitHub Release, usa environments separados npm y pypi, permisos OIDC (id-token: write) y publicación idempotente: consulta cada registry antes de publicar. El versionado de npm y PyPI debe coincidir con el tag vX.Y.Z.

Seguridad

  • No reportes tokens, passwords ni respuestas de login en issues.
  • Usá variables de entorno o stdin en CI.
  • El repositorio no contiene credenciales de MuMaps, Spotify, npm ni PyPI.
  • Para reportar una vulnerabilidad, usá el canal indicado en SECURITY.md.

Licencia MIT. MuMaps/Kantplanedo no está afiliado ni respaldado por Spotify.