Skip to main content

Quickstarts

Myrmic offers a new approach for building distributed edge applications. Instead of building application logic and worrying about connectivity - placement - database - observability - Myrmic handles that. You write application logic as cells: small, self-contained Rust programs that compile to WebAssembly and run on Myrmic runtimes across your device swarm. The focus shifts from infrastructure to logic.

To deliver that, Myrmic provides developers with three things:

  • Myrmic Runtime - the process you start on a device. It connects to other runtimes in the network peer-to-peer to form a swarm. It runs cells, decides where they are placed in the swarm, routes messages between them, provides a distributed database to store their data, and collects telemetry across the swarm.
  • Myrmic SDK - a full toolkit to build Myrmic cells and applications from the ground up. It provides macros to define cells and their interfaces, and utilities to communicate between them, interact with the runtime database, schedule tasks, access hardware on embedded targets, and logging.
  • Myrmic CLI - the command-line interface tool for developers to create, build, and deploy cells, interact with them, manage Myrmic runtimes, and observe the swarm - in development and production.

Supported Targets​

Myrmic Runtime runs on Linux-based systems and a growing set of embedded targets. The following table lists currently supported targets:

TargetArchitectureEmbedded Wasm Engine
Linuxx86_64 / aarch64Wasmtime (JIT)
ESP32-C5RISC-V (rv32imac)WAMR (AOT)
ESP32-C6RISC-V (rv32imac)WAMR (AOT)
ESP32-C61RISC-V (rv32imac)WAMR (AOT)

Installation (Linux)​

To work with Myrmic, you only need to install the Myrmic CLI. The Myrmic SDK is a Rust dependency you add to your cell code. The Myrmic Runtime is managed by the CLI - no separate installation needed.

See Installation for the system packages you need, installing from a release package on x86_64, building from source, and what Myrmic writes to your machine.

For embedded targets - building and flashing firmware for ESP32 boards - see Installation (Embedded).

Verify Installation​

Confirm the installation succeeded:

myrmic --version

Your First Cell​

In this section you will build your first cell and deploy it to a local runtime, then interact with the cell from the CLI.

1. Create a new Cell.​

Create a working directory and navigate into it:

mkdir myrmic-quickstart && cd myrmic-quickstart

If you built the CLI from source, create this outside the cloned repository. A cell created inside the myrmic checkout is captured by its Cargo workspace and fails to build with current package believes it's in a workspace when it's not. Cells inside your own app workspace are fine (see Cells).

Then scaffold the cell, run:

myrmic new counter

Expected output:

INFO Creating 'counter'

This command creates a minimal cell as a Rust crate, using a built-in template to quickly get started and remove the complexity of manual setup. The resulting layout looks like this:

counter/
Cargo.toml -- crate named "counter"; depends on myrmic-sdk and serde
.gitignore
src/
lib.rs -- the Cell code lives here

2. Inspect the generated Cell.​

Open counter/Cargo.toml. It looks like this:

[package]
name = "counter"
version = "0.1.0"
edition = "2024"
publish = false

[package.metadata.myrmic]
heap_size = 32_768

[dependencies]
myrmic-sdk = "x.x.x"

serde = { version = "1", default-features = false, features = ["alloc", "derive"] }

Most of that is self explaining except: heap_size - sets how much memory this Cell gets: 32 KB, baked into the Wasm binary at build time. See Cell and application configuration to understand more.

Now open counter/src/lib.rs. This is the starter Cell code that was generated:

#![no_std]

use myrmic_sdk::db::state::State;
use myrmic_sdk::{Callback, JsonValue, Metadata};

const STATE: State<i32> = State::new_const("my-key");

#[myrmic_sdk::init]
fn init(md: Metadata) -> myrmic_sdk::Result {
let _ = myrmic_sdk::info!("starting (id={:?})", md.id).ok();
Ok(())
}

#[myrmic_sdk::cmd]
fn count(md: Metadata, callback: Option<Callback<JsonValue>>) -> myrmic_sdk::Result {
let value = STATE.load()?.unwrap_or_default();

// `myrmic send` carries no callback, and a nil sender that could not be
// answered even if it did.
if let Some(callback) = callback
&& !md.sender.is_nil()
{
let _ = myrmic_sdk::info!("Returning count {} to (sender={:?})", value, md.sender).ok();
callback.invoke(md.sender, &JsonValue::from(value))?;
} else {
let _ = myrmic_sdk::info!("Count is {} (no caller to answer)", value).ok();
}

Ok(())
}

#[myrmic_sdk::cmd]
fn increment(md: Metadata) -> myrmic_sdk::Result {
let count = STATE.upsert_with(|count| {
*count = *count + 1;
})?;

let _ = myrmic_sdk::info!("Incremented count to {} (sender={:?})", count, md.sender).ok();

Ok(())
}

#[myrmic_sdk::cmd]
fn decrement(md: Metadata) -> myrmic_sdk::Result {
let count = STATE.upsert_with(|count| {
*count = *count - 1;
})?;

let _ = myrmic_sdk::info!("Decremented count to {} (sender={:?})", count, md.sender).ok();

Ok(())
}

A few things to note about the code:

  • #![no_std] - since Myrmic cells are meant to run on any target - including bare-metal devices where the standard library is not available - cells are built without it. The SDK provides what you need in its place.

  • State<i32> - persistent state stored in the runtime database.

  • #[myrmic_sdk::init] - marks the init function. Runs once per deployment of the Cell, before it handles anything else - so redeploying runs it again.

  • #[myrmic_sdk::cmd] - marks a function as a command handler. Myrmic cells are event-driven: they sit idle until a message arrives. Messages are either commands - a request directed at a cell to perform an action - or events. A function marked with this macro is invoked whenever the Cell receives its matching command. Events are not covered here - see the tutorials or the dedicated guide.

  • Metadata - holds the invocation context. It is passed to every handler and provides information such as the identity of the current cell and the identity of the sender.

This cell exposes three commands:

  • count - answers the caller with the current count when one sent a callback, and logs it otherwise.
  • increment - increments the count by 1 and logs the result.
  • decrement - decrements the count by 1 and logs the result.

3. Build the Cell.​

Run from the myrmic-quickstart/ folder:

myrmic build counter

Expected output:

INFO Attempting to build: .../counter
Compiling counter v0.1.0 (.../counter)
Finished release [optimized] target(s) in Xs

This compiles the Cell to WebAssembly. The binary counter.wasm is placed in counter/target/wasm32-unknown-unknown/release/.

4. Start a local runtime.​

The runtime must be running before you can deploy. Start it in a separate terminal and leave it running for the rest of the steps.

myrmic runtimes start

It logs some startup detail and then a readiness line once it is serving:

INFO runtime "default" ready (<id>)

On the first start you may also see one or two WARN lines about missing prior state - these are normal and can be ignored.

Verify the runtime is running from your original terminal:

myrmic runtimes list

Expected output:

default running pid=<pid>

This means that we have a local Myrmic runtime running on the machine.

You can also see the swarm from the network's side:

myrmic network status

Runtimes that can reach each other on the network automatically join one swarm, with no explicit join step, and cell names (SRNs) are shared across it, so the same name is the same cell on every node. On a single machine that swarm is just this runtime. See Operating a swarm for what this means once more machines are involved.

Finally, tell the runtime to keep telemetry. By default a runtime only prints its logs to its own stdout; nothing is stored in the telemetry database that myrmic telemetry logs reads until a retention period is set. Run this once - it applies to all connected runtimes immediately and only affects records emitted afterwards:

myrmic telemetry set-db-retention "1h"

Expected output:

INFO DB retention set to '1h' on all connected nodes

Retention lives in the running process. If you restart the runtime you have to set it again, or put db_retention: "1h" under a top-level telemetry: key in a runtime configuration file - see Runtime configuration.

5. Deploy to the runtime.​

myrmic deploy builds and deploys the cell in one step.

myrmic deploy counter

Expected output:

INFO deploying cell (srn = counter, sri = <uuid>)
INFO deployed cell (srn = counter, sri = <uuid>)

Each cell has two identifiers: an srn (Stable Resource Name) - the human-readable name - and an sri (Stable Resource Identifier) - a unique identifier used internally by the runtime. The srn is derived from the crate name by default and the sri is derived deterministically from it. The cell is reachable by either.

To use a different SRN, pass --name:

myrmic deploy counter --name other-name

6. Check what is running.​

Lists all Cells deployed to the runtime.

myrmic cells

Expected output:

cell sri kind runtime age policy class srn
──── counter ───────────────────────────────────────────────────────────────────────────────────
counter xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx wasm [x]xxxxxxx 0s never counter counter

In a terminal this is a live view: it redraws every couple of seconds until you press Ctrl-C. Use myrmic cells --once for a single listing - which is also what you get when the output is piped or redirected.

counter is deployed on the local runtime, which the runtime column shows by id, and waiting for commands.

7. Call the commands.​

myrmic send sends a command to a cell - it takes the cell identifier and the command name. Call increment three times, then ask for the count:

myrmic send counter increment
myrmic send counter increment
myrmic send counter increment
myrmic send counter count

count answers its caller with a callback when a cell sent one. A send from the terminal carries no callback and nobody to answer, so the cell logs the value instead - which is what the next step looks at.

8. Check the logs.​

The cell logs its state after every command. Check what happened:

myrmic telemetry logs

Look for these lines in the output:

Incremented count to 1 (sender=...)
Incremented count to 2 (sender=...)
Incremented count to 3 (sender=...)
Count is 3 (no caller to answer)

If the output is empty, retention was not set before the commands were sent (see step 4). Set it and send a few more increment commands. To confirm the cell itself logged, print the runtime's own log instead - it is written regardless of retention:

myrmic runtimes default logs

9. Remove the Cell.​

myrmic delete counter

Removes the Cell from the runtime. In a terminal this asks which of the cell, its app or its descendants to remove; run non-interactively (a script or a pipe) it will not prompt and needs the choice as a flag - here, myrmic delete counter --cell.

Expected output:

INFO undeployed cell 'counter' (sri xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)

Verify it is gone:

myrmic cells

Expected output:

No cells registered

10. Stop the runtime when you are done.​

myrmic runtimes stop

(stop is an alias; myrmic runtimes --help lists the command as delete.)

Expected output:

INFO sent SIGTERM to runtime "default" (pid <pid>)

Getting Help​

At any point, if you get stuck, you can always get help on Discord or GitHub Discussions. No question is too small - the community is here for all of them.

Next Steps​

  • Tutorials - hands-on walkthroughs to go further.
  • Guides - learn individual Myrmic features and concepts.
Cookie Policy