Skip to content

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. Scaffold an app with the cargo mero toolchain:

    Terminal window
    cargo mero new my-app
    cd my-app

    This writes a ready-to-build crate: Cargo.toml (SDK pins, the app-id metadata, and the build profiles), a working src/lib.rs, and a TestHost test. The tutorial walks the generated manifest field by field.

  2. The generated src/lib.rs is already a working app: a state struct plus methods. 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()))
    }
    }
  3. Build to WASM with the cargo mero toolchain:

    Terminal window
    cargo mero build

    One command compiles, optimizes, and embeds the ABI; the wasm lands at res/<crate_name>.wasm.

  4. Package and sign it into the installable .mpk:

    Terminal window
    cargo mero bundle --dev --no-icon

    The bundle is named from the manifest’s package and version, not the crate name: dist/com.example.my-app-0.1.0.mpk. --dev signs with the well-known development key, which the registry refuses - see Packaging & signing for release keys.

  1. Initialize a node’s config and data directory, then run it:

    Terminal window
    merod --node node1 init --server-port 2428 --swarm-port 2528
    merod --node node1 run

    merod --node node1 init --help lists the full set (swarm/server host and port, boot nodes, mDNS, auth mode). Config and data live under CALIMERO_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>.

  1. Install the signed bundle. The node returns an application id:

    Terminal window
    meroctl --node node1 app install --path ./dist/com.example.my-app-0.1.0.mpk

    List what is installed with meroctl --node node1 app ls.

    Only a signed .mpk installs: its package and signerId are what the application id is derived from, so every node derives the same one. Run cargo mero bundle to produce it - see Packaging & signing.

  2. 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>
  3. Call a method on the context. Mutations and views both go through the top-level call command — 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
    # mutate
    meroctl --node node1 call set \
    --context <context-id> \
    --args '{"key": "hello", "value": "world"}'
    # view
    meroctl --node node1 call get \
    --context <context-id> \
    --args '{"key": "hello"}'

    --args takes 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: