{"id":51399669,"url":"https://github.com/sudoaanish/loom","last_synced_at":"2026-07-04T05:14:33.114Z","repository":{"id":367640657,"uuid":"1281705523","full_name":"sudoaanish/loom","owner":"sudoaanish","description":"Local-first, serverless, peer-to-peer secure messaging client built on Tauri and Rust utilizing Double Ratchet encryption.","archived":false,"fork":false,"pushed_at":"2026-06-26T21:27:27.000Z","size":99,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-26T22:19:17.055Z","etag":null,"topics":["cryptography","double-ratchet","local-first","mdns","offline","p2p","rust","secure-messaging","serverless","tauri"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sudoaanish.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-26T20:48:44.000Z","updated_at":"2026-06-26T21:27:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sudoaanish/loom","commit_stats":null,"previous_names":["sudoaanish/loom"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/sudoaanish/loom","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudoaanish%2Floom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudoaanish%2Floom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudoaanish%2Floom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudoaanish%2Floom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sudoaanish","download_url":"https://codeload.github.com/sudoaanish/loom/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sudoaanish%2Floom/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35110668,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","double-ratchet","local-first","mdns","offline","p2p","rust","secure-messaging","serverless","tauri"],"created_at":"2026-07-04T05:14:32.649Z","updated_at":"2026-07-04T05:14:33.106Z","avatar_url":"https://github.com/sudoaanish.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# Loom\n\nExperimental local-first peer-to-peer messaging for desktop.\n\n[![Repository](https://img.shields.io/badge/GitHub-sudoaanish%2Floom-181717?style=for-the-badge\u0026logo=github)](https://github.com/sudoaanish/loom)\n[![Website](https://img.shields.io/badge/Website-aanishfarrukh.com-0f766e?style=for-the-badge)](http://aanishfarrukh.com/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue?style=for-the-badge)](LICENSE)\n[![Status](https://img.shields.io/badge/Status-Experimental-orange?style=for-the-badge)](#experimental-security-warning)\n\n\u003c/div\u003e\n\n## Overview\n\nLoom is a Tauri and Rust desktop messaging client exploring local network discovery, direct peer-to-peer communication, cryptographic identity, and message exchange without a central messaging server.\n\nThe current implementation is designed around local-first operation. It does not use user accounts, telephone registration, a central messaging service, or cloud relay infrastructure. Peers exchange Loom identity tokens out of band, discover one another through mDNS when available, and communicate over direct TCP connections.\n\n## Experimental Security Warning\n\nLoom is experimental software. It has not been independently audited and should not be treated as production-ready security software.\n\nThe repository contains a custom cryptographic protocol implementation using X25519 key agreement, Ed25519 signatures, HKDF-SHA256 key derivation, ChaCha20-Poly1305 message encryption, and a custom Double Ratchet-style state machine. Loom should not be used for high-risk, sensitive, regulated, or adversarial communications.\n\n## What Loom Does\n\n- Generates a local cryptographic identity from a 32-byte master seed.\n- Exports public identity material as a `LOOM-` token.\n- Imports contacts from Loom tokens.\n- Discovers local peers through mDNS using `_loom._tcp.local.`.\n- Opens a direct TCP listener on an ephemeral local port.\n- Supports manual peer address injection for loopback and local testing.\n- Performs signed handshake messages before chat.\n- Encrypts message payloads in transit after a ratchet session is established.\n- Persists contacts, message history, local identity seed, and ratchet state in SQLite.\n- Exposes a Tauri desktop UI for onboarding, contact management, peer discovery, handshakes, and chat.\n\n## Architecture\n\nLoom is split into three main layers.\n\n### Frontend\n\nThe frontend lives in `src/` and is implemented with HTML, CSS, and JavaScript.\n\n- `src/index.html` defines the single-page application shell.\n- `src/style.css` defines the desktop UI styling.\n- `src/main.js` handles UI state, Tauri command calls, contact rendering, peer rendering, chat rendering, and event listeners.\n\nThe frontend invokes Tauri commands such as `generate_new_identity`, `start_network`, `add_contact_token`, `initiate_chat_handshake`, `send_message`, and `get_messages`. It listens for backend events including `peer_discovered`, `message_received`, `session_established`, and `log`.\n\n### Tauri Backend\n\nThe Tauri backend lives in `src-tauri/`.\n\n- `src-tauri/src/main.rs` initializes the app, creates the `LoomEngine`, registers Tauri commands, and forwards core callbacks into frontend events.\n- `src-tauri/tauri.conf.json` defines the desktop app configuration.\n- `src-tauri/capabilities/default.json` defines the app capability permissions.\n\nThe backend stores the SQLite database under Tauri's app data directory. The default database filename is `loom.db`. A `LOOM_PROFILE` environment variable or `--profile` / `-p` argument changes the database filename to `loom_\u003cprofile\u003e.db`.\n\n### Core Engine\n\nThe Rust core lives in `crates/loom-core/`.\n\n- `src/lib.rs` exposes the `LoomEngine` API and callback interface.\n- `src/token.rs` implements Loom token serialization and parsing.\n- `src/storage.rs` implements SQLite persistence.\n- `src/network.rs` implements mDNS discovery, TCP transport, handshake handling, message send and receive paths, and connection tracking.\n- `src/protocol.rs` defines handshake and encrypted envelope wire messages.\n- `src/crypto.rs` implements key derivation, symmetric encryption helpers, and Double Ratchet-style session state.\n\n## Security Model\n\nLoom currently models identity as an Ed25519 public key and an X25519 public key encoded into an out-of-band Loom token. Private key material is derived from a locally generated master seed.\n\nThe implementation signs handshake payloads with Ed25519, derives shared session material from X25519 Diffie-Hellman outputs using HKDF-SHA256, initializes a Double Ratchet-style session, encrypts message payloads with ChaCha20-Poly1305, and signs encrypted chat envelopes with Ed25519.\n\nThese are implementation details, not audit results. The security model remains experimental.\n\n## Current Limitations\n\n- The protocol is custom and unaudited.\n- Loom is not equivalent to Signal.\n- SQLite stores plaintext message history after decryption.\n- SQLite stores the local master seed and serialized ratchet state without application-level encryption.\n- Tauri Content Security Policy is currently set to `null`.\n- mDNS exposes local presence and network metadata on the local network.\n- There is no documented identity revocation, key rotation, or recovery model.\n- There is no documented key verification ceremony beyond out-of-band token exchange.\n- TCP frame lengths are accepted from the network without an explicit maximum in the current implementation.\n\n## Tech Stack\n\n\u003cp\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Tauri-2-24C8DB?style=flat-square\u0026logo=tauri\u0026logoColor=white\" alt=\"Tauri 2\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Rust-000000?style=flat-square\u0026logo=rust\u0026logoColor=white\" alt=\"Rust\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Tokio-Async%20Runtime-6B46C1?style=flat-square\" alt=\"Tokio\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/JavaScript-ES6-F7DF1E?style=flat-square\u0026logo=javascript\u0026logoColor=black\" alt=\"JavaScript\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/HTML5-E34F26?style=flat-square\u0026logo=html5\u0026logoColor=white\" alt=\"HTML5\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/CSS3-1572B6?style=flat-square\u0026logo=css3\u0026logoColor=white\" alt=\"CSS3\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/SQLite-003B57?style=flat-square\u0026logo=sqlite\u0026logoColor=white\" alt=\"SQLite\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/mDNS-mdns--sd-0f766e?style=flat-square\" alt=\"mDNS\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Crypto-Ed25519%20%7C%20X25519%20%7C%20ChaCha20--Poly1305-orange?style=flat-square\" alt=\"Cryptography\" /\u003e\n\u003c/p\u003e\n\n- Desktop shell: Tauri 2\n- Frontend: HTML, CSS, JavaScript\n- Backend: Rust\n- Async runtime: Tokio\n- Storage: SQLite through `rusqlite`\n- Peer discovery: `mdns-sd`\n- Cryptography crates: `ed25519-dalek`, `x25519-dalek`, `chacha20poly1305`, `hkdf`, `sha2`, `blake2`, `rand`\n- Serialization: `serde`, `serde_json`\n- Message identifiers: `uuid`\n\n## Development\n\nThe repository is a Rust workspace with two members:\n\n- `crates/loom-core`\n- `src-tauri`\n\nPrerequisites:\n\n- Rust toolchain\n- Node.js and npm for invoking the Tauri CLI through `npx`\n\nRun the Rust test suite:\n\n```bash\ncargo test\n```\n\nStart the Tauri app in development mode:\n\n```bash\nnpx @tauri-apps/cli dev\n```\n\nFor local multi-instance testing, run separate profiles:\n\n```powershell\n$env:LOOM_PROFILE=\"peer1\"\nnpx @tauri-apps/cli dev\n```\n\nOpen a second terminal in the same repository directory. If you use [twin](https://github.com/sudoaanish/twin), you can open a matching terminal session from the current working directory:\n\n```powershell\ntwin\n```\n\nThen run the second profile:\n\n```powershell\n$env:LOOM_PROFILE=\"peer2\"\n.\\target\\debug\\loom-backend.exe\n```\n\n## Security Documentation\n\nAdditional security documentation:\n\n- [SECURITY.md](SECURITY.md)\n- [THREAT_MODEL.md](THREAT_MODEL.md)\n\n## License\n\nLoom is licensed under the [MIT License](LICENSE).\n\n## Author\n\nBuilt by [Aanish Farrukh](http://aanishfarrukh.com/).\n\nRepository: [github.com/sudoaanish/loom](https://github.com/sudoaanish/loom)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsudoaanish%2Floom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsudoaanish%2Floom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsudoaanish%2Floom/lists"}