The tmc CLI - The Modding Community

まだ未リリース

tmc は、私たちの公開コンテンツ API のためのコマンドラインクライアントです。アセット、MOD、サーバー、記事、コミュニティ、コレクション、グループの作成・編集・削除ができ、API が実際に使われている用途そのものとして、ファイルのアップロードとリリースの公開を 1 コマンドで行えます。

Python 3.10+依存関係ゼロMIT ライセンス

tmc はまだリリースされていません。 PyPI にはなく、公開リポジトリもありません — 現時点ではソースのチェックアウトからインストールします。このページはローンチの告知ではなく、このツールがすでにできることを説明しています。

install.sh
# From the source checkout — there is nothing to build
pip install .
pip install '.[fast]'   # optional: cryptography, for faster signing
tmc --version       # tmc 1.1.0

# Keys are made under Account → API Keys
tmc auth login --token tmc_xxxxxxxxxxxx
tmc auth whoami

# …or read public items with no key at all
tmc mod list --anon --app 4 -o json

標準ライブラリだけの単一パッケージなので、ビルドするものも解決すべき依存もありません — そしてすべてのコマンド、フラグ、終了コードはドキュメントに書かれています。

リリース

そもそもツールを持つ理由

素の API でリリースを切るには、決まった順序で 4 つのリクエストが要ります。ファイルをアップロードし、その id を集め、すでにあるリリース集合を読み、ほかを乱さずに新しいものを書き戻す。release publish はその一連の流れそのものです。

publish.sh
# Upload the files, attach them, write the release — one command
tmc release publish --mod 5 \
  --version 1.2.0 \
  --title "Bug fixes" \
  --content-file CHANGELOG.md \
  --file 'dist/*.zip' --file dist/checksums.txt

# Everything on the item, without re-sending the item
tmc release list  --mod 5
tmc release files --mod 5 --version 1.2.0

再実行すれば更新になります

同じ --version を 2 回指定すると、そのリリースが更新され、新しいファイルがその集合にマージされます。ほかのリリースは決して触られず、非公開のリリースは非公開のままです。

グロブをまとめて

--file 'dist/*.zip' のように、いくつでもファイルを渡せます。1 リクエストあたり 20 件というアップロード上限はこちらで処理します。

大きなファイルはストリーミング

1 GB のアップロードはメモリにではなく、ディスクからチャンク単位で読み出されます。キーのサイズ上限を超えるものは送信前に指摘されます。
できること

API にできることすべてを、明示的に

ブラウザでやるであろう操作ごとに 1 つのコマンド。そしてブラウザではやりたくないいくつか — 一括編集、パイプライン、スクリプト化したリリースも。

依存関係は一切なし

Python 3.10+ と標準ライブラリだけ。パッケージインデックスのないビルドマシンやゲームサーバーに置いても動きます。署名にはインストール済みであれば cryptography を、なければ同梱の RFC 8032 実装を使います — どちらでも署名は同じです。

両方の認証方式

Bearer tmc_ キー、または Ed25519 署名アサーション。後者では秘密鍵はあなたが持ち、私たちは公開鍵の側だけを保管します。

すべての型に共通の文法

同じ 5 つの動詞 — list、get、create、update、delete — が 14 の型すべてに使え、そのうち 12 は専用コマンドを持ちます。tmc content <type> が統一形式であり、独立した release と media 型に到達する唯一の道でもあります。

送り直さずに関連を操作

タグ、メディア、リリース、リンク、ソース、コレクション項目はそれぞれ独立して管理されるので、スクリーンショットを 1 枚足すのにアイテム全体を書き直す必要はありません。

一括処理、すべての上限の内側で

長さを問わない JSON ファイルから作成・編集できます。サーバー側の上限 — 書き込み 25 件、削除 100 件、関連メンバー 200 件、関連削除時のキー 500 件、アップロード 20 パート — はすべて自動で分割され、部分的な失敗では失敗した要素が示されるので、最初からやり直さず再開できます。

タイプミスはローカルで検出

フィールド名は API スキーマのローカルミラーと照合され、近い候補も示されます: 'mod' に 'tgs' というフィールドはありません。'tags' のことでしょうか? tmc schema mod は照合に使っているフィールド一覧を表示します。

パイプ向けに設計

7 つの出力形式 — table、json、jsonl、csv、tsv、yaml、ids — に加え、必要な列だけを残す --field。データは stdout、進捗は stderr に出力され、いま使っているシェル向けに tmc completion bash|zsh|fish も用意されています。

レート制限を自動処理

429 は API が求めるとおりの時間だけ待ち、上限は --retry-wait-max です。ビルドを無言でぶら下げるのではなく、あとどれだけ待つかを伝えます。バックオフは冪等なメソッドにのみ適用され、POST が黙って再送されることはありません。
資格情報

キー、プロファイル、そして公開鍵の側

一度ログインすれば、資格情報はモード 0600 で ~/.config/tmc/config.json に保存されます — あるいは環境変数で渡せば、ディスクには一切触れません。サイトごと・キーごとに 1 プロファイル。そして、そもそもキーの要らない半分の API 向けに --anon があります。

auth.sh
# A bearer key, or an Ed25519 key you hold the private half of
tmc auth login --token tmc_xxxxxxxxxxxx
tmc auth login --jwt --key-id tmcak_xxxxxxxx --private-key ~/keys/tmc.pem

# A second key on the same site — a scoped one for scripts
tmc auth login --profile ci \
  --base-url https://moddingcommunity.com --token tmc_…
tmc auth use ci

# Which key is active, and what the server lets it do
tmc auth whoami
tmc auth doctor

# …or no key at all
tmc mod list --anon --app 4 -o json

サイトごと、キーごとのプロファイル

--profile で 1 つを指定し、tmc auth use で既定を切り替えます。保存されるすべての値には環境変数の相方があります — TMC_TOKEN、TMC_KEY_ID、TMC_PRIVATE_KEY_FILE、TMC_BASE_URL、TMC_PROFILE。

そのキーに本当に何ができるかを尋ねる

auth whoami は、意図的に無害な 3 つのプローブ — 読み取り、検証に通らない作成、空の id リストに対する削除 — でキーの実際の権限を確かめます。何も作られず、何も削除されません。--read-only なら読み取りだけを送ります。

設定のためのドクター

auth doctor は、どの署名バックエンドが使われているか、設定ファイルのパーミッションが安全か、そしてサイトがそもそも応答するかを報告します — パイプラインをデバッグする前に知っておきたい 3 点です。

キーなしで読む

--anon は 7 つの型の公開サマリーを Authorization ヘッダーなしで読みます。これは本当に別のエンドポイントなので、書き込みはリクエストが出る前に拒否され、その面が持たないフィルタは一致したかのように見せずに捨てられ、保存済みのキーへ黙って昇格することもありません。--set apiPublic=false がアイテムをそこから外す方法です。
関連

動作どおりの名前を持つ 4 つの動詞

危険なのは set です。この API では関連への PUT は「これが完全な集合である」という意味なので、メンバー 1 件の PUT はそのアイテムのほかすべてを削除します。CLI はこの 4 つを区別し、破壊的なものを送る前に警告します。

コマンド メソッド 意味
tmc rel add POST これらを追加し、ほかはそのまま
tmc rel set PUT これが完全な集合になる
tmc rel rm DELETE 指定したものを外す
tmc rel clear DELETE すべて外す
relations.sh
# Add two tags. The rest of the item is untouched
tmc tags add mod 5 pvp vanilla

# Upload a screenshot and attach it in one step
tmc media add mod 5 --file shot.png --title Screenshot

# Read one relation back
tmc rel get mod 5 releases

# …and the one that REPLACES the whole gallery
tmc rel set mod 5 media --from-file gallery.json
自動化

CI で生きるために作られました

プロジェクトをビルドし、リリースを切り、タグごとにファイルをアップロード。資格情報は環境変数から来るので、ランナーのディスクには何も書かれません。

release.yml
- name: Publish to TMC
  env:
    TMC_TOKEN: ${{ secrets.TMC_TOKEN }}
  run: |
    tmc release publish --mod 42 \
      --version "${GITHUB_REF_NAME#v}" \
      --content-file CHANGELOG.md \
      --file 'dist/*.zip'

# Clean pipes: data on stdout, progress on stderr
tmc mod list --mine --all -o ids | xargs -n1 tmc mod get -o json

ランナーに何も書きません

資格情報は環境変数から取得されるため、プロファイルは作られず、ジョブより長く残るものもありません。JWT キーはランナーがマウントするシークレットファイルのままで構いません — 私たちが持つのはつねに公開鍵の側だけです。

意味のある終了コード

2 使い方、3 認証、4 見つからない、5 検証、6 レート制限、7 サーバー、8 ネットワーク — パイプラインが「再試行すべき」と「キーを直すべき」を区別できます。

古いビルドに足止めされません

ツールがまだ知らないフィールドも --allow-unknown-fields で通りますし、tmc raw ならどんなリクエストでも送れます。

本物を相手にテスト

75 個のテストが、実際のソケット越しにプロセス内の API モックへ本物の CLI を走らせます — 両方の認証方式、バッチ処理、関連のセマンティクス、リトライ経路まで。

キーは アカウント → API キー にあります

キーは無料で、すぐ作れます。読み取り/書き込み/削除のスコープ、有効期限、IP 許可リスト、そして独自のレート制限を持つので、ビルドサーバーに渡すキーにはただ 1 つのことだけをさせられます。すべてのコマンド、フラグ、終了コードはドキュメントに書かれています。

キーは今日から役に立ちます — API は稼働中で、ドキュメントも書かれています。tmc 自体はまだ未リリースで、PyPI パッケージも公開リポジトリもないため、それが変わるまではソースのチェックアウトです。