TypeScript implementation of the Marmot protocol - bringing end-to-end encrypted group messaging to Nostr using MLS (Messaging Layer Security).
Warning
This library is currently in Alpha and under heavy development. The API is subject to breaking changes without notice. It relies heavily on ts-mls for MLS cryptographic guarantees. Do not use in production yet.
This library provides the building blocks for creating secure, decentralized group chat applications on Nostr. It wraps ts-mls with Nostr-specific functionality, similar to how MDK wraps OpenMLS.
- 🔐 End-to-end encrypted group messaging using MLS protocol
- 🌐 Decentralized - groups operate across Nostr relays
- 🔑 Key package management - handle identity and invitations
- 📦 Storage-agnostic - bring your own storage backend (LocalForage, IndexedDB, etc.)
- 🔌 Network-agnostic - works with any Nostr client library
- 📱 Cross-platform - works in browsers and Node.js (v20+)
npm install @internet-privacy/marmot-ts
# or
pnpm add @internet-privacy/marmot-tsCurrently, marmot-ts supports the following Marmot Improvement Proposals (MIPs):
| MIP | Description | Status |
|---|---|---|
| MIP-00 | Introduction and Basic Operations | ✅ Supported |
| MIP-01 | Network Transport & Relay Communication | ✅ Supported |
| MIP-02 | Identities and Keys | ✅ Supported |
| MIP-03 | Group State & Memberships | ✅ Supported |
Comprehensive documentation is available in the documentation/ directory:
- Getting Started - A fast track to initializing the library.
- Architecture - High-level component overview and Nostr/MLS integration mapping.
- MarmotClient - Deep dive into the main entry point class, initialization, and identity management.
- Bytes-First Storage - Explaining the storage-agnostic philosophy and group state hydration.
- Ingest Methods - Handling incoming messages and network input robustly.
- Examples - Concise snippets for group creation, invitations, sending messages, and more.
To begin using the client, you need an established EventSigner interface and proper storage backends:
import { MarmotClient, KeyValueGroupStateBackend, KeyPackageStore } from "@internet-privacy/marmot-ts";
// Setup backends via your choice of db (e.g. LocalForage)
const groupStateBackend = new KeyValueGroupStateBackend(/* ... */);
const keyPackageStore = new KeyPackageStore(/* ... */);
const client = new MarmotClient({
signer: yourNostrSigner,
groupStateBackend,
keyPackageStore,
network: /* NostrNetworkInterface */,
});
const group = await client.createGroup("My Secret Group", {
description: "A private discussion",
relays: ["wss://relay.example.com"],
// Optional: add additional admins (the creator is always included automatically)
adminPubkeys: ["<other-admin-pubkey-hex>"],
// Optional: override MLS ciphersuite
ciphersuite: "MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519",
});See Getting Started and Examples for full usage instructions.
pnpm install # Install dependencies
pnpm build # Compile TypeScript
pnpm test # Run tests (watch mode)
pnpm format # Format code with Prettier