Matt, N3PAY - HAM radio hobbyist

Reticulum

Wow! I really enjoyed Guy Royse's talk about Reticulum at KCDC 2026. He provides a github repo with his code and slides. It's really worthwhile to read Guy's slides.

Here's some of the notes I took:

  1. pip install rns # Installs reticulum
    1. Rust and JavaScript implementations also exist
  2. Reticulum protocol is public domain.
  3. LXMF is a related to Reticulum and allows a message to be contained in a QR code!
    1. The start page says "LXMF is a distributed, delay and disruption tolerant message transfer protocol built on Reticulum."

Links from Guy's repo's readme include:

  1. MeshChat — A chat client and NomadNet browser for Reticulum.
  2. RServer — The webserver Guy wrote for Reticulum.
  3. Mesh Browser — The web browser Guy wrote for Reticulum.

It was great to see live demostrations of this during Guy's KCDC 2026 talk.

When I google: Reticulum hello world

Google's AI says, do the pip and then try these two python programs:

server.py:

import RNS
import time

# Initialize Reticulum
rns = RNS.Reticulum()

# Define an application name and aspect
APP_NAME = "helloworld"
ASPECT = "echo"

def main():
    # Create a destination that others can find
    identity = RNS.Identity()
    destination = RNS.Destination(
        identity, 
        RNS.Destination.IN, 
        RNS.Destination.SINGLE, 
        APP_NAME, 
        ASPECT
    )
    
    # Set up a callback to handle incoming data
    def packet_callback(data, packet):
        message = data.decode("utf-8")
        print(f"Received message: '{message}'")

    destination.set_packet_callback(packet_callback)

    # Announce this destination so clients can discover its identity
    destination.announce()

    print(f"Server is running. Destination address: {RNS.prettyhexrep(destination.hash)}")
    print("Announced destination. Waiting for messages... (Press Ctrl+C to exit)")

    while True:
        time.sleep(30)
        # Re-announce periodically so clients started after the first
        # announce can still discover this destination
        destination.announce()

if __name__ == "__main__":
    main()

client.py:

import RNS
import sys
import time

# Initialize Reticulum
rns = RNS.Reticulum()

APP_NAME = "helloworld"
ASPECT = "echo"

# Listens for announces from the server so we can learn its real identity
class ServerAnnounceHandler:
    def __init__(self, aspect_filter):
        self.aspect_filter = aspect_filter
        self.identity = None
        self.destination_hash = None

    def received_announce(self, destination_hash, announced_identity, app_data):
        self.identity = announced_identity
        self.destination_hash = destination_hash

def main():
    print("Looking for server destination...")

    # Wait for the server to announce itself so we learn its real identity.
    # A destination created with a random identity would have a different
    # hash than the server's and packets sent to it would go nowhere.
    handler = ServerAnnounceHandler(aspect_filter=f"{APP_NAME}.{ASPECT}")
    RNS.Transport.register_announce_handler(handler)

    while handler.identity is None:
        time.sleep(0.1)

    print("Server destination found.")

    destination = RNS.Destination(
        handler.identity,
        RNS.Destination.OUT,
        RNS.Destination.SINGLE,
        APP_NAME,
        ASPECT
    )

    # Send the data packet
    message = "Hello World over Reticulum!"
    packet = RNS.Packet(destination, message.encode("utf-8"))
    
    packet_receipt = packet.send()
    print(f"Sent: '{message}'")
    
    # Confirm delivery if possible
    if packet_receipt:
        print("Packet handed over to the network.")
    else:
        print("Failed to send packet.")

    # Reticulum transmits asynchronously via a background thread, so give it
    # a moment before the process exits - otherwise the packet can be dropped
    # before it's actually written to the interface.
    time.sleep(2)

if __name__ == "__main__":
    main()