Skip to content

Development Workflow

The practical loop: build, run a cluster, test, and the conventions a PR has to meet.

  • Linux. merod and the node’s tests need Linux (x86_64 or aarch64). On macOS, run the node in Docker (Install) and build meroctl natively; run the node’s test suites in a Linux container or VM.

  • Rust pinned by rust-toolchain.toml (1.98.0, with clippy and rustfmt), and the wasm32-wasip2 target apps build for (the toolchain file lists it; rustup target add wasm32-wasip2 otherwise).

  • System packages: clang, libclang-dev, make, pkg-config, libssl-dev.

Terminal window
cargo build -p merod -p meroctl # the two binaries
cargo check --workspace # everything
scripts/install-mero-app-build.sh # once: puts mero-app-build on PATH
mero-app-build apps/kv-store --out kv_store.wasm # one app's component
cargo test --manifest-path apps/kv-store/Cargo.toml # an app's own tests, on the real engine

An app is a calimero:app component; the node reads its ABI (methods, views, confirm methods, timers, search fields) from the component’s own calimero:abi section. A WASM core module (an SDK 0.12 app) is refused.

The quickest cluster is one process:

Terminal window
cargo run -p merod -- local # 3 nodes on 127.0.0.1:2501-2503, state in .merod-local/
cargo run -p merod -- local --fresh # start over

then, in another terminal:

Terminal window
cargo run -p meroctl -- node add local http://127.0.0.1:2501/ --allow-mock
cargo run -p meroctl -- login --dev-passkey ./dev-passkey.json --name dev
cargo run -p meroctl -- context create --name kv --path kv_store.wasm

merod local runs every node in one process, with mock attestation and the development storage key. To exercise separate processes (crashes, restarts, a frozen node), run each node yourself:

  1. Initialize three nodes under a scratch home:

    Terminal window
    export CALIMERO_HOME=$PWD/.nodes
    P=1=http://127.0.0.1:2601/,2=http://127.0.0.1:2602/,3=http://127.0.0.1:2603/
    for i in 1 2 3; do
    merod --node n$i init --dev --node-id $i --listen 127.0.0.1:260$i \
    --public-url http://127.0.0.1:260$i/ --peers $P --ops-token devtoken
    done
    merod --node n1 config --bootstrap
  2. Run each in its own terminal:

    Terminal window
    merod --node n1 run
    merod --node n2 run
    merod --node n3 run
  3. Point meroctl at any of them with --allow-mock.

All three share the default --cluster dev, so they derive the same development storage key. Add --origins for a browser frontend on another port, and --registry-url to install PACKAGE@VERSION.

Terminal window
RUST_LOG=debug merod --node n1 run
RUST_LOG=info,calimero_node=debug,openraft=info merod --node n1 run

run defaults to info,openraft=warn, local to warn,openraft=off. Keep account ids and user or app content out of info! and above: scripts/check-no-user-data-at-info.py fails a change that logs them.

Run these locally; they are what the required checks are built from:

Terminal window
cargo fmt --check
cargo clippy --workspace --all-targets -- -D warnings
cargo clippy -p calimero-tee-attestation -p calimero-node --all-targets \
--features calimero-tee-attestation/mock-attestation,calimero-node/outbound-testing -- -D warnings

then the tests for what you changed (Testing has the fixtures they need), for example:

Terminal window
cargo test -p calimero-node
cargo test -p merod -p meroctl

./scripts/check-like-ci.py runs every job the required Rust check waits on, read from .github/workflows/ci-checks.yml (--list shows them, --only <name> runs some). Always run clippy with -D warnings: -A warnings allows every lint and can only pass.

Commit subjects and PR titles follow the commit rule in the coding standards. For pull requests:

  • A PR focuses on functionality or style, not both.
  • The PR template’s Description, Test plan and Documentation update sections are filled in, and its Trust boundary block where a trust-boundary path is touched.
  • A bug fix shows its reproduction and before and after output; the reproducing test stays as the regression test.
  • Maintainers squash-and-merge; resolve each review conversation as you address it.

The rest of the Definition of Done is in the root AGENTS.md.

Imports, module layout, error handling, dead code and trust boundaries are in CODING_STANDARDS.md.

Location What’s there
docs/ This documentation site (Astro Starlight).
AGENTS.md (root and per crate) Orientation for each part of the tree; crates/node/AGENTS.md is the node’s mental model.
CODING_STANDARDS.md How code in the repository is written.