Favorites are the mutual-trust relationship at the heart of Bitchat’s delivery guarantees. Favoriting a peer tells Bitchat that you know them, pins their cryptographic identity across sessions, and unlocks the full delivery stack — including the Nostr internet fallback and a larger share of the offline courier system. Because the features unlocked are meaningful, both sides must favorite each other for the Nostr path to activate.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/permissionlesstech/bitchat/llms.txt
Use this file to discover all available pages before exploring further.
Favorites
Favoriting a peer does three things:- Pins their Noise public key. Without a favorite pin, a peer’s identity is only known while they are in range. A favorite persists the full 32-byte Noise static public key in the Keychain so Bitchat can recognize the peer across sessions and reboots.
- Enables the Nostr delivery path. When a mutual favorite is unreachable over Bluetooth, Bitchat can route private messages through the global Nostr relay network using BitChat’s encrypted envelope format. This path requires both peers to have exchanged Nostr public keys — which happens automatically when both sides favorite each other.
- Grants a larger courier deposit quota. The courier store gives mutual favorites 5 envelope slots each, compared to 2 slots for any peer with a signature-verified announcement. This means your messages to a favorite are more likely to survive in transit even in a crowded mesh.
- Command
- UI
/unfav @alice or tap the star again to toggle it off.
Favorites are a mesh-only feature and are stored keyed by Noise public key (not nickname). The
/fav and /unfav commands are only available in the #mesh channel.Message Delivery
Bitchat uses a layered delivery stack. Every private message walks down the list until one path succeeds:Direct Bluetooth (Noise XX session)
Fastest and most private. Used whenever the recipient is reachable within Bluetooth multi-hop range and a live Noise session exists. The Noise XX pattern provides mutual authentication and forward secrecy. Intermediate relays see only encrypted
noiseEncrypted packets and cannot read the content or identify the participants.Delivery and read receipts are exchanged inside the Noise session.Nostr fallback (mutual favorites only)
Used when Bluetooth is unavailable. Routes through the global Nostr relay network via BitChat’s app-specific encrypted envelope format. Messages travel inside Nostr kind-1059 events whose content is XChaCha20-Poly1305 ciphertext — the sender’s stable identity and message content are hidden from relays. The recipient’s Nostr public key is exposed in the outer
p tag.This path requires a mutual favorite relationship: both peers must have favorited each other and exchanged Nostr public keys. On reconnect, Bitchat re-subscribes to relays with a 24-hour lookback to collect any stored mail.The Nostr path does not provide forward secrecy. A compromise of the recipient’s Nostr private key could expose stored envelopes addressed to that key before they were retrieved.
Courier System
The courier system solves the “recipient is out of range right now” problem without requiring the internet. It works entirely over Bluetooth, across physical encounters between people carrying devices.The courier system operates entirely offline between Bluetooth encounters. No internet connection is required at any point in the courier chain.
How a Message Becomes a Courier Envelope
When the message router determines that neither a live Bluetooth session nor a Nostr path is available, it seals the message into a courier envelope:- The plaintext is encrypted with the Noise X one-way pattern, sealed to the recipient’s static Curve25519 key. The sender’s identity is authenticated inside the ciphertext. Intermediate couriers cannot read the message, identify the sender, or link the envelope to the recipient.
- The only routing information visible to couriers is a 16-byte rotating recipient tag — an HMAC of the recipient’s static key and the current UTC day. Tags change daily, so an envelope from Monday cannot be correlated with one from Tuesday. Couriers cannot compute this tag themselves unless they already know the recipient’s static key.
Spray-and-Wait Delivery
Bitchat uses a spray-and-wait algorithm to spread copies of the envelope across multiple potential couriers:- Each envelope starts with a copy budget of 4 (maximum 8).
- When a device carrying an envelope meets another eligible courier, it hands over half its remaining budget (binary spray). The sending device retains the other half and marks the recipient as already sprayed.
- Copy budgets are capped so mail cannot be amplified indefinitely.
- Up to 3 distinct couriers carry the message before deposit is considered complete.
- When a courier encounters the intended recipient directly (a verified direct announce), all matching envelopes are delivered over the live link and removed from the courier’s store.
Trust Tiers and Quotas
Not all couriers are treated equally. The courier store enforces strict per-depositor quotas based on the relationship between the depositing device and the courier:| Relationship | Max envelopes per depositor | Pool limit |
|---|---|---|
| Mutual favorite | 5 | No cap on favorites’ share |
| Verified peer (signed announce) | 2 | 20 of 40 total slots |
Courier Persistence
Carried envelopes, spray history, and copy budgets persist across app restarts using iOS file protection (completeUntilFirstUserAuthentication). A device that is turned off and back on will still carry its courier mail.
Outbox
When a private message has no available delivery path at send time, it enters the encrypted outbox — a per-peer queue persisted to disk and encrypted with a ChaChaPoly key that lives only in the Keychain. Outbox behavior:- Stores up to 100 messages per peer.
- Messages are retained for up to 24 hours.
- On reconnect (Bluetooth session or Nostr event), queued messages are re-sent automatically.
- After 8 failed send attempts, a message is dropped and marked as failed in the UI.
- The outbox is sealed at the OS level: the encryption key is stored as
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, so queued mail can be flushed even from a background BLE wake but cannot be read by another device or a backup restore.