@saezbaldo/mumaps
v0.1.3
Published
Agent-friendly CLI for creating MuMaps playlists from Kantplanedo 100k
Downloads
247
Maintainers
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 mumapsSin instalar globalmente:
npx --package @saezbaldo/mumaps mumaps --help
pipx run mumaps --helpInicio rápido para agentes
mumaps search "Bille Jean" --jsonRespuesta 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 --jsonSi 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 similaritySi 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 --jsonEl 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 "..." --jsonPreferí 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 --jsonOpciones:
--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 \
--jsonOpciones:
--seed-id <id>: seed confirmado; es el flujo recomendado para agentes.--artist <name>: desambigua un[song]exacto.--method <method>: estrategia de armado; defaultsimilarity.--duration <minutes>: duración objetivo;0solicita 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 --jsonMé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:
- Ejecutá
searchocreate [song]. - Si
exact=false,confirmation_required=trueo el proceso sale con2, presentámatchesy solicitá un ID. - No transformes
scoreen consentimiento. Solo el ID confirmado habilitacreate --seed-id. - Exit code
4implica login/token; no repitas automáticamente credenciales. - Exit code
5implica 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 pythonci.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.
