Skip to main content

mops-cli

Manage Motoko projects with the mops CLI — toolchain pinning, dependency management, type-checking, building, and linting. Use when working with mops.toml, mops.lock, running mops commands, adding/removing packages, pinning moc or lintoko versions, checking or building canisters, configuring moc flags, or setting up a new Motoko project.

跳到安装

来源信息

仓库
dfinity/icskills
最近来源活动
2026年9月8日 10:07
检测到的 SKILL.md 语言
英语
星标
35
分支
13

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
mops-cli
description
Manage Motoko projects with the mops CLI — toolchain pinning, dependency management, type-checking, building, and linting. Use when working with mops.toml, mops.lock, running mops commands, adding/removing packages, pinning moc or lintoko versions, checking or building canisters, configuring moc flags, or setting up a new Motoko project.
license
Apache-2.0
compatibility
mops >= 3.2.0
metadata
{"title":"Mops CLI","category":"Infrastructure"}
# Mops CLI Opinionated guide for Motoko projects. Covers project config, dependency management, type-checking, building, and linting. ## Key Principles 1. **No dfx** — mops neither invokes nor supports `dfx`. There is no `mops toolchain init`, no `moc-wrapper`, and no `mops watch --generate` / `--deploy`. Always pin `moc` in `[toolchain]`; every command that compiles requires it. Use the newest `moc` version. Pin `pocket-ic` too if you have replica tests, benchmarks, or `--check-deploy` — with no pin those commands error, naming `mops toolchain use pocket-ic 15.0.0`. When `MOPS_POCKET_IC_URL` points at an already-running PocketIC server, no pin is needed and an existing pin is ignored with a warning — do not add one to silence it; unset the variable instead. 2. **No `mo:base`** — it is deprecated. Always use `mo:core` (`import Array "mo:core/Array"`). 3. **All config in `mops.toml`** — canisters, moc flags, toolchain versions, build settings. 4. **Canister-centric workflow** — define all canisters in `[canisters]`; never pass file paths to `mops check`. Exception: library packages (no `[canisters]`) use file paths directly: `mops check src/**/*.mo`. ## Project Setup ### Minimal `mops.toml` ```toml [toolchain] moc = "1.7.0" lintoko = "0.10.0" pocket-ic = "15.0.0" # required for replica tests / benchmarks / --check-deploy [dependencies] core = "2.5.0" [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` runs ICP's upgrade-time stable-variable compatibility check locally, so incompatible changes fail in `mops check` instead of being rejected when upgrading a live canister. It compares the current code against a `.most` from the deployed version. Bootstrap that `.most`: new project → `mops deployed init` (empty-actor baseline); already-deployed canister → build from the deployed commit, then `mops deployed`. After every deploy, run `mops deployed` to promote the just-built `.most` (see [`mops deployed`](#mops-deployed) below). Optional canister fields: `candid` (path to .did for compatibility checking), `initArg` (Candid-encoded init args). ### Warning Flags `-W=M0223,M0236,M0237` — redundant type instantiation (M0223), suggest contextual dot notation (M0236), suggest redundant explicit arguments (M0237). These are allowed (disabled) by default; `-W=` enables them as warnings. ### Moc Args Layering Flags are applied in this order (later overrides earlier): 1. `[moc].args` — global, all commands (check, build, test, bench, etc.) 2. `[build].args` — build only (e.g. `--release`) 3. `[canisters.<name>.migrations]` — auto-injected `--enhanced-migration` (managed by mops) 4. `[canisters.<name>].args` — per-canister 5. CLI `-- <flags>` — one-off overrides; supported by `mops check`, `mops build`, `mops check-stable`, `mops generate`, `mops migrate`, `mops test`, and `mops bench` ## Core Commands ### `mops install` ```bash 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 ``` Run after cloning or after manual `mops.toml` edits. `mops.lock` is always maintained — there is no flag to opt out, and no `--lock` flag (removed in v3). A missing, unparseable, legacy-format or `mops.toml`-inconsistent lock is regenerated by a plain `mops install`, including locks that still carry absolute local paths from older CLIs. `--locked` requires an up-to-date lock and never writes it. It is also available on every implicitly-installing command (`mops build`, `mops check`, `mops check-stable`, `mops check-candid`, `mops test`, `mops bench`, `mops generate candid`), so CI can run `mops test --locked` with no prior install. `mops sources` has no `--locked` (a packtool caller parses its stdout mid-build) — put `mops install --locked` earlier in the pipeline instead. The `CI` env var no longer affects lockfile behavior (removed in v3). Commit `mops.lock` — for applications and libraries alike. A lock also goes stale when a local `path` dependency's own `mops.toml` changes — including one nested further down the chain. `mops install` regenerates it; `--locked` fails until the regenerated lock is committed. Note the first `mops install` after upgrading regenerates the lock of any project that has a `path` dependency, so commit it before running `--locked` in CI. Projects without `path` dependencies keep their existing lock. `{MOPS_ENV}` in a `path` dependency expands to `$MOPS_ENV` (default `local`), which makes the lock environment-specific. Switching `MOPS_ENV` makes it stale: `mops install` regenerates it, and `--locked` fails with a message naming `MOPS_ENV`. Keep one lock per environment, or drop `--locked` — a lock generated under one `MOPS_ENV` will not satisfy `--locked` under another. Integrity is verified at download time, so `mops install` no longer re-hashes `.mops/`: editing a dependency in place will not fail the next install. Use `mops verify` for the on-demand on-disk audit. Downloaded files are always checked before anything enters the cache — against `mops.lock` when it already records the package, otherwise against the registry. A committed lock therefore makes verification free, which is why a clean checkout installs without asking the registry about hashes. Two consequences worth knowing: a corrupt or hand-edited `mops.lock` now fails a _download_ (the error names `mops.lock` as a possible culprit — restore it from version control; already-cached packages are unaffected), and a package the registry publishes no hashes for still installs, unverified, with a warning. Packages download in parallel through a bounded pool. `mops install --concurrency <n>` or the `MOPS_CONCURRENCY` env var (works on every installing command) caps simultaneous registry requests; the default derives from the CPU count and the file-descriptor soft limit (4–16). Transient network errors (`fetch failed`, `ECONNRESET`, `EMFILE`) retry automatically with the concurrency halved, up to twice. Set `MOPS_CONCURRENCY=1` only if installs still fail after the retries (an egress proxy capping connections, for example). ### `mops verify` ```bash mops verify # re-hash .mops/ against mops.lock, and mops.lock against the registry ``` Covers GitHub dependencies as well as registry ones. Exits 1 with the offending files and a recovery hint. This is the replacement for anyone who relied on `mops install` failing when `.mops/` had been modified. ### `mops add <package>` ```bash mops add core # latest version mops add core@2.5.0 # 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 ``` Updates `mops.toml` and `mops.lock`. Adding a package that is already declared in the other section **moves** it rather than declaring it twice. `<pkg>@<version>` replaces the declared version and reports what it replaced; it leaves pinned aliases like `"core@1.0.0" = "1.0.0"` alone, and there is no flag to create one — write it by hand. ### `mops check` Primary correctness command — runs moc check, then check-stable (if configured), then lint (if lintoko is in toolchain). On moc 1.15.0+, canisters with `[migrations]` get stricter upgrade diagnostics: a field the initial actor requires that no migration produces fails as an `M0267` error instead of only warning (`M0254`), and compat errors carry a source location. Older moc pins and canisters without `[migrations]` are unaffected either way. The `check-stable` baseline is always a `.most` file — as `[canisters.<name>.check-stable].path` or as the `mops check-stable <baseline.most>` argument. A `.mo` source is rejected. See [`mops deployed`](#mops-deployed) for where the baseline comes from — that differs between a fresh project and an already-deployed canister. ```bash 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 ``` **Always use canister names, not file paths.** Per-canister args from `mops.toml` are applied automatically. `--fix` applies machine-applicable fixes from both moc and lintoko in one pass. Concurrent `--fix` runs (across processes) serialize automatically via an advisory lock at `.mops/fix.lock` — safe to invoke from multiple agents on the same project. Read-only files (e.g. frozen migrations) are skipped with a warning, not fixed. ### `mops build` ```bash 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 ``` Produces `.wasm`, `.did`, and `.most` files in `[build].outputDir` (default `.mops/.build`). With `[optimize]` in `mops.toml`, runs `wasm-opt` after candid metadata (default `-O3 -g`). Requires a Binaryen pin: `mops toolchain use wasm-opt 131`. Build commands never write the pin themselves, and a `wasm-opt` failure fails the build. Pass `--no-optimize` (on `build` or `bench`) to skip the pass for a single run without editing `mops.toml`. When `--check-wasm` or `[build].check-wasm = true` is enabled, Mops runs fast Walrus analysis on the final Wasm without starting PocketIC. Per-function IC0505 complexity below 750,000 is quiet, 750,000 through 899,999 emits an early warning, and 900,000 or more emits a critical warning. `MOPS-WASM-COMPLEXITY` output includes actionable function metrics, the three largest complexity contributors, and Motoko correction guidance. The estimate never fails the build. Use `--no-check-wasm` to skip configured analysis once. ### `mops deployed` Post-deploy hook — keeps the on-disk `.most` baseline used by `check-stable` in sync with what's actually deployed. ```bash 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 ``` Default destination is `deployed/<name>.most`; override with `[deployed].dir` in `mops.toml` or `--dir`. It reads built `.most` files from `[build].outputDir` (default `.mops/.build`); override with `--build-dir`. `mops deployed` errors if the source `.most` is missing — it never regenerates. Run it from your deploy pipeline immediately after a successful deploy. ### `mops generate candid` ```bash mops generate candid # all canisters mops generate candid backend # single canister mops generate candid backend -o <path> # single canister, ad-hoc path ``` (Re)generates the curated `.did` from current Motoko source. With `[canisters.<name>].candid` set, overwrites that file. Without it, writes `<name>.did` next to `main` (e.g. `main = "src/Backend.mo"` → `src/backend.did`) and sets `[canisters.<name>].candid` in `mops.toml`. Run after every interface change; commit `.did` + `mops.toml` together. Same moc invocation as `mops build`, so the result always passes `mops build`'s subtype check. ### `mops toolchain` ```bash mops toolchain use moc 1.7.0 # pin specific version mops toolchain use moc latest # pin latest version (non-interactive) mops toolchain use lintoko 0.10.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 stable releases, newest first mops toolchain info <tool> --versions --all # full stable history (cache warming) mops toolchain bin moc # print path to binary ``` **`pocket-ic` versions**: pin anything from `9.0.0` up, `latest` included — mops keeps no list of blessed versions. Pins below `9.0.0` error with a migration message (they ran on the legacy client that mops 3.0.0 removed). With no pin, replica tests / `mops bench` / `--check-deploy` / `mops toolchain bin pocket-ic` error naming `mops toolchain use pocket-ic 15.0.0`. That version is a hint, not a fallback. **Agent note**: `toolchain use <tool>` without a version opens an interactive picker — do not use in scripts or agents. Always pass a version or `latest`. `toolchain update` only works when the tool already has a `[toolchain]` entry. `toolchain info <tool> --versions` works without `mops.toml` (first GitHub page by default; pass `--all` for full history). ### Enhanced migrations When `[canisters.<name>.migrations]` is configured, `mops check`, `mops build`, and `mops check-stable` automatically inject `--enhanced-migration`. Do not add `--enhanced-migration` to `[canisters.<name>].args` — mops will error. Create migration files directly in the `chain` directory. After `mops check --fix` (or `mops check <canister>`) confirms the chain compiles, run `mops build` to produce the wasm artifact. Use `mops build --check-deploy`, or set `[build].check-deploy = true` for every build, to install each built Wasm on a fresh PocketIC canister and catch module validation, initialization, and installation failures. Requires `[toolchain] pocket-ic` (a version from `9.0.0` up, or a local binary path) — or set `MOPS_POCKET_IC_URL` to an already-running PocketIC server (the pin is then ignored). Unpinned with no URL, the build errors naming `mops toolchain use pocket-ic 15.0.0`. Use `--no-check-deploy` to skip configured validation once. The command uses each canister's `initArg`, or `()` when omitted. Set `wasmMemoryLimit` to a positive integer byte limit on a canister to check deployment under that limit. PocketIC errors are reported as provided by the client, and installation failures are collected across canisters. Before installation, Mops runs `moc --stable-compatible` from a temporary empty-actor `.most` to each generated `.most`. If moc reports incompatibility, Mops emits `MOPS-CHECK-DEPLOY-SKIPPED` with the compiler diagnostic and does not check that canister on fresh PocketIC. Eligible siblings are still checked; validate the skipped upgrade against representative baseline state. `check-limit` (optional) caps how many recent chain files `mops check` and `mops lint` consider — useful when the chain grows long and re-checking every old migration slows feedback down. `mops build` is unaffected by `check-limit`; it compiles the full chain, and when `[canisters.<name>.check-stable].path` is set it also folds the deployed baseline via `--stable-baseline`, so an applied migration edited, deleted, or backdated since deploy fails the build with `M0268` — the backstop for when `check-limit` trims that migration out of the folded `mops check`. When the limit kicks in, mops stages the included files into `.migrations-<canister>/` next to the `chain` directory (auto-`.gitignore`d). `moc` diagnostics may then print paths there — the real file lives in the `chain` directory with the same name. Override `check-limit` for a single run with `--no-check-limit` (`mops check`, `mops check-stable`, `mops lint`) — e.g. `mops check --fix --no-check-limit` to autofix older, normally-trimmed migrations. On `mops check` and `mops check-stable`, `--no-check-limit` also suppresses the pending-migration warning. When `check-limit` is set, `mops check-stable` (and the stable check inside `mops check`) reports if more migrations are pending than the limit allows — as an error if compat failed (replacing the misleading `moc` message), otherwise a warning. ### `mops remove <package>` ```bash mops remove core ``` Removes from whichever section declares the package; `--dev` limits it to `[dev-dependencies]`. A package declared in both sections is removed from both. ### Dependency Management ```bash 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
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看