Skip to content

title: "Referencia de la CLI" description: "Manejar Mercy SF desde otro programa: cada comando, su salida JSON, los códigos de salida y ejemplos resueltos."

Referencia de la CLI, manejar Mercy SF desde otro programa

mercy-cli tiene un modo no interactivo: argumentos dentro, un objeto JSON fuera. Está pensado para paneles, supervisores y scripts.

Esta página es la promesa. Los comandos y los nombres de campo de abajo no cambiarán sin avisar. Todo lo demás de la CLI, el menú, su redacción, la disposición de su salida, es libre de cambiar en cualquier momento, así que por favor no construyas sobre ello.

Ejecutada sin argumentos, el menú interactivo arranca exactamente como antes.

Cada respuesta lleva "api". Hoy es 1. Añadir un campo no lo cambia, un llamante que solo lee los campos que conoce no se ve afectado. Cambia cuando se elimina un campo o cambia su significado, así que puedes negarte a funcionar contra una forma para la que no fuiste construido.


Iniciar sesión

Las cuentas creadas mediante el inicio de sesión único de S&F no necesitan nada más. Una cuenta que pertenece a un servidor y nunca formó parte del inicio de sesión único no existe para él, y necesita --server:

bash
mercy-cli --status --user <account> --server https://f1.sfgame.net/

--server funciona con todos los comandos de abajo.

Salida

Todos los comandos salvo --start imprimen JSON y nada más, así que --json ya es lo predeterminado y pasarlo no cambia nada. Existe para llamantes que prefieren decirlo antes que confiar en un valor por defecto, y para --start, que si no escribe un registro para humanos.


Leer

Listar los personajes de una cuenta

bash
mercy-cli --characters --user <account>
json
{
  "ok": true,
  "characters": [
    { "character": "Hero", "server": "https://s1.sfgame.net/", "level": 345 },
    { "character": "Alt",  "server": "https://s42.sfgame.net/", "level": 88 }
  ]
}

Un solo inicio de sesión cubre todos los personajes de la cuenta, en todos los servidores. level es null si no se pudo obtener el estado de ese personaje; la entrada se lista igualmente, porque saber que existe es el objeto de la llamada.

Leer el estado de un personaje

bash
mercy-cli --status --user <account> --character <name>

--character se puede omitir cuando la cuenta tiene exactamente uno.

json
{
  "ok": true,
  "character": "Hero",
  "server": "https://s1.sfgame.net/",
  "level": 345,
  "class": "DemonHunter",
  "race": "DarkElf",
  "experience": { "current": 740300000, "next_level": 769800000 },
  "silver": 725000000,
  "mushrooms": 8,
  "honor": 12043,
  "rank": 1800,
  "action": "CityGuard",
  "attributes": {
    "strength":     { "base": 4077, "bonus": 1200 },
    "dexterity":    { "base": 1000, "bonus": 300 },
    "intelligence": { "base": 900,  "bonus": 250 },
    "constitution": { "base": 3000, "bonus": 800 },
    "luck":         { "base": 700,  "bonus": 150 }
  },
  "equipment": [
    {
      "slot": "Weapon",
      "model_id": 55,
      "color": 1,
      "class": "DemonHunter",
      "epic": true,
      "legendary": false,
      "armor": 0,
      "min_damage": 900,
      "max_damage": 1400,
      "upgrades": 3,
      "attributes": { "strength": 420, "constitution": 210 },
      "rune": { "type": "FireDamage", "value": 60 },
      "enchantment": "SwordOfVengeance",
      "gem": { "type": "Strength", "value": 300 }
    }
  ],
  "arena": {
    "fights_for_xp": 7,
    "next_free_fight": "2026-08-06T12:04:11+02:00",
    "opponents": [50099, 34316, 13668]
  },
  "tavern": {
    "thirst_for_adventure_sec": 3600,
    "beer_drunk": 2,
    "mushroom_skip_allowed": true,
    "quests": [
      { "length_sec": 600, "silver": 120000, "experience": 45000,
        "location": "Wolves", "item": true }
    ]
  },
  "guild": {
    "name": "Blvck Clover",
    "rank": 12,
    "honor": 90000,
    "members": [
      { "name": "Hero", "level": 345, "last_online": "2026-08-06T09:12:00+02:00" }
    ]
  },
  "scrapbook_items": 1102
}

Todo sale de una única obtención de estado, así que no hay secciones que pedir ni nada que ahorrar pidiendo menos.

guild es null cuando el personaje no está en ninguno. scrapbook_items es null hasta que el álbum se ha leído al menos una vez. Una ranura de equipo vacía se omite en vez de listarse como null.

Sobre los nombres de objeto: el protocolo lleva un id de modelo y una ranura, no un nombre visible, así que eso es lo que obtienes. Es también aquello por lo que se direcciona la ilustración, así que un panel puede dibujar exactamente la misma imagen que la aplicación de escritorio. Inventarse un nombre aquí sería una suposición que no podrías comprobar.

Repetir una lectura a intervalos

bash
mercy-cli --status --user <account> --character <name> --watch 60

Un inicio de sesión y luego un objeto cada 60 segundos hasta que se detenga el proceso. Usa esto en vez de volver a ejecutar el comando en un bucle: cada ejecución es un inicio de sesión nuevo, que es la manera más cara de vigilar un número y la más llamativa desde el lado del servidor. El mínimo son 30 segundos. Una ronda fallida se imprime y el bucle sigue; un vigilante que se rinde al primer hipo se ve exactamente igual que uno en el que no pasa nada.

Contra quién peleará después, y por qué

bash
mercy-cli --plan --user <account> --character <name>
json
{
  "ok": true,
  "outcome": "planned",
  "reason": "Next: Someone — 3 scrapbook items, 72% odds",
  "candidates": [
    {
      "name": "Someone",
      "level": 340,
      "source": "pool",
      "missing_items": 3,
      "rank_gain": 12,
      "favourite": false,
      "win_chance": 0.72,
      "item_score": 300.0,
      "xp_score": 60.0,
      "rank_score": 25.0,
      "base": 385.0,
      "score": 277.2
    }
  ]
}

La misma decisión que dibuja la aplicación: candidatos puntuados por objetos, XP diaria y rango, y después multiplicados por las probabilidades. outcome es planned, waiting, blocked o empty, y reason dice cuál en una frase.

Esto no gasta ningún combate ni ninguna seta. Sí rastrea en busca de candidatos, así que no es gratis en peticiones; no lo pongas en un bucle apretado.

Ensayar un combate

bash
mercy-cli --simulate --user <account> --character <name> --against <player>
json
{ "ok": true, "against": "Someone", "against_level": 340, "win_chance": 0.63, "iterations": 1000 }

Aritmética. Una consulta va al servidor para averiguar quién es; el combate en sí no se envía nunca. win_chance son victorias sobre combates resueltos, así que una simulación que no consigue resolver informa sobre menos de los que ejecutó.

Qué se lleva encima

bash
mercy-cli --inventory --user <account> --character <name>
json
{ "ok": true, "carried": 12, "backpack": [ { "slot_index": 0, "model_id": 55 } ] }

Una lista, porque el juego mantiene una. Los objetos tienen la misma forma que en --status, más slot_index.

Álbum

bash
mercy-cli --scrapbook --user <account> --character <name>
json
{ "ok": true, "unlocked": true, "owned": 1102, "monsters": 214 }

unlocked es false por debajo del nivel que concede un álbum, y owned es null ahí. Eso no es un error.

Combates registrados

bash
mercy-cli --history --user <account> --character <name> --limit 50
json
{ "ok": true, "total": 4210, "returned": 50, "battles": [] }

Los más recientes primero. Los registra la instalación que ejecutó el bot, no se traen del servidor, así que un proceso que acaba de arrancar no tiene nada que mostrar, y eso no es un fallo. total es lo que existe, returned es lo que dejó --limit.


Actuar

Ejecutar el bot

bash
mercy-cli --start --user <account> --character <name>

Corre hasta que se detenga el proceso, registrando por el camino. --character es obligatorio aquí: listar y leer estado son inofensivos, pero arrancar el bot juega la partida, y elegir el personaje equivocado no es algo que puedas deshacer.

--all ejecuta en cambio todos los personajes de la cuenta en este único proceso. Eso es un inicio de sesión para la cuenta en vez de uno por personaje, lo que sale más barato e impide que los personajes se invaliden la sesión entre ellos.

Con Ctrl-C (o SIGTERM) se deja terminar el movimiento en curso antes de que el proceso salga, en vez de cortarlo a mitad de una petición.

Eventos en lugar de prosa

bash
mercy-cli --start --user <account> --character <name> --events

Un objeto JSON por línea, así que un supervisor lee línea a línea:

json
{"at":"2026-08-06T17:22:04+02:00","api":1,"event":"arena_win","character":"Hero"}
{"at":"2026-08-06T17:22:31+02:00","api":1,"event":"quest_done","character":"Hero"}

event es uno de started, stopping, stopped, arena_win, arena_loss, dungeon_win, dungeon_loss, quest_done, scrapbook_win, scrapbook_loss, scrapbook_items (que lleva count).

Esta lista crecerá. Trata un evento que no reconozcas como uno a ignorar, no como un error; esa es toda la razón de que los nombres estén escritos en vez de ser lo que Rust imprimiese.

Usa esto en vez de leer el registro para humanos. Ese registro está escrito para una persona y puede reformularse en cualquier momento; analizarlo significa que tu herramienta se rompe cuando alguien mejora una frase.

Recoger lo que espera

bash
mercy-cli --claim --user <account> --character <name>

Calendario, tareas diarias, desbloqueos pendientes. --character es obligatorio, por la misma razón que en --start.

Leer o cambiar la configuración

bash
mercy-cli --config --user <account> --character <name>
mercy-cli --config --user <account> --character <name> --set auto_arena=false
json
{ "ok": true, "settable": ["auto_arena"], "changed": [ { "key": "auto_arena", "from": true, "to": false } ] }

Leer devuelve toda la configuración bajo config. Los nombres de campo dentro de ese bloque no forman parte de esta promesa, solo las claves listadas en settable lo hacen. La configuración tiene bastante más de cien campos y crece con cada versión; prometerlos todos significaría no poder volver a reorganizar los ajustes nunca.

--set acepta true/false, on/off, yes/no, 1/0, exige siempre --character (un interruptor pertenece a un personaje, y «el único» es una suposición aceptable para leer y equivocada para escribir), y se puede repetir. El valor se vuelve a leer del disco después y la llamada falla si no llegó, porque informar de un cambio que no ocurrió es el único resultado del que no puedes recuperarte.


Operar

Qué compilación es esta

bash
mercy-cli --version
json
{ "ok": true, "version": "2.12.0", "api": 1 }

El único comando que no necesita ni contraseña ni red. Un supervisor tiene que poder preguntar con qué está hablando antes de tener credenciales con las que hablar.

¿Está accesible?

bash
mercy-cli --health --user <account> --character <name>
json
{ "ok": true, "character": "Hero", "level": 345, "round_trip_ms": 412 }

Iniciar sesión, obtener, informar, salir. Deliberadamente pequeño: una comprobación de salud que devuelve una ficha de personaje completa invita a analizarla, y entonces la comprobación se convierte en una interfaz por sí misma.


La contraseña

No hay una opción --password, a propósito. Los argumentos de la línea de comandos son legibles por cualquier otro proceso de la máquina, ps, /proc, el administrador de tareas, así que un panel que ejecutase esto para varias personas estaría entregando todas sus contraseñas del juego a cualquiera con una shell en esa máquina.

Dos vías en su lugar:

bash
MERCY_SF_PASSWORD='…' mercy-cli --status --user someone
bash
printf '%s' "$password" | mercy-cli --status --user someone --password-stdin

--password-stdin lee la primera línea de la entrada estándar, lo que además mantiene el secreto fuera del entorno.


Códigos de salida

CódigoSignificado
0Éxito, y para --help
1Se ejecutó y falló, el motivo está en error, y ok es false
2La llamada estaba mal: opción desconocida, valor ausente, ninguna acción. En stderr

La diferencia entre 1 y 2 le importa a un supervisor: 2 fallará igual siempre y necesita a una persona; 1 puede perfectamente funcionar al siguiente intento.


Errores

Los fallos también son JSON, así que un solo analizador vale para ambos:

json
{ "ok": false, "error": "no character called 'Typo' on this account" }

ok está presente en todas las respuestas. Compruébalo antes que nada.

Causas habituales:

MensajeQué hacer
--user is requiredFalta --user (toda acción salvo --version)
--start needs --character (or --all)Nombra el objetivo; no se va a adivinar
this account has N characters — name one with --characterHay varios, elige uno
no character called '…' on this accountErrata; --characters lista los nombres válidos
no password: set MERCY_SF_PASSWORD or pass --password-stdinElige una de las dos vías para la contraseña
login failed: …Comprueba las credenciales o el servidor; las cuentas sin inicio de sesión único necesitan --server
'…' is not settable from hereNo está en la lista permitida; --config sin --set imprime settable
'…' did not save — it still reads back unchangedEl cambio no llegó; comprueba los permisos de escritura

Recetas

Recoger en todas las cuentas una vez al día

bash
for account in alpha beta gamma; do
  MERCY_SF_PASSWORD="$(pass mercy/$account)" \
    mercy-cli --claim --user "$account" --character Hero || echo "failed: $account"
done

Mantener al día una tarjeta de panel

bash
MERCY_SF_PASSWORD='…' mercy-cli --status --user someone --character Hero --watch 60

Un inicio de sesión, un objeto por minuto. No lances esto desde cron cada minuto en su lugar; eso es un inicio de sesión nuevo cada vez.

Registrar eventos en un archivo

bash
MERCY_SF_PASSWORD='…' mercy-cli --start --user someone --character Hero --events \
  >> events.ndjson

Comprobar con qué hablas antes de iniciar sesión

bash
api=$(mercy-cli --version | jq -r .api)
[ "$api" = "1" ] || { echo "unknown contract version: $api"; exit 1; }

Como servicio de systemd

ini
[Service]
Environment=MERCY_SF_PASSWORD=…
ExecStart=/usr/local/bin/mercy-cli --start --user someone --all --events
Restart=on-failure
KillSignal=SIGTERM

SIGTERM deja terminar el movimiento en curso. Por favor, no le mandes SIGKILL.


Lo que esto todavía no hace

Arrancar varios personajes y pararlos por separado (--all los arranca todos y los para todos juntos), un canal de control hacia un proceso en marcha, y cambiar cualquier cosa más allá de los interruptores de los módulos.

Si necesitas alguna de ellas, di cuál; es más fácil construir lo correcto que adivinar y que luego no se use.

Mercy SF no está afiliado a Shakes & Fidget ni a Playa Games. Úsalo bajo tu responsabilidad.