git collaboration over whatever AKA radicle over reticulum
Go to file
Maciek "mab122" Bator d65401e546 docs: remove unnecessary lines from README.md and fix clone command 2026-04-24 13:05:01 +02:00
src/radicle_reticulum fix: replace RNS.Link.FAILED with TIMEOUT and STALE 2026-04-24 12:44:22 +02:00
tests refactor: use RNS.Buffer for tunnel, drop dead code and --lora flag 2026-04-24 10:54:25 +02:00
.gitignore feat: initial implementation of radicle-reticulum bridge 2026-04-21 12:14:57 +02:00
README.md docs: remove unnecessary lines from README.md and fix clone command 2026-04-24 13:05:01 +02:00
audit.md docs: remove unnecessary lines from README.md and fix clone command 2026-04-24 13:05:01 +02:00
integration_claude_research.md docs: remove unnecessary lines from README.md and fix clone command 2026-04-24 13:05:01 +02:00
last_notes_from_claude.md docs: remove unnecessary lines from README.md and fix clone command 2026-04-24 13:05:01 +02:00
pyproject.toml feat: watchdog push detection, setup command, and gossip refactor 2026-04-22 22:28:42 +02:00

README.md

radicle-reticulum

Bridges Radicle (decentralized Git) over Reticulum mesh networking — LoRa, packet radio, serial, I2P, and more.

rad push and rad fetch work normally. The bridge is transparent: radicle-node sees ordinary TCP peers, unaware it is talking over a mesh.


Prerequisites


Install

rad clone rad:z4NMdcKbw2TETQ56fbQfbibFHtZqZ
cd radicle-reticulum
uv sync

Optional — faster push detection on Linux/macOS (inotify):

uv sync --extra watch

Quick start

1. Reticulum connectivity

On the same LAN, Reticulum discovers peers automatically via multicast — no configuration needed.

For other transports (internet, LoRa, packet radio, I2P) configure the appropriate Reticulum interface in ~/.reticulum/config first. If this is your first time using Reticulum, generate the annotated example config:

rnsd --exampleconfig > ~/.reticulum/config

Then edit it to enable the interface for your transport. See Reticulum interfaces below and the Reticulum manual for details. Once Reticulum can reach between your machines the bridge works the same regardless of transport.

2. Configure radicle-node to listen on localhost

Edit ~/.radicle/config.json:

"node": {
    "listen": ["127.0.0.1:8776"]
}

Restart:

rad node start
rad node status   # should show "listening … 127.0.0.1:8776"

3. Start the bridge on both machines

uv run radicle-rns bridge

The bridges announce themselves over RNS and discover each other within about a minute. When a peer is found its radicle NID is registered automatically:

[+] Discovered bridge: <hash>  (NID: z6Mk...)

Once radicle-node connects through the tunnel:

Tunnel 1 opened
[Status] Tunnels: 1, Remote bridges: 1, TX: 1551, RX: 1831

4. Use radicle normally

# Machine A
rad init --name myproject --description "" --default-branch main
rad push          # prints RID: rad:z3...

# Machine B
rad clone rad:z3...

That's it. rad push, rad fetch, and rad sync all work as usual — they talk to the local daemon, which syncs through the bridge.


Reticulum interfaces

For LoRa, serial, or I2P, edit ~/.reticulum/config:

[[lora_interface]]
  type = RNodeInterface
  port = /dev/ttyUSB0
  frequency = 868000000
  bandwidth = 125000
  spreadingfactor = 7
  codingrate = 5

See the Reticulum manual for the full interface list.

Initial clones over LoRa are impractical (pack objects can be megabytes; LoRa is ~15 kbps). Clone over a fast link first, then sync incrementally over the mesh.


Commands

radicle-rns bridge                  # TCP↔RNS bridge
radicle-rns gossip [RID ...]        # ref-change relay (auto-detected from CWD)
radicle-rns setup                   # check prerequisites
radicle-rns identity generate       # create identity
radicle-rns identity info           # show DID and RNS hash

Global flags: -v verbose logging, --identity PATH (default ~/.radicle-rns/identity).

bridge flags

Flag Default Description
-l, --listen-port 8777 Base TCP port for incoming radicle-node connections
--radicle-port 8776 Port radicle-node listens on
-c, --connect <hash> Connect to a specific bridge by RNS hash
--nid <NID> auto-detect Local radicle NID to announce
--no-auto-connect Disable auto-connect on discovery
--no-auto-seed Disable auto-registering remote NIDs
--announce-retry-delays 5,15,30 Startup re-announce delays (seconds, comma-separated)

gossip flags

Flag Default Description
--nid auto-detect Local radicle NID to advertise
--bridge-port 8777 TCP port of the local bridge
--poll-interval 30 Seconds between ref polls

How it works

radicle-node ─TCP─ RadicleBridge ──RNS Link── RadicleBridge ─TCP─ radicle-node
  (Machine A)        (Machine A)                (Machine B)        (Machine B)
                         │                           │
                    GossipRelay ──RNS Packet── GossipRelay

The bridge tunnels radicle-node's TCP stream over an RNS.Buffer — an ordered, reliable channel that works across all Reticulum interfaces including LoRa. Reticulum handles peer discovery, routing, encryption, and retransmission transparently.

The gossip relay is a lightweight side-channel (~300 bytes per event) that wakes peers when refs change, useful when the bridge TCP session is not yet live.


Development

uv run pytest        # 97 tests
uv run pytest -x -q  # stop on first failure
mypy src/