Quickstart
This walks from an empty crate to a method call. The two binaries you use are
merod (the node daemon — init, run) and meroctl (the operator
CLI — app, context, namespace, call).
1. Write and build the app
Section titled “1. Write and build the app”-
Create a library crate with a WASM-compatible
crate-type. A minimalCargo.toml, modelled onapps/kv-store/Cargo.toml:[lib]crate-type = ["cdylib", "rlib"][dependencies]calimero-sdk = { git = "https://github.com/calimero-network/core" }calimero-storage = { git = "https://github.com/calimero-network/core" }[dev-dependencies]# native test harness (TestHost) + CRDT merge under `cargo test`calimero-storage = { git = "https://github.com/calimero-network/core", features = ["testing"] } -
Write the smallest possible app — a state struct plus one method. This is the shape every Calimero app follows (see SDK macros):
use calimero_sdk::app;use calimero_storage::collections::{LwwRegister, UnorderedMap};#[app::state]pub struct KvStore {items: UnorderedMap<String, LwwRegister<String>>,}#[app::logic]impl KvStore {#[app::init]pub fn init() -> KvStore {KvStore { items: UnorderedMap::new() }}pub fn set(&mut self, key: String, value: String) -> app::Result<()> {self.items.insert(key, value.into())?;Ok(())}#[app::view]pub fn get(&self, key: String) -> app::Result<Option<String>> {Ok(self.items.get(&key)?.map(|v| v.get().clone()))}} -
Build to WASM. The example apps ship a
build.sh; the load-bearing line is:Terminal window rustup target add wasm32-unknown-unknowncargo build --target wasm32-unknown-unknown --profile app-releaseThe artifact lands at
target/wasm32-unknown-unknown/app-release/<crate_name>.wasm. The example scripts then copy it into a localres/directory and (ifwasm-optis installed) shrink it:Terminal window wasm-opt -Oz --enable-bulk-memory ./res/my_app.wasm -o ./res/my_app.wasm
2. Run a node
Section titled “2. Run a node”-
Initialize a node’s config and data directory, then run it:
Terminal window merod --node node1 init --server-port 2428 --swarm-port 2528merod --node node1 runmerod --node node1 init --helplists the full set (swarm/server host and port, boot nodes, mDNS, auth mode). Config and data live underCALIMERO_HOME/--home.
3. Install the app, attach a context, call a method
Section titled “3. Install the app, attach a context, call a method”meroctl talks to a running node. Select the node with --node node1 (a
configured alias) or --api <URL>.
-
Install the WASM module. The node returns an application id:
Terminal window meroctl --node node1 app install \--path ./res/my_app.wasm \--package com.example.myapp \--version 1.0.0List what is installed with
meroctl --node node1 app ls. -
Attach the app to a context. A context is a running instance of an app over a shared state. The simplest entry is to create a namespace bound to the application id:
Terminal window meroctl --node node1 namespace create --application-id <app-id> -
Call a method on the context. Mutations and views both go through the top-level
callcommand — whether a call mutates or is a read-only view is decided by the method’s own#[app::view]marker, not a CLI flag:Terminal window # mutatemeroctl --node node1 call set \--context <context-id> \--args '{"key": "hello", "value": "world"}'# viewmeroctl --node node1 call get \--context <context-id> \--args '{"key": "hello"}'--argstakes JSON matching the method’s parameters.<context-id>accepts a context id or an alias you created with--name.
These three commands trace one path from a built artifact to a method result — install the code, attach a context over shared state, then call into it: