Calimero Developer Tools¶
Developer tools for building, testing, and scaffolding Calimero applications locally. These tools streamline the development workflow from initial project setup to testing and deployment.
Overview¶
| Tool | Purpose | Language | Installation |
|---|---|---|---|
| Merobox | Local multi-node networks, workflow orchestration, testing | Python | pipx install merobox or brew install merobox |
| ABI Codegen | Generate TypeScript clients from Rust application ABIs | TypeScript/Node.js | npm install @calimero-network/abi-codegen |
| create-mero-app | Scaffold new Calimero apps from kv-store boilerplate | TypeScript/Node.js | npx create-mero-app@latest |
Merobox¶
Merobox is a Python CLI tool for managing Calimero nodes in Docker containers. It's essential for local development and testing, enabling you to spin up multi-node networks, execute complex workflows, and automate testing scenarios.
Features¶
- Node Management - Start, stop, and monitor Calimero nodes in Docker
- Multi-Node Networks - Run multiple nodes locally for testing P2P synchronization
- Workflow Orchestration - Execute complex multi-step workflows with YAML files
- Auth Service Integration - Traefik proxy and authentication service with nip.io DNS
- Context Management - Create and manage blockchain contexts
- Identity Management - Generate and manage cryptographic identities
- Function Calls - Execute smart contract functions via JSON-RPC
- Testing Support - Python testing fixtures for integration tests
Installation¶
Option 1: Using pipx (recommended)
# Using pipx (recommended)
$: pipx --version
> 1.7.1
$: pipx install merobox
> Installing to existing venv 'merobox'
> installed package merobox 0.2.13, installed using Python 3.13.3
> These apps are now globally available: merobox
> done! โจ ๐ โจ
Option 2: Using Homebrew
$: brew install calimero-network/tap/merobox
> ...
> ๐บ /opt/homebrew/Cellar/merobox/0.1.23: 4 files, 15.6MB, built in 0 seconds
> ==> Running `brew cleanup merobox`...
# Verify installation
$: merobox --version
> merobox, version 0.2.16
Option 3: From source
$: git clone https://github.com/calimero-network/merobox.git
> Cloning into 'merobox'...
> remote: Enumerating objects: 3979, done.
> ...
> Resolving deltas: 100% (2677/2677), done.
$: cd merobox
$: pipx install -e .
> Installing to existing venv 'merobox'
> installed package merobox 0.3.4, installed using Python 3.11.14
> These apps are now globally available
> - merobox
> done! โจ ๐ โจ
Quick Start¶
Basic Node Management¶
# Start a single Calimero node
$: merobox run --count 1
> ...
> โ Node calimero-node-1 initialized successfully
> Starting node calimero-node-1...
# Start multiple nodes
$: merobox run --count 2
> ...
> โ Node calimero-node-1 initialized successfully
> Starting node calimero-node-1...
> ...
> โ Node calimero-node-2 initialized successfully
> Starting node calimero-node-2...
# Start with custom ports
$: merobox run --name <NODE_ID> --base-port <BASE_PORT>
$: merobox run --name calimero-node-1 --base-port 2423
> ...
> - P2P Port: 2423
> ...
# List running nodes
$: merobox list
> Running Calimero Nodes
> โโโโโโโโโโโโโโโโโโโณโโโโโโโโโโณโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโณโโโโโโโโโโโณโโโโโโโโโโโโโโโโโณโโโโโโโโโโโโณโโโโโโโโโโโโโโโโโโโโโโ
> โ Name โ Status โ Image โ P2P Port โ RPC/Admin Port โ Chain ID โ Created โ
> โกโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฉ
> โ calimero-node-1 โ running โ ghcr.io/calimero-network/merod:edge โ 2423 โ 56928 โ testnet-1 โ 2026-01-29 11:09:37 โ
> โโโโโโโโโโโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโ
# Check node health
$: merobox health --node <NODE_ID>
$: merobox health --node calimero-node-1
> Checking health of node calimero-node-1 via http://localhost:56928
> Calimero Node Health Status
> โญโโโโโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโโฌโโโโโโโโโโฎ
> โ Node โ Health โ Authenticated โ Peers โ Status โ
> โโโโโโโโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโโค
> โ calimero-node-1 โ alive โ Unknown โ 0 โ Healthy โ
> โฐโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโดโโโโโโโโดโโโโโโโโโโฏ
# View node logs
$: merobox logs <NODE_ID> --follow
$: merobox logs calimero-node-1 --follow
> ...
> 2026-01-29T11:14:13.352058500Z [2m2026-01-29T11:14:13.351606Z[0m [34mDEBUG[0m [1mSwarm::poll[0m[2m:[0m [2mlibp2p_gossipsub::behaviour[0m[2m:[0m RANDOM PEERS: Got 0 peers
> 2026-01-29T11:14:13.352067750Z [2m2026-01-29T11:14:13.351628Z[0m [34mDEBUG[0m [1mSwarm::poll[0m[2m:[0m [2mlibp2p_gossipsub::behaviour[0m[2m:[0m Updating mesh, new mesh: {}
> ...
# Stop a node
$: merobox stop <NODE_ID>
$: merobox stop calimero-node-1
> โ Stopped and removed node calimero-node-1
# Remove all node data (destructive!)
$: merobox nuke --prefix calimero-node-1
> Found 1 Calimero node data directory(ies):
> Calimero Node Data Directories
> โญโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโฎ
> โ Directory โ Status โ
> โโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโค
> โ data/calimero-node-1 โ Found โ
> โฐโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโฏ
> Total data size: 848.6 KB
> โ ๏ธ WARNING: This will permanently delete ALL Calimero node data!
> This action cannot be undone.
> Type 'YES' to confirm deletion: YES
> Found 1 Calimero node data directory(ies)
> โ Found merod binary in PATH: /opt/homebrew/bin/merod
> Stopping Docker container calimero-node-1...
> Deleting 1 data directory(ies)...
> โ Successfully deleted 1 data directory(ies)
> Total space freed: 848.6 KB
> To start fresh, run:
> merobox run
Application Management¶
# Install a WASM application on a node
$: merobox install --node <NODE_ID> --dev --path <PATH_TO_WASM>
$: merobox install --node calimero-node-1 --dev --path res/my_app.wasm
> โ Application installed successfully!
> Application ID: 7mHCKUsCeb84hDF8trn1eNzcqH8L1LNbdZiCcvFUWx7s
Identity & Context Creation¶
# Merobox command for creating contexts
$: merobox context create --node <NODE_ID> --protocol <PROTOCOL> --application-id <APP_ID>
# Creating context with application ID from previous steps using NEAR protocol
$: merobox context create --node calimero-node-1 --protocol near --application-id 7mHCKUsCeb84hDF8trn1eNzcqH8L1LNbdZiCcvFUWx7s
> Creating context for application 7mHCKUsCeb84hDF8trn1eNzcqH8L1LNbdZiCcvFUWx7s on node calimero-node-1
> โ Context created successfully!
> Context ID: FCaGbSngPec9u2mTSXJy1jRjzqLZUfHuuEppPiaRKJHS
> Member Public Key: CgZxoj9mMECAGFVrGQ3mA8X57bWt38jvTPuAo3RAPhos
# Merobox command to view created context data
$: merobox context list --node calimero-node-1
> Listing contexts on node calimero-node-1
> Found 1 context(s):
> Fetching member public keys...
> Contexts
> โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
> โ Context ID โ Application ID โ Member Public Key โ
> โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
> โ FCaGbSngPec9u2mTSXJy1jRjzqLZUfHuuEppPiaRKJHSโ 7mHCKUsCeb84hDF8trn1eNzcqH8L1LNbdZiCcvFUWxโฆ โ CgZxoj9mMECAGFVrGQ3mA8X57bWt38jvTPuAo3RAPhos โ
> โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
# Merobox command for viewing context data
$: Getting context FCaGbSngPec9u2mTSXJy1jRjzqLZUfHuuEppPiaRKJHS from node calimero-node-1
> โ Context details:
> Context ID: FCaGbSngPec9u2mTSXJy1jRjzqLZUfHuuEppPiaRKJHS
> Application ID: 7mHCKUsCeb84hDF8trn1eNzcqH8L1LNbdZiCcvFUWx7s
> Root Hash: 3qKcevhyARug9bwrfn4mWWHyVdTYGEokgvxJ5NpJiFU9
Interact with the Application¶
# Merobox - call a mutation command
$: merobox call --node <NODE_ID> --context-id <CONTEXT_ID> --function <METHOD_NAME> --args <ARGS_IN_JSN> --executor-key <IDENTITY_PUBLIC_KEY>
# Commands from previous steps
$: merobox call --node calimero-node-1 --context-id FCaGbSngPec9u2mTSXJy1jRjzqLZUfHuuEppPiaRKJHS --function add_item --args '{"key": "hello", "value": "world"}' --executor-key CgZxoj9mMECAGFVrGQ3mA8X57bWt38jvTPuAo3RAPhos
> Using RPC endpoint: http://localhost:59603
> ...
> ๐ JSON-RPC Parsed Response: {
> jsonrpc: 2.0,
> id: 1,
> result: {
> output: null
> }}
> โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ Function Call Result โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
> โ Function call successful! โ
> โ โ
> โ Function: add_item โ
> โ Context: FCaGbSngPec9u2mTSXJy1jRjzqLZUfHuuEppPiaRKJHS โ
> โ Node: calimero-node-1 โ
> โ Result: {'id': '1', 'jsonrpc': '2.0', 'result': {'output': None}} โ
> โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
# Merobox - call a view command
$: merobox call --node <NODE_ID> --context-id <CONTEXT_ID> --function <METHOD_NAME> --args <ARGS_IN_JSN> --executor-key <IDENTITY_PUBLIC_KEY>
# Commands from previous steps
$: merobox call --node calimero-node-1 --context-id FCaGbSngPec9u2mTSXJy1jRjzqLZUfHuuEppPiaRKJHS --function get_item --args '{"key": "hello"}' --executor-key CgZxoj9mMECAGFVrGQ3mA8X57bWt38jvTPuAo3RAPhos
> Using RPC endpoint: http://localhost:59603
> ...
> ๐ JSON-RPC Parsed Response: {
> jsonrpc: 2.0,
> id: 1,
> result: {
> output: world
> }
> }
> โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ Function Call Result โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
> โ Function call successful! โ
> โ โ
> โ Function: get_item โ
> โ Context: FCaGbSngPec9u2mTSXJy1jRjzqLZUfHuuEppPiaRKJHS โ
> โ Node: calimero-node-1 โ
> โ Result: {'id': '1', 'jsonrpc': '2.0', 'result': {'output': 'world'}} โ
> โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
Context Invitations¶
# Create new context identity we will use for context invitation
$: merobox identity generate --node <NODE_ID>
# From invitee node use following (calimero-node-2)
$: merobox identity generate --node calimero-node-2
> Generating new identity on node calimero-node-2 via http://localhost:2529
> Used endpoint: http://localhost:2529/admin-api/identity/context
>
> โ Identity generated successfully!
> New Identity Details
> โญโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
> โ Property โ Value โ
> โโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
> โ Public Key โ 8XPcdpWW8213DUGvFd1WCM3FDcYmwwpJdGWADqRwD2ek โ
> โฐโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
# From calimero-node-1 fetch context identity as it will be used for invitation
$: merobox identity list-identities --node <NODE_ID> --context-id <CONTEXT_ID>
$: merobox identity list-identities --node calimero-node-1 --context-id 6XwNgtagbiMB8SojkznnmWm83aG93HJPo5HJsGpnYDQs
> Listing identities for context 6XwNgtagbiMB8SojkznnmWm83aG93HJPo5HJsGpnYDQs on node calimero-node-1 via http://localhost:2528
> โญโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
> โ Identity โ Value โ
> โโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
> โ Public Key โ i1ZPRqvQNE43e2gMtfbaX1zaJLk4ahBkxcTgHmShFXs โ
> โฐโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
# From calimero-node-1 create invitation for calimero-node-2
$: merobox identity invite --node <NODE_ID> --context-id <CONTEXT_ID> --inviter-id <INVITER_IDENTITY> --invitee-id <INVITEE_IDENTITY>
$: merobox identity invite --node calimero-node-1 --context-id 6XwNgtagbiMB8SojkznnmWm83aG93HJPo5HJsGpnYDQs --inviter-id i1ZPRqvQNE43e2gMtfbaX1zaJLk4ahBkxcTgHmShFXs --invitee-id 8XPcdpWW8213DUGvFd1WCM3FDcYmwwpJdGWADqRwD2ek
> Inviting identity 8XPcdpWW8213DUGvFd1WCM3FDcYmwwpJdGWADqRwD2ek to context 6XwNgtagbiMB8SojkznnmWm83aG93HJPo5HJsGpnYDQs on node calimero-node-1 via http://localhost:2528
> Used endpoint: http://localhost:2528/admin-api/contexts/invite
>
> โ Identity invited successfully!
> Identity Invitation Details
> โญโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
> โ Property โ Value โ
> โโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
> โ Context ID โ 6XwNgtagbiMB8SojkznnmWm83aG93HJPo5HJsGpnYDQs โ
> โ Inviter ID โ i1ZPRqvQNE43e2gMtfbaX1zaJLk4ahBkxcTgHmShFXs โ
> โ Invitee ID โ 8XPcdpWW8213DUGvFd1WCM3FDcYmwwpJdGWADqRwD2ek โ
> โ Invitation โ 8XgbiMB8Sojkznngtagd1WCM3FDcYmwwpJdGWAbiMXPcdpWWJdGWADqRwm83aG938213DUGv โ
> โฐโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
# From calimero-node-2 join invitation
$: merobox join context --node <NODE_ID> --context-id <CONTEXT_ID> --invitee-id <INVITEE_ID> --invitation <INVITATION_PAYLOAD>
$: merobox join context --node calimero-node-2 --context-id 6XwNgtagbiMB8SojkznnmWm83aG93HJPo5HJsGpnYDQs --invitee-id 8XPcdpWW8213DUGvFd1WCM3FDcYmwwpJdGWADqRwD2ek --invitation 8XgbiMB8Sojkznngtagd1WCM3FDcYmwwpJdGWAbiMXPcdpWWJdGWADqRwm83aG938213DUGv
> Joining context 6XwNgtagbiMB8SojkznnmWm83aG93HJPo5HJsGpnYDQs with identity 8XPcdpWW8213DUGvFd1WCM3FDcYmwwpJdGWADqRwD2ek on node calimero-node-2 via http://localhost:2529
> Context joined successfully!
# Invitations using Open Invitations
# Open Invitations - invitations that are not bounded by specific invitee id and can by used by any node. Once claimed (node joins the context), it stop being valid.
$: merobox identity invite-open --node <NODE_ID> --context-id <CONTEXT_ID> --inviter-id <INVITER_IDENTITY>
$: merobox identity invite-open --node calimero-node-1 --context-id 6XwNgtagbiMB8SojkznnmWm83aG93HJPo5HJsGpnYDQs --inviter-id i1ZPRqvQNE43e2gMtfbaX1zaJLk4ahBkxcTgHmShFXs
> Creating open invitation for context 6XwNgtagbiMB8SojkznnmWm83aG93HJPo5HJsGpnYDQs on node calimero-node-1
> Valid for 1000 blocks
> Used endpoint: http://localhost:2528/admin-api/dev/contexts/invite-open
>
> โ Open invitation created successfully!
> Open Invitation Details
> โญโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
> โ Property โ Value โ
> โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
> โ Context ID โ 6XwNgtagbiMB8SojkznnmWm83aG93HJPo5HJsGpnYDQs โ
> โ Inviter ID โ i1ZPRqvQNE43e2gMtfbaX1zaJLk4ahBkxcTgHmShFXs โ
> โ Valid for Blocks โ 1000 โ
> โฐโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
>
> Invitation Data:
> {
> "data": {
> "invitation": {
> "context_id": [82, ...],
> "contract_id": "v0-6.config.calimero-context.testnet",
> "expiration_height": 1000000999,
> "inviter_identity": [10, ...],
> "network": "testnet",
> "protocol": "near",
> "secret_salt": [123, ...]
> },
> "inviter_signature": "8024d458e38d42970e89e24c046c9a2f3b13cc98727e5ec3d576113e2c4f02"
> }
> }
> Save this invitation data to share with others who want to join.
# Join open invitation from calimero-node-2
$: merobox join open --node <NODE_ID> --invitee-id <INVITEE_ID> --invitation <INVITATION_PAYLOAD_JSON>
$: merobox join open --node calimero-node-2 --invitee-id 8XPcdpWW8213DUGvFd1WCM3FDcYmwwpJdGWADqRwD2ek --invitation '{"data":{"invitation":{"c....'
> Joining context on node calimero-node-2 as 8XPcdpWW8213DUGvFd1WCM3FDcYmwwpJdGWADqRwD2ek via open invitation
> Used endpoint: http://localhost:2529/admin-api/dev/contexts/join-open
>
> โ Successfully joined context via open invitation!
> Context Join Details
โญโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Property โ Value โ
โโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Context ID โ N/A โ
โ Member Public Key โ N/A โ
โ Invitee ID โ 8XPcdpWW8213DUGvFd1WCM3FDcYmwwpJdGWADqRwD2ek โ
โ Node โ calimero-node-2 โ
โฐโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
Workflow Orchestration¶
Merobox supports complex multi-step workflows defined in YAML files:
# Core repository apps/kv-store example
# workflow.yml
description: Simple Store Application Workflow (Rust)
name: Simple Store App Test
force_pull_image: true
nodes:
chain_id: testnet-1
count: 1
image: ghcr.io/calimero-network/merod:edge
prefix: simple-store-node
steps:
- name: Install Simple Store Application
type: install_application
node: simple-store-node-1
path: "res/kv_store.wasm"
dev: true
outputs:
app_id: applicationId
- name: Create Simple Store Context
type: create_context
node: simple-store-node-1
application_id: '{{app_id}}'
params: '{}'
outputs:
context_id: contextId
member_public_key: memberPublicKey
- name: Create Identity on Node 2
type: create_identity
node: simple-store-node-2
outputs:
member_public_key_2: publicKey
- name: Invite Node 2 from Node 1
type: invite_identity
node: simple-store-node-1
context_id: '{{context_id}}'
grantee_id: '{{member_public_key_2}}'
granter_id: '{{member_public_key}}'
capability: member
outputs:
invitation_2: invitation
- name: Join Context from Node 2
type: join_context
node: simple-store-node-2
context_id: '{{context_id}}'
invitee_id: '{{member_public_key_2}}'
invitation: '{{invitation_2}}'
- name: Set Value from node 1
type: call
node: simple-store-node-1
context_id: '{{context_id}}'
executor_public_key: '{{member_public_key}}'
method: set
args:
key: greeting
value: hello-world
- name: Set Value from node 2
type: call
node: simple-store-node-2
context_id: '{{context_id}}'
executor_public_key: '{{member_public_key_2}}'
method: join_chat
method: set
args:
key: greeting2
value: hello-world2
- name: Get Value
type: call
node: simple-store-node-1
context_id: '{{context_id}}'
executor_public_key: '{{member_public_key}}'
method: get
args:
key: greeting
outputs:
store_result: result.output
- name: Get Value
type: call
node: simple-store-node-2
context_id: '{{context_id}}'
executor_public_key: '{{member_public_key_2}}'
method: get
args:
key: greeting2
outputs:
store_result2: result.output
- name: Assert Value Matches
type: json_assert
statements:
- 'equal({{store_result}}, "hello-world")'
- name: Assert Value Matches
type: json_assert
statements:
- 'equal({{store_result2}}, "hello-world2")'
stop_all_nodes: false
restart: false
wait_timeout: 120
Execute a workflow:
$: merobox bootstrap run workflow.yml
> ...
> run_workflow: incoming log_level='debug'
> run_workflow: incoming rust_backtrace='0'
> WorkflowExecutor: resolved log_level='debug', binary_mode=False
> WorkflowExecutor: workflow_id='ad731613' (for test isolation)
> WorkflowExecutor: resolved rust_backtrace='0', binary_mode=False
>
> ๐ Executing Workflow: Simple Store App Test
> ...
Workflow steps:
identity- Create cryptographic identities and context invitationscontext- Create blockchain contextsinstall- Install WASM applicationsexecute- Execute function callsjoin- Join contextsinvite_open- Create open invitationsjoin_open- Join via open invitationwait- Wait for conditionsassert- Assert expected resultsrepeat- Repeat steps multiple timesscript- Execute shell scripts
Auth Service Integration¶
Merobox can integrate with authentication services using Traefik proxy:
This automatically:
- Starts Traefik proxy (
traefik:v2.10) - Starts auth service (
ghcr.io/calimero-network/calimero-auth:latest) - Creates Docker networks (
calimero_web,calimero_internal) - Configures nip.io DNS resolution
- Sets up forward authentication middleware
Access patterns:
- Node 1 API:
http://node1.127.0.0.1.nip.io/jsonrpc(protected) - Node 1 Dashboard:
http://node1.127.0.0.1.nip.io/admin-dashboard(public) - Auth Service:
http://localhost/auth/(authentication endpoints)
Use Cases¶
- Local Development - Spin up local nodes for development and testing
- Integration Testing - Multi-node test scenarios with automated workflows
- CI/CD Pipelines - Automated testing in CI environments
- Demo Environments - Quick setup for demonstrations
- Network Simulation - Test P2P synchronization with multiple nodes
Related Documentation¶
- Repository:
calimero-network/merobox - PyPI Package:
merobox - README:
merobox/README.md
ABI Codegen¶
ABI Codegen (@calimero-network/abi-codegen) generates TypeScript client code and type definitions from Rust application ABI manifests. It parses WASM-ABI v1 manifest files and generates fully-typed TypeScript clients for interacting with your Calimero applications.
Features¶
- TypeScript Generation - Fully-typed client classes and type definitions
- WASM-ABI v1 Support - Parses standard ABI manifest format
- Method Generation - Generates methods for all Rust functions
- Event Types - Generates TypeScript types for events
- Error Types - Generates error types for method errors
- CLI & Programmatic - Use as CLI tool or import programmatically
Installation¶
$: npm install @calimero-network/abi-codegen
> ...
> dependencies:
> + @calimero-network/abi-codegen 1.0.0
Quick Start¶
CLI Usage¶
# Basic usage
$: npx calimero-abi-codegen -i abi.json -o src
# With custom client name
$: npx calimero-abi-codegen -i abi.json -o src --client-name MyClient
# Validate ABI manifest only (no code generation)
$: npx calimero-abi-codegen --validate -i abi.json
# Derive client name from WASM file
$: npx calimero-abi-codegen -i abi.json -o src --name-from kv_store.wasm
CLI Options¶
-i, --input <file>- Input ABI JSON file (default:abi.json)-o, --outDir <dir>- Output directory for generated files (default:src)--client-name <Name>- Custom client class name (default:Client)--name-from <path>- Derive client name from file path (e.g., WASM file)--import-path <path>- Custom import path for CalimeroApp and Context (default:@calimero-network/calimero-client)--validate- Validate ABI manifest only (no code generation)-h, --help- Show help message
Programmatic Usage¶
import { loadAbiManifestFromFile } from '@calimero-network/abi-codegen/parse';
import { generateTypes } from '@calimero-network/abi-codegen/generate/types';
import { generateClient } from '@calimero-network/abi-codegen/generate/client';
// Load ABI manifest
const manifest = loadAbiManifestFromFile('./abi.json');
// Generate TypeScript types
const typesContent = generateTypes(manifest);
// Generate client class
const clientContent = generateClient(manifest, 'MyClient');
// Write to files
await fs.writeFile('src/types.ts', typesContent);
await fs.writeFile('src/MyClient.ts', clientContent);
Generated Files¶
ABI Codegen generates two files:
- types.ts - TypeScript type definitions for all types, events, and errors
- {ClientName}.ts - Client class with methods for all Rust functions
Example Generated Client¶
import { CalimeroApp, Context } from '@calimero-network/calimero-client';
// Generated types
export interface SetValueArgs {
key: string;
value: string;
}
export interface GetValueArgs {
key: string;
}
export interface ItemAddedEvent {
key: string;
value: string;
timestamp: number;
}
// Generated client
export class KvStoreClient {
constructor(
private app: CalimeroApp,
private context: Context
) {}
async setValue(args: SetValueArgs): Promise<void> {
await this.app.mutate({
contextId: this.context.id,
method: 'set_value',
argsJson: args,
executorPublicKey: this.context.executorPublicKey,
});
}
async getValue(args: GetValueArgs): Promise<string | null> {
const response = await this.app.query({
contextId: this.context.id,
method: 'get_value',
argsJson: args,
executorPublicKey: this.context.executorPublicKey,
});
return response.result as string | null;
}
}
ABI Manifest Format¶
ABI manifests follow the WASM-ABI v1 specification:
{
"version": "1",
"methods": [
{
"name": "set_value",
"args": {
"key": "string",
"value": "string"
},
"returns": null,
"errors": []
},
{
"name": "get_value",
"args": {
"key": "string"
},
"returns": "string | null",
"errors": []
}
],
"events": [
{
"name": "ItemAdded",
"payload": {
"key": "string",
"value": "string",
"timestamp": "number"
}
}
],
"types": {
"SetValueArgs": {
"fields": {
"key": "string",
"value": "string"
}
}
}
}
Integration with Build Process¶
Add to your package.json:
{
"scripts": {
"generate:client": "calimero-abi-codegen -i abi.json -o src/generated",
"build": "npm run generate:client && npm run build:app"
}
}
Use Cases¶
- Type Safety - End-to-end type safety from Rust to TypeScript
- API Generation - Automatic client generation from Rust applications
- Developer Experience - Auto-complete and type checking in IDEs
- Documentation - Types serve as documentation for your API
Related Documentation¶
- Repository:
calimero-network/mero-devtools-js - NPM Package:
@calimero-network/abi-codegen - README:
mero-devtools-js/README.md
create-mero-app¶
create-mero-app scaffolds new Calimero applications by cloning the kv-store example repository and copying its files (excluding Git artifacts). It provides a ready-to-use boilerplate for building new Calimero applications.
Features¶
- Quick Scaffolding - Generate new apps in seconds
- kv-store Boilerplate - Based on the proven kv-store example
- Clean Output - Excludes Git artifacts and node_modules
- Package Name Setup - Automatically configures package.json name
Installation¶
No installation required - use via npx:
$: npx create-mero-app@latest my-app
> ? Select backend template โบ - Use arrow-keys. Return to submit.
> โฏ Rust (kv-store)
> JavaScript (kv-store-js)
> ...
> โ Select backend template โบ Rust (kv-store)
> ...
> Scaffolding project in /Users/X/Desktop/my-app
> Using template: Rust (kv-store)
> Cloning into '/var/folders/p2/_b7fvy792s3458_0jlf6r0jm0000gn/T/mero-create-SY6uxl/repo'...
> Done.
Quick Start¶
# Create a new app
$: npx create-mero-app@latest my-kv-store
> Need to install the following packages:
> create-mero-app@0.2.0
> Ok to proceed? (y) Y
>
> โ Select backend template โบ Rust (kv-store)
>
> Scaffolding project in /Users/X/Desktop/my-kv-store
> Using template: Rust (kv-store)
> Cloning into '/var/folders/p2/_b7fvy792s3458_0jlf6r0jm0000gn/T/mero-create-r9f8D4/repo'...
> Done.
> Next steps:
> cd my-kv-store
> pnpm install
> pnpm dev
# Navigate to the new app
$: cd my-kv-store
# Install dependencies
$: pnpm install
> ...
> dependencies:
> + @calimero-network/mero-icons 0.0.4
> + @calimero-network/mero-ui 0.3.6
>
> devDependencies:
> + chokidar-cli 3.0.0
> + concurrently 9.2.1
> + husky 9.0.11
# Build the WASM application
$: cd logic
$: chmod +x ./build.sh
$: ./build.sh
> info: component 'rust-std' for target 'wasm32-unknown-unknown' is up to date
> Compiling proc-macro2 v1.0.105
> ...
> Finished `app-release` profile [optimized] target(s) in 17.93s
# Start the frontend
$: cd ../app
$: pnpm install && pnpm build
> ...
> dependencies:
> + @calimero-network/calimero-client 1.25.0-beta.1
> + @calimero-network/mero-icons 0.0.4
> ...
> kv-store-app@1.0.0 build /Users/frandomovic/Desktop/my-kv-store/app
> vite build
> ...
> โ built in 1.33s
$: pnpm dev
> ...
> VITE v7.2.1 ready in 172 ms
>
> โ Local: http://localhost:5173/
> ...
What Gets Generated¶
The tool clones the calimero-network/kv-store repository and copies:
- Rust Application (
logic/) - WASM application with CRDT state - React Frontend (
app/) - React application with TypeScript - Build Scripts - Build scripts for Rust and TypeScript
- Configuration - TypeScript config, package.json, etc.
- Workflows (
workflows/) - Merobox workflows for local testing
Excluded:
.git/and.github/- Git artifactsnode_modules/- Dependencies (installed viapnpm install)
Project Structure¶
my-kv-store/
โโโ logic/ # Rust WASM application
โ โโโ src/
โ โ โโโ lib.rs # Main application logic
โ โโโ Cargo.toml
โ โโโ build.sh # Build script
โโโ app/ # React frontend
โ โโโ src/
โ โ โโโ App.tsx # Main React component
โ โโโ package.json
โ โโโ vite.config.ts
โโโ workflows/ # Merobox workflows
โ โโโ local-network.yml
โโโ package.json # Root package.json
โโโ README.md
Customization¶
After scaffolding, customize your app:
- Update Application Logic - Modify
logic/src/lib.rswith your business logic - Update Frontend - Modify
app/src/App.tsxwith your UI - Update Package Names - Update
package.jsonfiles with your project name - Add Dependencies - Install additional npm/Rust packages as needed
Next Steps¶
- Build the WASM - Compile Rust or TypeScript to WASM:
cd logic && ./build.sh - Generate TypeScript Client - Use ABI codegen to generate client types
- Start Local Network - Use Merobox to start local nodes:
merobox bootstrap run workflows/local-network.yml - Run Frontend - Start the React app:
cd app && pnpm dev - Deploy - Deploy your WASM to Calimero nodes and host your frontend
Use Cases¶
- Quick Prototyping - Rapidly scaffold new application ideas
- Learning - Start with a working example to understand Calimero
- Boilerplate - Base template for new applications
- Development - Ready-to-use development environment
Related Documentation¶
- Repository:
calimero-network/mero-devtools-js - NPM Package:
create-mero-app - README:
mero-devtools-js/create-mero-app/README.md - kv-store Example:
calimero-network/kv-store
Related Topics¶
- Client SDKs - Client libraries for interacting with nodes
- meroctl CLI - Command-line interface for node management
- SDK Guide - Building Calimero applications
- Core Apps Examples - Reference implementations