- feat:
--untrusted, onbuild,deployandsync, holds a project someone else handed over to what it may read and run. Every file the project reads — manifests, argument and environment files, modules — must be under the project root and reached through no symlink. Each build step must be a pre-built module and each sync step a plugin, taken from a regular file in the project. A recipe is refused, wherever it is from. It expects to be run from the directory that holdsicp.yaml, which it takes as the project root: it does not look in the directories above, and running from a subdirectory fails.--project-root-overridenames another directory. Anything else is refused before the command acts on it, naming what was found. The.icpdirectory is the tool's own state and is neither confined nor checked, so delete one that came with the project before running. - chore: macOS on Intel (
x86_64-apple-darwin) is no longer a release target. Releases ship no Intel macOS archive, the shell installer refuses that platform, and npm no longer publishes@icp-sdk/icp-cli-darwin-x64, so installing@icp-sdk/icp-clion an Intel Mac warns of an unsupported platform. Homebrew dropped Intel macOS in September 2026, and GitHub is retiring its Intel macOS runners. v1.8.0 is the last release with an Intel macOS build.
- fix(bundle):
icp project bundleholds only regular files and directories. A symlink inside a plugin'sfiles:ordirs:directory used to be recorded as a link with its target unchecked, so one pointing outside the project reached that file on whatever machine unpacked the bundle. A link to somewhere inside the project is now copied as what it points at; one that leads outside the project, dangles, or leads back to a directory being copied fails the bundle, naming the link and where it leads. The same holds for afiles:entry that is itself a symlink.
- fix:
icp syncno longer needs controller rights. Its check that each canister is running usedcanister_status, which only a controller or a listed status viewer may read, so an identity the canister merely authorizes (a developer preparing an SNS-owned frontend for a commit proposal, say) was refused before anything was uploaded. It now probes with a query, asicp deployalready does after starting a canister. A stopped canister is still refused with the same advice, after the probe's 30-second wait rather than at once. - fix:
icp cycles buy --jsonandicp cycles buy -qimply--yes: a machine-readable run has nobody to ask, so neither prompts for confirmation on a terminal nor refuses without one, and the quote stays off stderr. - fix:
icp cycles buysays, with neither--amountnor--cycles, that one of the two is needed; and that a negative--amountor--cycles(-1,-5t) is negative, in the same words and with exit status 2 for both, where clap read-5tas an unknown flag - fix:
icp cycles buysays in words what is wrong with a--gatewaythat is not a canister id, a canister that serves no gateway, and one a boundary node cannot route to, where it printed the replica's IC0536 or the HTTP gateway's routing error; CyclePay and Stripe are named only for CyclePay's gateway, any other is "the gateway" - fix:
icp cycles buydraws the payment QR code black on white on any terminal theme. It used to take the terminal's own colours, which a light theme inverts and a dark theme often renders grey on near-black, and many phone cameras read neither. A terminal without colour support gets the plain drawing as before.
- feat(extension): extensions add third-party commands to icp. An extension is a WebAssembly component that runs sandboxed: it has no filesystem, environment variables, sockets or processes, and reaches the outside only through what icp hands it, namely canister calls as the resolved identity on the resolved network, a yes/no prompt, and showing the user an http(s) URL to visit. On mainnet it may call only the canisters it declares; on other networks this allowlist is not enforced, so it can be tried against a local network. Calls to the management canister are refused on every network.
icp extension install <NAME> <SOURCE>installs one from an https URL or a local path as the commandicp <NAME>;--sha256refuses a component with a different hash. Install shows the extension, its sha256 and the mainnet canisters it will call, flagging ledgers, and asks for approval (--yesskips the prompt). The sha256 is recorded and checked before every run. Installing under a name already installed replaces it, and any name works, so a build can be tried beside the installed one (cyclepay-betabesidecyclepay).icp extension list,icp extension show <NAME>(both with--json) andicp extension uninstall <NAME>manage what is installed.- An extension declares its commands, and they become ordinary icp subcommands: help, parse errors and shell completion work as for built-ins, and
--identity,-e/-nand the like are icp's own, resolved before the extension runs. A built-in command always wins over an extension of the same name.
- feat:
icp cycles buy --amount <amount> [--currency USD]buys cycles with a card for the current identity through CyclePay (https://www.cyclepay.org);--cycles <cycles>instead names the cycles to receive and pays the least amount that buys them, card fee included. It quotes the amount at CyclePay's published rate, asks for confirmation, creates the order as the identity on the CyclePay backend canister, prints the page to pay on with a QR code to scan (and opens it in a browser from a terminal, but not over SSH or on CI) and waits for the cycles to land on the identity's cycles-ledger account; Ctrl-C stops the wait, not the order.--gatewayorICP_CYCLES_GATEWAY_CANISTER_IDpicks another backend canister. - feat:
icp deployandicp canister createtake--engine <name>to target a cloud engine by name. The name is resolved to the engine's subnet through the engine canister, among the engines visible to the identity in use, and then behaves as--subnetwould with that subnet; a subnet id passed as the engine is used as-is.name/slugor the engine's id picks one of several engines sharing a name. - fix: reject path-like network and environment names
- feat:
icp canister uninstallremoves a canister's code and state, leaving it empty with its id, cycles and settings intact — the equivalent ofdfx canister uninstall-code.--proxyroutes it through a proxy canister, as forstopanddelete. - fix(sync-plugin): Wasmtime is updated 49.0.2 → 49.0.3, patching the runtime that executes
pluginsync steps against RUSTSEC-2026-0352 through RUSTSEC-2026-0364 — among them a WASI filesystem sandbox escape when renaming symlinks with trailing slashes (RUSTSEC-2026-0352), and a set of guest-triggerable host panics in the component model. No manifest, API, or minimum-toolchain change.
- chore: the macOS
icprelease binaries are now code-signed with DFINITY's Developer ID certificate. This improves the Keychain experience for identities stored in the keyring. macOS used to treat each unsigned release as a different app, so choosing "Always Allow" lasted only until the next upgrade. The signed binary keeps the same identity across releases, so after you allow access once more on the first signed version, it stays allowed through later upgrades. The signed binary is what you get from the GitHub release (including the shell installer) and npm.brew install icp-clifrom homebrew-core is not signed, because Homebrew builds that formula from source on its own infrastructure. The binary is not notarized, so a release archive downloaded through a browser still gets a Gatekeeper warning; the shell installer and npm are unaffected. - chore: the codebase is reorganized as groundwork for running project operations inside a canister. The former
icplibrary crate is split intoicp-project(the project model and the build, install, sync and deploy operations) andicp-app(identities, settings, local networks and other machine-level state), andicp-projectnow reaches the file system, the network and sync plugins only through traits. This is internal only — no command, flag or manifest behavior changes.
- feat(sync-plugin): Introduced v0.2.0 of the sync-plugin interface. v0.1.0 plugins are still supported. v0.2.0 introduces the following features:
canister-callcan call canisters besides the hosticp.yamlcan list key-value settings for pluginsicp.yaml's file/dir list is merged into a singlefileskey, which is also key-value instead of a list- A new function
canister-metadata-sectioncan fetch ICP metadata sections - Plugin input includes canister-principal mappings and the gateway and API URLs
- feat: a canister that uses a
recipecan now declare its ownsyncsteps, which previously was rejected outright. They run after the sync steps the recipe renders, so a recipe's post-deployment work stays intact and yours is appended to it.recipeandbuildremain mutually exclusive. - feat: Env-specific builds previously did not affect which canisters were being built. Now, any canisters not listed in that environment will not be built.
- feat: Environment declarations in workspaces no longer require all canisters to be declared at the top level. Instead, each subproject declares its own canisters' membership in environment blocks.
- feat(bundle):
icp project bundle -e <ENV>now decides what the bundle carries, not just what its build steps are told. The archive holds the canisters that environment contains and the bundled manifests declare only those, so a bundle built for one environment no longer ships every canister in the project. References the pruning would leave dangling go with them: another environment'scanisters:list, a dependency'scanisters:exposure list, an environment'ssettings:/init_args:override of a canister that is gone, and a controller naming a canister the environment does not hold — in a canister's own settings or in an environment's override of them — which is reported as a warning. The environment is now resolved rather than passed through as a name, so naming one the project does not declare — or one a workspace member does not declare — is an error, as it already was foricp buildandicp deploy. - fix(dependencies)!: an environment's
canisters:list is now honored in a workspace — a vendored project's own list used to be dropped, so all of its canisters deployed. Membership is decided locally and only locally: each project'scanisters:list names that project's own canisters, so every canister's membership is decided by the manifest that declares it, and a vendored project holds the same canisters in an environment as it would deployed on its own. This is breaking for a root that named a dependency's canister —canisters: [app, "vendor/openemail:frontend"]is now rejected when the project is loaded, and keeping a dependency's canister out of an environment means editing that dependency.canisters: []likewise empties only the project that writes it, and a listed environment's canisters now come in declaration order. See Which canisters an environment holds.
- feat: a canister can now declare
upgrade_argsalongsideinit_args, in its own manifest and as a per-canister environment override. It is passed whenicp deployupgrades the canister, whereinit_argsis passed when it installs or reinstalls it. It takes exactly the formsinit_argsdoes (inline Candid string, or{ value | path, format }), and paths resolve against the canister's own directory the same way. A canister that declares noupgrade_argsis upgraded with itsinit_args, as before, and--args/--args-filestill override whichever applies. - feat: a new
status_visibilitycanister setting controls who may read a canister's status (its running state, cycles, memory usage, and settings) through the management canister. It takes the same forms aslog_visibility—controllers(the default),public, or{ allowed_viewers: [...] }— and can be set in a manifest'ssettings:block or withicp canister settings update --status-visibility / --add-status-viewer / --remove-status-viewer / --set-status-viewer.icp canister statusandicp canister settings shownow report it. See the canister settings reference.icp canister statusandicp canister settings shownow list principals one per line under their label rather than comma-separated on the label's line:log viewer:/status viewer: <principal>for the allowed viewers of a visibility setting,controller: <principal>for a canister's controllers. This applies tolog_visibilityand to the controller list as well, so scripts matching those lines need updating. Both lists are sorted, which the controller list previously was not.icp canister settings updateno longer lets a relative viewer edit silently revoke public access.--add-log-viewer/--remove-log-viewerand their--*-status-viewercounterparts are now rejected while that setting ispublic, which carries no allowed-viewers list for them to be relative to — previously they started one from empty, so adding a viewer to a public canister took access away from everyone else. The error points at--set-*-viewer, which states the new list outright, and at--*-visibility controllers, which revokes public access on its own. Both remain allowed and now warn about what they cost: replacing apublicpolicy with a list, and removing the last viewer. This is breaking for the pre-existing log flags.- This raises the minimum replica version: reading a canister's status now requires one that reports
status_visibility, and against an older replicacanister_statusfails to decode — which affectsicp deploy,icp canister status, andicp canister settings show/sync, not just the new setting. Every mainnet subnet reports it. Amanagednetwork resolves the launcher tolatestunless it pinsversion:, so only a pinned launcher older than15.0.0-2026-08-13-03-55is affected; raise the pin to that version or later.
- feat: a new
snapshot_visibilitycanister setting controls who may read the canister's snapshots — thelist_canister_snapshots,read_canister_snapshot_metadata, andread_canister_snapshot_dataendpoints behindicp canister snapshot listandicp canister snapshot download. It takes the same forms aslog_visibilityandstatus_visibility—controllers(the default),public, or{ allowed_viewers: [...] }— in a manifest'ssettings:block or withicp canister settings update --snapshot-visibility / --add-snapshot-viewer / --remove-snapshot-viewer / --set-snapshot-viewer, and follows the same rule that a relative viewer edit is refused while the setting ispublic.icp canister statusandicp canister settings shownow report it, it is applied at creation, andicp canister settings synckeeps it in sync. Taking, restoring, and deleting snapshots remains controller-only; the setting governs reading alone. See the canister settings reference. - feat:
scriptbuild steps now receiveICP_CLI_ENVIRONMENT, the name of the environment the canisters are being built for, so a build can vary by environment the way a sync step already could. - feat:
icp completions <SHELL>prints a shell completion script forbash,zsh,fish,powershell, orelvishto stdout. See the installation guide for where to put it. - fix(sync-plugin): Wasmtime is updated 47.0.3 → 47.0.4, patching two advisories in the runtime that executes
pluginsync steps: a WASI filesystem sandbox escape when paths or symlinks carry trailing slashes (RUSTSEC-2026-0269), and a guest-controlled host heap allocation through WASIp3 streams (RUSTSEC-2026-0268). The escape is the one that bears on this crate: plugins run against directories preopened under the canister directory, and containing a symlink that escapes a preopen is the runtime's job rather than something the declared-path checks can cover. Lockfile-only — no manifest, API, or minimum-toolchain change. - fix: canister settings from the manifest are no longer silently discarded when a canister is created through the legacy management-canister fallback (a CloudEngine subnet with no registered engine operator). That path went through
ic-utils, which encodescreate_canister's argument as a barecanister_settingsrecord rather than therecord { settings : opt canister_settings; ... }the interface spec defines, so the replica read no settings at all and created the canister with defaults.icp deploymasked this by syncing settings afterwards;icp canister createdoes not, and left the canister unconfigured. - fix:
icp canister logsoutput formats are corrected.--jsonnow emits machine-readable JSON and the default emits the human-readable lines (the two were swapped), and--follow --jsonemits newline-delimited JSON, one record per line, streamed as each record arrives. This is breaking for scripts: parsing the default output as JSON now requires--json, and consumers of--follow --jsonmust read one JSON object per line.
- feat(signing): a canister call can now be signed on one machine and submitted from another, restoring what
dfx canister sign/dfx canister sendcovered.icp canister call --sign-only <FILE>composes and signs a call and writes it to a JSON file instead of submitting it;icp message send <FILE>submits that file and prints the reply. So a machine that holds the key needs no network, and the machine with the network needs no key — it never resolves an identity at all.-writes to stdout and reads from stdin respectively.- Nothing is fetched while signing: the Candid interface comes from
--candidor from the canister's local build artifact rather than from the canister itself, and--root-keymust name a key (mainnetor a hex-encoded key) rather thanfetch.--proxyis not supported. icp message sendshows what the message contains — sender, canister, method, decoded argument, window, and destination — and asks before submitting.--yesskips the prompt, and a non-TTY proceeds without one so a scripted courier works.--dry-runprints the same summary and stops without touching the network at all, which makes it the file-inspection command.--candid,--outputand--jsonrender the reply exactly asicp canister calldoes. Where the message is submitted comes from the file alone — there is no--networkoverride, so no environment variable can silently redirect a signed message; a courier who has to change it edits the file'snetworkfield, which is unauthenticated in either case.- If sending fails after the message may already have gone out, re-run
icp message sendon the same file: the request id is a hash of the signed content, so resubmitting the identical message is de-duplicated by the IC and cannot execute twice. Signing again produces a new expiry, hence a different request id, which is not de-duplicated — for a transfer, a double spend. Every post-submission failure says so. --valid-from <WHEN>places the message's submission window, as a duration from now (55m,2h) or an RFC 3339 timestamp; it defaults to now. The window is always five minutes wide, because the IC rejects an ingress message whose expiry is further ahead than that — so this places the window rather than sizing it. Note that this is not dfx's--expire-after, which names the window's end and leaves you to subtract the five minutes yourself.- The file records the signed envelope, where to submit it, a tagged canister-or-subnet destination, the Candid interface, and a human-readable summary of what was signed. An update also carries a pre-signed
request_statusread, so the submitting machine can await the outcome with no key of its own; it shares the call's expiry, so both live in the same window.
- Nothing is fetched while signing: the Candid interface comes from
- feat: a canister environment variable's value can now be read from a file, by writing
var: { path: <file> }in place ofvar: value. The path resolves against the canister's directory — including in an environment override, matchinginit_args— and surrounding whitespace is trimmed off the file's contents. The file is read when the project is loaded, so a missing file fails before anything is deployed.icp project bundlewrites the value into the bundled manifest inline, rejecting a file outside the project as it does for other manifest file references. - fix:
icp network startnow explains why a Docker-based network failed to come up. A container that exited before the network was ready was reported asfailed to watch docker container <id> for exitwith an empty cause, discarding the actual reason (e.g. the gateway port already being taken); the container's output is now attached to the error. - feat: Docker-based networks now show the launcher's output like non-containerized ones do. In the foreground the container's stdout and stderr are streamed to your terminal as it runs; in background mode
icp network startprints thedocker logs -f <container-id>command to follow it. Previously container output was never shown at all — which on Windows, where the launcher always runs in a container, meanticp network startwas silent. - fix: a network launcher running in a container (
icp settings autocontainerize true, and always on Windows) now receives--verbosewhenicp -dis used, matching the non-containerized launcher.
- feat(bundle):
icp project bundletakes-e/--environment, naming the environment its canisters are built for — it reaches build scripts asICP_CLI_ENVIRONMENT. It defaults toic, unlike the rest of the CLI, because a bundle is built to be deployed somewhere else;ICP_ENVIRONMENToverrides that default as it does elsewhere. Which canisters are bundled is unaffected. - feat(bundle):
icp project bundlenow works on projects that declaredependencies:, which it previously refused outright. The bundle mirrors the workspace instead of flattening it: the root project'sicp.yamlsits at the archive root, each dependency instance gets its ownicp.yamlat the directory it occupies in the workspace, and thedependencies:declarations are preserved, each pointing at the directory its dependency occupies in the archive (the same path a plainly vendored layout already used). A shared (diamond) dependency is still a single instance, canister names stay as each project wrote them, and canister discovery (PUBLIC_CANISTER_ID:<alias>:<canister>) works in the extracted bundle exactly as it did in the source workspace.- Every dependency must resolve to a directory inside the workspace root; one that resolves outside it (including through a symlink) is rejected, because the archive could not contain it. As a result, a vendored member that depends on a sibling cannot be bundled as a standalone project (e.g. via
ICP_PROJECT_ROOT) — bundle the workspace root instead. - Projects with script sync steps still cannot be bundled, and the restriction now covers every project in the workspace.
- Every dependency must resolve to a directory inside the workspace root; one that resolves outside it (including through a symlink) is rejected, because the archive could not contain it. As a result, a vendored member that depends on a sibling cannot be bundled as a standalone project (e.g. via
- feat(sync-plugin): the compute-time limit for
pluginsync steps is now configurable via theICP_CLI_PLUGIN_COMPUTE_LIMIT_SECSenvironment variable (default60). Raise it for compute-heavy plugins (e.g. brotli-compressing a large asset bundle) that legitimately exceed the default, especially on slower CI runners. The limit-exceeded error now names the variable and the current limit, and a malformed value is rejected rather than silently ignored. - feat:
icp canister linkassigns an existing canister principal to a project canister - feat:
icp canister create --with-icp(not supported inicp deploy) uses the CMC to create canisters. Only needed for deploying to restricted system subnets. - feat:
icp deploy --no-createwill error if any canisters do not exist, rather than creating them. - fix:
icp deploynow prints the frontend URL for any canister that exposes anhttp_requestendpoint. Previously a canister whosehttp_requestsignature differed from a hard-coded shape (e.g. some certified-asset canisters) was misdetected and shown a Candid UI URL instead of its site URL. Deploy URLs are also now grouped by kind (frontends vs. Candid UI) instead of interleaved.
- feat:
icp token [TOKEN|LEDGER_ID] approve <AMOUNT> <SPENDER>grants an ICRC-2 allowance, letting a spender transfer tokens on your behalf. Supports--from-subaccount(the account debited for the allowance),--spender-subaccount, and an optional--expires-in <DURATION>(e.g.24h,30d) to auto-expire the allowance. - feat:
icp token [TOKEN|LEDGER_ID] allowance <SPENDER>displays the ICRC-2 allowance granted to a spender. Supports--subaccount,--spender-subaccount, and--of-principalto inspect any account. - feat:
icp canister deletewill now send the canister's remaining cycles to the caller - feat: Connected networks now take an explicit
root-key, which accepts a hex-encoded key or one of two new values:mainnet: use the canonical IC mainnet root key — handy for reaching mainnet through a custom boundary node without repeating the literal.fetch: fetch the key from the network on each use. This is trust-on-first-use and does not verify the key's provenance, so it's meant only for testnets you or someone you trust operate;icpprints a warning whenever it fetches.network statusreports where the key came from — aroot_key_sourcefield in--json, and a(fetched - unverified, trust-on-first-use)label in text output.root-keyis now required for connected networks (previously optional, silently defaulting to the mainnet key). This is technically breaking, but most working projects are unaffected: a non-mainnet connected network already needed an explicit key, so in practice only a mainnet-via-custom-URL network needs to addroot-key: mainnet. The built-inicnetwork is unchanged.
- feat: Projects can now depend on other
icpprojects vendored into them (e.g. as git submodules) via a top-leveldependencies:block inicp.yaml.icp deploydeploys the dependency alongside your project and injects its canister IDs.- Running
icpfrom inside a vendored sub-project resolves up to the workspace root, so the whole workspace shares one network and one set of canister IDs. - Canister names and dependency aliases must now contain only ASCII letters, digits,
_, and-, with:reserved as the dependency namespace separator. Names using other characters are now rejected. - See the Project Dependencies concept guide for details.
- feat(sync-plugin):
pluginsync steps now reject anydirs/filesentry that is, or traverses, a symlink. Together with the existing relative-path and..checks, this keeps a declared path from resolving to a target outside the canister directory. The restriction may be relaxed in a future release if a safe use case emerges.
- fix(bundle): path validation use parent-dir analysis without canonicalize.
- feat:
icp identity importcan now be used with a--delegationflag to import a delegated identity. This is most useful for containers or other internal-only delegations; for anything involving a network,icp identity delegation requestremains the recommended way to work with delegations.
- feat: The default gateway domain is now
icp.net, noticp0.io. - feat: Password-protected identities now only need your password once per session. The session length defaults to 5 minutes and can be changed with
icp settings session-length <DURATION>(e.g.30m,1h) or turned off withicp settings session-length disabled. You can also explicitly create or refresh a session withicp identity reauth <NAME> [--duration <DURATION>]. - feat!: Remove
--set-controllerand replace with a new flag--remove-all-controllers. For the old behavior, combine this flag with--add-controller
- feat:
icp canister callnow accepts--candid <PATH>to load the canister's Candid interface from a local.didfile instead of fetching it from the network. The supplied interface drives method selection, argument building, and response decoding.
- fix: Account seeding in new networks is now done via transfer instead of mint. This should eliminate minting ratelimit errors for users with a lot of local identities.
- feat:
icp identity link webnow lets you sign in with web-based identities, especially Internet Identity. You can use your NNS-UI or Oisy principals locally with--app nns.ic0.appor--app oisy.com. When the session expires, sign in again withicp identity reauth. - BREAKING: removed the
assetssync step type (type: assets). Asset uploading is no longer built into icp-cli — use ascriptorpluginsync step instead (for example, a recipe that provides a sync plugin). A manifest that still usestype: assetsnow fails to load with a message explaining the change. - feat: Recipe templates can now use
{{_.canister.name}}to reference the canister's name fromicp.yamlwithout repeating it in theconfiguration:block. The_namespace is reserved and cannot be overridden by user-provided configuration.
- feat:
scriptsync steps now receiveICP_CLI_ENVIRONMENT,ICP_CLI_NETWORK,ICP_CLI_CID(the current canister's principal), andICP_CLI_CID_<NAME>(every canister's principal) as environment variables. - fix:
icp canister callwith both--jsonand-o hexno longer prints both kinds of output at once. - fix:
icpno longer picks up a stale inherited$PWDwhen launched as a subprocess viachdir(2)+execve(e.g. from a test harness). The logical$PWDpath is now validated againstgetcwd()by inode before use, preserving symlink-aware project root discovery while ignoring stale values.
- feat(sync-plugin): Plugins can now surface messages that persist after the step completes. Anything the plugin writes to stderr (e.g.
eprintln!in Rust) is streamed live in the rolling step view AND printed under the canister name once the step ends; stdout remains transient. Theexec()return signature has changed fromresult<option<string>, string>toresult<_, string>— plugins that returned a summary string shouldeprintln!it instead.
- feat:
icp token/cycles balancenow accept--of-principal - fix: The local wasm cache has moved from
.icp/cache/canisters/to.icp/cache/wasms/. Existing cached files will be re-downloaded automatically on the next run. - fix:
icp canister callnow serializes arguments built via the interactive Candid assist prompt against the method's declared signature, matching the behavior of arguments passed on the command line. Previously, narrower values (e.g. a variant case from a multi-case variant) were encoded with a type table inferred only from the value, which the target canister rejected with errors like "Variant index N larger than length 1".
- feat(sync-plugin): Canister manifests now support a
pluginsync step type. Plugins are WebAssembly components that run in a sandboxed environment and can drive arbitrary post-deployment logic against the canister being synced. Seecrates/icp-sync-plugin/DESIGN.mdfor details. - feat(sync-plugin):
icp syncnow accepts--proxyto route sync plugin calls to the target canister through a proxy canister.
- feat:
icp new --initno longer requires specifying a project name. If non is provided, the containing folder's name is used as the project name - fix:
icp canister call --jsonno longer produces blank output.
- feat:
icp identity delegation request/sign/usenow permit creating and importing identity delegations - feat:
icp identity importnow takes--seed-curve, for seed phrases for non-k256 keys. - fix:
icp canister settings shownow outputs only the canister settings, consistent with the command name - fix: Fail early when attempting to create an identity with an already existing name.
- fix: Find icp.yaml even from within a symlinked folder.
- feat: Add
--proxytoicp canistersubcommands andicp deployto route management canister calls through a proxy canister - feat: Add
--args,--args-file, and--args-formatflags toicp deployto pass install arguments at the command line, overridinginit_argsin the manifest
Important: A network launcher more recent than v12.0.0-83c3f95e8c4ce28e02493df83df5f84a166451c0 is required to use internet identity.
- feat: Many more commands support
--jsonand--quiet. - feat: When a local network is started internet identity is available at id.ai.localhost
- fix: Network would fail to start if a stale descriptor was present
- feat: icp-cli will now inform you if a new version is released. This can be disabled with
icp settings update-check - fix: Duplicate identities no longer cause an error when starting a network
- feat: Added support for creating canisters on cloud engine subnets. Note that local networks cannot yet create these subnets.
- feat: Upgrading canisters now stops them before the upgrade and starts them again afterwards
- feat:
icp canister logssupports filtering by timestamp (--since,--until) and log index (--since-index,--until-index) - feat: Support
log_memory_limitcanister setting inicp canister settings updateandicp canister settings sync - feat: Leaving off the method name parameter in
icp canister callprompts you with an interactive list of methods - fix: Correct templating of special HTML characters in recipes
- feat: Added a notification about new versions of the network
- feat: Added 'friendly name' domains for canisters - instead of
<frontend principal>.localhostyou can accessfrontend.local.localhost. - feat: Added
bindkey to network gateway config to pick your network interface (previous documentation mentioned ahostkey, but it did not do anything) - feat: check for Candid incompatibility when upgrading a canister
- feat: Add
bitcoind-addranddogecoind-addroptions for managed networks to connect to Bitcoin and Dogecoin nodes - feat: Init/call arg files now support raw binary without conversion to hex
- feat!: Remove argument type inference in init/call args in commands and manifest. Args are always assumed Candid, new parameters allow specifying other formats like hex, and alternate parameters are used to specify loading from a file.
- feat: Network gateway now supports a
domainskey - feat:
icp identity exportnow takes an--encryptflag to avoid rendering the key in plaintext - feat: Optionally split connected networks'
urlintoapi-urlandhttp-gateway-url - feat: Allow specifying a version of the network launcher to use
- feat: Support subaccounts and ICRC-1 IDs in
icp token,icp cycles, andicp identity account-id - feat!: Recipes are now specified
@registry/recipe@version, the version component is required. Thelatestversion is no longer assumed and the version tags will be removed soon. - feat: Recipes and prebuilt canisters are now cached locally
- feat:
icp settings autocontainerize true, always use a docker container for all networks - feat:
icp canister migrate-id- initiate canister ID migration across subnets - feat: Install proxy canister when starting managed networks with all identities as controllers (or anonymous + default if more than 10 identities)
icp network statusdisplays the proxy canister principal
- feat:
icp network statusdisplay more information about networks - feat:
icp canister logsto display the current canister logs- use
--followto continuously poll for new logs.--interval <n>to poll everynseconds
- use
- feat: Support
k,m,b,tsuffixes in.yamlfiles when specifying cycles amounts - feat: Support
kb,kib,mb,mib,gb,gibsuffixes in.yamlfiles and CLI arguments when specifying memory amounts - feat: Add an optional root-key argument to canister commands
- feat:
icp canister callnow supports--output <mode>with the following modes:auto(default): Try decoding the response as Candid, then UTF-8, then fall back to hex.candid: Parse as Candid and pretty-print; error if parsing fails.text: Parse as UTF-8 text; error if invalid.hex: Print raw response as hex.
- chore!: new passwords for identity encryption need to be at least 8 characters long
- feat: Anonymous usage telemetry — collects command name, arguments, duration, and outcome
- Enabled by default; opt out with
icp settings telemetry false,DO_NOT_TRACK=1, orICP_TELEMETRY_DISABLED=1 - Automatically disabled in CI environments (
CIenv var set) icp settings telemetryto view or change the current setting
- Enabled by default; opt out with
- feat:
icp canister snapshot- create, delete, restore, list, download, and upload canister snapshots - feat:
icp canister callnow supports--proxyflag to route calls through a proxy canister- Use
--proxy <CANISTER_ID>to forward the call through a proxy canister'sproxymethod - Use
--cycles <AMOUNT>to specify cycles to forward with the proxied call (defaults to 0)
- Use
- feat:
icp identity exportto print the PEM file for the identity
- fix: Fix error when loading network descriptors from v0.1.0-beta.3
- feat:
icp identity deleteandicp identity rename
- fix: More reliably detect occupied ports' project locations across containers and backgrounded networks
- feat: Bind Docker networks to 127.0.0.1
- feat: Add IC options to network manifest (
ii,nns,subnets,artificial-delay-ms) - feat: Release for Windows
- feat: Add safety controls for
--set-controllerand--remove-controller- Warn and prompt for confirmation when removing yourself from controllers
- Add
-f/--forceflag to skip confirmation prompts
- feat: Show
nameincanister statuscommand - feat:
icp canister metadata <canister> <metadata section>now fetches metadata sections from specified canisters - fix: Validate explicit canister paths and throw an error if
canister.yamlis not found - feat!: Rename the implicit "mainnet" network to "ic"
- The corresponding environment "ic" is defined implicitly which can be overwritten by user configuration.
- The
--mainnetand--icflags are removed. Use-n/--network ic,-e/--environment icinstead.
- feat: Allow overriding the implicit
localnetwork and environment. - chore: get rid of
TCYCLESmentions and replace them withcycles - feat: Add
icp cycles transferas replacement foricp token cycles transfer - chore!: remove support for
cyclesinicp token. Useicp cyclesinstead - chore!: Change display format of token and cycles amounts
- feat: Token and cycles amounts now support new formats. Valid examples:
1_000,1k,1.5m,1_234.5b,4T - feat: Allow installing WASMs that are larger than 2MB
- feat: Add
icp identity account-idcommand to display the ICP ledger account identifier- Supports
--of-principalflag to convert a specific principal instead of the current identity
- Supports
- feat:
icp token transfernow accepts AccountIdentifier hex strings for ICP ledger transfers- Legacy ICP ledger transfers using AccountIdentifier are automatically used when a 64-character hex string is provided
- AccountIdentifier format is only supported for the ICP ledger; other tokens require Principal format
- feat:
icp canister callcan now take arguments in hex - feat: allow specifying paths to files that contain canister arguments:
- in
icp canister call <canister> <function> <argument>the argument can now point to a file that contains hex or Candid - in
icp canister install <canister> <argument>the argument can now point to a file that contains hex or Candid - in
icp.yaml, a canister'sinstall_argsfield can now point to a file that contains hex or Candid
- in
- feat: Remove requirement that the user install
icp-cli-network-launcher, auto-install it on first use - feat: Support keyring storage and password-protected encryption for identity keys (and make keyring the default)
- fix: Use EOP when upgrading motoko canisters
- feat: Network startup verbose output now requires
--debugflag - feat: Add
icp network statuscommand to display network information- Displays port, root key, and candid UI principal (if available)
- Supports
--jsonflag for JSON output
- feat:
icp deploynow displays URLs to interact with the deployed canister(s) - feat: Allow overriding the
localnetwork in the config file- This makes it more convenient to configure the default environment
- feat: Validate call argument against candid interface
- The interface is fetched from canister metadata onchain
- feat: Accept an environment as argument for network commands
- feat: call argument building interactively using candid assist
- feat: specifying canister
init_argsinicp.yaml - fix: overriding canister settings from the
canisterssection oficp.yamlwith settings from theenvironmentssection now works as intended
- feat: Add support for launching dockerized local networks (#233)
- fix: When deleting a canister, also delete the id from the id store.
- chore!: rename
icp network runto `icp network start - feat: install Candid UI canister after starting a local network
- feat!: Switch to using icp-cli-network-launcher instead of pocket-ic directly. Download it here.
- feat!: Introduce
newcommand to create projects from templates (#219)
This is a the first beta release of icp-cli.
Supports:
- Creating an identity.
- Launching a local network with pocket-ic.
- Executing operations against a network.
- Building and deploying canisters to a network.