Skip to content

Repository files navigation

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 user@example.com --password-stdin --json

# Agente/CI: variable de entorno (MUMAPS_PASSWORD por defecto)
mumaps auth login --email user@example.com --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.

About

Agent-friendly npm and PyPI CLI for creating playlists from Kantplanedo 100k

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages