Skip to content

meroctl CLI Reference

meroctl is the operator CLI. It connects to a running merod node over its RPC server and manages applications, namespaces, groups, contexts, blobs, and method calls.

FlagType / valuesNotes
--home <PATH>pathDirectory for config and data. Env: CALIMERO_HOME.
--node <ALIAS>stringUse a pre-configured node alias. Conflicts with --api.
--api <URL>URLAPI endpoint URL of the node to target.
--output-format <FORMAT>enumOutput format (e.g. JSON) — used by commands such as network status.

When neither --node nor --api is given, meroctl uses the active node (set with node use), falling back to http://127.0.0.1:2528.

Almost every command accepts an alias wherever it accepts an id. An alias is a human-readable name (max 50 characters) that the node resolves server-side to a ContextId, an ApplicationId, or a member PublicKey. Aliases live on the node, not in the CLI: they are created, looked up, and deleted through the admin API alias endpoints, so every client talking to the same node sees the same aliases.

Scoping is not uniform across the three target types:

Alias targetScopeCreated with
ContextIdNode-globalcontext alias add, or context create --name
ApplicationIdNode-globaladmin API alias/create/application
PublicKey (identity)Per contextcontext identity alias add (scoped to one context)

Context and application aliases are unique across the whole node; an identity alias only has meaning within the context it was created in, so the same name can resolve to different keys in different contexts.

A reserved default alias exists for both contexts and identities. Commands that take --context (or an executor identity) fall back to default when the flag is omitted, and context use <CONTEXT> / context identity use <IDENTITY> just point the default alias at a chosen target. The call --substitute flag is a related but distinct feature: it resolves a comma-separated list of identity aliases and templates them into the request payload wherever you write {alias} (see call).

GroupPurpose
appManage applications (install, list, versions, watch).
contextManage contexts, identities, aliases, and sync.
groupManage groups: members, contexts, metadata, upgrades, settings.
namespaceManage namespaces (root groups / application instances). Alias ns.
blobUpload, download, inspect, and delete blobs.
callCall a method on a context (mutation or view).
devDeveloper workflow: build, install, create context, watch.
networkInspect libp2p networking state.
peersReturn the number of connected peers.
teeTEE fleet-node commands.
nodeManage node connections used by meroctl (local config).

Subcommand (aliases)PurposeKey args
get <APP_ID>Fetch application details.APP_ID
installInstall an application.--path/-p, --url/-u, --metadata/-m, --hash, --watch/-w, --package, --version
list (ls)List installed applications.
uninstall <APP_ID>Uninstall an application.APP_ID
versions <APP_ID>List locally installed versions of an app.APP_ID
watchWatch a WASM file and update all contexts using the app.--path/-p, --metadata, --current-app-id, --package, --version
list-packagesList all packages.
list-versions <package>List registry versions of a package.package
get-latest-version <package>Get the latest version of a package.package
Terminal window
meroctl --node node1 app install --package com.example.myapp --version 1.0.0 --path ./my-app.wasm
meroctl --node node1 app ls

--path and --url are mutually exclusive; --version defaults to 0.0.0.


Subcommand (aliases)PurposeKey args
list (ls)List all contexts.
createCreate a new context.--application-id/-a, --group-id (required), --params/-p, --watch/-w <path>, --seed/-s, --as (identity alias), --name (context alias), --service, --identity-secret, --group-name, positional metadata (requires --watch)
get <CONTEXT>Fetch context details: info, client-keys, or storage.CONTEXT, subcommand
delete (del) <CONTEXT>Delete a context.CONTEXT, --requester
updateUpdate the application in a context.--context/-c, --application-id/-a, --path, --metadata, --watch/-w, --as (executor)
watch (ws)Stream context events, optionally run a command.--context, -x/--exec, -n/--count
syncExplicitly request a sync.--context/-c, --all
invite-specialized-nodeInvite a specialized (e.g. read-only TEE) node.--context, --inviter
identityManage context identities (see below).subcommand
aliasManage context aliases: add, remove, get, list.subcommand
use <CONTEXT>Set the default context.CONTEXT, --force
Subcommand (aliases)PurposeKey args
list (ls)List identities in a context.--context, --owned
generate (new)Generate a new identity keypair.
use <IDENTITY>Set the default identity for a context.IDENTITY, --context, --force
aliasManage identity aliases.subcommand
grantRemoved. Parses but errors, pointing you to group members set-caps.identity, capability, --context, --as
revokeRemoved. Parses but errors, pointing you to group members set-caps.identity, capability, --context, --as
Terminal window
meroctl --node node1 context create --application-id <app_id> --group-id <group_id>
meroctl --node node1 group members set-caps <group_id> <identity> --can-create-context

Subcommand (aliases)PurposeKey args
get <GROUP_ID>Get information about a group.GROUP_ID
delete (del) <GROUP_ID>Delete a group.GROUP_ID, --requester
update <GROUP_ID>Update group settings.GROUP_ID, --upgrade-policy, --requester
membersManage group members (see below).subcommand
contextsList (list/ls) or detach contexts in a group.subcommand
metadataShow / update a group’s metadata record.subcommand
member-metadataShow / update a member’s metadata record.subcommand
context-metadataShow / update a registered context’s metadata.subcommand
reparent <GROUP_ID> <NEW_PARENT_ID>Atomically move a group to a new parent.GROUP_ID, NEW_PARENT_ID, --requester
subgroups <GROUP_ID>List direct subgroups of a group.GROUP_ID
signing-keyManage signing keys: register.subcommand
upgradetrigger, status, or retry a group upgrade.subcommand
sync <GROUP_ID>Sync a group from local state.GROUP_ID, --requester
join-context <CONTEXT_ID>Join a context via group membership.CONTEXT_ID
leave-context <CONTEXT_ID>Locally opt out of a context (no DAG op).CONTEXT_ID
leave <GROUP_ID>Voluntarily leave a group (publishes MemberLeft).GROUP_ID
settingsManage group-level default settings (see below).subcommand
Subcommand (aliases)PurposeKey args
list (ls) <GROUP_ID>List all members of a group.GROUP_ID
add <GROUP_ID> <IDENTITY>Add a member to a group.--role, --requester
remove <GROUP_ID> <IDENTITY...>Remove members from a group.identities, --requester
set-role <GROUP_ID> <IDENTITY> <ROLE>Update a member’s role.--requester
set-capabilities (set-caps)Set capabilities for a member (admin-only).GROUP_ID, IDENTITY, --can-* flags
get-capabilities (get-caps)Get a member’s capabilities.GROUP_ID, IDENTITY
check-accessCheck if an identity can join a context.GROUP_ID, identity
Subcommand (aliases)PurposeKey args
get <GROUP_ID>Get current default settings.GROUP_ID
set-default-capabilities (set-default-caps)Set default capabilities for new members.GROUP_ID, --can-* flags, --requester
set-subgroup-visibility (set-subgroup-vis)Set subgroup visibility (open/restricted).GROUP_ID, --mode, --requester
Terminal window
meroctl --node node1 group members list <group_id>
meroctl --node node1 group reparent <group_id> <new_parent_id>
meroctl --node node1 group signing-key register <group_id> <hex_signing_key>

Alias: ns. Namespaces are root groups (application instances).

Subcommand (aliases)PurposeKey args
createCreate a new namespace.--application-id, --upgrade-policy, --name, --app-key
get <NAMESPACE_ID>Get details about a namespace.NAMESPACE_ID
delete (del) <NAMESPACE_ID>Delete a namespace.NAMESPACE_ID, --requester
invite <NAMESPACE_ID>Create an invitation for a namespace.NAMESPACE_ID, --requester, --expiration-timestamp, --recursive
join <NAMESPACE_ID> <INVITATION>Join a namespace using an invitation.NAMESPACE_ID, invitation JSON
leave <NAMESPACE_ID>Leave a namespace (cascades through descendants).NAMESPACE_ID
groups <NAMESPACE_ID>List direct groups under a namespace.NAMESPACE_ID
create-group <NAMESPACE_ID>Create a child group in a namespace.NAMESPACE_ID, --alias
list (ls)List all namespaces.
identity (id) <NAMESPACE_ID>Get this node’s identity for a namespace.NAMESPACE_ID
Terminal window
meroctl --node node1 namespace create --application-id <app_id>
meroctl --node node2 namespace join <namespace_id> '<invitation_json>'

Subcommand (aliases)PurposeKey args
list (ls)List all blobs.
uploadUpload a blob from a file.--file, --context-id
downloadDownload a blob to a file.--blob-id, --output, --context-id
infoGet information about a blob.--blob-id
delete (rm)Delete a blob by its ID.--blob-id
Terminal window
meroctl --node node1 blob upload --file /path/to/file
meroctl --node node1 blob download --blob-id <blob_id> --output /path/to/output

Call a method on a context. Whether a call mutates state or runs as a read-only view is determined by the method’s own declaration (#[app::view]), not by a CLI flag; the call executes under the context’s default identity.

Arg / flagType / valuesDefaultPurpose
<METHOD>stringMethod to call (omit with --interactive).
--context/-c <CONTEXT>context alias/iddefaultContext to call the method on.
--args <JSON>JSON{}JSON arguments to pass to the method.
--substitute <ALIAS>comma-separated aliasesAliases to substitute into the payload (reference them as {alias}).
--id <ID>stringJSON-RPC call id.
--interactive/-iboolfalseOpen a persistent WebSocket shell and run many calls.
--timeout <SECONDS>u64120Per-call timeout in the interactive shell (0 disables).
Terminal window
meroctl --node <NODE> call <METHOD> --context <CONTEXT_ID> --args '<ARGS_JSON>'
meroctl --node <NODE> call -i --context <CONTEXT_ID>

SubcommandPurposeKey args
start <path>Build, install, create/reuse a context, optionally watch.--group-id (required), --watch/-w, --new, --params/-p, --seed/-s, --no-build, --metadata

<path> may be a .wasm, a .mpk bundle, or a project directory with a Cargo.toml (which is built with cargo build --target wasm32-unknown-unknown --release).

Terminal window
meroctl --node node1 dev start ./my-app --group-id <group_id> --watch

SubcommandPurpose
statusDump swarm connectivity: listen/external addresses, relay reservations, rendezvous registrations, DCUtR upgrades, AutoNAT.
Terminal window
meroctl --node node1 network status
meroctl --output-format json --node node1 network status

No subcommand — returns the number of connected peers.

Terminal window
meroctl --node node1 peers

Subcommand (aliases)PurposeKey args
fleet-join <GROUP_ID>Announce this node as a TEE fleet member and auto-join contexts in the group once admitted.GROUP_ID
Terminal window
meroctl --node node1 tee fleet-join <GROUP_ID>

These commands manage meroctl’s local connection config — they do not call a node. A node may be a local home directory or a remote URL.

Subcommand (aliases)PurposeKey args
add (connect) <NAME> <LOCATION>Add or connect to a node.LOCATION (path or URL), --access-token, --refresh-token
remove (rm, disconnect) <NAME>Remove a node connection.NAME
use <NAME>Set a node as active (default for commands).NAME
list (ls)List all configured nodes.
identity (id)Display the node’s peer ID (local nodes only).
Terminal window
meroctl node add node1 /path/to/home
meroctl node add node3 http://public.node.com
meroctl node use node1
meroctl node ls

For a remote node that needs authentication, login starts automatically; pass --access-token (and optionally --refresh-token) to skip it with explicit JWTs.

The node commands above read and write a single client-side config file at ~/.config/calimero/meroctl/nodes.toml (under your platform config dir). This is meroctl’s own state — it is never sent to a node. It records:

  • Each configured node connection under its connection name, as either a local node (a path to a node home) or a remote node (a url).
  • active_node — the connection used when neither --node nor --api is given.
  • Per-node JWT access and refresh tokens, saved here after a login so subsequent commands reuse them.

Because it holds bearer tokens, the file is written with owner-only permissions (0600) and re-written atomically with those permissions on every update. Treat it as secret material:

active_node = "node1"
[nodes.node1]
path = "/home/alice/.calimero"
[nodes.node1.jwt_tokens]
access_token = "<jwt>"
refresh_token = "<jwt>"
[nodes.prod]
url = "https://node.example.com/"

A complete run from an installed WASM module to reading back state. Each command below adds --output-format json so the ids you need to copy forward are machine-readable; drop it to get the default human-readable table.

  1. Install the application. The node returns an applicationId:

    Terminal window
    meroctl --node node1 app install \
    --path ./kv_store.wasm \
    --package com.example.kvstore \
    --version 0.1.0 \
    --output-format json
    {"data":{"applicationId":"<app-id>"}}
  2. Create a namespace bound to that application id. A namespace is a root group; its id is the --group-id a context attaches to:

    Terminal window
    meroctl --node node1 namespace create --application-id <app-id> \
    --output-format json
    {"data":{"namespaceId":"<namespace-id>"}}
  3. Create a context from the application id and the namespace id, giving it a memorable alias with --name:

    Terminal window
    meroctl --node node1 context create \
    --application-id <app-id> \
    --group-id <namespace-id> \
    --name my-kv \
    --output-format json
    {"data":{"contextId":"<context-id>","memberPublicKey":"<public-key>"}}
  4. Call a mutating method. Whether a call mutates or only reads is decided by the method’s own #[app::view] declaration, not a CLI flag — set here writes a key. Refer to the context by its alias:

    Terminal window
    meroctl --node node1 call set \
    --context my-kv \
    --args '{"key": "hello", "value": "world"}' \
    --output-format json

    set returns (), so the result is null:

    {"jsonrpc":"2.0","id":null,"result":{"output":null}}
  5. Read it back with a view method. get is declared #[app::view], so the same call command runs it read-only:

    Terminal window
    meroctl --node node1 call get \
    --context my-kv \
    --args '{"key": "hello"}' \
    --output-format json
    {"jsonrpc":"2.0","id":null,"result":{"output":"world"}}

The value you stored comes back under result.output.