System Overview
merobox is a Python CLI that runs Calimero Core
nodes and drives them through declarative YAML scenarios. It is the end-to-end
test harness for Calimero: it boots real merod nodes — as Docker containers or
native processes — then bootstraps contexts, installs applications, invites
members, calls methods, and asserts on the results.
This page is the entry point. It names the moving parts, says what each one does,
and points at where it lives in the merobox/ package so you can jump from the
concept to the code.
The shape of a run
Section titled “The shape of a run”Everything funnels through one CLI. The most common entry point is a workflow:
merobox bootstrap run workflow.ymlThat single command walks through the whole lifecycle:
merobox bootstrap run workflow.yml │ ▼┌─────────────────────────────────────────────────────────┐│ WorkflowExecutor (commands/bootstrap/run/executor.py) ││ parse & validate YAML ││ nuke_on_start (optional) → force_pull_image (optional) ││ start local nodes → resolve/connect remote nodes ││ run steps sequentially → cleanup / nuke_on_end │└─────────────────────────────────────────────────────────┘ │ │ │ ▼ ▼ ▼ DockerManager / NodeResolver each step calls BinaryManager + AuthManager merod over (start merod) + RemoteNodeManager JSON-RPC │ (calimero-client-py) ▼ merod nodes (Docker containers or native processes)The moving parts
Section titled “The moving parts”CLI (Click)
Section titled “CLI (Click)”The command surface lives in merobox/cli.py,
a Click group. The entry point is
merobox.cli:main (declared in pyproject.toml under [project.scripts]). It
registers these top-level commands: bootstrap, run, health, logs,
stop, nuke, remote, group, and namespace. Each command module lives
under merobox/commands/. The full command and flag reference is in the
CLI reference.
run starts nodes directly; bootstrap runs (and validates) YAML workflows.
Docker node manager — DockerManager
Section titled “Docker node manager — DockerManager”DockerManager (merobox/commands/manager.py) is the default backend. Using
the Docker SDK (docker-py), it manages the full container lifecycle: pulling
the merod image, creating the network, starting/stopping/removing containers,
and mapping ports. When a workflow enables the auth service it also stands up a
Traefik reverse proxy and the auth stack in
front of the nodes. See node management.
Binary node manager — BinaryManager
Section titled “Binary node manager — BinaryManager”BinaryManager (merobox/commands/binary_manager.py) is the alternative
backend, selected with --no-docker. Instead of containers it spawns native
merod processes, tracks them with PID files, and tears them down with signals
(SIGTERM/SIGKILL). Binary mode is what supports passing extra flags straight
to merod run (--merod-args=...) and the embedded JWT auth path
(--auth-mode embedded).
Node resolution — NodeResolver, AuthManager, RemoteNodeManager
Section titled “Node resolution — NodeResolver, AuthManager, RemoteNodeManager”Steps refer to nodes by name; NodeResolver (merobox/commands/node_resolver.py)
turns a reference into a concrete URL and handles authentication. Its resolution
order is: registered remote node → direct URL → Docker container → binary
process. Along the way it uses AuthManager (merobox/commands/auth.py) for
JWT authentication (user/password or API key) and RemoteNodeManager
(merobox/commands/remote_nodes.py) for the registry of pre-existing remote
nodes. This is what lets a workflow target locally-started nodes and remote ones
uniformly — see remote nodes.
Workflow engine — WorkflowExecutor and the steps
Section titled “Workflow engine — WorkflowExecutor and the steps”The workflow engine is the heart of merobox. WorkflowExecutor
(merobox/commands/bootstrap/run/executor.py) orchestrates the whole run:
parse and validate the YAML, optionally nuke prior state, start local nodes,
connect remote ones, execute the steps in order, and clean up. It maintains a
workflow_results dictionary that accumulates each step’s output so later steps
can reference earlier values.
- Steps live in
merobox/commands/bootstrap/steps/. Every step subclassesBaseStep(steps/base.py), which defines an asyncexecute()plus field validation helpers. There are nearly 100 step types — application install, context create, identity create, invite/join,call,assert,wait,repeat,parallel,script, blob upload, group/namespace governance, fault injection,fuzzy_test, and more. - Dispatch is a direct
type → step classmapping in the executor’s_create_step_executor(atypestring selects the handler); there is no separate factory registry. - Config parsing is in
bootstrap/config.py; validation (forbootstrap validate) is inbootstrap/validate/validator.py. - Placeholders use
{{...}}syntax:{{step_output}}values captured from a step’soutputs:map, and random generators (e.g.{{uuid}},{{random_int(1, 100)}}) insidefuzzy_test. Environment variables are${VAR}, expanded at load time.
See the workflow engine for internals and the YAML reference for the full schema and step catalog.
Testing harness
Section titled “Testing harness”merobox/testing.py exposes merobox to pytest. It provides two context
managers — cluster() (start N nodes, yield endpoints, tear down) and
workflow() (run a YAML workflow, yield the environment) — plus the nodes()
and run_workflow() fixture factories and a using() helper. Their return
shapes are the ClusterEnv and WorkflowEnv TypedDicts. This is how a Python
test suite spins up real nodes as fixtures. See the
testing guide.
Cross-cutting utilities
Section titled “Cross-cutting utilities”| Concern | Where it lives | What it provides |
|---|---|---|
| Result shapes | commands/result.py |
ok() / fail() helpers that return standard success/error dictionaries (not a result class) |
| Retries | commands/retry.py |
RetryConfig and the @with_retry decorator (exponential backoff); applied to network calls via NETWORK_RETRY_CONFIG |
| Errors | commands/errors.py |
MeroboxError and its subclasses — NodeResolutionError, AuthenticationError, WorkflowError (StepValidationError, StepExecutionError), ValidationError, ClientError (MeroboxTimeoutError), ConfigurationError |
| Node config | commands/config_utils.py |
merod config.toml helpers: apply_bootstrap_nodes, apply_e2e_defaults, apply_mdns_setting, and peer/bootstrap readers |
The error hierarchy is documented in error handling.
External dependencies
Section titled “External dependencies”merobox is glue over a handful of libraries (see pyproject.toml):
| Dependency | Role |
|---|---|
calimero-client-py |
JSON-RPC client for talking to merod nodes; steps use it to install apps, create contexts, call methods, and query state |
docker (docker-py) |
Docker Engine API used by DockerManager for container lifecycle |
aiohttp |
Async HTTP used for health checks and node communication |
click |
The CLI framework |
PyYAML |
Parses workflow definition files |
rich |
Console output and progress rendering |
pydantic |
Workflow schema modelling |
toml |
Reads and writes merod config.toml |
Where to go next
Section titled “Where to go next”- Workflow engine — how
WorkflowExecutorand steps work. - YAML reference — the schema and every step type.
- Node management and remote nodes.
- Testing guide — the pytest harness.
- Glossary — the terms used across these docs.