First contact works like this: every user has a Sherlock-ID, a random code like SH-a1b2c3... generated locally on the device on first launch. To start a conversation, one person passes that ID to the other through any channel, manually (copy-paste, SMS, spoken out loud). No QR code or invite link - the ID is just text.
Once you enter an ID, the app fetches that person's public key from the server, and on the first message it runs an X3DH handshake extended with post-quantum ML-KEM-768. From there it's Double Ratchet - every message has its own key that rotates automatically. Private keys never leave the device; the server only ever sees public material.
On trust: the server is what maps a Sherlock-ID to public keys, so in theory it could substitute keys - the classic MITM problem any messenger with a directory server has. That's why there's an option to manually compare a "safety number" (key fingerprint) with the other person over a separate channel - same principle as Signal's safety number. It's not enforced by default; verification is on the user.
And you're dead right about the hardest part. Encryption is the fun bit to build, but getting people onto a new app is the real wall - Signal already exists and does more than most people need. I don't have a clean answer to that yet, honestly. I built this mostly because I wanted it to exist, and I'm trying to figure out if it's worth more than that.