A person is the unit that joins a room. Not a device.
Bring a phone for the camera and microphone, and a laptop for the screen share. Everyone else in the room sees one participant carrying three tracks, not two strangers who happen to share a name.
Every incumbent gets this wrong, Jitsi included. Identity is per-connection, so the same person joining from a laptop and a phone arrives as two tiles, two names and two mute buttons. KithMoot groups by participant instead of by connection. That is the whole product; everything else exists to make that one thing true.
What it does
- Video, voice, chat and screen share
- Media is negotiated device to device over WebRTC. There is no media server in the path, and nothing to run.
- Join by URL
- A room is a 32-byte secret carried in the link's fragment. Fragments are never sent to a server, so whatever serves this page has never seen a room key. Anyone holding the link can walk in; nobody outside it can tell the room exists.
- No account
- Type a name and you are in. The name is self-asserted. Anyone can type any name, including yours, so a short version of your key sits beside it everywhere. If you would rather use a Nostr key you already hold, sign in with an extension, a bunker or Amber; the key stays where it is and this page never holds it.
- No operator
- Rooms ride the public Nostr relays that already exist. Presence and chat are encrypted to the room key, so a relay carrying a room cannot read its guest list, by name or by key.
What it looks like
The native Android client, as it ships. The start screen is off a Pixel 10 Pro XL; the two room shots are off an Android emulator, so the camera is pointed at its synthetic test scene rather than at anybody's front room. None of it is a mockup.
Which platforms
| Platform | Video | Voice | Chat | Screen share |
|---|---|---|---|---|
| Desktop browser (Chrome, Firefox, Safari) | yes | yes | yes | yes |
| Android (native app) | yes | yes | yes | yes |
| Android (browser / PWA) | yes | yes | yes | unreliable |
| iOS / iPadOS (Safari or PWA) | yes | yes | yes | no |
There is no iOS app. The web app loads on iOS and video, voice
and chat all work, but getDisplayMedia does not exist on iOS Safari,
so screen sharing is impossible from an iPhone or iPad in any browser, including
Chrome and Firefox for iOS, which are Safari underneath. Sharing an iOS screen
needs a native app using ReplayKit, and that is not built.
This is also why the Android client is native rather than a browser tab: mobile browsers cannot reliably share a screen, and screen sharing is half the point.
What does not work yet
Stated plainly, before anyone else finds it.
- No iOS app. See above. It is the largest gap.
- Forwarder trees are two levels deep. Enough for a room of about 21; beyond that nobody has measured anything.
- No browser-as-forwarder. It needs WebRTC Encoded Transform, which is solid in Chrome and patchy in Safari, so it stays opportunistic and never load-bearing. The reference forwarder is a small Node process.
- Android consumes forwarders; it cannot act as one. It also has no persisted identity yet, so leaving a room and rejoining makes you a new participant.
- Encrypted media costs an extra encode and decode pass, and interacts badly with some hardware codec paths. It is only needed once a forwarder is in the path; pure mesh is already end-to-end via DTLS-SRTP.
- Kind numbers are provisional and will change once the spec is written.
Get the Android app
Package dev.forgesworn.kithmoot, version 0.1.0, Android 8.0 and
later. About 50 MB.
Download the APK Build from source
It is a debug build. There is no release signing key yet, so it carries Android's shared debug key. It installs and runs, but Android treats a debug-signed app and a release-signed one as two different applications: when a properly signed build appears, this one has to be uninstalled first. Android will also warn you about installing outside a store, which is the warning working correctly.
- Obtainium
-
Installs and updates straight from GitHub Releases, with no store in the middle.
Nothing is published there yet; once it is, adding
https://github.com/forgesworn/kithmoot-androidas a source will track new builds on its own. - Zapstore
- The Nostr app store, and the other route once builds are signed and published there.
- Or skip the app
- The web app is an installable PWA. Add it to a home screen or a dock and a service worker carries the shell offline. On Android it does video, voice and chat; screen sharing is the part a browser cannot be relied on for.
How it is checked
- 53 published interop vectors
- Room derivation, join URLs, device credentials, roster events, signal wrapping, kindred proofs, access evaluation, TURN credentials and room descriptors. Both implementations are checked against them.
- Two independent implementations
- The Kotlin client was written against those published vectors rather than against the TypeScript source, so anything the contract left ambiguous turned up as a failing vector instead of as a shared assumption nobody had written down.
- 454 tests, plus a live suite
- The fast suite runs against an in-process relay simulator with no network. A separate live suite checks the wire format against real public relays, and an end-to-end acceptance test drives three browsers through the whole claim.