Reed: anonymous, end-to-end encrypted messaging over relays, radio and mesh. One Rust core for Android, web and iOS. Unaudited pre-release.
  • Rust 53.2%
  • Kotlin 16.6%
  • Shell 8.4%
  • Swift 8.2%
  • TypeScript 7.1%
  • Other 6.5%
Find a file
exo 9bd9be4e59
Some checks failed
android / android (push) Has been cancelled
assurance / proofs (push) Has been cancelled
assurance / ct-bench (push) Has been cancelled
assurance / voice-opus-crosscheck (push) Has been cancelled
assurance / wasm-surface (push) Has been cancelled
assurance / fuzz (push) Has been cancelled
assurance / miri (push) Has been cancelled
assurance / kani (push) Has been cancelled
assurance / fuzz-24h (push) Has been cancelled
devices / devices (push) Has been cancelled
rust / rust (push) Has been cancelled
site / site (push) Has been cancelled
web / web (push) Has been cancelled
fdroid: canonical recipe, metadata upstream, commit at the Fastlane hash
Align the recipe with fdroiddata inclusion rules: drop the inline
Summary/Description (now in upstream Fastlane) and the reed-internal
comment header, run fdroid rewritemeta for the canonical layout, switch
Categories to the current set (Internet is deprecated -> Messaging;
Security kept), keep only the latest version, and point commit at the
Fastlane commit 0bd667d7 (same Android build inputs as v0.3.0, so the
APK reproduces identically).

Reason: make the fdroiddata MR follow the App inclusion template and rules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-30 20:09:45 +02:00
.cargo cargo: cap build jobs at 6 on the shared Mac 2026-09-06 00:56:20 +02:00
.forgejo/workflows M4.1: voice messages, the core (Fable) 2026-09-18 13:13:58 +02:00
apps release: v0.3.0 2026-09-30 17:38:14 +02:00
bindings M4.1 shell wave: wasm lift of the M4.1 core surfaces to the web PWA (Fable) 2026-09-28 09:15:53 +02:00
build-status M4.1 shell wave: FFI lift of the M4.1 core surfaces to Android + iOS (Fable) 2026-09-28 07:57:26 +02:00
core M4.1: live and ephemeral messaging, the core (Fable) 2026-09-28 06:31:37 +02:00
deploy 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
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 design-bar: reconcile C1, C4, F6 to the shipped M4.1 design (rev 2.1) 2026-09-29 16:49:57 +02:00
fastlane/metadata/android/en-US fastlane: en-US store metadata for F-Droid inclusion 2026-09-30 20:00:17 +02:00
fuzz M4.1: view-once as a first-class message class + the capture floor (Fable) 2026-09-18 19:47:48 +02:00
host M4.1: image messages, the core (Fable) 2026-09-18 14:35:28 +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 FIX-KANI-BOUNDS (Fable): Kani decoder harnesses reworked with per-harness bounds from PROTOCOL.md 3 and three over-approximating stubs (URL rule, UTF-8, all-zero scan) in the card family; window harnesses stub postcard::from_bytes through a serde value source; kani.sh with -Z stubbing, harness timeout, memory watchdog, per-harness verdict table and exit 1 on any missing verdict; expected.txt parser splits on whitespace runs; KNOWN-ISSUES A-10, A-11 and table 3.1; verified by lead (18 of 20 harnesses SUCCESSFUL, the window pair carried by A-11) 2026-09-10 08:20:56 +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 M4 Google Messages interim path: the 0x0C carrier family, the AGPL bridge, the host and the CLI feature (Fable) 2026-09-17 15:05:39 +02:00
tests M4.1: live and ephemeral messaging, the core (Fable) 2026-09-28 06:31:37 +02:00
tools fdroid: canonical recipe, metadata upstream, commit at the Fastlane hash 2026-09-30 20:09:45 +02:00
vectors M4.1: live and ephemeral messaging, the core (Fable) 2026-09-28 06:31:37 +02:00
.gitignore gitignore: the bench runner's tests/device/out/ directory 2026-09-08 06:42:03 +02:00
.gitlab-ci.yml 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
.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 M4.1: image messages, the core (Fable) 2026-09-18 14:35:28 +02:00
Cargo.toml M4.1: image messages, the core (Fable) 2026-09-18 14:35:28 +02:00
CHANGELOG.md release: bump versions to 0.3.0-rc1 2026-09-29 21:14:25 +02:00
deny.toml WP-M2-22 closing wiring behind the frozen accessors: session keeps SK, ncap plumbing, links and narrow seeded from the pair key, relay pool, prekeys and device revocation on the CLI, relay registration log and scripted clock, Android chatmail persistence through the core, iOS Keep; cli-lan step 5, cli-onion 8c and 8d, push through Core; deny.toml allows NCSA for the fuzz-only libfuzzer-sys 2026-09-07 21:06:03 +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.