CLI
nx is the Numax command line interface. It has five commands:
nx run- load and execute a WASM modulenx serve- run a node without executing a WASM modulenx config- manage configuration filesnx migrate- migrate a datastore schema offlinenx completions- generate shell completion scripts
nx run
nx run <MODULE> [OPTIONS]Loads <MODULE>, starts the runtime, calls run() once, then exits.
If --listen is passed, sync is enabled and the runtime stays alive
until --settle-for elapses, or until SIGINT/SIGTERM if no settle window is set.
Required
| Argument | Description |
|---|---|
<MODULE> | Path to the .wasm file to execute |
Storage
| Flag | Env | Description |
|---|---|---|
--datastore-path <PATH> | NX_DATASTORE_PATH | Directory for the local sled datastore. Default: ./nx-data |
--config <PATH> | - | Path to a Numax TOML config file |
Networking
Sync is disabled by default. Pass --listen to enable it.
| Flag | Env | Description |
|---|---|---|
--listen <ADDR> | NX_LISTEN | Address to listen on (e.g. 0.0.0.0:9000). Required for sync |
--peer <ADDR> | NX_PEER / NX_PEERS | Peer address to connect to. Can be repeated. Requires --listen |
--discovery-mode <MODE> | NX_DISCOVERY_MODE | static, bootstrap, mdns, dns-srv, or file |
--bootstrap-seed <URL> | NX_DISCOVERY_SEEDS | Bootstrap endpoint. Can be repeated |
--mdns-instance <NAME> | NX_DISCOVERY_INSTANCE_NAME | Local mDNS instance name |
--dns-srv-name <NAME> | NX_DISCOVERY_SERVICE_NAME | Fully qualified DNS-SRV service name |
--peer-file <PATH> | NX_DISCOVERY_FILE | Peer file to watch |
NX_PEERS accepts a comma-separated list: NX_PEERS=127.0.0.1:9001,127.0.0.1:9002
Dynamic discovery still requires --listen. Explicit --peer values remain an
additional static source and are not treated as bootstrap seeds.
Timing
| Flag | Description |
|---|---|
--wait-before-run <DURATION> | Wait after starting sync and before calling run(). Gives peers time to connect. Requires --listen |
--settle-for <DURATION> | Keep sync alive for this duration after run() returns, then shut down. Requires --listen |
--shutdown-timeout <DURATION> | Maximum time allowed for graceful shutdown before returning an error |
Duration format: 500ms, 5s, 2m, or a plain number (interpreted as seconds).
Inspecting CRDT state
These flags print the final host-side value of a CRDT key after the settle window completes.
All of them require --listen.
| Flag | CRDT type | Output format |
|---|---|---|
--print-gcounter <KEY> | GCounter | key = 42 |
--print-pncounter <KEY> | PNCounter | key = -3 |
--print-lww-register <KEY> | LWW-Register | key = value or key = <unset> |
--print-lww-map <KEY> | LWW-Map | key = {field1=val1, field2=val2} |
--print-orset <KEY> | ORSet | key = [tag1, tag2] |
--print-rga <KEY> | RGA | key = [item1, item2] |
Logging
| Flag | Env | Values | Description |
|---|---|---|---|
-v / --verbose | - | - | Sets log level to debug |
--log-level <LEVEL> | NX_LOG_LEVEL | trace debug info warn error | Explicit log level. Overrides --verbose |
--log-format <FORMAT> | NX_LOG_FORMAT | text json | Output format for runtime logs. Default: text |
Observability
| Flag | Env | Description |
|---|---|---|
--observability-listen <ADDR> | NX_OBSERVABILITY_LISTEN | Expose a local HTTP metrics endpoint (e.g. 127.0.0.1:9100) |
--tokio-console | — | Expose opt-in Tokio task diagnostics from an instrumented build |
tokio-console support is excluded from normal builds. Build and run the CLI explicitly with Tokio’s experimental instrumentation enabled:
RUSTFLAGS="--cfg tokio_unstable" cargo run -p nx-cli \ --features tokio-console -- run module.wasm --tokio-consoleThen connect from another terminal with tokio-console. The subscriber listens on 127.0.0.1:6669 by default; use TOKIO_CONSOLE_BIND to select another address. Keep this diagnostic endpoint bound to a trusted interface.
TLS / mTLS
TLS is optional. To enable it, provide --tls-cert and --tls-key together.
For mTLS (mutual authentication), also provide --tls-ca.
| Flag | Env | Description |
|---|---|---|
--tls-cert <PATH> | NX_TLS_CERT | Path to this node’s TLS certificate (PEM) |
--tls-key <PATH> | NX_TLS_KEY | Path to this node’s TLS private key (PEM) |
--tls-ca <PATH> | NX_TLS_CA | Path to the CA certificate used to verify peers (PEM). Enables mTLS |
--allowed-peers <ID1,ID2,...> | NX_ALLOWED_PEERS | Comma-separated allowlist of peer NodeIds (hex). Requires --tls-ca |
--tls-insecure | NX_TLS_INSECURE | Skip TLS certificate verification. Development only. Never use in production. |
Rules:
--tls-certand--tls-keymust always be provided together.--tls-insecureis mutually exclusive with--tls-caand--allowed-peers.--allowed-peersrequires--tls-ca.
Debug
| Flag | Description |
|---|---|
--debug-protocol | Use JSON instead of bincode for the sync wire protocol. Useful for inspecting traffic with a packet capture tool. Requires --listen |
Configuration precedence
When a flag has a corresponding environment variable and a TOML file entry, the resolution order is:
CLI flags > NX_* environment variables > TOML config file > runtime defaultsnx completions
nx completions <SHELL>Generates shell completion scripts for the Numax CLI.
Arguments
| Argument | Description | Values |
|---|---|---|
<SHELL> | Target shell for completions | bash, elvish, fish, powershell, zsh |
Example:
nx completions zsh > ~/.zfunc/_nxnx migrate
nx migrate [OPTIONS]Opens an existing local datastore, runs the registered schema migrations,
flushes the store, and exits. Run this while no nx run process is using the
same datastore.
| Flag | Default | Description |
|---|---|---|
--datastore-path <PATH> | ./nx-data | Existing datastore directory to migrate |
--max-records <COUNT> | 512 | Maximum records processed per migration batch |
--max-bytes <BYTES> | 4MiB | Maximum bytes processed per migration batch, including generated mutations |
Example:
nx migrate --datastore-path ./node-a-datanx config
nx config init
nx config init [--output <PATH>] [--force]Generates a commented Numax TOML configuration file with all available fields and their defaults.
| Flag | Default | Description |
|---|---|---|
--output <PATH> | numax.toml | Where to write the file |
--force | - | Overwrite the file if it already exists |
Example:
nx config init --output node-a.tomlThe generated file looks like this:
# Numax configuration file.# Precedence: CLI flags > NX_* environment variables > this file > defaults.
[storage]datastore_path = "./nx-data"
[network]listen = "0.0.0.0:9000"peers = []serialization_format = "bincode"
[tls]# cert = "./certs/node.pem"# key = "./certs/node-key.pem"# ca = "./certs/ca.pem"allowed_peers = []insecure = false
[observability]# listen = "127.0.0.1:9100"log_level = "info"log_format = "text"request_timeout_secs = 5
[management]# listen = "127.0.0.1:9102"# token_file = "./management.token"allow_non_loopback = falserequest_timeout_secs = 10
[limits]max_peers = 64queued_ops_limit = 10000op_log_limit = 10000seen_ops_limit = 100000max_message_size = "16MiB"socket_timeout_secs = 30reconnect_initial_delay = "500ms"reconnect_max_delay = "30s"peer_dead_after_failures = 3anti_entropy_interval = "30s"
[discovery]mode = "static"# cluster_id = "default"# advertised_endpoint = "127.0.0.1:9000"# max_candidates = 1024# Bootstrap: seeds, refresh_interval, retry_initial, retry_max, stale_after, max_seeds# mDNS: instance_name, max_instances# DNS-SRV: service_name, retry_interval, max_refresh_interval# File: path, poll_interval, max_file_bytesnx config validate
nx config validate [--config <PATH>]Parses and validates a TOML config file without running a module. Exits with a non-zero code and an error message if the file is invalid.
| Flag | Default | Description |
|---|---|---|
--config <PATH> | numax.toml | Path to the config file to validate |
Example:
nx config validate --config node-a.toml# configuration is valid: node-a.tomlnx config show
nx config show --config <PATH> --effectiveResolves and prints the effective configuration after applying CLI flags, environment variables, the config file, and runtime defaults - in that order.
| Flag | Default | Description |
|---|---|---|
--config <PATH> | numax.toml | Path to the config file |
--effective | - | Required. Prints the fully resolved config |
Example:
nx config show --config node-a.toml --effectivenx serve
nx serve [OPTIONS]Starts the datastore and any configured sync, observability or management services without requiring a WASM module. The node remains active until SIGINT, SIGTERM or SIGHUP, including when sync is disabled, and then performs a graceful shutdown.
nx serve accepts the storage, networking, logging, observability, TLS, debug
protocol and shutdown options documented below for nx run. It rejects
module-only options such as --settle-for, --wait-before-run and --print-*.
Configuration precedence is identical for both commands.
nx serve --config numax.tomlThe Management API starts on 127.0.0.1:9102 when [management].token_file or
NX_MANAGEMENT_TOKEN is configured. It stops accepting requests and drains
active connections before the runtime shuts down. Authenticated v1 endpoints
register and run modules and inspect modules, peers, application keys, health
and readiness. See the Management API guide.
If sync, observability and management are all disabled, the process still waits for a shutdown signal and logs a warning.
TOML config file reference
A config file can provide any subset of the following sections. All fields are optional. Unknown fields are rejected.
[storage]
[storage]datastore_path = "./nx-data"| Field | Type | Description |
|---|---|---|
datastore_path | path | Directory for the local sled datastore |
[network]
[network]listen = "0.0.0.0:9000"peers = ["127.0.0.1:9001"]serialization_format = "bincode"| Field | Type | Values | Description |
|---|---|---|---|
listen | string | host:port | Address to listen on. Required for sync |
peers | string[] | host:port | Peer addresses to connect to |
serialization_format | string | bincode json | Wire format. Default: bincode |
[tls]
[tls]cert = "./certs/node.pem"key = "./certs/node-key.pem"ca = "./certs/ca.pem"allowed_peers = ["node-a", "node-b"]insecure = false| Field | Type | Description |
|---|---|---|
cert | path | Node certificate (PEM) |
key | path | Node private key (PEM) |
ca | path | CA certificate for peer verification (PEM). Enables mTLS |
allowed_peers | string[] | Allowlist of peer NodeIds |
insecure | bool | Skip verification. Development only |
[observability]
[observability]listen = "127.0.0.1:9100"log_level = "info"log_format = "text"request_timeout_secs = 5| Field | Type | Values | Description |
|---|---|---|---|
listen | string | host:port | HTTP metrics endpoint address |
log_level | string | trace debug info warn error | Log verbosity |
log_format | string | text json | Log output format |
request_timeout_secs | integer | > 0 | Observability request timeout in seconds |
[management]
[management]listen = "127.0.0.1:9102"token_file = "./management.token"allow_non_loopback = falserequest_timeout_secs = 10The listener is disabled without a token. NX_MANAGEMENT_TOKEN overrides the
token file and is never printed by nx config show. Non-loopback binds require
allow_non_loopback = true; protect external traffic with TLS or a
TLS-terminating reverse proxy.
[limits]
[limits]max_peers = 64queued_ops_limit = 10000op_log_limit = 10000seen_ops_limit = 100000max_message_size = "16MiB"socket_timeout_secs = 30reconnect_initial_delay = "500ms"reconnect_max_delay = "30s"peer_dead_after_failures = 3anti_entropy_interval = "30s"| Field | Type | Description |
|---|---|---|
max_peers | integer | Maximum number of connected peers |
queued_ops_limit | integer | Maximum ops queued for broadcast |
op_log_limit | integer | Maximum ops kept in the local op-log |
seen_ops_limit | integer | Maximum op IDs tracked for deduplication |
max_message_size | string | Maximum sync message size (e.g. 16MiB, 4KiB) |
socket_timeout_secs | integer | Socket read/write timeout in seconds |
reconnect_initial_delay | duration | Initial backoff before reconnecting to a peer |
reconnect_max_delay | duration | Maximum backoff for reconnect attempts |
peer_dead_after_failures | integer | Consecutive failures before a peer is marked dead |
anti_entropy_interval | duration | Interval between anti-entropy repair cycles |
reconnect_initial_delay and reconnect_max_delay must be provided together.
reconnect_initial_delay must be less than or equal to reconnect_max_delay.
[discovery]
[discovery]mode = "static"| Field | Type | Values | Description |
|---|---|---|---|
mode | string | static, bootstrap, mdns, dns-srv, file | Peer discovery provider |
Provider selectors are seeds for bootstrap, instance_name for mDNS,
service_name for DNS-SRV, and path for file discovery. See the
configuration reference for all tuning fields and environment variables.
Full two-node example
# Generate config filesnx config init --output node-a.toml --forcenx config init --output node-b.toml --force
# Edit node-a.toml: set listen = "0.0.0.0:9000", peers = ["127.0.0.1:9001"]# Edit node-b.toml: set listen = "0.0.0.0:9001", peers = ["127.0.0.1:9000"]
# Validatenx config validate --config node-a.tomlnx config validate --config node-b.toml
# Inspect resolved confignx config show --config node-a.toml --effective
# Runnx run my_module.wasm --config node-a.toml --settle-for 5s --print-gcounter counter:visitsnx run my_module.wasm --config node-b.toml --settle-for 5s --print-gcounter counter:visits