Mosh is a desktop-first, decentralized, end-to-end-encrypted messenger. It is built with Tauri v2 (Rust) and React + TypeScript, uses OpenMLS for message-layer encryption, and discovers peers over the Moss mesh runtime — no central server.
- Private 1:1 DMs — invite-URI onboarding with out-of-band fingerprint confirmation.
- Channels and private groups — multi-party conversations with their own membership and per-conversation DMs.
- Attachments and voice messages — chunked, encrypted file transfer with thumbnails and voice waveforms.
- Voice calls — encrypted real-time audio with jitter buffering.
- End-to-end encryption — OpenMLS group messaging over every channel.
- Decentralized discovery — Moss tracker / mesh-based peer discovery; users never enter hosts or ports in the primary flow.
- Encrypted persistent history — conversations and MLS session state survive restarts (see Persistence & Privacy).
src/— React + TypeScript frontend (Vite). Feature code lives undersrc/features/.src-tauri/— Rust backend (Tauri v2). Runtime adapters undersrc-tauri/src/adapters/bridge the UI to crypto, transport, storage, and the Moss shared library.- Moss runtime — the decentralized transport/discovery layer, built from Go
sources into a native shared library and loaded via FFI. Its source is the
redstone-md/mossrepository, vendored here as a git submodule atmoss/and pinned to a release tag inmoss.config.json.
git clone --recursive https://github.com/redstone-md/mosh # includes the moss submodule
# already cloned without --recursive? fetch the submodule:
git submodule update --init
npm install
npm run tauri dev # run the app in developmentThe Go toolchain is required: npm run build:app (and moss:prepare) build the
Moss native library from the moss/ submodule.
Onboarding flow:
- Open Mosh on two desktops.
- One device clicks Create invite; Mosh copies a
mosh://invite?...#fp=...URI. - Share that URI through any existing channel.
- The other device pastes it into Invite URI and confirms the fingerprint out of band.
- Both sides can now message, send attachments, and call. Receiving refreshes automatically over Moss discovery.
npm run dev # frontend only (Vite)
npm run tauri dev # full desktop app in development
npm run build # type-check + build the frontend
npm run build:app # bundle installers -> src-tauri/target/release/bundle/
npm test # typecheck + vitest + cargo test
npm run format # check Rust formattingPrivate-DM history and MLS session state persist across restarts, encrypted at rest:
- Stored in a local redb database under the app-data directory.
- Each record is encrypted with AES-256-GCM; the 256-bit key lives in the OS keychain (Windows Credential Manager) and is never written to disk in plaintext.
- MLS group state is snapshotted and restored via
MlsGroup::load, so an existing encrypted conversation keeps working after a restart with no re-invite. - Attachments re-render from the local cache; call events keep their duration.
- Fail-closed: if the keychain or database is unavailable, Mosh runs in-memory only and never writes unencrypted data.
See CHANGELOG.md for release notes.
- Cargo reuses
src-tauri/targetfor Rust build artifacts; the first build compiles the full Tauri + OpenMLS dependency tree and can take several minutes. npm run build:apprunsmoss:preparefirst to stage the Moss shared library next to the app.
moss/is a git submodule trackingredstone-md/moss, pinned to a release tag.npm run moss:updateresolves and pins the version inmoss.config.json.npm run moss:preparebuilds the native library from the submodule intosrc-tauri/moss-runtime/.
Do not commit built Moss shared-library binaries or generated credentials.