MESH ONLINECODENAME: Circus Maximus
$ lang
v0.33
getting started

Install

Net ships as one release across five surfaces: a Rust crate, native Node and Python bindings built from that same crate, a Go module over its C ABI, and the C ABI itself. They are not independent ports. A version number means the same code underneath, whichever package you install.

What you are installing

Two layers, and knowing which one you have saves an afternoon:

  • The core binding — the bus, the mesh transport, the storage stack. In Rust that is the crate; in Node and Python it is the native addon.
  • The ergonomic SDK — typed channels, node builders, RPC helpers. A thin layer over the core, published separately.

Some surfaces reach features only through the core layer, never the SDK. That is not a bug to work around and it is the most common way to be wrong about Net in Node and Python: if an import fails, check which layer the symbol lives on before concluding the feature is missing.

Versions move together

Every package publishes at the same version from the same commit. The current published release is 0.33. Pin the same version across layers — a core at one version and an SDK at another is a combination nobody built or tested.

What an install gives you

Whichever surface you start on:

  • the event bus — publish, poll, filters, shards;
  • mesh transport with NAT traversal — peer discovery, encrypted sessions, identity-bound routing;
  • the storage stack — RedEX logs, CortEX folds, NetDB queries, Dataforts blobs;
  • daemon authoring through MeshOS;
  • typed RPC through nRPC.

You do not have to use any of the higher layers to use the bus. They are there when you need them.

One thing to expect on your first run

The default transport is memory, and memory discards events after counting them. A first program that publishes and then tries to read the event back will not fail — it will hang, waiting for something that is never coming. Verifying that the bus accepted an event is the right first check, and every language's instructions below end with exactly that.

Receiving events back needs an adapter that retains them (Redis, JetStream) or the mesh transport between two nodes. That is a separate decision, not a default.

Deck, the operator TUI

A separate binary that nothing else depends on. Install it from whichever ecosystem is convenient — it is the same tool either way:

code
cargo install net-deck
npm i -g @net-mesh/deck
pip install net-deck

See the Deck reference for the tabs and the signed admin surface.

Install it — Rust

code
cargo add net-mesh          # the core crate
cargo add net-mesh-sdk      # the ergonomic SDK, if you want typed channels

net-mesh re-exports as net, so user code keeps use net::… short. The SDK imports as net_sdk.

Pinning explicitly, and note the version — 0.33 is the published release:

code
[dependencies]
net-mesh = "0.33"
net-mesh-sdk = "0.33"

Feature flags

Rust is the one surface where you choose what gets compiled. The default set compiles the full stack:

FeatureWhat it addsOn by default
netMesh transport — Noise handshakes, ChaCha20-Poly1305, ed25519 identitiesyes
nat-traversalReflex probes, classification, rendezvous punchyes
cortexFolded-state driver (pulls in redex)yes
meshdbFederated query layeryes
meshosCluster behaviour engine, daemon supervisionyes
datafortsContent-addressed blobs, greedy-LRU cache, gravity placementyes
redexRedEX append-only logs — implied by cortexvia cortex
redex-diskDisk-backed RedEX segments rather than memory-onlyno
netdbNetDB query surface over folded stateno
toolToolDescriptor + tool-metadata RPC (requires cortex)no
regexRegex predicates in the filter DSLno
batched-ingressBatched receive path on the Net adapterno
port-mappingUPnP-IGD / NAT-PMP opportunistic port mappingno
redisRedis Streams adapterno
jetstreamNATS JetStream adapterno
cliThe net-blob operator CLIno
ffiC ABI surface — enabled by the cdylib / staticlib buildsno

Features compose: cortex implies redex, and meshdb, netdb and tool each imply cortex. Turning on netdb therefore also pulls in the fold driver and the log underneath it.

One flag fails quietly. Without regex, a peer can still send you a regex predicate and your node matches it closed — the pattern matches nothing rather than erroring. If you rely on regex predicates, enable it explicitly.

A minimal build — in-memory bus only, no mesh, no persistence:

code
[dependencies]
net-mesh = { version = "0.33", default-features = false }

What is peculiar about Rust here

The SDK is async and expects a Tokio runtime; #[tokio::main] is enough for a first program. Builder methods are async and fallible, so .build().await? rather than a constructor.

Verify it worked

code
use net_sdk::Net;
use serde::{Deserialize, Serialize};
 
#[derive(Serialize, Deserialize)]
struct Hello {
    msg: String,
}
 
#[tokio::main(flavor = "current_thread")]
async fn main() -> net_sdk::error::Result<()> {
    let node = Net::builder().shards(1).memory().build().await?;
    node.emit(&Hello { msg: "hello, mesh".into() })?;
 
    // Counts at the PRODUCER boundary: the bus accepted the event. It does not
    // say anything received or stored it — see the note above about memory.
    let stats = node.stats();
    assert_eq!(stats.events_ingested, 1, "the bus did not accept the event");
    println!("accepted: ingested={}", stats.events_ingested);
 
    node.shutdown().await?;
    Ok(())
}

Expect one line, accepted: ingested=1, and a clean exit. This program is the same one CI runs on every commit — see Claude Skills for the executed examples.

Next: the Rust SDK spine.