radicle-reticulum/README.md

175 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# radicle-reticulum
Bridges [Radicle](https://radicle.xyz) (decentralized Git) over [Reticulum](https://reticulum.network) 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
- **Radicle** — `rad` CLI + `radicle-node`: [radicle.xyz/install](https://radicle.xyz/install)
- **uv**: [docs.astral.sh/uv](https://docs.astral.sh/uv/getting-started/installation/) (manages Python and dependencies)
---
## Install
```sh
git clone rad:z4NMdcKbw2TETQ56fbQfbibFHtZqZ
cd radicle-reticulum
uv sync
```
Optional — faster push detection on Linux/macOS (inotify):
```sh
uv sync --extra watch
```
---
## Quick start
Do this on **every machine**.
### 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:
```sh
rnsd --exampleconfig > ~/.reticulum/config
```
Then edit it to enable the interface for your transport. See [Reticulum interfaces](#reticulum-interfaces) below and the [Reticulum manual](https://reticulum.network/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`:
```json
"node": {
"listen": ["127.0.0.1:8776"]
}
```
Restart:
```sh
rad node start
rad node status # should show "listening … 127.0.0.1:8776"
```
### 3. Start the bridge on both machines
```sh
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
```sh
# 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`:
```ini
[[lora_interface]]
type = RNodeInterface
port = /dev/ttyUSB0
frequency = 868000000
bandwidth = 125000
spreadingfactor = 7
codingrate = 5
```
See the [Reticulum manual](https://reticulum.network/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
```sh
uv run pytest # 97 tests
uv run pytest -x -q # stop on first failure
mypy src/
```