Skip to content

CLI リファレンス、別のプログラムから Mercy SF を動かす

mercy-cli には非対話モードがあります。引数を入れると、JSON オブジェクトが 1 つ出 てきます。ダッシュボード、監視プロセス、スクリプトのためのものです。

このページが約束です。 以下のコマンドと項目名は、予告なく変わることはありませ ん。CLI のそれ以外、メニュー、その文言、出力の体裁は、いつでも変わってよいことにな っているので、そこに依存して作らないでください。

引数なしで実行すれば、対話メニューがこれまでどおり立ち上がります。

すべての応答は "api" を持ちます。今日は 1 です。項目を足してもこれは変わらず、 自分の知っている項目だけを読む呼び出し側は影響を受けません。項目が消えたり意味が変 わったときに上がるので、自分が想定していなかった形に対しては動かない、と決められま す。


ログイン

S&F のシングルサインオン経由で作られたアカウントには、追加で何も要りません。ある サーバーに属していて、シングルサインオンに一度も属さなかったアカウントは、その仕組 みから見れば存在せず、--server が必要です。

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

--server は以下のすべてのコマンドで使えます。

出力

--start を除くすべてのコマンドは JSON だけを出力するので、--json はすでに既定 であり、渡しても何も変わりません。既定に頼るより明示したい呼び出し側のため、そして そうしなければ人間向けのログを書く --start のために存在します。


読み取り

アカウントのキャラクター一覧

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 }
  ]
}

1 回のログインでアカウントの全キャラクターを、サーバーをまたいで扱えます。そのキャ ラクターの状態を取得できなかった場合 levelnull になりますが、項目自体は残り ます。存在することを知ることこそ、この呼び出しの目的だからです。

キャラクター 1 体の状態を読む

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

アカウントにちょうど 1 体しかいない場合、--character は省けます。

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
}

すべては 1 回の状態取得から得られるので、要求する区分もありませんし、少なく頼んで節 約できるものもありません。

キャラクターがギルドに属していない場合 guildnull です。スクラップブックを一 度も読んでいないうちは scrapbook_itemsnull です。空の装備枠は null として並 べるのではなく、省かれます。

アイテム名について。 プロトコルが運ぶのはモデル ID と枠であって表示名ではないの で、得られるのもそれです。同時にそれは絵の参照先でもあるので、ダッシュボードはデス クトップアプリとまったく同じ絵を描けます。ここで名前を作り出すのは、あなたが確かめ ようのない推測になってしまいます。

一定間隔で読み直す

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

ログインは 1 回、あとはプロセスを止めるまで 60 秒ごとにオブジェクトが 1 つ。ループ でコマンドを再実行するのではなく、こちらを使ってください。実行のたびに新しいログイ ンが起こり、それは 1 つの数字を見張るのにいちばん高くつく方法で、サーバー側からいち ばん目立つ方法でもあります。下限は 30 秒です。失敗した回は出力され、ループは続きま す。最初のしゃっくりで諦める見張りは、何も起きていない見張りとまったく同じに見える からです。

次に誰と戦うか、そしてなぜか

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
    }
  ]
}

アプリが描くのと同じ判断です。候補をアイテム、日々の経験値、順位で採点し、勝率を掛 けます。outcomeplannedwaitingblockedempty のいずれかで、 reason がどれなのかを 1 文で述べます。

これは戦闘もキノコも使いません。ただし候補を探して巡回はするので、要求という意味で は無料ではありません。詰めたループに入れないでください。

戦いの下稽古

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

計算です。相手が誰かを知るために照会が 1 回サーバーへ行きますが、戦い自体は決して送 られません。win_chance は決着した戦いに対する勝ち数なので、決着しきれなかったシミ ュレーションは、走らせた回数より少ない件数で報告します。

何を持っているか

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

一覧は 1 つです。ゲームが 1 つしか持っていないからです。アイテムの形は --status と同じで、slot_index が加わります。

スクラップブック

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

スクラップブックが与えられるレベルより下では unlockedfalse で、そこでは ownednull になります。これはエラーではありません。

記録された戦い

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

新しいものから。これはボットを走らせたその環境が記録したものであって、サーバーか ら取ってくるものではありません。 ですから起動したばかりのプロセスには見せるものが なく、それは不具合ではありません。total は存在する件数、returned--limit が残した件数です。


実行

ボットを走らせる

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

プロセスを止めるまで走り、その間ログを書きます。ここでは --character必須で す。一覧を出すことや状態を読むことは無害ですが、ボットを起動することはゲームを遊ぶ ことであり、キャラクターを間違えるのは取り消しのきくことではありません。

--all を使うと、代わりにアカウントの全キャラクターをこの 1 プロセスで走らせます。 キャラクターごとに 1 回ではなくアカウントで 1 回のログインになるので安く済み、キャ ラクター同士がセッションを無効化し合うのも防げます。

Ctrl-C(または SIGTERM)では、要求の途中で断ち切るのではなく、現在の手を終えてから プロセスが終了します。

文章ではなくイベント

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

1 行につき JSON オブジェクト 1 つ。監視プロセスは 1 行ずつ読めます。

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"}

eventstartedstoppingstoppedarena_winarena_lossdungeon_windungeon_lossquest_donescrapbook_winscrapbook_lossscrapbook_itemscount を伴います)のいずれかです。

この一覧は増えます。 知らないイベントはエラーではなく、無視するものとして扱って ください。名前が Rust の出力そのままではなく、はっきり書き出されているのは、まさに そのためです。

人間向けのログを読むのではなく、こちらを使ってください。あのログは人のために書かれ ていて、いつでも書き直されてよいものです。それを解析するということは、誰かが一文を 良くしたときにあなたの道具が壊れる、ということです。

待っているものを回収する

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

カレンダー、日課、保留中の解放。--character は必須で、理由は --start と同じで す。

設定を読む、または変える

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 } ] }

読み取りは設定全体を config の下に返します。そのブロックの中の項目名はこの約束 に含まれません。 含まれるのは settable に並ぶキーだけです。設定は 100 をゆうに 超える項目があり、リリースごとに増えます。それらすべてを約束するということは、設定 を二度と組み替えられないということです。

--settrue/falseon/offyes/no1/0 を受け取り、常に --character を要求し(スイッチは 1 体のキャラクターに属するもので、「唯一の 1 体」は読むぶんに は構わないが書くには誤った推測です)、繰り返し指定できます。値はそのあとディスクか ら読み戻され、書き込まれていなければ呼び出しは失敗します。起きていない変更を報告す ることは、唯一そこから立て直せない結果だからです。


運用

これはどのビルドか

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

パスワードもネットワークも要らない唯一のコマンドです。監視プロセスは、話すための認 証情報を持つ前に、何と話しているのかを尋ねられなければなりません。

届いているか

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

ログインし、取得し、報告し、終了します。あえて小さくしてあります。キャラクターシー ト全体を返す死活確認は、それを解析したくなるものを招き、そうなれば確認そのものがま た 1 つのインターフェイスになってしまいます。


パスワード

--password のフラグは、意図的にありません。コマンドライン引数はその機械の他のあら ゆるプロセスから読めます。ps/proc、タスクマネージャー。ですから、これを何人分 も動かすダッシュボードは、その箱にシェルを持つ誰にでも、全員のゲームのパスワードを 渡すことになります。

代わりに 2 つの道があります。

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

--password-stdin は標準入力の最初の 1 行を読みます。これなら秘密は環境変数にも残 りません。


終了コード

コード意味
0成功、および --help のとき
1実行して失敗した。理由は error にあり、okfalse
2呼び出しが誤り。未知のオプション、値の欠落、アクション指定なし。stderr に出ます

1 と 2 の違いは監視プロセスにとって意味があります。2 は毎回同じように失敗し、人の手 が要ります。1 は次の試行でうまくいくかもしれません。


エラー

失敗も JSON なので、1 つのパーサーで両方さばけます。

json
{ "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 なしの --configsettable を出します
'…' did not save — it still reads back unchanged変更が書き込まれていません。書き込み権限を確認してください

レシピ

すべてのアカウントで 1 日 1 回まとめて回収する

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

ダッシュボードのタイルを最新に保つ

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

ログインは 1 回、1 分に 1 オブジェクト。代わりに cron から毎分これを回さないでくだ さい。それは毎回新しいログインです。

イベントをファイルに記録する

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

ログインする前に、何と話しているかを確かめる

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

systemd のサービスとして

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

SIGTERM なら現在の手を終えられます。SIGKILL は使わないでください。


まだできないこと

複数のキャラクターを起動して個別に止めること(--all は全部を起動し、全部をまとめ て止めます)、動作中のプロセスへの制御チャンネル、そしてモジュールのスイッチを超え た変更。

そのどれかが必要なら、どれなのか教えてください。当て推量で作って使われないままにす るより、正しいものを作るほうが簡単です。

Mercy SF は Shakes & Fidget および Playa Games とは無関係です。ご利用は自己責任でお願いします。