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.

Flag Type / values Notes
--home <PATH> path Directory for config and data. Env: CALIMERO_HOME.
--node <ALIAS> string Use a pre-configured node alias. Conflicts with --api.
--api <URL> URL API endpoint URL of the node to target.
--output-format <FORMAT> enum Output 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, a member PublicKey, or a DeviceId. 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 four target types:

Alias target Scope Created with
ContextId Node-global context alias add, or context create --name
ApplicationId Node-global admin API alias/create/application
DeviceId Node-global account alias add

Context, application, and device aliases are unique across the whole node.

A reserved default alias exists for contexts. Commands that take --context fall back to default when the flag is omitted, and context use <CONTEXT> just points the default alias at a chosen target.

Group Purpose
app Manage applications (install, list, versions, watch).
context Manage contexts, identities, aliases, and sync.
group Manage groups: members, contexts, metadata, upgrades, settings.
namespace Manage namespaces (root groups / application instances). Alias ns.
blob Upload, download, inspect, and delete blobs.
call Call a method on a context (mutation or view).
dev Developer workflow: build, install, create context, watch.
network Inspect libp2p networking state.
peers Return the number of connected peers.
tee TEE fleet-node commands.
node Manage node connections used by meroctl (local config).

Subcommand (aliases) Purpose Key args
get <APP_ID> Fetch application details. APP_ID
install Install a signed .mpk application bundle. PACKAGE@VERSION, --path/-p, --watch/-w
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
watch Watch a .mpk bundle and update all contexts using the app. --path/-p, --current-app-id
list-packages List the packages installed on this node.
list-versions <package> List this node’s installed versions of a package. package
get-latest-version <package> Highest installed version of a package. package
Terminal window
meroctl --node node1 app install com.example.myapp@1.0.0
meroctl --node node1 app install --path ./my-app.mpk
meroctl --node node1 app ls

Positional PACKAGE@VERSION installs a published version from the one application source the node is configured with (its [registry] section); --path installs a local signed bundle. The two are mutually exclusive, and --watch applies to a --path install only.

A .mpk bundle is the only thing either form installs - there is no raw-.wasm path and no way to name a URL. A node in dht mode has no registry to ask, so PACKAGE@VERSION reports the coordinates as unpublished there; use --path, or let governance deliver the application.

list-packages, list-versions and get-latest-version all read this node’s own installed rows, not the registry. Because a bundle’s application id is version-stable, a package occupies one row, so list-versions reports the version this node currently holds.


Subcommand (aliases) Purpose Key args
list (ls) List all contexts.
create Create a new context. --application-id/-a, --group-id (required), --params/-p, --watch/-w <path>, --seed/-s, --name (context alias), --service, --identity-secret, --group-name
get <CONTEXT> Fetch context details: info, client-keys, or storage. CONTEXT, subcommand
delete (del) <CONTEXT> Delete a context. CONTEXT
update Update the application in a context. --context/-c, --application-id/-a, --path, --watch/-w
watch (ws) Stream context events, optionally run a command. --context, -x/--exec, -n/--count
sync Explicitly request a sync. --context/-c, --all
identity Manage context identities (see below). subcommand
alias Manage context aliases: add, remove, get, list. subcommand
use <CONTEXT> Set the default context. CONTEXT, --force
Subcommand (aliases) Purpose Key args
list (ls) List identities in a context. --context, --owned
generate (new) Generate a new identity keypair.
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) Purpose Key args
get <GROUP_ID> Get information about a group. GROUP_ID
delete (del) <GROUP_ID> Delete a group. GROUP_ID
members Manage group members (see below). subcommand
contexts List (list/ls) or detach contexts in a group. subcommand
metadata Show / update a group’s metadata record. subcommand
member-metadata Show / update a member’s metadata record. subcommand
context-metadata Show / 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
subgroups <GROUP_ID> List direct subgroups of a group. GROUP_ID
upgrade trigger, status, or retry a group upgrade. subcommand
sync <GROUP_ID> Sync a group from local state. GROUP_ID
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
settings Manage group-level default settings (see below). subcommand
Subcommand (aliases) Purpose Key args
list (ls) <GROUP_ID> List all members of a group. GROUP_ID
add <GROUP_ID> <IDENTITY> Add a member to a group. --role
remove <GROUP_ID> <IDENTITY...> Remove members from a group. identities
set-role <GROUP_ID> <IDENTITY> <ROLE> Update a member’s role.
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-access Check if an identity can join a context. GROUP_ID, identity
Subcommand (aliases) Purpose Key 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
set-subgroup-visibility (set-subgroup-vis) Set subgroup visibility (open/restricted). GROUP_ID, --mode
Terminal window
meroctl --node node1 group members list <group_id>
meroctl --node node1 group reparent <group_id> <new_parent_id>

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

Subcommand (aliases) Purpose Key args
create Create a new namespace. --application-id, --name, --bytecode-id (alias: --app-key)
get <NAMESPACE_ID> Get details about a namespace. NAMESPACE_ID
delete (del) <NAMESPACE_ID> Delete a namespace. NAMESPACE_ID
invite <NAMESPACE_ID> Create an invitation for a namespace. NAMESPACE_ID, --expiration-timestamp, --recursive, --admitter, --admitter-addr (see below)
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>'

namespace invite takes two optional flags that decide who may admit a joiner and where the joiner should look for them. Both are repeatable.

flag value what it does
--admitter account, 64 hex Narrows who may admit this invitation. Omit and the node uses the group’s admins plus its TEE nodes. Signed, so it cannot be redirected afterwards.
--admitter-addr /ip4/…/tcp/…/p2p/<peer-id> Where a joiner can dial an admitter. Unsigned, and must include the /p2p/ suffix.

You usually need neither. The node names the admitters itself and fills in addresses from what it already has on file. Reach for them when:

  • --admitter — you want a narrower set than every admin and TEE node.
  • --admitter-addr — the node’s address for an admitter is stale or missing (it has not seen that peer within the cache’s 24-hour window).
Terminal window
# Ordinary case: let the node decide who admits and where they are.
meroctl namespace invite $NS
# Narrow admission to one account, and say where it is.
meroctl namespace invite $NS \
--admitter 8f2c...e1 \
--admitter-addr /ip4/203.0.113.7/tcp/2528/p2p/12D3KooWExample

Addresses are unsigned, deliberately. A wrong one costs a failed dial and nothing more: libp2p authenticates the peer id on connect, and the signed --admitter list still decides who may answer. See Direct Admission for why an address travels unsigned while the admitter list cannot.

Subcommand (aliases) Purpose Key args
list (ls) List all blobs.
upload Upload a blob from a file. --file, --context-id
download Download a blob to a file. --blob-id, --output, --context-id
info Get 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 / flag Type / values Default Purpose
<METHOD> string Method to call (omit with --interactive).
--context/-c <CONTEXT> context alias/id default Context to call the method on.
--args <JSON> JSON {} JSON arguments to pass to the method.
--id <ID> string JSON-RPC call id.
--interactive/-i bool false Open a persistent WebSocket shell and run many calls.
--timeout <SECONDS> u64 120 Per-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>

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

<path> may be a signed .mpk bundle, or a project directory with a Cargo.toml (which is bundled with cargo mero bundle --dev --no-icon into dist/dev.mpk).

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

Subcommand Purpose
status Dump 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) Purpose Key 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) Purpose Key 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 application bundle 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 ./dist/com.example.kv-store-0.1.0.mpk \
    --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.