title: "Riferimento della CLI" description: "Guidare Mercy SF da un altro programma: ogni comando, il suo output JSON, i codici di uscita ed esempi svolti."
Riferimento della CLI, guidare Mercy SF da un altro programma
mercy-cli ha una modalità non interattiva: argomenti in ingresso, un oggetto JSON in uscita. È pensata per dashboard, supervisori e script.
Questa pagina è la promessa. I comandi e i nomi dei campi qui sotto non cambieranno senza preavviso. Tutto il resto della CLI, il menu, il modo in cui è scritto, l'impaginazione del suo output, è libero di cambiare in qualsiasi momento, quindi per favore non costruiteci sopra.
Eseguita senza argomenti, parte il menu interattivo esattamente come prima.
Ogni risposta porta "api". Oggi è 1. Aggiungere un campo non lo cambia, un chiamante che legge solo i campi che conosce resta inalterato. Cambia quando un campo viene rimosso o il suo significato cambia, così potete rifiutarvi di girare contro una forma per cui non siete stati costruiti.
Accedere
Gli account creati tramite il single sign-on di S&F non hanno bisogno di altro. Un account che appartiene a un server e non ha mai fatto parte del single sign-on per esso non esiste, e ha bisogno di --server:
mercy-cli --status --user <account> --server https://f1.sfgame.net/--server funziona con ogni comando qui sotto.
Output
Ogni comando tranne --start stampa JSON e nient'altro, quindi --json è già il comportamento predefinito e passarlo non cambia nulla. Esiste per i chiamanti che preferiscono dirlo piuttosto che affidarsi a un valore di serie, e per --start, che altrimenti scrive un registro per persone.
Leggere
Elencare i personaggi di un account
mercy-cli --characters --user <account>{
"ok": true,
"characters": [
{ "character": "Hero", "server": "https://s1.sfgame.net/", "level": 345 },
{ "character": "Alt", "server": "https://s42.sfgame.net/", "level": 88 }
]
}Un solo accesso copre ogni personaggio dell'account, su tutti i server. level è null se lo stato di quel personaggio non è stato recuperato, la voce viene comunque elencata, perché sapere che esiste è il senso della chiamata.
Leggere lo stato di un personaggio
mercy-cli --status --user <account> --character <name>--character si può omettere quando l'account ne ha esattamente uno.
{
"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
}Tutto viene da un solo recupero di stato, quindi non ci sono sezioni da chiedere e niente da risparmiare chiedendo di meno.
guild è null quando il personaggio non è in nessuna. scrapbook_items è null finché l'album non è stato letto almeno una volta. Uno slot di equipaggiamento vuoto viene omesso invece che elencato come null.
Sui nomi degli oggetti: il protocollo porta un id di modello e uno slot, non un nome visualizzato, quindi è quello che ottenete. È anche ciò con cui viene indirizzata la grafica, quindi una dashboard può disegnare esattamente l'immagine che disegna l'app desktop. Inventare qui un nome sarebbe un'ipotesi non verificabile.
Ripetere una lettura a intervalli
mercy-cli --status --user <account> --character <name> --watch 60Un accesso, poi un oggetto ogni 60 secondi finché il processo non viene fermato. Usate questo invece di rilanciare il comando in un ciclo: ogni esecuzione è un accesso nuovo, che è il modo più costoso di sorvegliare un numero e il più vistoso dal lato del server. Il minimo è 30 secondi. Un giro fallito viene stampato e il ciclo prosegue: un osservatore che si arrende al primo singhiozzo sembra esattamente uno in cui non succede nulla.
Chi affronterà dopo, e perché
mercy-cli --plan --user <account> --character <name>{
"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 stessa decisione che disegna l'app: candidati valutati su oggetti, XP quotidiana e posizione, poi moltiplicati per le probabilità. outcome è planned, waiting, blocked o empty, e reason dice quale in una frase.
Questo non spende alcun combattimento né alcun fungo. Fa però una scansione per trovare candidati, quindi non è gratis in richieste: non mettetelo in un ciclo stretto.
Provare un combattimento
mercy-cli --simulate --user <account> --character <name> --against <player>{ "ok": true, "against": "Someone", "against_level": 340, "win_chance": 0.63, "iterations": 1000 }Aritmetica. Una consultazione va al server per scoprire chi è; il combattimento in sé non viene mai inviato. win_chance sono le vittorie sui combattimenti decisi, quindi una simulazione che non riesce a risolvere riferisce su meno di quanti ne ha eseguiti.
Cosa si porta addosso
mercy-cli --inventory --user <account> --character <name>{ "ok": true, "carried": 12, "backpack": [ { "slot_index": 0, "model_id": 55 } ] }Un solo elenco, perché il gioco ne tiene uno. Gli oggetti hanno la stessa forma che in --status, più slot_index.
Album
mercy-cli --scrapbook --user <account> --character <name>{ "ok": true, "unlocked": true, "owned": 1102, "monsters": 214 }unlocked è false sotto il livello che concede un album, e lì owned è null. Non è un errore.
Combattimenti registrati
mercy-cli --history --user <account> --character <name> --limit 50{ "ok": true, "total": 4210, "returned": 50, "battles": [] }I più recenti per primi. Sono registrati dall'installazione che ha fatto girare il bot, non recuperati dal server: un processo appena avviato non ha nulla da mostrare, e non è un guasto. total è ciò che esiste, returned è ciò che --limit ha lasciato.
Agire
Far girare il bot
mercy-cli --start --user <account> --character <name>Gira finché il processo non viene fermato, registrando man mano. Qui --character è obbligatorio: elencare e leggere lo stato sono innocui, ma avviare il bot gioca la partita, e sbagliare personaggio non è una cosa che si possa annullare.
--all fa invece girare ogni personaggio dell'account in questo unico processo. È un accesso per l'account invece di uno per personaggio, il che costa meno e impedisce ai personaggi di invalidarsi la sessione a vicenda.
Su Ctrl-C (o SIGTERM) la mossa in corso può concludersi prima che il processo esca, invece di essere troncata a metà richiesta.
Eventi invece di prosa
mercy-cli --start --user <account> --character <name> --eventsUn oggetto JSON per riga, così un supervisore legge una riga alla volta:
{"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 è uno tra started, stopping, stopped, arena_win, arena_loss, dungeon_win, dungeon_loss, quest_done, scrapbook_win, scrapbook_loss, scrapbook_items (che porta count).
Questo elenco crescerà. Trattate un evento che non riconoscete come uno da ignorare, non come un errore: è tutta la ragione per cui i nomi sono scritti per esteso invece di essere ciò che Rust ha stampato.
Usate questo invece di leggere il registro per persone. Quel registro è scritto per una persona ed è libero di essere riscritto in qualsiasi momento; analizzarlo significa che il vostro strumento si rompe quando qualcuno migliora una frase.
Raccogliere ciò che aspetta
mercy-cli --claim --user <account> --character <name>Calendario, incarichi quotidiani, sblocchi in attesa. --character è obbligatorio, per lo stesso motivo di --start.
Leggere o cambiare la configurazione
mercy-cli --config --user <account> --character <name>
mercy-cli --config --user <account> --character <name> --set auto_arena=false{ "ok": true, "settable": ["auto_arena"], "changed": [ { "key": "auto_arena", "from": true, "to": false } ] }Leggere restituisce l'intera configurazione sotto config. I nomi dei campi dentro quel blocco non fanno parte di questa promessa, solo le chiavi elencate in settable ne fanno parte. La configurazione ha ben oltre cento campi e cresce a ogni versione; prometterli tutti significherebbe non poter mai più rimettere mano alle impostazioni.
--set accetta true/false, on/off, yes/no, 1/0, richiede sempre --character (un interruttore appartiene a un personaggio, e «l'unico» è un'ipotesi accettabile per leggere e sbagliata per scrivere), e si può ripetere. Il valore viene poi riletto da disco e la chiamata fallisce se non è atterrato, perché segnalare un cambiamento che non è avvenuto è l'unico esito da cui non ci si riprende.
Esercizio
Che build è questa
mercy-cli --version{ "ok": true, "version": "2.12.0", "api": 1 }L'unico comando che non ha bisogno né di una password né della rete. Un supervisore deve poter chiedere con che cosa sta parlando prima di avere le credenziali per parlarci.
È raggiungibile
mercy-cli --health --user <account> --character <name>{ "ok": true, "character": "Hero", "level": 345, "round_trip_ms": 412 }Accedere, recuperare, riferire, uscire. Volutamente minuscolo: un controllo di salute che restituisce una scheda personaggio completa invita ad analizzarla, e a quel punto il controllo diventa un'interfaccia a sé.
La password
Non c'è un'opzione --password, di proposito. Gli argomenti da riga di comando sono leggibili da ogni altro processo sulla macchina, ps, /proc, Gestione attività, quindi una dashboard che lo eseguisse per più persone consegnerebbe tutte le loro password di gioco a chiunque abbia una shell su quella macchina.
Due strade invece:
MERCY_SF_PASSWORD='…' mercy-cli --status --user someoneprintf '%s' "$password" | mercy-cli --status --user someone --password-stdin--password-stdin legge la prima riga dello standard input, il che tiene il segreto anche fuori dall'ambiente.
Codici di uscita
| Codice | Significato |
|---|---|
0 | Successo, e per --help |
1 | Ha girato ed è fallito, il motivo è in error, e ok è false |
2 | La chiamata era sbagliata: opzione sconosciuta, valore mancante, nessuna azione. Su stderr |
La differenza tra 1 e 2 conta per un supervisore: 2 fallirà allo stesso modo ogni volta e ha bisogno di una persona, 1 può benissimo funzionare al tentativo successivo.
Errori
Anche i fallimenti sono JSON, quindi un solo parser gestisce entrambi:
{ "ok": false, "error": "no character called 'Typo' on this account" }ok è presente in ogni risposta. Controllatelo prima di ogni altra cosa.
Cause comuni:
| Messaggio | Cosa fare |
|---|---|
--user is required | Manca --user (ogni azione tranne --version) |
--start needs --character (or --all) | Nominate il bersaglio; non verrà indovinato |
this account has N characters — name one with --character | Ce ne sono diversi, sceglietene uno |
no character called '…' on this account | Refuso; --characters elenca i nomi validi |
no password: set MERCY_SF_PASSWORD or pass --password-stdin | Scegliete una delle due strade per la password |
login failed: … | Controllate le credenziali o il server; gli account senza single sign-on richiedono --server |
'…' is not settable from here | Non è nell'elenco consentito; --config senza --set stampa settable |
'…' did not save — it still reads back unchanged | La modifica non è atterrata; controllate i permessi di scrittura |
Ricette
Raccogliere su ogni account una volta al giorno
for account in alpha beta gamma; do
MERCY_SF_PASSWORD="$(pass mercy/$account)" \
mercy-cli --claim --user "$account" --character Hero || echo "failed: $account"
doneTenere aggiornato un riquadro della dashboard
MERCY_SF_PASSWORD='…' mercy-cli --status --user someone --character Hero --watch 60Un accesso, un oggetto al minuto. Non rilanciatelo invece da cron ogni minuto: quello è un accesso nuovo ogni volta.
Registrare gli eventi su file
MERCY_SF_PASSWORD='…' mercy-cli --start --user someone --character Hero --events \
>> events.ndjsonControllare con cosa state parlando prima di accedere
api=$(mercy-cli --version | jq -r .api)
[ "$api" = "1" ] || { echo "unknown contract version: $api"; exit 1; }Come servizio systemd
[Service]
Environment=MERCY_SF_PASSWORD=…
ExecStart=/usr/local/bin/mercy-cli --start --user someone --all --events
Restart=on-failure
KillSignal=SIGTERMSIGTERM lascia concludere la mossa in corso. Per favore non usate SIGKILL.
Cosa non fa ancora
Avviare più personaggi e fermarli singolarmente (--all li avvia tutti e li ferma tutti insieme), un canale di controllo verso un processo in esecuzione, e cambiare qualsiasi cosa oltre agli interruttori dei moduli.
Se vi serve una di queste, dite quale: è più facile costruire la cosa giusta che tirare a indovinare e vederla inutilizzata.