Secure large file transfer. No cloud. No accounts.
mirall.app »
Docs
·
Changelog
·
Report a bug
Mirall moves terabyte-scale files directly between devices. You and the people you share with form private spaces; files transfer peer-to-peer over end-to-end encrypted connections — no cloud storage, no accounts, no telemetry. Built for workflows where files are huge and privacy is non-negotiable.
- Direct. Bytes go from one member's disk to another's — never through a server. Peers find each other over a global DHT and connect over encrypted sockets.
- Private. Everything is end-to-end encrypted. Joining a space is approved cryptographically: approval hands the newcomer the space's content key — without it, file listings are unreadable and peers refuse to serve a single byte.
- Built for big files. Files are shared in place — no second copy, no staging upload. Transfers are content-addressed, verified chunk by chunk, and resume exactly where they stopped, even after a restart. Terabyte-scale files are a design target, not an edge case.
- Local-first. Everything persists on your machine and keeps working offline. The entire client is free software (AGPL-3.0).
- Spaces — private groups for sharing; create one, send an invite, approve who joins
- Invite links with optional expiry, auto-approve policy, and per-link revocation
- Folder shares — publish a whole directory; members browse it, pick single files, or mirror it to a local folder that stays in sync (read-only, deletion-safe)
- Resumable transfers — automatic pause when a peer goes offline, automatic resume on reconnect, no re-downloading of verified data
- Automatic updates over P2P — the app updates itself through the same peer-to-peer network it shares files on
- Native notifications, system tray,
mirall://invite deep links, command palette, light & dark themes, English · Deutsch · Español · Français · Italiano
The easiest way to get Mirall is from mirall.app. Direct downloads of the latest release:
| Platform | Download |
|---|---|
| macOS (Apple silicon) | Mirall.dmg |
| macOS (Intel) | Mirall.dmg |
| Windows 10/11 (x64) | Mirall.msix |
| Linux (x64) | Mirall.AppImage |
| Linux (arm64) | Mirall.AppImage |
Note
After the first install, Mirall keeps itself up to date automatically — new releases are distributed over the same peer-to-peer network and applied on the next start.
Signed releases: the macOS app is code-signed and notarized by Apple; the Windows MSIX is signed with a Certum code-signing certificate; the Linux AppImage is unsigned, as is common for AppImages.
- A space is a random 256-bit topic on the Hyperswarm DHT. Members discover each other there and talk over encrypted (Noise) sockets — the invite code never touches a server.
- Sharing a file advertises metadata, not bytes: the file is hashed once, in place, and its entry lands in the space's encrypted catalog. Your disk stays the only copy until someone asks for the file.
- Downloads are content-addressed: the receiver fetches chunks by hash from any online member who holds the file, verifies each chunk as it arrives, and lands the result next to a resume journal — interruptions continue instead of starting over.
- Access control is cryptography, not UI: membership approval hands over the space content key, and every protocol frame is signed by the sender's identity, bound to its connection.
- The data layer runs on the Holepunch stack (Hypercore, Hyperbee, Hyperswarm, Corestore) inside a Bare worker process, hosted by Electron.
The full design — process model, data model, security model, glossary — is documented in
.claude/solution-architecture.md.
- First launch — pick a display name (and optionally an avatar).
- Create a space — name it, pick an icon, and share the invite code or
mirall://link. - Approve — when someone joins, you (or any member) approve them; approval is what makes the space's contents readable to them.
- Share — drop files into the space, or add a whole folder as a share. Members download what they want, when they want; nothing syncs without consent.
Step-by-step guides live in the documentation.
Prerequisites: Node.js 22+.
git clone https://github.com/ok/mirall-app.git
cd mirall-app
npm ci
npm start # build + launch the app (updates disabled)For iterative development, npm run dev runs esbuild + Tailwind in watch mode with a
hot-reloading renderer. Useful flags: --storage <dir> (separate data directory — enables
multiple instances), --no-updates, --menu (show the menu on Windows/Linux). DevTools:
F12 / Ctrl-Shift-I (Cmd-Opt-I on macOS).
Packaging needs UPGRADE_KEY — the Pear channel the built app checks for over-the-air
updates. Official releases pass the key for their channel; set UPGRADE_KEY=none to build
an app with no update channel at all. Don't invent a pear:// link instead: the key is
decoded at startup, so a made-up one crashes the app rather than disabling updates.
UPGRADE_KEY=none npm run package # unpackaged app dir in out/
UPGRADE_KEY=none npm run make:linux # AppImage in out/make/ (needs jq + squashfs-tools)make:linux builds for the host architecture and must run on Linux. macOS (make:darwin)
and Windows (make:win32) additionally need signing credentials for a distributable
artifact; a local unsigned build works without them.
Mirall is a P2P app — most features need two or more running instances. Electron's single-instance lock prevents two copies of the same build from running at once, so use one dev instance plus one packaged instance:
npm run dev # instance 1
UPGRADE_KEY=none npm run package # then, instance 2:
out/Mirall-darwin-*/Mirall.app/Contents/MacOS/Mirall --storage /tmp/mirall-peer2npm test runs the unit, two-peer flow, and integration suites (the same gates as CI).
The frontend suite (npm run test:fe) drives the real app through the macOS accessibility
tree and runs locally only. See CONTRIBUTING.md for the testing and
accessibility bar.
| Path | Purpose |
|---|---|
src/main/ |
Electron main process — window, tray, updater, worker spawn, IPC relay |
src/preload/ |
The window.bridge surface exposed to the sandboxed renderer |
src/renderer/ |
React UI (TypeScript + Tailwind) |
src/worker/ |
Bare worker entrypoint — boot sequence + IPC command handlers |
src/shared/ |
The worker's data layer: stores, spaces, transfers, folder sync |
test/ |
Unit, integration, two-peer flow, and frontend suites |
scripts/ |
Build and maintenance scripts |
.github/workflows/ |
CI: tests and multi-platform release builds |
Contributions are welcome — read CONTRIBUTING.md for the development setup, testing discipline, and the CLA (signed once, automatically, on your first pull request). Translations currently cover English, German, Spanish, French, and Italian; corrections and new languages are appreciated.
Mirall is end-to-end encrypted: space contents are readable only with a per-space key that members receive upon approval, and every peer connection is authenticated and encrypted. If you believe you've found a vulnerability, please do not open a public issue — see SECURITY.md for how to report it privately.
Mirall's content-addressed transfer layer builds on the work by fleeky and his hyper-overlay framework — thank you.
This repository is 100% free and open source under the GNU AGPL-3.0 — use it, study it, modify it, share it.