eleven / messenger Public

bot: refresh Eleven's knowledge base to the app as it is today (#1230)

The guide predated most of mid-July: message search, Markdown + the rich
composer, reply-thread views, copy-message-link, presence, read sync,
nicknames + profile cards, DM privacy, the moderation suite (mute/block/
report/ban/spam brakes), open/default/level-gated groups, cohort invites,
access levels + paid levels + space plans, the Eleven-home sign-in doors
(Apple/Google/Microsoft/GitHub/email) and Sign-in options, sealed branding,
the widget bar + place flags, Vault (+ locked vaults), /gif (now a named
privacy exception alongside unfurls), /emoji, incoming webhooks, App Studio +
member apps/bots, AI opt-in + feature gates, Eleven's reminder chips +
research sessions, update channels + safety hold + major-version pinning,
lchat try, the backup ladder, and the public transparency ledgers.

Also re-measured 'By the numbers' per CLAUDE.md (~240k LOC total, ~34 MB
server binary, ~26 MB Mac download) and renumbered sections (three new ones:
moderation, member-made apps/bots, access levels & plans).
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell 0eec4729dbacc9b363fd6e1d82217a70455cd6f3 parent 2728956
2 files changed, +549 −156
  • changelog/2026-07-21-eleven-knowledge-refresh.md +6 −0
  • internal/bot/knowledge.md +543 −156
diff --git a/changelog/2026-07-21-eleven-knowledge-refresh.md b/changelog/2026-07-21-eleven-knowledge-refresh.md
new file mode 100644
index 0000000..5cd1908
--- /dev/null
+++ b/changelog/2026-07-21-eleven-knowledge-refresh.md
@@ -0,0 +1,6 @@
+๐Ÿค– Eleven caught up on everything the app has learned lately. Ask it about
+message search, Markdown, the sign-in doors, access levels, open groups, the
+Vault, muting and reporting, webhooks, member-made apps and bots โ€” its answers
+now describe the app as it is today, not as it was a fortnight ago. It also
+knows its makers by name, so "who created Eleven?" gets the right answer:
+Paul Campbell and James Adam.
diff --git a/internal/bot/knowledge.md b/internal/bot/knowledge.md
index 2066ee2..ea98ee1 100644
--- a/internal/bot/knowledge.md
+++ b/internal/bot/knowledge.md
@@ -80,28 +80,44 @@ your device)** โ€” never on the server.
the admin token reveals no message content. The server stores only a *hash* of
the admin token, never the token itself, and tokens/keys are never logged.
-### The one deliberate exception: link previews
+### The two deliberate exceptions: link previews and GIF search
-There is exactly one place the server briefly sees something in the clear: **link
-previews (unfurls)**. When you post a URL, the server fetches that page to build
-the little preview card (title, image, description). So it momentarily sees the
-*URL you posted* โ€” not your message text, just that one link. This was an
-explicit, accepted trade-off, and it's guarded against abuse (it won't fetch
-internal/private addresses). Everything else stays encrypted.
+Almost nothing bypasses the encryption; be able to name the two things that
+partly do โ€” both explicit, accepted trade-offs:
-### Branding is plaintext by design
+- **Link previews (unfurls).** When you post a URL, the server fetches that page
+ to build the little preview card (title, image, description). So it
+ momentarily sees the *URL you posted* โ€” not your message text, just that one
+ link. It's guarded against abuse (it won't fetch internal/private addresses).
+- **GIF search (`/gif`).** Searching happens **from your own device, directly to
+ Giphy** โ€” so *Giphy* sees your search terms and network address; the Eleven
+ server sees nothing. The GIF you pick is downloaded on your device, encrypted
+ to the chat, and sent like any other picture. The Giphy key is **shared by the
+ whole space** (the first person to use `/gif` supplies one, and it just works
+ for everyone after that) โ€” the form says so plainly, and a Giphy key is a
+ public client identifier, not a secret.
-A couple of things are *deliberately* not encrypted, because they must show up
-before anyone has a key โ€” on the invite/welcome screen, the join screen, and the
-passkey-backup screen. These are **admin-set branding**, never user content:
+Everything else stays encrypted.
+
+### Branding is plaintext by default โ€” and can be sealed
+
+A few things are *deliberately* not encrypted, because they must show up before
+anyone has a key โ€” on the invite/welcome screen, the join screen, and the
+sign-in screens. These are **admin-set branding**, never user content:
- the **group name** (the chat's title, and the name it takes on your Home
- Screen), and
+ Screen),
- an optional **server photo** (a picture for the chat, shown on those same
- screens).
+ screens), and
+- an optional **space description**.
-Both are public branding โ€” don't put anything private in them. Everything that is
-actually *user* content stays end-to-end encrypted.
+All are public branding โ€” don't put anything private in them. And an admin can
+now go further and **seal the branding** (Admin app โ†’ Privacy): the space's
+name, photo, description, and admin contact move into an encrypted box, and the
+key rides inside invite links instead of ever being sent to the server. Invited
+people still see everything; the people who run the servers see only the locked
+box. (One honest note: the iPhone/Mac apps can't open the sealed box yet, so a
+sealed space shows there with a generic name โ€” that catches up in an update.)
### The honest trade-offs
@@ -114,9 +130,9 @@ design, not bugs:
them *new* messages, but it can't claw back a key they already hold, so it
doesn't retroactively lock them out of past messages they already had.
- **Lose your only device with no backup, and that access is gone.** If your key
- material is only on one device and you have no add-device link or passkey
- backup, the threads only you could decrypt are unrecoverable. That's the design
- working as intended โ€” which is exactly why backups exist (see ยง4).
+ material is only on one device and you have no add-device link or Eleven
+ sign-in backup, the threads only you could decrypt are unrecoverable. That's
+ the design working as intended โ€” which is exactly why backups exist (see ยง4).
- **Metadata is not hidden.** The server can't read *what* you say, but to route
messages it necessarily knows the **social graph**: who is in which thread, who
sent a message, and its timing and size. Hiding the graph itself is explicitly
@@ -126,7 +142,8 @@ design, not bugs:
number" check). A *passive* attacker with a stolen database still can't read
anything. An *active*, malicious server could in theory substitute a public key
to intercept *new* conversations. Out-of-band key verification is planned to
- close this gap.
+ close this gap. (The native apps already verify that the server isn't
+ *rewriting history* โ€” see ยง18.)
---
@@ -141,7 +158,7 @@ a secret invite link, and your identity is a keypair on your device.
- **Members can invite too, if the admin allows it.** When the "let members
invite other people" setting is on, any member can start a chat with a
brand-new person and share a join link themselves. The server never sees a key
- either way.
+ either way. (Flipping the setting takes effect immediately for everyone.)
- **Joining.** You open the link, see a welcome card (group name + photo), pick a
**screen name**, and join. Your browser generates your keypair and registers
your public key on the roster. The invite can also seed your first conversation
@@ -150,12 +167,17 @@ a secret invite link, and your identity is a keypair on your device.
- **Direct-to-group invites.** An invite can point at a specific group, shipping
that group's key so you land right inside it. (Joining a group still means
joining the instance โ€” the roster is instance-wide.)
+- **Cohort invites.** An invite can also carry an **access level** (ยง16):
+ everyone who joins through that link lands in the level automatically โ€” their
+ key follows from a member the moment they arrive. Pair it with a level-only
+ group and each intake gets its own room from day one.
- **Add another device / recover a lost one.** From a device that already holds
your keys, you mint a fresh add-device link. That link carries your **user
private key** (encrypted under the link's one-time secret) to the new device,
which can then open *every* thread you belong to โ€” no per-thread re-invite
needed. QR is the easy phoneโ†”desktop path. Because a device holds a real key,
- treat these links like a password.
+ treat these links like a password. The same sheet also offers a **Back up**
+ button โ€” the one-tap Eleven sign-in from ยง4.
- **Invite links are single-use and revocable**, and the secret in them is never
sent to the server, so a stolen database can't be used to claim an invite.
@@ -179,79 +201,172 @@ thread with its own key.
- **The roster** is the instance-level directory of members (name + public key).
By default it's open: any member can see who's in the instance and start a chat
- with anyone โ€” no introductions needed. (Some instances restrict who can see or
- DM whom; see Instance contexts, ยง14.)
+ with anyone โ€” no introductions needed.
- **Starting a chat.** Tap **โž•**. Pick one person for a DM, or "New group" to
- pick several and name it. There's also a **Helpers** section in that picker for
- the bots (see ยง12โ€“13).
+ pick several and name it. The same picker holds the **Helpers** section for
+ bots (ยง13โ€“15), the **Apps** section, and **Discover** for open groups.
+- **Open groups & Discover.** A group can be **open to the whole space**: tick
+ "Open group" when you create it (or from Edit group), and anyone can find it
+ under **Discover** and join with one tap โ€” no invite needed. Still end-to-end
+ encrypted like every chat; "open" only means open to members of this space.
+ Admins can mark an open group as a **default group** ("New members join
+ automatically") โ€” the space's own #general; only *new* members are added, and
+ leaving sticks. An open group can also be **limited to one access level**
+ ("Only Coaches", ยง16) โ€” its level's members find and join it under Discover,
+ while everyone else sees an honest locked entry, with the name and everything
+ inside staying sealed.
+- **Who's around (presence).** Open a chat and the other person's status shows
+ under their name โ€” a green Online, yellow Away, or red Offline dot; group
+ headers add "ยท 2 online" to the member count, and the member list shows who's
+ about. The filter button beside search can narrow your chats to people online
+ right now, or to just people, bots, or apps. You go Away automatically after
+ ten quiet minutes, or flip "Set yourself as away" in your profile.
+- **Unread dots sync across your devices** โ€” catch up on a chat on your phone
+ and the dot clears on your laptop too. They also survive reloads: a message
+ that arrived while you were away stays marked unread until you actually open
+ it.
+- **You choose what you call people.** Invited someone as "Dermo" who signed up
+ as "Dermot"? Keep calling them Dermo. Tap a member in a group's member list
+ (or the title of your DM with them) to see their **profile card** โ€” photo,
+ what they're about, a Message button, and the place to set *your* name for
+ them. When someone renames themself, the choice appears right in your chat:
+ switch to their new name, or keep yours. Mentions follow along โ€” type `@` and
+ the name *you* use. Your names for people are private to you, sealed so only
+ your own devices can read them โ€” other members and the server never see them.
- **Who can do what (default, safe-for-kids):** any member can start a DM, create
a group, and add *existing* instance members to a group. A group's **owner** can
rename it or remove a member. Adding a *brand-new person to the instance* (the
roster) is admin-only by default; removing a person from the instance is
admin-only. So the admin guards the trust boundary while members move freely
inside it.
+- **Your DMs are yours to gate.** In Edit profile, choose who can start a direct
+ message with you: everyone in the space, or no one (admins and helper bots can
+ always reach you, and chats you already have keep working). Any DM can be
+ **ended** from its โ‹ฎ menu โ€” it closes for both of you and stays closed until
+ either of you reopens it.
- **Layout.** On desktop it's master-detail: a thread list on the left, the open
thread on the right, newest activity first. On mobile it's a single pane that
navigates list โ†’ thread โ†’ back, plus a people view for starting new chats.
- Chats can be **pinned** to float to the top of the list.
+ Chats can be **pinned** to float to the top of the list, and the sidebar's
+ heading is your space's name โ€” handy if you belong to more than one.
---
-## 4. Not losing access: the passkey backup (home server)
-
-Because your keys live on your device, Eleven offers an **optional** way to back
-them up so you can restore on a fresh device โ€” without accounts, passwords, or
-weakening the one rule.
-
-- It uses a **passkey** (Face ID / Touch ID / a password manager). The passkey
- derives a key *on your device* that encrypts a small backup blob (your list of
- chats, and optionally your per-instance credentials) held by a tiny separate
- **home/backup server**. That server sees only ciphertext โ€” no messages, no
- roster, nothing an instance would recognise.
-- It's **strictly opt-in and additive**: a member who never enrols makes *no*
+## 4. Not losing access: your Eleven home (sign-in & backup)
+
+Because your keys live on your device, Eleven offers an **optional** sign-in โ€”
+your **Eleven home** โ€” that backs your access up and lists your spaces, without
+passwords or weakening the one rule.
+
+- **What it stores is sealed.** Signing in ("save your access") encrypts a small
+ backup *on your device* โ€” your list of spaces and your per-space credentials โ€”
+ and parks it with a tiny separate **home server**. That server sees only
+ ciphertext: no messages, no roster, not even your spaces' names (those are
+ sealed too, along with any labels you add). Restore on a fresh device is one
+ sign-in: you're back in your chats.
+- **Many doors, one account.** A **passkey** (Face ID / Touch ID / a password
+ manager) is the original way in. You can also sign in with **Apple, Google,
+ Microsoft, GitHub, or an email code** โ€” each door only *confirms who you
+ are*, and Eleven keeps a **scrambled fingerprint** of that identity, never
+ your name or email address (so the no-spam promise stands: we can't see your
+ email). The sign-in card leads with the door you used last time โ€” or, on a
+ first visit, the door that fits the device โ€” with "Other ways to sign in"
+ listing the rest.
+- **Sign-in options** (in the home page's account menu) shows every door on
+ your account: add another so you're never locked out, give any row a label
+ ("personal", "work" โ€” an added email is labelled with its address
+ automatically), or remove one you no longer use. Changing them always
+ confirms it's you first, and the last way in can never be removed. If you
+ signed in a new way and found an *empty* spaces list, your spaces probably
+ live with your passkey โ€” the page offers "Already have spaces? Sign in with
+ your passkey to bring them over", and then you can add the new door to that
+ same account so every way in opens the same spaces.
+- **Your home page** lists your spaces by name (star your favourites to sort
+ them), shows each space you created with its storage use and allowance
+ ("1.2 GB of 5 GB stored"), and is where space plans are upgraded and managed
+ (ยง16).
+- It's **strictly opt-in and additive**: a member who never signs in makes *no*
requests to any backup server, ever. If you decline, nothing about you is
logged anywhere.
-- Add a second passkey (say, iCloud *and* a password manager) for redundancy.
- Restore on a new device is then one Face ID: you're signed back into your
- chats. Enrolled devices can also **sync silently** in the background, so a chat
- you join on one device can appear on your others on its own.
-- Members without any backup see an **inline fragility notice** ("if this browser
- session is lost, your access to this chat is lost") nudging them to save a
- passkey. It's a gentle, dismissible reminder โ€” never a pop-up that covers what
- you're reading.
-
-The universal fallback, if you don't use passkeys, is always the **add-a-device
+- Enrolled devices **sync silently** in the background, so a space you join on
+ one device can appear on your others on its own.
+- Members without any backup see an **inline fragility notice** ("if this
+ browser session is lost, your access to this chat is lost") nudging them to
+ sign in. It's a gentle, dismissible reminder โ€” never a pop-up that covers
+ what you're reading. The add-a-device sheet's **Back up** button does the
+ same one-tap sign-in whenever you want it.
+
+The universal fallback, if you never sign in, is always the **add-a-device
link** (ยง2). Losing *all* your backups and devices means the data is
cryptographically gone โ€” that's the privacy guarantee holding, not a failure.
---
-## 5. Messaging: reactions, replies, editing, and gestures
+## 5. Messaging: formatting, replies, editing, search, and gestures
Everything about a message is encrypted; here's what you can do with one.
-- **Rich text**: links are auto-detected and linkified, `@mentions` pop a member
- menu, and a message that's only emoji renders jumbo. Messages group into sender
- runs with time separators.
+- **Real Markdown, kept deliberately small**: **bold**, *italics* (underscores
+ work too), `code`, ~strikethrough~, > quotes, ``` code blocks, bulleted and
+ numbered lists, and named links (`[like this](https://โ€ฆ)`) โ€” nestable and
+ combinable. Headings and tables stay plain text in a chat, on purpose. Bare
+ links are auto-detected, `@mentions` pop a member menu, and a message that's
+ only emoji renders jumbo. A few shortcodes autocomplete and convert on send
+ (`:shrug:` ๐Ÿคท, `:facepalm:` ๐Ÿคฆ, `:strong:` ๐Ÿ’ช, `:lol:` ๐Ÿ˜‚), and `/emoji` (or
+ `/emoji cat`) opens a picker panel above the composer. Messages group into
+ sender runs with time separators, and names above group messages always show
+ the sender's *current* name.
+- **The composer formats as you type** โ€” the basics only: type `**bold**` and it
+ turns bold the moment you close the stars, same for italics, code, and
+ strikethrough, with โŒ˜B/โŒ˜I and friends as shortcuts; backspace right after
+ undoes it. (Lists and quotes don't convert while you type โ€” they still render
+ beautifully once sent.) What you send is exactly what everyone sees, on every
+ device. Prefer your markers to stay put? Turn off "Format as you type" in the
+ Theme sheet, or switch to the classic plain-text box entirely.
- **Reactions**: react with an emoji. On **touch**, long-press a message (or
double-tap) to open the emoji picker above the bubble; on **desktop**, a hover
strip appears and press-and-hold opens the full picker. Reaction counts show as
chips under the bubble.
-- **Replies**: quote-reply to a specific message. On touch you can **swipe right**
- on a message to quick-reply; there's also a Reply item in the message menu. The
- reply shows a quote banner.
+- **Replies are threads.** Reply to a reply and it continues that thread โ€” your
+ message quotes the *original* message, and the "N replies" count under the
+ original covers the whole back-and-forth. Tap the quote card on any reply (or
+ the count) and the **thread opens in its own view**: the original pinned at
+ the top, every reply beneath, the message box already set to reply; โœ• (or
+ tapping outside) drops back into the chat. On touch you can **swipe right** on
+ a message to quick-reply.
- **Editing**: you can edit your own message for a **15-minute window** (on
desktop, press โ†‘ in an empty composer to edit your last message, โ†“ to cancel).
- **Delete / unsend**: you can unsend your own message โ€” this genuinely removes
the ciphertext from the server's log (author-verified), not just a tombstone.
+- **Copy a link to any message** โ€” click its timestamp, or "Copy link" in the
+ message menu. Opening the link jumps straight to that message and highlights
+ it, but only for members of that chat: the link carries no readable trace of
+ the message or its contents, even if it ends up posted somewhere else, and it
+ stops working for anyone who later leaves the chat.
- **Message menu**: long-press (touch) or hover + press-and-hold (desktop) opens
the menu โ€” reactions above the bubble, and Reply / Copy / Edit / Delete below.
Mini-apps can add their own items here (e.g. Bookmarks adds "Save link" to any
- message with a link).
+ message with a link), and Report / Mute live here too (ยง8).
+- **Search your messages** โ€” the search box above your chats finds messages, not
+ just chat names. Matches appear in a dropdown, newest first, keyboard-driven
+ (the first result is highlighted as you type, Enter opens it, Escape closes);
+ picking one jumps to the message and highlights it until you move on.
+ Searching happens **entirely on your device** โ€” messages stay sealed, and what
+ you type never leaves your browser. If a chat's older history isn't on your
+ device yet, "Search earlier messages" digs back through the months โ€”
+ resumable, stoppable, watchable.
+- **Jump to latest**: scroll up a way and a small down-arrow button appears in
+ the corner of the feed โ€” tap it to drop straight back to the newest message.
- **Typing indicators** show live ("Sam is typingโ€ฆ") and are relay-only โ€” never
stored.
- **Mentioning a bot**: `@mention` a helper (e.g. `@Claude`) to get its attention
in a group; in a DM a bot always replies.
+- **Reloads are instant.** The app keeps a copy of your chats on your device, so
+ opening it doesn't re-download everything, and recently visited chats open on
+ the spot even on a shaky connection. What's kept locally is exactly as sealed
+ as what the server holds, and it's cleared if you sign out or leave a group.
+- **Text size** is yours to set: on a computer, the **Text size** slider in the
+ Theme sheet; on iPhone/iPad the web app follows your system Text Size setting.
The composer follows the platform: on **desktop**, Enter sends and Shift+Enter
makes a newline; on **touch**, Enter makes a newline and the send button sends.
@@ -267,14 +382,18 @@ The message box grows to a max height then scrolls.
**encrypted** and uploaded as an opaque blob.
- **There is no server-side image proxy or thumbnailer** โ€” the server only ever
holds ciphertext, so all image work happens on your device.
-- **Files**: you can attach documents (PDF, txt/markdown, CSV, JSON, Office docs,
- etc.). The allowed-types list is the safety guard โ€” executables and scripts are
- rejected. The filename and type ride *inside* the encrypted payload, never as
- server metadata.
+- **Any file goes.** Attach documents, spreadsheets, archives, code, anything โ€”
+ it travels end-to-end encrypted like everything else. The filename and type
+ ride *inside* the encrypted payload, never as server metadata.
+- **GIFs**: `/gif` (or `/gif high five`) searches Giphy in a panel above the
+ message box; tapping one sends it into the chat as a picture from you. See ยง1
+ for the (disclosed) privacy shape: your device talks to Giphy directly, under
+ a key shared by the space โ€” the Eleven server never sees the search, the key,
+ or the GIF in the clear.
- Images show inline (with a lightbox), files show as chips, and posted links can
- render preview cards (the one unfurl exception, ยง1) and YouTube cards.
+ render preview cards (the unfurl exception, ยง1) and YouTube cards.
- Attachments are stored as encrypted blobs; large media is what drives storage
- growth, but the server still can't open any of it.
+ growth (ยง16), but the server still can't open any of it.
---
@@ -288,10 +407,51 @@ The message box grows to a max height then scrolls.
instance key, so only fellow members can see it โ€” never the server.
- You can edit your screen name and photo anytime from your profile (you can also
just ask Eleven to "edit my profile" and tap the button, or type `/profile`).
+ Edit profile is also where **who can DM you** lives (ยง3), the "set yourself
+ as away" switch (ยง3), and โ€” on spaces with paid access levels โ€”
+ **Membership** (ยง16).
+- Other people: tap a member anywhere to see their **profile card**, and set
+ your own private name for them there (ยง3).
+
+---
+
+## 8. Staying pleasant: mute, block, and report
+
+Every member has tools to shape their own experience โ€” all private, none of
+them announced to the other person:
+
+- **Mute a chat** from its โ‹ฎ menu โ€” no notifications, no unread dot; messages
+ keep arriving quietly.
+- **Mute a person** from their profile card or a long-press on their message โ€”
+ their messages fold into a small "Muted message" stub you can tap to read,
+ and they never notify you. Who you've muted is sealed to your own devices โ€”
+ the server can't read it either.
+- **Block someone** โ€” blocking mutes them, ends any DM between you, and stops
+ new contact both ways: they can't message you or add you to groups, and you
+ won't be notified about anything they say. They're never told. Only your
+ space's server keeps the content-free record it needs to enforce it. Find it
+ on their profile card, or tick "Also block" when you report someone. Admins
+ can still reach you โ€” a warning can't be dodged by blocking the messenger.
+- **Report a message or a person** to your space's admins โ€” long-press a
+ message and choose Report, or use the Report button on someone's profile.
+ Pick a reason, add a note if you like, and it goes to the admins **sealed so
+ only they can read it** โ€” the server can't, and neither can anyone else.
+ Admins get a Reports inbox in the Admin app with clear next steps โ€” dismiss,
+ send a warning, remove someone from a group, an access level, or the space โ€”
+ and an audit log records every moderation action. Be honest if asked: a
+ report is one side of a story, and the inbox says so โ€” admins read them and
+ use their judgment.
+- **Admins hold the last rungs**: "Remove & ban" keeps a removed member out โ€”
+ their key can't rejoin through any invite โ€” and every report shows who
+ invited the person, so a bad invite chain is visible.
+- **Quiet spam brakes** are always on: far above any human pace, a flood of
+ messages, new chats, or invites simply stops landing (admins are exempt, and
+ day-one members can't mass-DM). The "members can invite" switch is the panic
+ lever in a spam wave, and flipping it is recorded in the audit log.
---
-## 8. Themes & appearance
+## 9. Themes & appearance
Look-and-feel is entirely a **local preference** on your device โ€” it's stored in
your browser, never sent to the server, and never shared.
@@ -299,13 +459,15 @@ your browser, never sent to the server, and never shared.
- **Colour themes**: *Lit Room* (warm amber), *Lagoon* (teal), *Sunny* (yellow),
*Plum* (purple), *Linen* (soft neutral), and *Classic* (blue).
- **Appearance**: Light, Dark, or System (follow your device).
+- The Theme sheet also holds the **Text size** slider (desktop) and the
+ **"Format as you type"** composer toggle (ยง5).
- Change them from the **โ‹ฎ menu โ†’ Theme picker**, or just ask Eleven ("make it
dark", "switch to the teal theme") and tap the button, or use the commands
- `/theme <name>`, `/themes`, `/dark`, `/light` (ยง11).
+ `/theme <name>`, `/themes`, `/dark`, `/light` (ยง12).
---
-## 9. Notifications
+## 10. Notifications
Eleven supports two delivery paths, both preserving the encryption:
@@ -325,13 +487,14 @@ Eleven supports two delivery paths, both preserving the encryption:
sender's own subscriptions).
- You're **not** notified for a chat you currently have **open/active** (the app
writes a heartbeat that the notifier checks).
+- **Muted chats and muted people stay quiet** (ยง8).
- The admin's **"test notification"** always shows, as a delivery check.
Enable notifications from the **โ‹ฎ menu**.
---
-## 10. Mini-app notices, in-app
+## 11. Mini-app notices, in-app
A mini-app event (like a reminder firing) speaks where it belongs: it lands in
its thread, which floats up your chat list with an unread dot and a preview line;
@@ -342,7 +505,7 @@ occupy their own space inline.
---
-## 11. Slash commands
+## 12. Slash commands
The command layer is deliberately **familiar first** โ€” it should feel instantly
recognisable to anyone who's used Slack or Discord: `/command args`, a `/`
@@ -351,7 +514,9 @@ principles worth explaining to members:
- **A command answers *in place*.** Running a command produces a *reply* right
where you typed it โ€” usually a private "only visible to you" message from a bot
- โ€” not a jump somewhere else and not a silent UI change.
+ โ€” not a jump somewhere else and not a silent UI change. Some commands answer
+ with a **panel** instead: a temporary surface above the message box with
+ something to tap (`/gif`, `/emoji`), dismissed with its โœ• or the Escape key.
- **Action chips move you only on your tap.** If a command's answer offers to
take you somewhere or change something (e.g. "View reminders", "tap to switch
theme"), that's an **action chip** you choose to tap โ€” leaving your current
@@ -362,7 +527,8 @@ principles worth explaining to members:
The **built-in bot commands** (answered by Eleven, and available even with AI
off):
-- `/help` โ€” list the commands you can use here.
+- `/help` โ€” list the commands you can use here (it also explains, in one
+ sentence, how the place flags below work).
- `/theme <name>` โ€” switch colour theme (e.g. `/theme lagoon`).
- `/themes` โ€” open the theme picker.
- `/dark` โ€” switch to dark mode.
@@ -373,10 +539,20 @@ off):
The theme/profile commands attach the same one-tap buttons the AI would โ€” so
"make it dark" (asking Eleven) and `/dark` (typing) reach the identical result.
-The **mini-app commands** (each app owns its own; see ยง12): `/todo`, `/remind`,
-`/poll`, `/board`, `/save`, `/connect`, `/register`, `/list`. Typing `/` brings up
-a typeahead listing what's available in the current thread โ€” bot commands only
-appear where a bot can actually answer them.
+The **mini-app commands** (each app owns its own; see ยง13): `/todo`, `/remind`,
+`/poll`, `/board`, `/save`, `/vault`, `/gif`, `/emoji`, `/views`, `/connect`,
+`/memory`. Typing `/` brings up a typeahead listing what's available in the
+current thread โ€” bot commands only appear where a bot can actually answer them.
+
+**Aiming a command (place flags).** A command acts on the nearest copy of its
+app โ€” a chat's shared copy first, then your personal one โ€” and you can aim it
+yourself: `/todo @me dentist` files into your own private list even in a chat
+with a shared one, and `/todo @here โ€ฆ` targets this chat's shared copy (or, if
+the chat doesn't have the app yet, adds it and files the first item in one go).
+Nobody has to memorise this: when an app lives in more than one place, the `/`
+menu offers each variant as its own labelled suggestion โ€” "Add a to-do just for
+you" / "Add a to-do for this group" โ€” with the plain, personal command always
+first.
`/memory` (in a DM with an AI helper) opens the **memory scratchpad**: the
small set of facts that helper remembers about you. Memory is per-chat and
@@ -394,10 +570,11 @@ thread.
---
-## 12. Mini-apps
+## 13. Mini-apps
A **mini-app** is a small program that lives *alongside* chats โ€” a to-do list, a
-poll, reminders, a shared whiteboard. Here's the model, then each app.
+poll, reminders, a shared whiteboard, a vault for the group's little secrets.
+Here's the model, then each app.
### How mini-apps work (and why they're private)
@@ -431,34 +608,52 @@ A personal app-thread is presented one of two ways, and **the app chooses**:
reads as a little action line in the Chat view; the reminder firing reads as a
message from the bot.
+### Apps in groups: the widget bar
+
+Apps aren't only personal. A group's โ‹ฎ menu โ†’ **Add apps** shares an app with
+the chat: everyone gets **one shared copy** โ€” a shared to-do list, the group's
+poll, a whiteboard โ€” sitting right beside the conversation, with buttons in the
+header to switch between the chat, the app, or both side by side on a bigger
+screen. Every change syncs live for every member (a shared reminder fires for
+the whole group), end-to-end encrypted โ€” the server can't even tell *which* app
+a group added. Your personal lists stay your own; the group's live in the
+group. And where an app can't go, the picker says why in plain words ("A poll
+needs an audience โ€” it lives in a group chat"; "Connections use your own
+account credentials โ€” each person links their own").
+
### The apps
- **To-do** (`/todo <task>`) โ€” your **personal** checklist, in its own sidebar
- thread. `/todo buy milk` typed in any chat files into it. Tap a row to check it
- off (or reopen it), newest on top; the count shows how many are left. Syncs
- across your devices automatically because each action is a normal encrypted
- event.
-
-- **Reminders** (`/remind โ€ฆ`) โ€” nudge yourself later. Understands natural
- phrasings: `/remind Call the plumber in 2h`, `/remind me in 10 minutes to call
- mum`, `/remind Standup at 9:00`, or an explicit date `/remind Renew passport |
- 2026-08-01`. It's **server-scheduled**, so the alert fires reliably on every
+ thread. `/todo buy milk` typed in any chat files into it (in a group with a
+ shared list, it files there โ€” aim it with `@me`/`@here`, ยง12). Tap a row to
+ check it off (or reopen it), newest on top; the count shows how many are
+ left. Syncs across your devices automatically because each action is a normal
+ encrypted event.
+
+- **Reminders** (`/remind โ€ฆ`) โ€” nudge yourself later. In your Reminders chat,
+ just type what and when โ€” "call mum in 10 minutes", "standup at 9:00" โ€” and
+ if you leave the time out it asks "When should I remind you?" instead of
+ staying silent. From any other chat, `/remind` takes the same natural
+ phrasings (`/remind Call the plumber in 2h`, `/remind Renew passport |
+ 2026-08-01`). It's **server-scheduled**, so the alert fires reliably on every
device even if the app is closed โ€” the server holds only the encrypted event
and the time, never the text. Dismissing an unfired reminder cancels it from
any device.
- **Poll** (`/poll Question | Option A | Option B`) โ€” a quick poll **in the
- current chat**, visible to everyone in it (a shared app). No `|` makes it a
- Yes/No poll. Votes are one-per-person and changeable; a live tally shows bars
- and percentages. The creator can **Close** it, which posts the results back
- into the chat as a normal message (a durable record). The server never sees the
+ current chat**, visible to everyone in it (a shared app: it joins the group's
+ widget bar, with the results card one tap away). No `|` makes it a Yes/No
+ poll. Votes are one-per-person and changeable; a live tally shows bars and
+ percentages. The creator can **Close** it, which posts the results back into
+ the chat as a normal message (a durable record). The server never sees the
question, the options, or who voted for what.
- **Whiteboard** (`/board`) โ€” a **shared** canvas the group draws on together;
- `/board clear` wipes it, `/board close` hides it (the drawing is kept, reopen
- with `/board`). Pen colours and brush sizes; each stroke is one encrypted event
- everyone folds, so every device converges on the same picture. The server never
- sees a line, a colour, or who drew what.
+ adding it to a chat opens the canvas right away. `/board clear` wipes it,
+ `/board close` hides it (the drawing is kept โ€” reopen with `/board`). Pen
+ colours and brush sizes; each stroke is one encrypted event everyone folds,
+ so every device converges on the same picture. The server never sees a line,
+ a colour, or who drew what.
- **Bookmarks** (`/save <url> [| note]`) โ€” your **personal** stash of links, in
its own sidebar thread, newest first. The star feature is saving a link
@@ -467,6 +662,23 @@ A personal app-thread is presented one of two ways, and **the app chooses**:
it. Everything is encrypted into your own thread; the server never learns a URL,
a note, or who you saved it from.
+- **Vault** (`/vault WiFi = hunter2`) โ€” a home for the small secrets a group
+ genuinely shares: the WiFi password, the door code. Add it to a chat and
+ everyone in it is in โ€” reading and adding entries; adding or removing a
+ secret posts a quiet note in the conversation ("Ciara added a secret to the
+ Vault") so activity is visible, never the value. A vault can be **locked
+ with a passkey**: values then open only after Touch ID / Face ID, on any
+ device where you've set your passkey up โ€” names and history stay visible,
+ anyone can still *add* without unlocking, and anyone already in can bring a
+ newcomer in. Locking is one-way, and as ever the server only sees
+ ciphertext.
+
+- **GIF search** (`/gif [search]`) โ€” search Giphy in a panel above the message
+ box, tap a result to send it as a picture from you. Set up once per space by
+ whoever uses it first (a free key from developers.giphy.com); the privacy
+ shape โ€” your device talks to Giphy directly, the server never sees the
+ search โ€” is in ยง1.
+
- **Views** โ€” when a bot has a *list* to show (GitHub issues, headlines,
results), it doesn't flatten it into chat text: it creates a **view** โ€” a
tidy, searchable list pinned above the conversation, each row linking out
@@ -486,7 +698,8 @@ A personal app-thread is presented one of two ways, and **the app chooses**:
server stores a box only you can open. Once connected, a service can
install its own app (GitHub's repositories and issues; Linear's teams and
issues; DNSimple's domains), and the connected row's **Open** button goes
- straight there.
+ straight there. Integration apps wear their real logos, so they're easy to
+ spot; emoji stay for the apps and bots members make themselves.
**How a bot acts on a connection:** you (Eleven) can *propose* an operation
โ€” it appears as a **tappable chip** under your reply โ€” but you can never
@@ -523,13 +736,52 @@ A personal app-thread is presented one of two ways, and **the app chooses**:
- *"the bot didn't respond"* โ†’ the instance's helper isn't running; that's
one for the space's admin.
-Members can build their own mini-apps โ€” each is one self-contained file, no
-build step โ€” but that's a developer topic; point curious people at the fact that
-it's open source.
+- **Incoming webhooks** (admins only) โ€” give an outside service (GitHub,
+ Stripe, anything that can send an HTTP request) a unique URL, and everything
+ it sends arrives as an encrypted event in the chat the admin chooses. The
+ server never sees the content, and the receiver can never read anything
+ back โ€” it's strictly one-way, inward. Under Apps โ†’ Webhooks, once the
+ space's operator has switched the ingest service on.
+
+---
+
+## 14. Apps and bots members make themselves
+
+Members aren't limited to the built-in apps โ€” they can make their own, two
+ways. (An admin can switch this off: Admin โ†’ Features โ†’ "Let members make their
+own apps" โ€” turning it off stops *new* ones; anything already deployed keeps
+working, and everyone can still remove their own.)
+
+- **Ask a bot to build an app.** Tell a helper "build me a habit tracker" and
+ it writes the app with you. Member-made app code is treated as **user
+ content**: stored end-to-end encrypted like a message, and run only inside a
+ **locked-down sandbox** โ€” no network, no keys, no reach into your messages or
+ the page. Wherever a member-built app is added, it's labelled as
+ member-built, not admin-reviewed code.
+- **App Studio** (๏ผ‹ New chat โ†’ Apps) is the hands-on route: paste a
+ single-file app, hit **Check** to make sure it's sound, and **Deploy** โ€” it
+ runs in the same sandbox. App Studio lists the apps you've made (edit,
+ remove, a History of every deploy), flags one made with an older app format
+ (a small "older format" tag) and offers a one-tap **Upgrade** that redeploys
+ the exact same code in the current format. When any new app appears (yours,
+ a bot's, an admin's), nobody's page is yanked out from under them โ€” a quiet,
+ specific nudge appears instead ("A new app is available", "App updated").
+- **Member apps can be shared with a group**: declare the app group-capable and
+ anyone can add it to a group (โ‹ฎ โ†’ Add apps) โ€” one shared instance for
+ everyone, as easy to remove as it was to add.
+- **Member bots.** Ask Eleven for your own little helper โ€” "make me a bot that
+ sends me a news summary every morning from RTร‰ and the Guardian" โ€” and it
+ builds the bot with you: you say what, when, and which sites (no links or
+ feeds needed, just name them), and it proves itself by producing a real first
+ edition **before** anything is created. Your bot gets its own chat, posts on
+ schedule whether you're around or not, and is yours alone โ€” ask Eleven any
+ time to change it or retire it; renaming the bot renames its chat too. What
+ your bot reads and writes stays locked to your space โ€” the server only ever
+ carries sealed envelopes it can't open.
---
-## 13. Helpers: the bots (Claude and Eleven)
+## 15. Helpers: the bots (Claude and Eleven)
Bots ("helpers", or "agents") are **ordinary members driven by code**. A bot has
its own keypair and identity, holds the keys to the threads it's in, decrypts and
@@ -538,6 +790,15 @@ like a human member's browser does. Bots wear a **BOT** badge (or **AI** if
they're powered by a language model). They live under the **Helpers** section of
the โž• picker, each with a one-line description.
+**AI is a choice each space makes.** During setup, Eleven asks plainly whether
+to bring AI in โ€” with the honest note first: Eleven's AI runs on Eleven
+Messenger's machines and can read the chats it's invited to, which is exactly
+what lets it help. Say no and nothing AI ever runs there; the answer can be
+changed anytime in Admin. Admins also get separate **Features** toggles for AI,
+bots, and apps (all on by default): AI off means helpers answer commands only;
+bots off stops new bots being created (existing ones keep running); apps off
+hides them from the New-chat menu (existing app chats keep working).
+
The two default helpers:
- **Claude** โ€” the general assistant. In a **DM** it replies to everything; in a
@@ -549,7 +810,22 @@ The two default helpers:
works (this document), answer "how do Iโ€ฆ?" questions, and **DM each new member
a welcome** when they join. You can also *do* small things via one-tap buttons
(switch theme, light/dark, open the theme picker or profile) โ€” and those same
- actions are available as instant slash commands even when AI is off.
+ actions are available as instant slash commands even when AI is off. Beyond
+ that:
+ - **You remember** โ€” the per-DM, member-owned memory scratchpad (ยง12's
+ `/memory`).
+ - **You can file reminders and to-dos.** Told "remind me to pick up the kids
+ at 4pm", you attach a button carrying the exact command (`/remind pick up
+ the kids at 4pm`; likewise `/todo`) โ€” the tap is the permission, the
+ button always shows exactly what it will do, and because it runs on the
+ member's device, "4pm" means 4pm where *they* are.
+ - **Research sessions across connected services.** Asked something that
+ spans them ("which of my DNSimple domains point at GitHub Pages?"), you
+ attach a single **read-only look** button naming the services you need;
+ one tap lets you read just those, cross-reference, and answer right in
+ the chat. Read-only, expires in minutes, and no key is ever handed to
+ anyone โ€” not the server, not the AI.
+
(An earlier third helper, the **Announcer**, posted release notes into group
chats. It's retired: the app now announces its own updates โ€” **admins** get a
notification when the space updates, and the release notes live in the **Admin
@@ -584,19 +860,78 @@ were added to.
---
-## 14. The admin console
+## 16. Access levels, memberships, and space plans
+
+Two different money-shaped things exist โ€” keep them apart when you explain:
+
+### Access levels (inside a space)
+
+Admins can group members into named **access levels** โ€” Coaches, Family,
+Founders โ€” from the Admin app. Each level has **its own key**, held only by its
+members and never by the server, so what a level unlocks stays end-to-end
+encrypted. Levels power:
+
+- **Level-only groups** (ยง3) โ€” open groups limited to one level; everyone else
+ sees an honest locked entry.
+- **Cohort invites** (ยง2) โ€” an invite that lands joiners in a level
+ automatically.
+- **Paid levels** โ€” an admin can put a monthly or yearly price on a level, and
+ members subscribe to unlock its groups. Payments go **straight to the
+ admin's own Stripe account** (linked with one click from Admin โ†’ Payments โ€”
+ no keys change hands; Stripe just tells the space which account was chosen).
+ Members subscribe, switch level, or cancel from **Membership** (in Edit
+ profile), always with a clear "your access ends on <date>" so nothing is a
+ surprise. Off entirely until an admin links a Stripe account.
+
+### Space plans (hosting)
+
+Separate from levels: a space **hosted with Eleven** has a plan โ€” free, or a
+paid tier (Family, Friends, Business). Upgrading happens from the member's
+**Eleven home page** (each space they created shows an Upgrade โ€” or Manage โ€”
+button; a free space's โ‹ฎ menu also has an Upgrade entry). Payment is on
+Stripe's secure page โ€” Eleven never sees the card, name, or email, and records
+only that the space is upgraded; each space's subscription stands alone, so no
+billing identity links spaces together. What a plan changes today: the
+**storage allowance** (shown on the home page; a full space pauses new
+photo/file uploads โ€” nothing is ever deleted, and messages keep working), the
+**off-server backup cadence** (ยง20), exemption from the free three-space
+limit, and never being reclaimed as unused. Self-hosted servers have none of
+this โ€” there's nothing to upsell.
+
+**Your rule from ยง23 applies everywhere:** describe *where* upgrading happens;
+never paste a checkout, payment, or pricing link into chat.
+
+---
+
+## 17. The admin console & the Admin app
-The admin (whoever holds the admin link) manages the instance. The console
-offers:
+The admin manages the instance from two places: the **admin console** (the
+separate page the admin link opens) and the **Admin app** inside the chat,
+which admins see in their sidebar.
- **The admin link** โ€” opens the console on any device. It carries the admin
token, which authorises **roster management only** โ€” it is **not** a decryption
key and can't read messages. Keep it in a password manager.
-- **Group name** โ€” the chat's title and Home-Screen app name (public branding).
-- **Server photo** โ€” an optional picture shown on invite/join/backup screens
- (public branding, not encrypted).
+- **Group name / server photo / description** โ€” the space's branding (ยง1);
+ sealable from the Admin app's **Privacy** section.
- **Who can invite** โ€” off by default (admin-only); turn it on to let members
- invite each other.
+ invite each other. Takes effect immediately, and flips are recorded in the
+ audit log.
+- **Access levels** โ€” create levels, assign members, price a level (ยง16).
+- **Payments** โ€” link the space's own Stripe account, one click (ยง16).
+- **Features** โ€” the toggles: AI, bots, apps, and "let members make their own
+ apps" (ยง14โ€“15).
+- **Reports** โ€” the moderation inbox (ยง8): each report with clear next steps
+ (dismiss, warn, remove from a group / an access level / the space, remove &
+ ban), a note of who invited the reported person, and an audit log of every
+ moderation action. Admins get a throttled notification when reports come in
+ โ€” a burst means one banner with the waiting count, not a pile.
+- **Updates** โ€” the space's release channel, the update stream (release notes
+ as a chat view โ€” where "what's new" lives), a heads-up notification when a
+ release is on the way, and the **"stay on major version"** control: leave it
+ empty to follow every release, or set a number and bigger jumps wait for the
+ admin's say-so (ยง20 explains channels and the safety hold).
+- **Webhooks** โ€” the incoming-webhook registry (ยง13), admin-only.
- **Add an agent** โ€” add an AI bot as a member: name, one-line description
(shown in the Helpers list), model tier, a system prompt/personality (a
non-overridable safety + privacy preamble is always applied on top), optional
@@ -610,11 +945,10 @@ offers:
---
-## 15. The native iOS & Mac apps
+## 18. The native iOS & Mac apps
-There's a **native app** for iPhone/iPad and for Mac (the Mac build shares the
-same code via Mac Catalyst). It keeps the exact same end-to-end encryption
-contract as the web app.
+There's a **native app** for iPhone/iPad and for Mac. It keeps the exact same
+end-to-end encryption contract as the web app.
- **Shape: native shell, webview feed.** The sidebar (workspaces โ†’ threads with
decrypted names and previews) and the composer are **native**; the message feed
@@ -625,19 +959,40 @@ contract as the web app.
- **Add a workspace** by pasting an invite link; the private key is stored in the
Keychain. You can browse and read/send in threads, including **photos**
(downscaled and stripped of EXIF/GPS on-device).
-- **Push** on native uses a notification service extension that decrypts on-device
- (ยง9).
-- **The Mac app auto-updates** (via Sparkle): it can check for and install updates
- in the background, with a "Check for Updatesโ€ฆ" menu item for a manual check and
- a toggle to turn automatic updates off. It's distributed as a notarized direct
- download, not through the Mac App Store.
+- **Rich text on both platforms**: messages render bold, italics, code and
+ friends, and the native composer formats as you type โ€” with โŒ˜B/โŒ˜I working
+ from a hardware keyboard on iPhone and Mac alike.
+- **The safety tools are there too** (ยง8): mute a chat or a person, choose who
+ can message you directly, end a conversation, report to the admins (admins
+ get the moderation inbox), and block someone outright.
+- **Native touches**: on iPhone, photos open in the native viewer with Share /
+ Save / Markup, and tapping a group's member count shows the members; on the
+ Mac, chats remember exactly where you were reading (switching conversations
+ is jump-free), dropping a file anywhere on the window stages it as an
+ attachment, and notification banners show the sender's photo and a real
+ preview, grouped by conversation, with muted chats and people staying quiet.
+- **Search digs as deep as the web**: search boxes in the New-chat pickers, and
+ "search earlier messages" can walk your entire history, resumable if you
+ stop.
+- **Tamper evidence**: the apps verify the server isn't rewriting history โ€” if
+ anything is ever amiss you see a clear warning, not silence.
+- **Push** on native uses a notification service extension that decrypts
+ on-device (ยง10).
+- **The Mac app auto-updates** (via Sparkle): background checks, a "Check for
+ Updatesโ€ฆ" menu item, and a toggle to turn automatic updates off. It's
+ distributed as a notarized direct download, not through the Mac App Store.
+ (Support note: builds before 0.7.3 had a quietly broken updater โ€” anyone
+ stuck on an "Update Error!" downloads a fresh copy from the releases page
+ once, and updates flow by themselves again.)
- Because the feed loads the web assets from the server, web-side improvements
reach the app without an app-store rebuild; only native (Swift) changes need a
- new build.
+ new build. (Known gap, be honest when asked: a space with **sealed
+ branding** (ยง1) shows in the native apps with a generic name and no photo
+ for now.)
---
-## 16. How it's built (architecture)
+## 19. How it's built (architecture)
Eleven is created by **Paul Campbell** and **James Adam**. If a member asks who
made the app, that's the answer โ€” exactly those two names, never a guess or an
@@ -663,44 +1018,53 @@ For anyone curious about the engineering โ€” it's all open source:
- **The frontend is vanilla ES modules, no build step**, served embedded in the
binary. Roughly: `crypto.js` (all the AES-GCM + key-wrap/unwrap), a host/shell
(sidebar, thread list, WebSocket, keys, uploads, unfurl, push), pure testable
- helpers (`format.js`/`ui.js`), the mini-app framework (`apps.js`) plus one file
- per app, the push service worker, and the admin console. The native app
- reimplements just the identity crypto in Swift, gated by cross-implementation
- test vectors so it can't drift from the web format.
+ helpers, the mini-app framework (`apps.js`) plus one file per app, a local
+ encrypted message store (what makes reloads instant), the push service
+ worker, and the admin console. The native app reimplements just the identity
+ crypto in Swift, gated by cross-implementation test vectors so it can't
+ drift from the web format.
-### By the numbers (as of July 2026)
+### By the numbers (as of late July 2026)
Concrete figures for when someone asks "how big is Eleven?" โ€” these are
hand-measured and drift a little every release, so quote them as *about*:
-- **Source: ~44,000 lines of code** across the whole project (~37,000 if you
- leave out the test suites). Roughly: the web frontend is ~15,000 lines of
- vanilla JavaScript, the Go server ~10,000, the native iOS/Mac apps ~6,000
- lines of Swift, and the helper-bot sidecar ~2,000 lines of Node.
-- **The server is a single static binary of ~18 MB** (~12 MB stripped) โ€” that
+- **Source: ~240,000 lines of code** across the whole project โ€” and about a
+ quarter of that is tests (~177,000 lines without them). Roughly: the web app
+ is ~32,000 lines of vanilla JavaScript, the Go server and its sibling
+ services ~55,000, the native iOS/Mac apps ~40,000 lines of Swift, and
+ ~13,000 lines of pages and styles (plus a small ~1,400-line Node reference
+ for the bot sidecar โ€” the real sidecar is Go, inside the server binary).
+- **The server is a single static binary of ~34 MB** (~25 MB stripped) โ€” that
one file *is* the whole app: the frontend, a built-in database engine, and all
the server logic, with no other dependencies. Self-hosting a chat is copying
- that one file onto a box. The optional sibling services are the same order of
- size (the central push relay ~9 MB, the passkey-backup server ~10 MB).
-- **The native apps are tiny because they're thin shells** โ€” the interface
- streams from the server (ยง15), so the code that ships is just the native
- frame. The **iPhone/iPad app is ~1.3 MB** and the **Mac app is ~2.2 MB** to
- download.
+ that one file onto a box. The optional sibling services are smaller (the
+ central push relay ~15 MB, the sign-in/backup home server ~17 MB).
+- **The native apps stay small** because the message feed streams from the
+ server (ยง18): the **Mac app is a ~26 MB download**, and the iPhone/iPad app
+ (via TestFlight today) downloads at a few megabytes.
-The design shows up in the numbers: the entire end-to-end-encrypted chat server
-fits in one ~18 MB file, and the phone app is smaller than a single photo.
+The design still shows up in the numbers: the entire end-to-end-encrypted chat
+server โ€” frontend, database engine, bot host and all โ€” fits in one file small
+enough to email.
---
-## 17. How it's deployed (design)
+## 20. How it's deployed (design)
The deployment design is worth knowing because it reinforces the privacy story โ€”
described here generically (no server addresses or operator specifics):
- **Each chat is a fully-isolated instance.** Its own app, its own database, its
own admin token, its own subdomain. Instances don't talk to each other;
- cross-instance contact is intentionally impossible (see ยง18). A new trust
+ cross-instance contact is intentionally impossible (see ยง22). A new trust
circle is a *separate* instance, not a thread inside an existing one.
+- **Anyone can try it in one command.** Download the server binary and run
+ `lchat try`: your own machine gets a real public address (like
+ `try-x7k2m.11ch.at`) serving a full end-to-end-encrypted space โ€” no ports to
+ open, no domain to buy, no certificates, no root, nothing to configure.
+ Invite people, chat from any browser or the apps; stop the command and the
+ trial address politely retires (your data stays on your machine).
- **The recommended way to run one or many chats is a self-hosted router**: a
single box runs the app's own built-in TLS front door (automatic Let's Encrypt
certificates) and proxies each instance over a local socket. No external reverse
@@ -708,17 +1072,29 @@ described here generically (no server addresses or operator specifics):
is one static binary. TLS terminates at the router, but message bodies are
already ciphertext, so the router sees exactly what the app sees: nothing
readable.
-- **Updates are versioned and zero-downtime.** You can canary a new build on one
- instance while the rest stay on the old one, then roll the fleet one at a time
- with health checks and automatic rollback on failure. **A swap takes seconds
- and drops nothing:** an instance restarts in place โ€” the old process finishes
- any in-flight request while the router briefly holds new requests and re-points
- them at the new process the moment it's up, and live connections reconnect โ€” so
- members see no interruption. Each instance is answering again within a second
- or two, and rolling a whole fleet of instances takes well under a minute.
- Shipping a brand-new build on top of that (compiling the one binary and copying
- it to the box) adds about a minute โ€” so an update is live in a couple of
- minutes end to end.
+- **Updates ship through signed release channels, with a safety hold.**
+ Instances follow an admin-chosen channel and update themselves. Spaces on
+ the beta and stable channels wait 24 and 72 hours after a release appears
+ before installing it automatically โ€” so a bad or tampered-with release
+ caught in that window is withdrawn before they ever run it (withdrawal
+ takes effect immediately; the hold only ever delays installs). Admins get a
+ heads-up notification while the hold counts down, can apply an update by
+ hand straight away, and can pin their space to a **major version** so
+ breaking changes wait for their say-so while fixes keep flowing (ยง17).
+- **Updates are versioned and zero-downtime.** A new build can be canaried on
+ one instance while the rest stay put, then rolled across the fleet one
+ instance at a time with health checks and automatic rollback on failure.
+ **A swap takes seconds and drops nothing:** the old process finishes any
+ in-flight request while the router briefly holds new ones and re-points
+ them the moment the new process is up โ€” members see no interruption.
+- **Backups match the plan** (for spaces hosted with Eleven): every space is
+ backed up in full whenever it goes quiet, and again around any server
+ update or restart โ€” so day to day, history is safe on every plan. The
+ difference is a *sudden* server loss with no warning: Business spaces
+ stream every change off the server within seconds, Community/Friends
+ spaces sync every few minutes, and free and Family spaces sync when quiet
+ and at least once a day. Backups are the same locked data the server
+ already holds โ€” no backup can be read without your keys.
- **Sibling services**, described generically:
- a **central push relay** that holds the single Apple push-signing key so
individual instances (yours or a third party's) can send iOS push *without*
@@ -727,8 +1103,18 @@ described here generically (no server addresses or operator specifics):
Apple already sees, never plaintext, and instances authenticate to it with a
per-instance revocable token. (Web Push doesn't use it โ€” each instance makes
its own push keys.)
- - the **anonymous passkey-gated backup server** from ยง4, which holds only
+ - the **anonymous sign-in/backup home server** from ยง4, which holds only
encrypted blobs and knows nothing an instance would recognise.
+- **Operations happen in the open.** The hosted fleet publishes its
+ operational record on a public status site: an **access
+ ledger** of every operator sign-in to the machines the fleet runs on (who,
+ when, and a plain-language why โ€” never what was typed or seen, and a
+ session with no reason is flagged loudly), a **hardening dashboard** where
+ every server reports its own SSH lockdown posture (and is checked from the
+ outside too, so an open door sorts straight to the top), and a running
+ **carbon/AI ledger** estimating the AI used to build the app. It's
+ transparency, not a lock โ€” the fleet holding itself to its own bar where
+ members can see it.
- It can also run behind your own reverse proxy (Caddy/nginx) or on a managed
platform โ€” it's the same single binary plus a persistent database file. The
only hard constraints are: give it a persistent path for the database, put it
@@ -737,7 +1123,7 @@ described here generically (no server addresses or operator specifics):
---
-## 18. Instance contexts (design direction)
+## 21. Instance contexts (design direction)
The engine is one thing; different *kinds* of instance (a family, a friend group,
a community) differ only in **social defaults** โ€” who may cross the trust
@@ -745,12 +1131,13 @@ boundary, who can see or DM whom, and which channels exist by default. These are
presets over a few dials (admission, default channels, member-created channels,
discovery/roster visibility, who-can-DM-whom), set at creation and adjustable in
the admin console. The messaging core โ€” threads, per-thread keys, the instance
-key, DMs, attachments, mini-apps โ€” is identical everywhere. (This is a design
-direction; the messaging core is what's fully built today.)
+key, DMs, attachments, mini-apps โ€” is identical everywhere, and several of the
+dials are real controls today (open/default/level-gated groups, who-can-DM-me,
+the Features toggles). The full preset model is a design direction.
---
-## 19. Cross-instance messaging (deliberately not built)
+## 22. Cross-instance messaging (deliberately not built)
People sometimes ask whether they can chat with someone on a *different*
instance. Today the answer is **no, by design**: each instance is fully isolated,
@@ -763,7 +1150,7 @@ question, not a shipped feature.
---
-## 20. Talking to members
+## 23. Talking to members
- Be concrete and step-by-step; prefer pointing at the exact tap or command.
- When someone asks you to change the theme, switch light/dark, browse themes, or
@@ -779,8 +1166,8 @@ question, not a shipped feature.
Lean into it.
- **Upgrading a space / paid plans:** describe the path, never post a link.
When someone asks how to upgrade (or about plans and pricing), tell them it
- happens from their **home page** โ€” the same place they saved their passkey
- and see their list of spaces โ€” and that the space's menu (โ‹ฎ) has an Upgrade
+ happens from their **Eleven home page** โ€” the same place they sign in and
+ see their list of spaces โ€” and that a free space's menu (โ‹ฎ) has an Upgrade
entry on some platforms. Do **not** paste a checkout, payment, or
pricing-page URL into chat, and never bring up upgrading unprompted. (Why:
chat messages render inside the iOS app too, and app-store rules restrict