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.36. 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:
cargo install net-deck
npm i -g @net-mesh/deck
pip install net-deckSee the Deck reference for the tabs and the signed admin surface.
Install it — Go
go get github.com/ai-2070/net/goOne unified module, imported as package net. There is no separate core-and-SDK
split here: the Go module wraps the core crate's shared library directly.
What is peculiar about Go here
cgo, which means a C toolchain on every build machine — gcc or clang on Linux and macOS, MSVC on Windows. Not just yours: anywhere this builds, including CI and any container that compiles rather than copies a binary. A pure-Go cross-compile will not work.
Check it before anything else, because Go turns cgo off by default when it cannot find a C compiler and says nothing:
go env CGO_ENABLED # must print 1If it prints 0, install a compiler and set CGO_ENABLED=1. Building without
it fails inside the binding with a message naming this requirement — the
package deliberately refuses to compile rather than presenting a hollowed-out
API and blaming your call to net.New.
The module needs the Rust shared library present to link. go vet
type-checks without it, which is why it is the fastest way to catch a mistake
before dealing with linking; a go build needs the real libnet.
Build it with cargo build --release -p net-ffi, then tell the fetched module
where it is. The package's cgo directives use a path relative to their own
source directory, which for a go get module is the module cache — so it
points at a sibling checkout that does not exist, and the link fails with
cannot find -lnet even though the library is sitting right there:
export CGO_LDFLAGS="-L/abs/path/to/net/crates/net/target/release"
# Linking and loading are separate steps. The loader needs its own pointer:
export LD_LIBRARY_PATH=/abs/path/to/net/crates/net/target/release # Linux
export DYLD_LIBRARY_PATH=/abs/path/to/net/crates/net/target/release # macOSOn Windows there is no LD_LIBRARY_PATH — put net.dll beside your
executable or add its directory to PATH. Skip that and the program exits
127 before reaching main, often with nothing on stderr, after a build that
reported success.
Errors come back as values, and the constructor is net.New. Naming is Go's,
not Rust's — IngestRaw, Stats, Shutdown — so do not carry method names over
from another binding's documentation.
Some surfaces are not exposed in Go at all. Agent-to-agent task handoff and the consumer-side filter DSL are the notable gaps. The binding coverage matrix records which; a missing method is sometimes a real absence rather than a different name.
Verify it worked
package main
import (
"fmt"
"log"
"github.com/ai-2070/net/go"
)
func main() {
bus, err := net.New(&net.Config{NumShards: 1})
if err != nil {
log.Fatal(err)
}
defer bus.Shutdown()
if err := bus.IngestRaw(`{"msg":"hello, mesh"}`); err != nil {
log.Fatal(err)
}
// Counts at the PRODUCER boundary: accepted, not received or stored.
stats, err := bus.Stats()
if err != nil {
log.Fatal(err)
}
if stats.EventsIngested != 1 {
log.Fatalf("the bus did not accept the event: ingested=%d", stats.EventsIngested)
}
fmt.Printf("accepted: ingested=%d\n", stats.EventsIngested)
}Expect one line, accepted: ingested=1, and a clean exit. This is the example CI
builds and runs against the real shared library on every commit.
Next: the Go SDK spine.