mops-cli について
mops-cliは、Motoko開発者向けのプロジェクトワークフローガイドです。設定、依存関係、チェック、ビルド、Lintを扱い、Canister中心の設定と安定変数の互換性確認を重視します。
主な機能
- 01mops.tomlでCanisterとツールチェーンを設定
- 02依存関係とロックファイルを管理
- 03型チェック、Lint、安定性互換性チェック
- 04CanisterのビルドとCandidインターフェース生成
活用シーン
- 01Motokoプロジェクトの初期設定とコンパイラ固定
- 02デプロイ前のCanister変更の検証
- 03CIで依存関係ロックを維持
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dfinity/ icskills --skill mops-cliインストール後、Claude Code で/mops-cliを入力して読み込まれたか確認します。
詳細
Mops CLI
Motoko プロジェクト向けの独自のガイドです。プロジェクト設定、依存関係の管理、型チェック、ビルド、リンティングについて説明します。
主な原則
- dfx は使用しません — mops は
dfxを呼び出すことも、サポートすることもありません。mops toolchain init、moc-wrapper、mops watch --generate/--deployはありません。常に[toolchain]でmocを固定してください。コンパイルを行うすべてのコマンドでmocが必要です。最新のmocバージョンを固定してください。レプリカテスト、ベンチマーク、または--check-deployを使用する場合は、pocket-icも固定してください。固定されていない場合、これらのコマンドはmops toolchain use pocket-ic 15.0.0と指定したエラーを出します。MOPS_POCKET_IC_URLがすでに起動している PocketIC サーバーを指している場合は、固定する必要はなく、既存の固定設定は警告付きで無視されます。警告を消すために固定設定を追加せず、代わりにこの変数を解除してください。 mo:baseは使用しません — 非推奨です。常にmo:coreを使用してください(import Array "mo:core/Array")。- 設定はすべて
mops.tomlに記述します — カニスター、moc フラグ、ツールチェーンのバージョン、ビルド設定を含みます。 - カニスター中心のワークフロー — すべてのカニスターを
[canisters]で定義してください。mops checkにファイルパスを渡さないでください。例外として、ライブラリパッケージ([canisters]がない場合)はファイルパスを直接使用します:mops check src/**/*.mo
プロジェクトのセットアップ
最小限の mops.toml
[toolchain]
moc = "1.15.1"
lintoko = "0.11.0"
pocket-ic = "15.0.0" # required for replica tests / benchmarks / --check-deploy
[dependencies]
core = "2.6.1"
[moc]
args = ["--default-persistent-actors", "-W=M0223,M0236,M0237"]
[canisters.backend]
main = "src/backend/main.mo"
[canisters.backend.migrations]
chain = "src/backend/migrations"
# check-limit = 10 # optional — speeds up `mops check` when the chain gets long
[canisters.backend.check-stable]
path = "deployed/backend.most"
[build]
outputDir = "src/backend/dist"
args = ["--release"]
# check-wasm = true # optional: analyze final Wasm complexity
# check-deploy = true # optional: verify fresh PocketIC installation after build
# Opt-in Wasm optimization (Binaryen wasm-opt) for build + bench
[optimize]
# level = "O3" # default
# keep-names = true # default
# wasm-opt pin: [toolchain] wasm-opt = "131" (required when [optimize] is set)
check-stable は、ICP のアップグレード時に行われる安定変数の互換性チェックをローカルで実行します。そのため、互換性のない変更があると、稼働中のカニスターのアップグレード時に拒否されるのではなく、mops check で失敗します。現在のコードと、デプロイ済みバージョンの .most を比較します。
この .most を初期化します。新しいプロジェクトの場合は mops deployed init(空のアクターを基準として使用)を実行します。すでにデプロイ済みのカニスターの場合は、デプロイ済みのコミットからビルドし、その後 mops deployed を実行します。デプロイのたびに mops deployed を実行して、直前にビルドした .most を昇格させてください(以下の mops deployed を参照)。
カニスターのオプションフィールド:candid(互換性チェック用の .did へのパス)、initArg(Candid 形式でエンコードされた初期化引数)。
警告フラグ
-W=M0223,M0236,M0237 — 冗長な型のインスタンス化(M0223)、コンテキストに応じたドット記法の提案(M0236)、冗長な明示的引数の提案(M0237)。デフォルトでは使用が許可されています(無効化されています)。-W= を指定すると、警告として有効になります。
Moc 引数の適用順序
フラグは次の順序で適用されます(後の設定が前の設定を上書きします)。
[moc].args— グローバル設定。すべてのコマンドに適用されます(check、build、test、bench など)。[build].args— build のみに適用されます(例:--release)。[canisters.<name>.migrations]—--enhanced-migrationを自動的に挿入します(mops が管理)。[canisters.<name>].args— カニスターごとの設定。- CLI
-- <flags>— その場限りの上書き。mops check、mops build、mops check-stable、mops generate、mops migrate、mops test、mops benchでサポートされています。
基本コマンド
mops install
mops install # dev flow: keeps mops.lock in sync, self-heals a broken one
mops install --locked # CI flow: fail if mops.lock is missing or would change
クローン後、または mops.toml を手動で編集した後に実行します。mops.lock は常に維持されます。無効にするフラグはなく、--lock フラグもありません(v3 で削除されました)。mops.toml と整合しないロック、存在しないロック、解析できないロック、旧形式のロックは、通常の mops install によって再生成されます。これには、古い CLI による絶対ローカルパスが残っているロックや、推移的依存関係が失われたロック(ロックされたパッケージが依存関係を宣言しているのに、deps に記載されていない場合。通常はマージの失敗が原因です)も含まれます。
--locked は最新のロックを要求し、ロックへの書き込みは行いません。また、暗黙的にインストールを行うすべてのコマンド(mops build、mops check、mops check-stable、mops check-candid、mops test、mops bench、mops generate candid)でも使用できるため、CI では事前にインストールせずに mops test --locked を実行できます。mops sources には --locked がありません(packtool の呼び出し元はビルド中に標準出力を解析するためです)。その代わりに、パイプラインの前の段階で mops install --locked を実行してください。
CI 環境変数は、ロックファイルの動作に影響しなくなりました(v3 で削除されました)。アプリケーションでもライブラリでも、mops.lock をコミットしてください。
ローカルの path 依存関係の mops.toml が変更された場合(依存関係のチェーンのさらに下にあるものも含む)、ロックは古くなります。mops install はロックを再生成します。--locked は、再生成されたロックをコミットするまで失敗します。アップグレード後に初めて mops install を実行すると、path 依存関係を持つプロジェクトのロックが再生成されます。そのため、CI で --locked を実行する前にコミットしてください。path 依存関係のないプロジェクトでは、既存のロックがそのまま維持されます。
path 依存関係内の {MOPS_ENV} は $MOPS_ENV(デフォルトは local)に展開されるため、ロックは環境ごとに異なります。MOPS_ENV を切り替えるとロックは古くなります。mops install はロックを再生成し、--locked は MOPS_ENV を示すメッセージとともに失敗します。環境ごとにロックを用意するか、--locked を使わないでください。ある MOPS_ENV のもとで生成されたロックは、別の MOPS_ENV での --locked を満たしません。
整合性の検証はダウンロード時に行われるため、mops install は .mops/ の再ハッシュを行わなくなりました。依存関係を直接編集しても、次回のインストールは失敗しません。必要に応じて、mops verify でディスク上の監査を実行してください。
ダウンロードしたファイルは、キャッシュに入る前に必ず検証されます。検証には、パッケージが mops.lock に記録されている場合はそのロックが、それ以外の場合はレジストリが使われます。そのため、コミット済みのロックがあれば検証の負担がなく、クリーンチェックアウトからのインストール時にハッシュについてレジストリへ問い合わせる必要はありません。
知っておくべき点が 2 つあります。破損した、または手動編集された mops.lock があると、ダウンロードは失敗します(エラーでは mops.lock が原因の可能性として示されます。バージョン管理から復元してください。すでにキャッシュにあるパッケージには影響しません)。また、レジストリがハッシュを公開していないパッケージも、警告を出したうえで検証されずにインストールされます。
パッケージは、上限付きのプールを使って並列にダウンロードされます。mops install --concurrency <n> または MOPS_CONCURRENCY 環境変数(インストールを行うすべてのコマンドで有効)で、同時に行うレジストリリクエストの数を制限できます。デフォルト値は CPU 数とファイルディスクリプターのソフトリミットに基づいて決まり、4~16 です。一時的なネットワークエラー(fetch failed、ECONNRESET、EMFILE)が発生した場合、同時実行数を半分にして最大 2 回まで自動で再試行します。再試行後もインストールに失敗する場合(たとえば、送信プロキシが接続数を制限している場合)にのみ、MOPS_CONCURRENCY=1 を設定してください。
mops verify
mops verify # re-hash .mops/ against mops.lock, and mops.lock against the registry
GitHub 依存関係とレジストリ依存関係の両方を対象にします。
問題のあるファイルと復旧方法のヒントを表示して、終了コード 1 で終了します。これは、.mops/ が変更されていると mops install が失敗することを前提にしていた場合の代替コマンドです。
mops add <package>
mops add core # latest version
mops add [email protected] # specific version
mops add --dev test # dev dependency
mops add org/repo # GitHub shorthand (also accepts a full github.com url)
mops add ./pkg # local package directory
mops.toml と mops.lock を更新します。
追加しようとするパッケージがすでに別のセクションで宣言されている場合、重複して宣言するのではなく、セクション間で移動します。<pkg>@<version> は宣言済みのバージョンを置き換え、置き換えた内容を報告します。"[email protected]" = "1.0.0" のような固定エイリアスはそのまま維持されます。固定エイリアスを作成するフラグはないため、手動で記述してください。
mops check
基本的な正当性チェックを行うコマンドです。moc check を実行し、設定されている場合は check-stable を、その後ツールチェーンに lintoko が含まれている場合は lint を実行します。
moc 1.15.0 以降では、[migrations] があるカニスターに対して、より厳格なアップグレード診断が行われます。初期アクターが必要とするフィールドを生成するマイグレーションがない場合、警告(M0254)だけではなく、M0267 エラーになります。また、互換性エラーにはソース位置が表示されます。古い moc のバージョンを固定している場合や、[migrations] がないカニスターには、どちらの場合も影響しません。
check-stable のベースラインは常に .most ファイルです。[canisters.<name>.check-stable].path として指定するか、mops check-stable <baseline.most> の引数として指定します。.mo ソースは拒否されます。ベースラインの取得元については、mops deployed を参照してください。新規プロジェクトと、すでにデプロイ済みのカニスターでは取得元が異なります。
mops check # all canisters
mops check backend # single canister
mops check --fix # autofix + check + stable + lint
mops check --no-lint # skip the lint step for one run
mops check --verbose # show moc invocations
mops check -- -Werror # treat warnings as errors
ファイルパスではなく、必ずカニスター名を使用してください。 mops.toml のカニスターごとの引数は自動的に適用されます。
--fix は、moc と lintoko の両方で機械的に適用できる修正を一度に適用します。複数のプロセスから同時に --fix を実行した場合、.mops/fix.lock のアドバイザリロックによって自動的に直列化されるため、同じプロジェクトで複数のエージェントから安全に実行できます。読み取り専用ファイル(凍結されたマイグレーションなど)は警告が表示され、修正は行われません。
mops build
mops build # all canisters
mops build backend # single canister
mops build --verbose # show compiler commands
mops build --check-wasm # analyze final Wasm complexity without PocketIC
mops build --no-check-wasm # skip configured [build].check-wasm once
mops build --check-deploy # verify fresh installation on PocketIC
mops build --no-check-deploy # skip configured [build].check-deploy once
mops build -- --ai-errors # pass extra moc flags
[build].outputDir(デフォルトは .mops/.build)に .wasm、.did、.most ファイルを生成します。
mops.toml に [optimize] がある場合、candid メタデータの生成後に wasm-opt を実行します(デフォルトは -O3 -g)。Binaryen のバージョン固定が必要です。mops toolchain use wasm-opt 131 を実行してください。ビルドコマンドがバージョン固定を書き込むことはありません。また、wasm-opt が失敗するとビルドも失敗します。build または bench に --no-optimize を指定すると、mops.toml を編集せずに、その実行時だけ最適化処理をスキップできます。
--check-wasm または [build].check-wasm = true が有効な場合、Mops は PocketIC を起動せずに、最終的な Wasm に対して高速な Walrus 分析を実行します。関数ごとの IC0505 複雑度が 750,000 未満の場合は何も表示されず、750,000 以上 899,999 以下の場合は早期警告が表示され、900,000 以上の場合は重大な警告が表示されます。MOPS-WASM-COMPLEXITY の出力には、実行可能な関数メトリクス、複雑度への寄与が大きい上位 3 つの要因、および Motoko の修正方法に関するガイダンスが含まれます。この推定によってビルドが失敗することはありません。一度だけ設定済みの分析をスキップするには、--no-check-wasm を使用します。
mops deployed
デプロイ後に実行するフックです。check-stable で使用するディスク上の .most ベースラインを、実際にデプロイされた内容と同期します。
mops deployed init backend # one-time bootstrap: empty-actor baseline + sets [check-stable].path
mops deployed backend # post-deploy: promotes .mops/.build/backend.most → deployed/backend.most
mops deployed # all canisters
デフォルトの出力先は deployed/<name>.most です。mops.toml の [deployed].dir または --dir で変更できます。[build].outputDir(デフォルトは .mops/.build)からビルド済みの .most ファイルを読み込みます。--build-dir で変更できます。ソースの .most がない場合、mops deployed はエラーになります。再生成は行いません。デプロイパイプラインから、デプロイ成功直後に実行してください。
mops generate candid
mops generate candid # all canisters
mops generate candid backend # single canister
mops generate candid backend -o <path> # single canister, ad-hoc path
現在の Motoko ソースから、精選された .did を(再)生成します。[canisters.<name>].candid が設定されている場合は、そのファイルを上書きします。設定されていない場合は、main の隣に <name>.did を書き込み(例:main = "src/Backend.mo" → src/backend.did)、mops.toml の [canisters.<name>].candid を設定します。インターフェイスを変更するたびに実行し、.did と mops.toml を一緒にコミットしてください。mops build と同じ moc 呼び出しを使うため、生成結果は常に mops build のサブタイプチェックに合格します。
mops toolchain
mops toolchain use moc 1.15.1 # pin specific version
mops toolchain use moc latest # pin latest version (non-interactive)
mops toolchain use lintoko 0.11.0 # pin specific version
mops toolchain use pocket-ic 15.0.0 # pin for replica tests / benchmarks / --check-deploy
mops toolchain use wasm-opt 131 # Binaryen for [optimize] (or `latest`)
mops toolchain update moc # update to latest (requires existing [toolchain] entry)
mops toolchain update # update all tools to latest
mops toolchain info <tool> # show release info (latest, pinned, history)
mops toolchain info <tool> --versions # list recent releases, newest first
mops toolchain info <tool> --versions --all # full release history (cache warming)
mops toolchain info <tool> --versions --prerelease # include prereleases
mops toolchain bin moc # print path to binary
pocket-ic のバージョン:9.0.0 以降は、latest を含め、どのバージョンでも固定できます。mops は推奨バージョンの一覧を管理していません。9.0.0 未満に固定すると、移行メッセージとともにエラーになります(それらのバージョンは、mops 3.0.0 で削除された旧クライアントで動作していました)。バージョンを固定していない場合、レプリカテスト/mops bench/--check-deploy/mops toolchain bin pocket-ic は、mops toolchain use pocket-ic 15.0.0 を示すエラーになります。このバージョンは参考情報であり、フォールバックではありません。
エージェント向けの注意:バージョンを指定せずに toolchain use <tool> を実行すると、対話形式の選択画面が開きます。スクリプトやエージェントでは使用しないでください。必ずバージョンまたは latest を指定してください。選択画面、latest、--versions は、いずれもデフォルトで安定版を対象とします。プレリリース版を含めるには --prerelease を指定してください。toolchain update は、そのツールに [toolchain] エントリーがすでにある場合にのみ機能します。toolchain info <tool> --versions は mops.toml がなくても機能します(デフォルトでは GitHub の最初のページが表示されます。全履歴を表示するには --all を指定してください)。
拡張マイグレーション
[canisters.<name>.migrations] が設定されている場合、mops check、mops build、mops check-stable は自動的に --enhanced-migration を挿入します。--enhanced-migration を [canisters.<name>].args に追加しないでください。mops がエラーになります。
マイグレーションファイルは chain ディレクトリ内に直接作成してください。
mops check --fix(または mops check <canister>)でチェーンがコンパイルできることを確認したら、mops build を実行して wasm アーティファクトを生成してください。
ビルドごとに検証するには、mops build --check-deploy を使用するか、[build].check-deploy = true を設定してください。ビルドされた各 Wasm を新しい PocketIC キャニスターにインストールし、モジュールの検証、初期化、インストールの失敗を検出します。[toolchain] pocket-ic(9.0.0 以降のバージョン、またはローカルのバイナリパス)が必要です。または、すでに起動している PocketIC サーバーの URL を MOPS_POCKET_IC_URL に設定してください(この場合、バージョン固定は無視されます)。URL を設定せず、バージョンも固定していない場合、ビルドは mops toolchain use pocket-ic 15.0.0 を示すエラーになります。設定済みの検証を一度だけスキップするには --no-check-deploy を使用してください。このコマンドでは、各キャニスターの initArg を使用します。省略されている場合は () を使用します。キャニスターに正の整数バイト数の wasmMemoryLimit を設定すると、その上限でデプロイを検査できます。PocketIC のエラーはクライアントから提供された内容のまま報告され、インストールの失敗はすべてのキャニスターを対象に収集されます。インストール前に、Mops は一時的な空の actor .most から moc --stable-compatible を実行し、生成された各 .most を検査します。moc が互換性の問題を報告した場合、Mops はコンパイラの診断とともに MOPS-CHECK-DEPLOY-SKIPPED を出力し、そのキャニスターを新しい PocketIC 上で検査しません。条件を満たすほかのキャニスターは引き続き検査されます。スキップされたアップグレードは、代表的なベースライン状態に対して検証してください。
check-limit(任意)は、mops check と mops lint が対象とする最近のチェーンファイルの数を制限します。チェーンが長くなり、古いマイグレーションをすべて再検査するとフィードバックが遅くなる場合に便利です。check-limit は mops build には影響しません。ビルドではチェーン全体をコンパイルします。また、[canisters.<name>.check-stable].path が設定されている場合は、デプロイ済みのベースラインも --stable-baseline で取り込みます。そのため、デプロイ後に適用済みのマイグレーションを編集、削除、または過去の日付に変更すると、ビルドは M0268 で失敗します。これは、check-limit によってそのマイグレーションが折りたたまれた mops check の対象から外れた場合の最後の防止策です。上限が適用されると、mops は対象のファイルを chain ディレクトリの隣にある .migrations-<canister>/ にステージングします(自動的に .gitignore に追加されます)。その場合、moc の診断にこのパスが表示されることがありますが、実際のファイルは同じ名前で chain ディレクトリにあります。
1 回の実行で check-limit を無効にするには、--no-check-limit を使用します(mops check、mops check-stable、mops lint)。たとえば、通常は対象から外れる古いマイグレーションを自動修正するには、mops check --fix --no-check-limit を実行します。mops check と mops check-stable では、--no-check-limit によって保留中のマイグレーションに関する警告も抑制されます。
check-limit が設定されている場合、mops check-stable(および mops check 内の stable チェック)は、保留中のマイグレーション数が上限を超えているかを報告します。互換性チェックに失敗した場合はエラーとして報告され、誤解を招く moc のメッセージに置き換わります。それ以外の場合は警告として報告されます。
mops remove <package>
mops remove core
パッケージが宣言されているセクションから削除します。--dev を指定すると、[dev-dependencies] のみに限定されます。両方のセクションで宣言されているパッケージは、両方から削除されます。
依存関係の管理
mops outdated # list outdated deps (caret-bound); exit 1 if any, 2 if the check failed
mops outdated core # check a single package
mops update # rewrite mops.toml versions within caret bound (no major-version crossing)
mops update core # update specific package within caret bound
mops update --major # allow updates that cross major versions
mops update --patch # restrict to patch bumps only (mutually exclusive with --major)
mops update --verbose # verbose output
mops sync # add missing / remove unused packages
mops sync --dry-run # print what would change, write nothing
mops update は mops.toml を直接書き換えます(cargo update ではなく、cargo upgrade のように動作します)。また、GitHub の依存関係をブランチの先端に再固定します。mops outdated と同様に、実行または完了できない場合は終了コード 2 を返します。たとえば、mops.toml がない場合、宣言されていないパッケージを指定した場合、依存関係の更新に失敗した場合です(ほかの依存関係は引き続き更新されます)。
mops sync には、固定された [toolchain] moc が必要です。moc --print-deps を使ってインポートを読み取ります。test/tests/bench/benchmark ディレクトリからのみインポートされているパッケージは [dev-dependencies] に追加されます。すでに宣言されているパッケージがセクション間で移動することはありません。
その他のコマンド
mops self update
グローバルインストール(npm/pnpm の -g)のみを更新します。PATH 上の mops が新しいバージョンにならなかった場合は失敗します。プロジェクトの依存関係として ic-mops を使用している場合は、代わりに npm i -D ic-mops@<version> を実行してください。
mops publish
mops publish # publish to the registry (runs tests/docs/bench by default)
mops publish --dry-run # same local steps as publish; no registry contact / identity
mops publish --dry-run --no-test --no-docs --no-bench # packaging checks only
mops publish --no-test --no-docs --no-bench
--dry-run は同じローカル公開パイプライン(パッケージングのチェック、ドキュメント、変更履歴、テスト、ベンチマーク)を実行し、最終的なファイル一覧を表示してから、本人確認/アップロードの前に停止します。--no-* フラグは通常どおり使用できます。canister 設定の検証(SPDX/semver/名前のルール)は実行せず、レジストリで受け付けられること(公開済みかどうか、権限、依存関係の不足)も確認しません。
mops test
テストは test/*.test.mo に配置します。
mops test # run all tests
mops test my-test # filter by name
mops test --mode wasi # use wasmtime (for to_candid/from_candid)
mops test --reporter files # one line per file (default is verbose)
mops test --watch # re-run on file changes
mops test -- -Werror # pass extra moc flags
レプリカテスト(アクターファイル、または // @testmode replica)は PocketIC 上で実行されます。[toolchain] の pocket-ic バージョンを使います。ただし、MOPS_POCKET_IC_URL が設定されている場合は、すでに稼働しているサーバーを使います(バージョンの固定は不要です。接続モードでは canister のログ出力はストリーミングされません)。バージョンが固定されておらず、URL も設定されていない場合は、mops toolchain use pocket-ic 15.0.0 というコマンドを示してエラーになります。mops bench と mops watch --test も同様です。--replica フラグや dfx replica はありません。
mops bench
ベンチマークは bench/*.bench.mo に配置します。
mops bench # run all benchmarks
mops bench my-bench # filter by name
mops bench --gc incremental # select GC
mops bench --save # save results to .bench/<name>.json
mops bench --compare # compare with saved results
mops bench -- -Werror # pass extra moc flags
mops lint
lintoko を実行します(toolchain に lintoko が含まれている場合、mops check の一部としても自動実行されます)。
mops lint # lint all .mo files
mops lint --fix # autofix lint issues
mops lint <name> # filter to .mo files matching <name>
[canisters.<name>.migrations].check-limit が設定されている場合、mops lint は、mops check で moc が認識する内容に合わせるため、トリミングされたチェーン移行をスキップします。トリミングされた移行を必要に応じて lint するには、明示的なフィルター(例:mops lint OldMigrationName)または --no-check-limit を指定して、チェーン全体を lint してください。
mops format
mops format # format all .mo files
mops format --check # check formatting without modifying
mops watch
mops watch # errors + warnings + format (the default set)
mops watch --warning # errors + warnings only
mops watch -t # errors + tests
エラーチェックは常に有効です。フラグを指定すると、指定したタスクのみが選択されるため、-t と一緒に実行する場合は -w/-f も追加してください。この4つがすべてであり、--generate や --deploy はありません。
よくあるパターン
canister の警告を抑制する
抑制には、グローバルではなく、canister ごとの args を使用します。
[canisters.backend]
main = "src/backend/main.mo"
args = ["-A=M0198"]
新しいプロジェクト
mops init -y
mops toolchain use moc latest # pin latest moc (non-interactive)
mops toolchain use lintoko latest # pin latest lintoko
mops add core
次に、mops.toml で [moc].args、[canisters]、[build] を設定します。
後でツールを更新するには、mops toolchain update moc または mops toolchain update(すべてのツール)を実行します。