CLI リファレンス、別のプログラムから Mercy SF を動かす
mercy-cli には非対話モードがあります。引数を入れると、JSON オブジェクトが 1 つ出 てきます。ダッシュボード、監視プロセス、スクリプトのためのものです。
このページが約束です。 以下のコマンドと項目名は、予告なく変わることはありませ ん。CLI のそれ以外、メニュー、その文言、出力の体裁は、いつでも変わってよいことにな っているので、そこに依存して作らないでください。
引数なしで実行すれば、対話メニューがこれまでどおり立ち上がります。
すべての応答は "api" を持ちます。今日は 1 です。項目を足してもこれは変わらず、 自分の知っている項目だけを読む呼び出し側は影響を受けません。項目が消えたり意味が変 わったときに上がるので、自分が想定していなかった形に対しては動かない、と決められま す。
ログイン
S&F のシングルサインオン経由で作られたアカウントには、追加で何も要りません。ある サーバーに属していて、シングルサインオンに一度も属さなかったアカウントは、その仕組 みから見れば存在せず、--server が必要です。
mercy-cli --status --user <account> --server https://f1.sfgame.net/--server は以下のすべてのコマンドで使えます。
出力
--start を除くすべてのコマンドは JSON だけを出力するので、--json はすでに既定 であり、渡しても何も変わりません。既定に頼るより明示したい呼び出し側のため、そして そうしなければ人間向けのログを書く --start のために存在します。
読み取り
アカウントのキャラクター一覧
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 }
]
}1 回のログインでアカウントの全キャラクターを、サーバーをまたいで扱えます。そのキャ ラクターの状態を取得できなかった場合 level は null になりますが、項目自体は残り ます。存在することを知ることこそ、この呼び出しの目的だからです。
キャラクター 1 体の状態を読む
mercy-cli --status --user <account> --character <name>アカウントにちょうど 1 体しかいない場合、--character は省けます。
{
"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
}すべては 1 回の状態取得から得られるので、要求する区分もありませんし、少なく頼んで節 約できるものもありません。
キャラクターがギルドに属していない場合 guild は null です。スクラップブックを一 度も読んでいないうちは scrapbook_items は null です。空の装備枠は null として並 べるのではなく、省かれます。
アイテム名について。 プロトコルが運ぶのはモデル ID と枠であって表示名ではないの で、得られるのもそれです。同時にそれは絵の参照先でもあるので、ダッシュボードはデス クトップアプリとまったく同じ絵を描けます。ここで名前を作り出すのは、あなたが確かめ ようのない推測になってしまいます。
一定間隔で読み直す
mercy-cli --status --user <account> --character <name> --watch 60ログインは 1 回、あとはプロセスを止めるまで 60 秒ごとにオブジェクトが 1 つ。ループ でコマンドを再実行するのではなく、こちらを使ってください。実行のたびに新しいログイ ンが起こり、それは 1 つの数字を見張るのにいちばん高くつく方法で、サーバー側からいち ばん目立つ方法でもあります。下限は 30 秒です。失敗した回は出力され、ループは続きま す。最初のしゃっくりで諦める見張りは、何も起きていない見張りとまったく同じに見える からです。
次に誰と戦うか、そしてなぜか
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
}
]
}アプリが描くのと同じ判断です。候補をアイテム、日々の経験値、順位で採点し、勝率を掛 けます。outcome は planned、waiting、blocked、empty のいずれかで、 reason がどれなのかを 1 文で述べます。
これは戦闘もキノコも使いません。ただし候補を探して巡回はするので、要求という意味で は無料ではありません。詰めたループに入れないでください。
戦いの下稽古
mercy-cli --simulate --user <account> --character <name> --against <player>{ "ok": true, "against": "Someone", "against_level": 340, "win_chance": 0.63, "iterations": 1000 }計算です。相手が誰かを知るために照会が 1 回サーバーへ行きますが、戦い自体は決して送 られません。win_chance は決着した戦いに対する勝ち数なので、決着しきれなかったシミ ュレーションは、走らせた回数より少ない件数で報告します。
何を持っているか
mercy-cli --inventory --user <account> --character <name>{ "ok": true, "carried": 12, "backpack": [ { "slot_index": 0, "model_id": 55 } ] }一覧は 1 つです。ゲームが 1 つしか持っていないからです。アイテムの形は --status と同じで、slot_index が加わります。
スクラップブック
mercy-cli --scrapbook --user <account> --character <name>{ "ok": true, "unlocked": true, "owned": 1102, "monsters": 214 }スクラップブックが与えられるレベルより下では unlocked は false で、そこでは owned が null になります。これはエラーではありません。
記録された戦い
mercy-cli --history --user <account> --character <name> --limit 50{ "ok": true, "total": 4210, "returned": 50, "battles": [] }新しいものから。これはボットを走らせたその環境が記録したものであって、サーバーか ら取ってくるものではありません。 ですから起動したばかりのプロセスには見せるものが なく、それは不具合ではありません。total は存在する件数、returned は --limit が残した件数です。
実行
ボットを走らせる
mercy-cli --start --user <account> --character <name>プロセスを止めるまで走り、その間ログを書きます。ここでは --character が必須で す。一覧を出すことや状態を読むことは無害ですが、ボットを起動することはゲームを遊ぶ ことであり、キャラクターを間違えるのは取り消しのきくことではありません。
--all を使うと、代わりにアカウントの全キャラクターをこの 1 プロセスで走らせます。 キャラクターごとに 1 回ではなくアカウントで 1 回のログインになるので安く済み、キャ ラクター同士がセッションを無効化し合うのも防げます。
Ctrl-C(または SIGTERM)では、要求の途中で断ち切るのではなく、現在の手を終えてから プロセスが終了します。
文章ではなくイベント
mercy-cli --start --user <account> --character <name> --events1 行につき JSON オブジェクト 1 つ。監視プロセスは 1 行ずつ読めます。
{"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 は started、stopping、stopped、arena_win、arena_loss、 dungeon_win、dungeon_loss、quest_done、scrapbook_win、scrapbook_loss、 scrapbook_items(count を伴います)のいずれかです。
この一覧は増えます。 知らないイベントはエラーではなく、無視するものとして扱って ください。名前が Rust の出力そのままではなく、はっきり書き出されているのは、まさに そのためです。
人間向けのログを読むのではなく、こちらを使ってください。あのログは人のために書かれ ていて、いつでも書き直されてよいものです。それを解析するということは、誰かが一文を 良くしたときにあなたの道具が壊れる、ということです。
待っているものを回収する
mercy-cli --claim --user <account> --character <name>カレンダー、日課、保留中の解放。--character は必須で、理由は --start と同じで す。
設定を読む、または変える
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 } ] }読み取りは設定全体を config の下に返します。そのブロックの中の項目名はこの約束 に含まれません。 含まれるのは settable に並ぶキーだけです。設定は 100 をゆうに 超える項目があり、リリースごとに増えます。それらすべてを約束するということは、設定 を二度と組み替えられないということです。
--set は true/false、on/off、yes/no、1/0 を受け取り、常に --character を要求し(スイッチは 1 体のキャラクターに属するもので、「唯一の 1 体」は読むぶんに は構わないが書くには誤った推測です)、繰り返し指定できます。値はそのあとディスクか ら読み戻され、書き込まれていなければ呼び出しは失敗します。起きていない変更を報告す ることは、唯一そこから立て直せない結果だからです。
運用
これはどのビルドか
mercy-cli --version{ "ok": true, "version": "2.12.0", "api": 1 }パスワードもネットワークも要らない唯一のコマンドです。監視プロセスは、話すための認 証情報を持つ前に、何と話しているのかを尋ねられなければなりません。
届いているか
mercy-cli --health --user <account> --character <name>{ "ok": true, "character": "Hero", "level": 345, "round_trip_ms": 412 }ログインし、取得し、報告し、終了します。あえて小さくしてあります。キャラクターシー ト全体を返す死活確認は、それを解析したくなるものを招き、そうなれば確認そのものがま た 1 つのインターフェイスになってしまいます。
パスワード
--password のフラグは、意図的にありません。コマンドライン引数はその機械の他のあら ゆるプロセスから読めます。ps、/proc、タスクマネージャー。ですから、これを何人分 も動かすダッシュボードは、その箱にシェルを持つ誰にでも、全員のゲームのパスワードを 渡すことになります。
代わりに 2 つの道があります。
MERCY_SF_PASSWORD='…' mercy-cli --status --user someoneprintf '%s' "$password" | mercy-cli --status --user someone --password-stdin--password-stdin は標準入力の最初の 1 行を読みます。これなら秘密は環境変数にも残 りません。
終了コード
| コード | 意味 |
|---|---|
0 | 成功、および --help のとき |
1 | 実行して失敗した。理由は error にあり、ok は false |
2 | 呼び出しが誤り。未知のオプション、値の欠落、アクション指定なし。stderr に出ます |
1 と 2 の違いは監視プロセスにとって意味があります。2 は毎回同じように失敗し、人の手 が要ります。1 は次の試行でうまくいくかもしれません。
エラー
失敗も JSON なので、1 つのパーサーで両方さばけます。
{ "ok": false, "error": "no character called 'Typo' on this account" }ok はすべての応答にあります。何よりも先にそれを確かめてください。
よくある原因:
| メッセージ | どうするか |
|---|---|
--user is required | --user がない(--version を除くすべてのアクション) |
--start needs --character (or --all) | 対象を指定してください。推測はしません |
this account has N characters — name one with --character | 複数あります。1 体を選んでください |
no character called '…' on this account | 綴り違い。--characters が有効な名前を出します |
no password: set MERCY_SF_PASSWORD or pass --password-stdin | パスワードの 2 つの道のどちらかを選んでください |
login failed: … | 認証情報かサーバーを確認。シングルサインオン外のアカウントには --server が必要です |
'…' is not settable from here | 許可一覧にありません。--set なしの --config が settable を出します |
'…' did not save — it still reads back unchanged | 変更が書き込まれていません。書き込み権限を確認してください |
レシピ
すべてのアカウントで 1 日 1 回まとめて回収する
for account in alpha beta gamma; do
MERCY_SF_PASSWORD="$(pass mercy/$account)" \
mercy-cli --claim --user "$account" --character Hero || echo "failed: $account"
doneダッシュボードのタイルを最新に保つ
MERCY_SF_PASSWORD='…' mercy-cli --status --user someone --character Hero --watch 60ログインは 1 回、1 分に 1 オブジェクト。代わりに cron から毎分これを回さないでくだ さい。それは毎回新しいログインです。
イベントをファイルに記録する
MERCY_SF_PASSWORD='…' mercy-cli --start --user someone --character Hero --events \
>> events.ndjsonログインする前に、何と話しているかを確かめる
api=$(mercy-cli --version | jq -r .api)
[ "$api" = "1" ] || { echo "unknown contract version: $api"; exit 1; }systemd のサービスとして
[Service]
Environment=MERCY_SF_PASSWORD=…
ExecStart=/usr/local/bin/mercy-cli --start --user someone --all --events
Restart=on-failure
KillSignal=SIGTERMSIGTERM なら現在の手を終えられます。SIGKILL は使わないでください。
まだできないこと
複数のキャラクターを起動して個別に止めること(--all は全部を起動し、全部をまとめ て止めます)、動作中のプロセスへの制御チャンネル、そしてモジュールのスイッチを超え た変更。
そのどれかが必要なら、どれなのか教えてください。当て推量で作って使われないままにす るより、正しいものを作るほうが簡単です。