Rust LXMF messaging and propagation for Reticulum.
rsLXMF is a Rust implementation of LXMF, the Reticulum messaging layer. This is not a fork of LXMF, this is LXMF written in a different language focused on staying interoperable. This is not a source of truth implementation, do not use it as such.
Commands are intentionally namespaced for Rust with the Rust-specific lxmd-rs command, so rsLXMF can live beside other
LXMF daemons on PATH without worry.
- Build It
- Operating lxmd-rs
- Configuration
- Delivery Model
- Feature Status
- Compatibility Notes
- Contributing
- License
The current development layout for rsLXMF requires rsReticulum as a sibling directory/repo next to it, such as:
ratspeak-src/
|-- rsReticulum/
`-- rsLXMF/
If you're starting fresh:
mkdir ratspeak-src
cd ratspeak-src
git clone https://github.com/ratspeak/rsReticulum
git clone https://github.com/ratspeak/rsLXMF
cd rsLXMFInstall Rust with rustup, then install Apple's build tools:
xcode-select --installBuild from the sibling checkout:
cd rsLXMF
cargo build --releaseDebian, Ubuntu, and Raspberry Pi OS:
sudo apt update
sudo apt install -y build-essential pkg-config libudev-devFedora:
sudo dnf install gcc make pkgconf-pkg-config systemd-develArch:
sudo pacman -S --needed base-devel pkgconf systemdcd rsLXMF
cargo build --releaseInstall Rust with the MSVC toolchain. If Rust or Cargo asks for Visual Studio Build Tools, install the "Desktop development with C++" workload.
Build from PowerShell:
cd rsLXMF
cargo build --releaseAfter the build, use the commands below with ./target/release/lxmd-rs on
macOS/Linux or .\target\release\lxmd-rs.exe on Windows.
lxmf-tools builds one public command name:
| Binary | Purpose |
|---|---|
| lxmd-rs | Rust LXMF daemon and control utility. |
Generate the example config:
lxmd-rs --exampleconfigRun a regular LXMF daemon:
lxmd-rs --config ~/.rsLXMF --rnsconfig ~/.rsReticulumRun a propagation node:
lxmd-rs --config ~/.rsLXMF --rnsconfig ~/.rsReticulum --propagation-nodeSend a message and exit:
lxmd-rs --config ~/.rsLXMF --rnsconfig ~/.rsReticulum \
--send <destination_hash> "message body"The --send flag is an rsLXMF convenience. Normal
daemon and propagation-control operation does not require it for anything.
Send UTF-8 file content or select a delivery method:
lxmd-rs --config ~/.rsLXMF --rnsconfig ~/.rsReticulum \
--send <destination_hash> --send-file ./message.txt --send-method directSupported --send-method values are opportunistic, direct, and
propagated. Paper messages aren't supported yet in the CLI.
Attach custom LXMF fields from scripts:
lxmd-rs --config ~/.rsLXMF --rnsconfig ~/.rsReticulum \
--send <destination_hash> "with fields" \
--send-fields-json '{"1":"aGVsbG8=","42":"AAECAw=="}'The JSON object maps field IDs to base64-encoded bytes. It is only a shell convenience; LXMF fields remain MessagePack field maps on the wire.
Control a propagation node:
lxmd-rs --config ~/.rsLXMF --rnsconfig ~/.rsReticulum --status
lxmd-rs --config ~/.rsLXMF --rnsconfig ~/.rsReticulum --peers
lxmd-rs --config ~/.rsLXMF --rnsconfig ~/.rsReticulum --sync <peer_hash>
lxmd-rs --config ~/.rsLXMF --rnsconfig ~/.rsReticulum --break <peer_hash>These commands query an lxmf.propagation.control endpoint over Reticulum.
They do not inspect local files and do not start local daemon state. If no
reachable daemon answers, they time out with compatibility-oriented control
exit behavior.
For a remote propagation node, pass the node's propagation destination hash:
lxmd-rs --config ~/.rsLXMF --rnsconfig ~/.rsReticulum \
--status --peers --remote <propagation_destination_hash> --timeout 5Control queries use <config-dir>/identity by default. Use --identity PATH
when the query should authenticate as a different LXMF identity.
Run an inbound hook:
lxmd-rs --config ~/.rsLXMF --rnsconfig ~/.rsReticulum --on-inbound /path/to/handlerThe handler receives the saved .lxm message path as an argument.
lxmd-rs --config <dir> expects a directory and reads <dir>/config.
lxmd-rs --rnsconfig <dir> expects a Reticulum config directory.
If no LXMF config directory is supplied, the default is:
| Platform | Default LXMF config file |
|---|---|
| Linux/macOS | /etc/rsLXMF/config, then ~/.config/rsLXMF/config, then ~/.rsLXMF/config |
| Windows | %APPDATA%\rsLXMF\config |
If --rnsconfig is omitted, Reticulum config resolution follows
rsReticulum-specific defaults.
Recommended standalone locations:
| Environment | LXMF config | Reticulum config |
|---|---|---|
| macOS/Linux desktop | ~/.rsLXMF/config |
~/.rsReticulum/config |
| Windows desktop | %APPDATA%\rsLXMF\config |
%APPDATA%\rsReticulum\config |
| Linux service | /var/lib/rsLXMF/config |
/etc/rsReticulum/config or another explicit Reticulum directory |
Use existing LXMF or Reticulum directories, such as ~/.lxmd, ~/.lxmf, or
~/.reticulum, only by passing them explicitly. That keeps the default install
isolated while still allowing deliberate drop-in and migration tests.
Minimal config:
[lxmf]
display_name = Rat
announce_at_start = no
delivery_transfer_max_accepted_size = 1000
# stamp_cost = 8
# on_inbound = /path/to/handler
[propagation]
enable_node = no
announce_at_start = yes
autopeer = yes
autopeer_maxdepth = 6
auth_required = no
# node_name = Rat Nest
# static_peers = e17f833c4ddf8890dd3a79a6fea8161d
# outbound_node = e17f833c4ddf8890dd3a79a6fea8161d
# max_peers = 20
# propagation_stamp_cost_target = 16
# propagation_stamp_cost_flexibility = 3
[logging]
loglevel = 4Supported sections:
| Section | Keys |
|---|---|
[lxmf] |
display_name, announce_at_start, announce_interval, delivery_transfer_max_accepted_size, stamp_cost, on_inbound |
[propagation] |
enable_node, node_name, auth_required, announce_at_start, announce_interval, autopeer, autopeer_maxdepth, message_storage_limit, propagation_message_max_accepted_size, propagation_sync_max_accepted_size, propagation_stamp_cost_target, propagation_stamp_cost_flexibility, peering_cost, remote_peering_cost_max, max_peers, static_peers, prioritise_destinations, control_allowed, from_static_only, outbound_node, propagation_stamp_cost, propagation_limit, enforce_ratchets, enforce_stamps |
[control] |
auth_required, allowed |
[logging] |
loglevel |
Optional hash-list files live next to <config-dir>/config:
| File | Meaning |
|---|---|
ignored |
Hashes loaded into the router ignored list. |
allowed |
Hashes loaded into the router delivery allow-list. Empty means no allow-list restriction. |
Hash-list files accept one raw 32-character hex destination hash per line.
LXMF supports several delivery shapes. rsLXMF exposes them through the router
and, where network-backed, through lxmd-rs --send-method.
| Method | Behavior |
|---|---|
| Opportunistic | Single-packet delivery when the packed message fits the Reticulum packet path. Oversized opportunistic messages are downgraded to Direct by the router. |
| Direct | Link-backed delivery over a Reticulum Link, with resource transfer for larger content. |
| Propagated | Store-and-forward delivery through a propagation node, including deposit, retrieve, peer sync, stamps, and tickets. |
| Paper | Library support for lxm:// URI generation and ingest. The CLI does not generate QR images. |
An ordinary direct or opportunistic LXMF message is a signed Reticulum payload:
destination_hash 16 bytes
source_hash 16 bytes
signature 64 bytes
payload MessagePack([timestamp, title, content, fields, optional_stamp])
title and content are bytes on the wire. fields is a map<u8, bytes> for
application-defined data such as tickets, attachments, location data, or
application envelopes.
| Area | Current behavior |
|---|---|
| Message format | Signed LXMF envelopes, custom field maps, propagation wrappers, .lxm containers, and paper URI encode/decode. |
| Delivery | Opportunistic, Direct, Propagated, callbacks, failure callbacks, cancellation, progress state, and opportunistic-to-direct downgrade. |
| Propagation | Disk-backed store, deposit, retrieve, peer sync, autopeer/static peers, weighted culling, duplicate checks, size checks, and stamp checks. |
| Stamps and tickets | Soft/hard stamp validation, HKDF-expanded workblocks, cached destination stamp costs, propagation tickets, and restart-safe ticket persistence. |
| Control | --status, --peers, --sync, and --break over the propagation-control link. |
| Access lists | ignored and allowed hash-list files in the LXMF config directory. |
Most daemon and control flags are implemented: --config, --rnsconfig,
--propagation-node, --on-inbound, --status, --peers, --sync,
--break, --remote, --identity, --timeout, --exampleconfig, and
--version.
Additional rsLXMF-only flags: --send, --send-file, --send-method,
--send-timeout-secs, and --send-fields-json.
If the issue or contribution belongs upstream as well, start there. Python LXMF and Reticulum remain the reference implementations.
PRs are closed for now until I have time to catch up on everything. I'm tired.
GNU Affero General Public License v3.0 or later. See LICENSE.