---
name: cryptopeer-stack
description: Use first in any project that builds on the cryptopeer stack (UDX, dart_libp2p and its packages, Ricochet, go-p2p-forge) to pick the right packages for a P2P task, see how Dart, Go and TypeScript peers connect, and find the detailed skill for each package.
triggers: cryptopeer, dart_libp2p, dart_udx, go-udx, js-udx, ricochet, go-p2p-forge, udx transport
---

# The cryptopeer stack

cryptopeer is a family of open-source peer-to-peer libraries for Dart/Flutter,
Go and TypeScript, documented at https://cryptopeer.net. There are three layers,
and each builds on the one below:

1. **UDX**: a reliable, multiplexed, QUIC-style transport over UDP.
2. **dart-libp2p**: a full libp2p implementation for Dart and Flutter, plus
   transports for browsers (WebRTC) and nearby devices (Bluetooth LE) and the
   protocols built on top (GossipSub, Kademlia DHT, Bitswap, Merkle-CRDTs).
3. **Ricochet**: store-and-forward messaging and storage, modelled on email,
   so a peer can write to another peer that is offline.

Use this skill to decide what to use, then load the detailed skill for each
package you touch. Do not write code against a package from memory: these are
not the upstream libp2p packages, and their APIs differ.

## Packages

| Package | Language | Install | Skill |
|---|---|---|---|
| `dart_udx` | Dart | `dart_udx: ^4.3.0` | `udx-dart` |
| `github.com/stephanfeb/go-udx` | Go | `go get github.com/stephanfeb/go-udx@v0.3.0` | `udx-go` |
| `@go-ricochet/udx`, `@go-ricochet/libp2p-udx` | TypeScript (Node.js, browser entry) | `npm i @go-ricochet/udx @go-ricochet/libp2p-udx` | `udx-js` |
| `github.com/stephanfeb/go-libp2p-udx-transport` | Go (go-libp2p) | `go get github.com/stephanfeb/go-libp2p-udx-transport@v0.1.8` | `go-libp2p-udx` |
| `dart_libp2p` | Dart | `dart_libp2p: ^4.12.0` | `dart-libp2p-host`, `dart-libp2p-custom-protocol`, `dart-libp2p-nat-relay` |
| `dart_libp2p_webrtc` | Dart / Flutter | `dart_libp2p_webrtc: ^0.1.0` | `dart-libp2p-webrtc` |
| `dart_libp2p_ble` | Flutter (Android, iOS, macOS) | `dart_libp2p_ble: ^0.2.0` | `dart-libp2p-ble` |
| `dart_libp2p_pubsub` | Dart | `dart_libp2p_pubsub: ^3.1.0` | `dart-libp2p-gossipsub` |
| `dart_libp2p_kad_dht` | Dart | `dart_libp2p_kad_dht: ^1.6.0` | `dart-libp2p-kad-dht` |
| `dart_libp2p_bitswap` | Dart | `dart_libp2p_bitswap: ^2.0.0` | `dart-libp2p-bitswap` |
| `merkledag` | Dart | `merkledag: ^2.0.0` | `merkle-crdt` |
| `dart_libp2p_merkle_crdt` | Dart | `dart_libp2p_merkle_crdt: ^2.0.0` | `merkle-crdt-sync` |
| `github.com/stephanfeb/go-ricochet` | Go (server, and a Go client in `pkg/client`) | build from source or the `.deb` (v1.6.0) | `ricochet-server`, `ricochet-mailbox` |
| `ricochet` (ricochet-dart-client) | Dart / Flutter | `ricochet: ^0.3.1` | `ricochet-dart-client` |
| `github.com/stephanfeb/go-p2p-forge` | Go | `go get github.com/stephanfeb/go-p2p-forge@v0.2.2` | `go-p2p-forge` |

Versions are the latest at the time of writing. Check pub.dev, the Go module
proxy or npm before you pin, and keep every `dart_libp2p*` package on versions
whose constraints agree (`dart pub deps` shows the resolution).

Cross-cutting skills: `cryptopeer-interop-testing` (tests across languages and
processes) and `cryptopeer-connectivity-debugging` (peers that will not connect,
streams that stall).

## Choosing what to use

| You need to… | Use |
|---|---|
| Send reliable streams over UDP between two processes, no libp2p | `dart_udx` / `go-udx` / `@go-ricochet/udx` |
| Build a Dart or Flutter peer with identities, encryption and many protocols | `dart_libp2p` (`dart-libp2p-host`) |
| Let a Go service join Dart peers over UDX | go-libp2p with `go-libp2p-udx-transport` |
| Let a Node.js js-libp2p node join over UDX | `@go-ricochet/libp2p-udx` |
| Connect a browser app (js-libp2p) to a Dart or Flutter app | `dart_libp2p_webrtc`, signalled through a relay |
| Connect phones or Macs with no network at all | `dart_libp2p_ble` |
| Reach a peer behind NAT | Circuit Relay v2, then hole punching (`dart-libp2p-nat-relay`) |
| Broadcast to many peers on a topic | GossipSub (`dart-libp2p-gossipsub`) |
| Find peers or content by key, store signed records | Kademlia DHT (`dart-libp2p-kad-dht`) |
| Fetch content-addressed blocks from peers | Bitswap (`dart-libp2p-bitswap`) |
| Shared state that many peers edit offline and merge | `merkledag` + `dart_libp2p_merkle_crdt` |
| Deliver to a peer that is offline; mailboxes, documents, feeds | Ricochet (`ricochet-server`, `ricochet-dart-client`) |
| A Go request/response service over libp2p streams with codecs and middleware | `go-p2p-forge` |

A request/response protocol between peers that are online at the same time
needs no extra package: write it on `dart_libp2p` streams
(`dart-libp2p-custom-protocol`).

## How the pieces connect

```text
 Flutter app ─┐                       ┌─ Go service (go-libp2p + go-libp2p-udx-transport)
 Dart CLI    ─┼── UDX/Noise/Yamux ────┼─ Ricochet server (go-ricochet)
              │   /ip4/…/udp/…/udx    └─ Node.js (js-libp2p + @go-ricochet/libp2p-udx)
              │
              ├── WebRTC (/webrtc, signalled via a relay) ── browser (js-libp2p)
              └── Bluetooth LE (/ble) ── Flutter app nearby
```

- The UDX address is `/ip4/<addr>/udp/<port>/udx` (and `/ip6/…`). Every
  implementation uses the same one, so Dart, Go and Node.js peers dial each
  other directly.
- dart-libp2p speaks the libp2p wire protocols (multistream-select, Noise,
  Yamux, Identify, Ping, Circuit Relay v2, DCUtR), so it interoperates with
  go-libp2p and js-libp2p on a shared transport.
- Ricochet servers are ordinary libp2p peers over UDX, Noise and Yamux. They
  find each other through GossipSub and relay for clients behind NAT.

## Rules that hold everywhere

- **Identity is the key.** A peer ID is derived from the host's private key.
  Persist the key if the peer must keep its identity across restarts;
  generating a fresh key each start breaks peerstore entries, DHT records,
  Ricochet mailboxes and ACLs.
- **Trust the connection, not the message.** Authorise by the peer ID the
  Noise handshake proved (the remote peer of the stream), never by an ID a
  request body claims.
- **Upgrade UDX on both ends together.** UDX v3 does not interoperate with
  v2, and a version mismatch is dropped silently: it looks like an
  unreachable peer, not an error.
- **Protocol IDs are a contract.** Never change a deployed protocol ID or its
  message format in place; add `/name/2.0.0` and keep serving the old one
  while peers migrate.
- **Close what you open.** Hosts, streams, subscriptions and UDX sockets hold
  ports, timers and memory. Tests that leak them hang or fail in later tests.
- **Bound everything you read from a peer.** Peers are untrusted: cap message
  sizes, apply timeouts, validate before acting.

## Starting a new project

1. Load this skill, then the skills for the packages the task needs.
2. Add dependencies with the versions above, checked against the registry.
3. Start from a working example rather than from scratch: each repo has
   `example/` (Dart) or `examples/` (Go, TypeScript), and
   https://cryptopeer.net/demos/internet-chat/ is a complete relay + DHT +
   GossipSub + hole-punching app.
4. Get two peers talking on loopback in a test before adding NAT traversal,
   discovery or a UI (`cryptopeer-interop-testing`).
5. Put the stack rules in the project's agent instructions. A template is at
   https://cryptopeer.net/skills/AGENTS.md.

## Red lines

- Do not substitute upstream packages (`libp2p` on npm, `go-libp2p` QUIC, other
  Dart libp2p ports) for cryptopeer ones in a project built on this stack
  without being asked: the transports and protocol sets differ.
- Do not disable Noise or run plaintext connections outside a test.
- Do not hard-code private keys, relay credentials or Ricochet server keys in
  source.
- Do not edit generated or vendored native code (for example the WebRTC
  native build) to work around a bug; report it upstream.

## Reference

- Site: https://cryptopeer.net (UDX: /udx/, dart-libp2p: /libp2p/, Ricochet: /ricochet/)
- Skill catalogue: https://cryptopeer.net/skills/ (machine-readable: https://cryptopeer.net/skills/index.json)
- Source: https://github.com/stephanfeb
