Reed: anonymous, end-to-end encrypted messaging over relays, radio and mesh. One Rust core for Android, web and iOS. Unaudited pre-release.
  • Rust 56.8%
  • Kotlin 14.8%
  • Shell 8.2%
  • TypeScript 7.6%
  • Swift 6.5%
  • Other 6%
Find a file
exo e9ccdd497a
Some checks failed
android / android (push) Successful in 23m23s
assurance / proofs (push) Successful in 8m21s
assurance / ct-bench (push) Successful in 2m39s
assurance / voice-opus-crosscheck (push) Successful in 4m36s
assurance / wasm-surface (push) Successful in 3m3s
assurance / fuzz (push) Successful in 1h33m12s
assurance / miri (push) Has been skipped
assurance / kani (push) Has been skipped
rust / rust (push) Successful in 38m3s
site / site (push) Successful in 1m38s
web / web (push) Successful in 31m56s
release / toolchain-image (push) Has been skipped
release / desktop-linux (linux/amd64, x86_64-unknown-linux-gnu) (push) Has been skipped
release / desktop-linux (linux/arm64, aarch64-unknown-linux-gnu) (push) Has been skipped
reproducible / double-build (push) Failing after 50m51s
reproducible / desktop-linux (push) Has been skipped
release / build (push) Has been skipped
assurance / fuzz-mac (push) Has been cancelled
devices / devices (push) Has been cancelled
release / desktop-macos (push) Has been cancelled
web, site, status, authority-panel: pin pnpm 11.5.2 (packageManager)
The toolchain image activates pnpm 11.5.2 through corepack in root's cache only. Builds that run
as another user with another HOME (the CI job containers, uid 1000) found no pinned version, so
the corepack shim fetched pnpm "latest" from npm: pnpm 12.14.0 in the web jobs, and the v0.5.0
tag's `reproducible` double build stopped when registry.npmjs.org answered 503 on
pnpm/latest (task 3949). The field pins the same version everywhere, as
apps/desktop/tests/tauri-driver already does; checked as uid 1000 with a fresh HOME in the
toolchain image: pnpm 11.5.2, and `pnpm install --frozen-lockfile` passes for apps/web and
apps/site (status and authority-panel have no lockfile and no release or CI build).

Reason: an unpinned package manager in a reproducible build is a supply-chain and determinism gap.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 07:13:09 +02:00
.cargo cargo: cap build jobs at 6 on the shared Mac 2026-09-06 00:56:20 +02:00
.forgejo/workflows ci(site, web): install only Chromium's headless shell; site job 45 minutes 2026-10-22 03:50:21 +02:00
apps web, site, status, authority-panel: pin pnpm 11.5.2 (packageManager) 2026-10-22 07:13:09 +02:00
bindings FED-S03: compile fixes (nested comment in the bindings, Chats relay line) 2026-10-08 10:27:04 +02:00
build-status rc deps note: ruzstd upstream status and the reporting decision 2026-10-19 15:52:46 +02:00
core reed-core: a voice note's waveform is checked before its attachment name is built 2026-10-20 17:43:31 +02:00
deploy device and appliance legs admit the reusable-address first contact 2026-10-20 14:24:03 +02:00
design M3 c6: design pass wave 2 to round 7 PASS, RCS networks row, the invite-link fuzz fix, and the M4 program 2026-09-17 06:45:56 +02:00
docs authority: Onion holds through a failed onion probe, retried at the next round 2026-10-22 02:36:37 +02:00
fastlane/metadata/android/en-US release: 0.5.1, versionCode 11 2026-10-22 04:49:56 +02:00
fuzz release: 0.5.1, versionCode 11 2026-10-22 04:49:56 +02:00
host release: 0.5.1, versionCode 11 2026-10-22 04:49:56 +02:00
i18n M3 c6: design pass wave 2 to round 7 PASS, RCS networks row, the invite-link fuzz fix, and the M4 program 2026-09-17 06:45:56 +02:00
proofs FED-T06: property twins green, ProVerif federation note 2026-10-07 17:48:48 +02:00
research M3 wave 1 (Fable): profiles, onboarding with the Networks step, directory role and discovery client, contact discovery UI, SMS invitations and App Links, push notifier row, copy 3.1, file bearer 0x03, rendezvous over restricted onions, SimpleX phase 2, Bramble stage 2 and 3 (Briar in person, LAN, Mailbox), desktop shells, plus the device bench fixes, the BLE LoRa bridge and the D9 band check 2026-09-14 16:38:17 +02:00
services authority: Onion holds through a failed onion probe, retried at the next round 2026-10-22 02:36:37 +02:00
tests release: 0.5.1, versionCode 11 2026-10-22 04:49:56 +02:00
tools release: 0.5.1, versionCode 11 2026-10-22 04:49:56 +02:00
vectors release: bootstrap snapshot at valid_after 1792594800 listing reed-public 2026-10-21 17:35:51 +02:00
.gitignore gitignore: the bench runner's tests/device/out/ directory 2026-09-08 06:42:03 +02:00
.gitlab-ci.yml ci: one dependency gate over every shipped lockfile (tools/release/advisories.sh) 2026-10-20 14:17:21 +02:00
.weblate M3 batch (c), the last three (Fable): broadcast-log channels on the three shells, localisation with the Weblate layout and the reader passes, the Android Nearby stack made deterministic 2026-09-15 01:47:55 +02:00
Cargo.lock release: 0.5.1, versionCode 11 2026-10-22 04:49:56 +02:00
Cargo.toml release: 0.5.1, versionCode 11 2026-10-22 04:49:56 +02:00
CHANGELOG.md release: 0.5.1, versionCode 11 2026-10-22 04:49:56 +02:00
deny.toml deps: rustls-webpki 0.103.16 and webpki-roots 1.0.10 (RUSTSEC-2026-0382, -0381) 2026-10-20 21:47:39 +02:00
HANDOFF.md HANDOFF: name confirmed (Reed), M2 start; provenance of the M2 research wave 2026-09-05 20:44:14 +02:00
LICENSE WP-00: interface freeze, workspace skeleton, reed-api and reed-proto (Fable); wave-0 gate verified 2026-09-05 05:10:43 +02:00
README.md M3 c6: design pass wave 2 to round 7 PASS, RCS networks row, the invite-link fuzz fix, and the M4 program 2026-09-17 06:45:56 +02:00
rust-toolchain.toml WP-00: interface freeze, workspace skeleton, reed-api and reed-proto (Fable); wave-0 gate verified 2026-09-05 05:10:43 +02:00
SECURITY.md M3 integration round 2 and wave 2 reading (Fable): the 1.5 additive API block on the core and its mirrors, the shells' mounts and copy rows, the adversarial review with property and fuzz targets, the relay appliance stack 2026-09-15 16:22:39 +02:00

Reed

Reed is a messenger with no phone number, email or account. Messages are end-to-end encrypted with forward secrecy and travel as fixed-size cells through relays that store ciphertext they cannot read, over Tor when the user turns it on, directly between two nearby phones over Wi-Fi or Bluetooth, through a LoRa companion radio, and to people on other networks (Briar, SimpleX, Nostr, Delta Chat, Meshtastic, MeshCore) with those networks' own encryption. One Rust core runs on Android, in the browser as an installable web app, on iOS and on the command line.

Reed is an unaudited pre-release. Do not rely on it if your safety depends on it.

Historical codename: sotto (the repository directory keeps that name; nothing else does). Store display name: Reed Messenger (docs/DECISIONS.md ADR-47).

What this repository contains

Path Content
core/ The sans-IO Rust core: reed-api (shared types), reed-proto (byte layouts), reed-crypto (primitive facade), reed-session (first contact, Double Ratchet, period layer, prekeys), reed-store and reed-store-sqlite (encrypted records), reed-bearer (relay driver, link driver, socket pool, simulators), reed-bearer-lora (Meshtastic and MeshCore companions, band check, narrow codec), reed-core (the state machine: sockets, links, narrow, groups, MLS adapter, notify, families), reed-interop, reed-bramble (Briar), reed-simplex, reed-nostr, reed-mesh-client, reed-rcs (carrier messaging over an IMS core, ADR-58; skeleton)
host/ Host-side crates that need an OS: reed-tor (arti client leg, onion hosting), reed-smptls (SimpleX transport), reed-chatmail (the Delta Chat engine behind a pipe, its own lockfile per ADR-50)
services/reed-relay/ The blind mailbox relay: binary, library, group-log and notifier roles, deployment files, operator README
bindings/ reed-ffi (UniFFI, Kotlin and Swift; the network host object) and reed-wasm (wasm-bindgen)
apps/android/ The Android app (Jetpack Compose, applicationId fr.ekaii.reed, flavours foss and play)
apps/web/ The web client (Svelte 5, Vite 8, a Web Worker owns the core, Web Push)
apps/ios/ ReedKit (Swift package over the UniFFI XCFramework) and the SwiftUI app with its notification service extension
apps/site/ The static website
tools/ reed-cli (headless client and integration gate), xtask (build and check tasks), release/ (toolchain container, reproduce, sign, publish, F-Droid), oracles/ (the real Briar, SimpleX, Nostr, Meshtastic and MeshCore software the interop tests run against)
tests/ End-to-end scripts (cli-e2e.sh, cli-onion.sh, cli-lan.sh, cli-group.sh), the demo runner, interop and simulator harnesses, device scripts, the independent ratchet reference, conformance, property, constant-time and Kani tests
proofs/, fuzz/ ProVerif models with their expected verdicts; cargo-fuzz targets on the pinned nightly
vectors/ Frozen test vectors, M1 and the 1.3 families
docs/ Architecture (M1 and the M2 addendum), protocol (1.3, plus the Bramble and SimpleX transcriptions), threat model, decisions, roadmap, build plans, UI copy, runbooks, release and store procedures, toolchain, review packet
design/, research/ Frozen inputs from the research and design phases, including the M2 research reports under research/m2/

Documents

Read in this order: docs/ARCHITECTURE.md and docs/ARCHITECTURE-M2.md (shape, crates, hosts, build commands), docs/PROTOCOL.md (the byte-level contract, version 1.3), docs/THREAT-MODEL.md (assets, adversaries, ceilings per bearer and per foreign network, the claims policy in section 10), docs/DECISIONS.md (ADRs), docs/ROADMAP.md (M1 to M4), docs/BUILD-PLAN-M2.md (work packages), docs/TOOLCHAIN.md (verified local build facts), docs/UI-COPY.md (every user-facing security sentence), docs/RUNBOOK-M2.md (the demo, step by step), docs/RELEASE.md and docs/STORE.md (releases and store submissions), SECURITY.md (reporting, disclosure, the legal record).

Build quickstart (M2)

Verified on macOS with Rust 1.97.1 (the pinned toolchain, the only one with the iOS targets), JDK 21, Gradle 9.6.0 (wrapper), Node 24.14 and pnpm 11.5, Xcode with the iOS 26.5 simulators. Details and the reasons behind each pin are in docs/TOOLCHAIN.md; the full command table is docs/ARCHITECTURE-M2.md section 12 (additions to docs/ARCHITECTURE.md section 10). Always build from the repository so the pinned toolchain is used; nightly (nightly-2026-08-25) only inside fuzz/ and for Miri.

Environment for every shell:

export ANDROID_HOME=/opt/homebrew/share/android-commandlinetools
export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/27.2.12479018
export JAVA_HOME=/opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home
export CARGO_TARGET_DIR=/tmp/reed-target/local    # any directory; scripts never assume target/
export IPHONEOS_DEPLOYMENT_TARGET=17.0 MACOSX_DEPLOYMENT_TARGET=14.0   # iOS builds

Core, tests and checks on the host:

cargo build --workspace
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo deny check                       # licences, bans, advisories, sources (deny.toml is frozen, ADR-18, ADR-40)
cargo xtask vectors --check            # vectors/*.json unchanged
cargo xtask copy                       # every governed sentence on Android, web, site and iOS comes from docs/UI-COPY.md;
                                       # one transport.name id per bearer kind; Disabled reasons resolved (UI-COPY.md section 5);
                                       # the family fixture holds
cargo xtask copy --self-test           # the fixture under docs/ui-copy-fixture/ fails exactly as listed
cargo xtask copy --fold-table          # the profile fold table (docs/PROFILE-FOLD.md) against the screen fixture (M3, UI-COPY.md 1.6)
cargo xtask check                      # the whole local CI equivalent

Web core must stay pure Rust (no C toolchain variables, no ring, no rusqlite, and none of the host crates):

cargo build -p reed-core -p reed-nostr --target wasm32-unknown-unknown
cargo tree -p reed-core --target wasm32-unknown-unknown -e normal | grep -c -E 'rusqlite|ring v|cc v|tokio|arti|rustls|deltachat'   # prints 0

Tor host, relay and the command-line gates:

cargo build -p reed-tor --release
cargo build --release -p reed-relay -p reed-cli
tests/e2e/cli-e2e.sh                   # the M1 gate: two CLIs through the real relay
tests/e2e/cli-onion.sh                 # relay on loopback, local tor hosting the onion, two `reed-cli --tor`
tests/e2e/cli-lan.sh                   # two CLIs over lan+tcp with mDNS
tests/e2e/cli-group.sh                 # eight CLIs: create, add, remove, rotate, late fetch

Interop against the real oracles (tools/oracles; each script says what it needs and skips what is absent):

tests/interop/briar/run.sh             # briar-headless 1.5.19 over Tor
tests/interop/simplex/run.sh           # smp-server, xftp-server (Docker) and the SimpleX CLI 7.1.0.4
tests/interop/nostr/run.sh             # nostr-rs-relay with NIP-42
tests/interop/chatmail/run.sh          # the deltachat test context; ONLINE=1 for a live chatmail relay
tests/interop/mesh/run.sh              # meshtasticd --sim 2.7.26 and the MeshCore simulator
tests/sim/lora/meshtastic.sh; tests/sim/lora/meshcore.sh     # the LoRa bearer on the firmware simulators

Android native library, Kotlin bindings and APKs (two flavours; the emulator is a singleton under lockf, the Pixel 9a is reached with adb -s 53261JEBF04604):

cargo xtask android --abis arm64-v8a,armeabi-v7a,x86_64          # debug; --release-repro for the release build
cd apps/android && ./gradlew assembleFossDebug assemblePlayDebug testFossDebugUnitTest

iOS (unsigned, simulator):

cargo xtask ios                                    # three static archives, Swift bindings, apps/ios/ReedKit/ReedFFI.xcframework
cd apps/ios/ReedKit && swift test
cd apps/ios/Reed && xcodegen generate && xcodebuild test -project Reed.xcodeproj -scheme Reed \
  -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.5' CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO

Web client and website:

cargo xtask wasm                                       # release wasm build, wasm-bindgen 0.2.127, integrity hash
cd apps/web  && pnpm install --frozen-lockfile && pnpm build && pnpm preview --port 4173 --strictPort   # REED_CSP_DEV=0 for the production CSP
cd apps/site && pnpm install --frozen-lockfile && pnpm build && pnpm test:e2e && pnpm preview --port 4174 --strictPort
cd apps/site && pnpm check                                             # typecheck, unit tests, build, link check, site copy check (data-copy-fill aware)

Assurance:

proofs/install-proverif.sh && cargo xtask proofs      # every ProVerif model against proofs/proverif/expected.txt
cargo xtask fuzz-ci --minutes 10                       # seeded fuzz run of every target
cargo run --release -p reed-ct-bench                   # dudect timing classes
MIRIFLAGS=-Zmiri-disable-isolation cargo +nightly-2026-08-25 miri test -p reed-proto -p reed-crypto -p reed-session
cargo xtask sbom

Release (Mac, owner present; keys come only from the vault, never from CI): tools/release/reproduce.sh vX.Y.Z, then tools/release/sign.sh, then tools/release/publish.sh; tools/release/fdroid-rebuild.sh verifies from outside. Procedure and rules in docs/RELEASE.md.

Demo: tests/demo/run.sh --m2 --pixel 53261JEBF04604 --ios 'iPhone 17' --tor --lan --ble --pcap (described in docs/RUNBOOK-M2.md; a device that is absent marks its legs SKIPPED with the reason, never FAIL).

Status

Milestone M2 (docs/ROADMAP.md 2.0): the M1 relay exchange between Android, browser, iOS simulator and command-line clients, plus the Tor client leg and onion mirror, Wi-Fi and Bluetooth links between two Android phones, LoRa through Meshtastic and MeshCore companions on the firmware simulators (untested on hardware), groups of up to 64 members, content-free wake-ups (UnifiedPush, Web Push, FCM, APNs), rotating prekeys and device lists, and conversations with Briar, SimpleX, Nostr, Delta Chat, Meshtastic and MeshCore users through their own protocols, tested against the real software. Reproducible builds, three signature systems and an F-Droid recipe are in place; no release has been published yet. Attachments, disappearing messages, multi-device linking, the File bearer and XMPP or Matrix are M3 (ADR-49).

Security

Vulnerability reports, the disclosure policy, the audit status, the abuse address and the export-control record are in SECURITY.md. The protected and unprotected properties per bearer are in docs/THREAT-MODEL.md section 4, per foreign network in 4.7; what the UI may claim is section 10 of the same document, and docs/UI-COPY.md holds every sentence.

Licence

Code (core crates, host crates, bindings, relay, apps, tools, tests) is licensed under the Mozilla Public License 2.0 (LICENSE). Documentation under docs/ is licensed under CC BY 4.0. Third-party dependencies are limited by deny.toml (docs/DECISIONS.md ADR-18, ADR-40); the embedded Delta Chat engine has its own tree and lockfile (ADR-50). Briar and SimpleX are implemented from their specifications; no GPL or AGPL code is linked, copied or translated.