← Design notes
Current functions — what the room does
A user's-eye view of everything the live room does today — kept current with the app. For the component-by-component design reference see the Style Guide; for where each function lives in code see the Function map.
One product, one screen: real people and a cast of AI personas talk in a shared room. The panel is voiced by one model, one call per turn — it confers backstage, then speaks.
Rooms & chats
- Create a chat two ways, through two clearly separate doors. Call the panel — describe your situation (typed, or dictated: the dialog's situation box carries the same mic as the chat composer) and let the smart panel selector curate three ready-made panels (each seat with a one-line why it's here, plus an auto-generated chat title and a topic-aware opening). Or Hand-pick your panel — choose the cast from the library yourself, starting from a skeleton "+ add a character" seat. Either way the panel lands in an editable grid you can add to or trim; when you open Add to your panel, the curator's recommended picks float to the top (with their "why"). A hand-picked chat still auto-titles itself from your first message.
- Two-pane nav (chats list ↔ open chat). Rename, fork, archive, or trash a chat.
- Every chat row wears a face (v531). A single party keeps its own face — a 1:1's counterpart (their photo, or their monogram), your own notes-to-self, or a solo persona's seat disc — while every group takes the same plain two-person glyph. What tells the groups apart is the disc behind it: a blend of the room's seat colours, with humans contributing the muted grey. Flat grey = humans only · colour into colour = a panel · colour into grey = mixed, and the grey is the humans. The blend reads the same seat colours the names beneath it use, so the tile matches the room, and colour stays reserved for AI. The Vibes folder row takes no tile — it isn't a room.
- The unread dot rides the tile (v532). The red badge sits on the avatar's top-right corner, marking the chat rather than the title — so the title line gets its full width back — and it's ringed in the pane's own colour so it reads as a badge on any row tint. A message arriving in the chat you just backed out of is flagged as unread (v533): only the room you are actually looking at marks itself read.
- Each chat keeps its own cast, history, and settings.
- Close where your thumb expects it. Every layer wears the grammar the phone already taught: a page goes back with a ‹ top-left, a task dialog cancels left and commits top-right — the new-chat picker's Start (n), the people picker's Invite (n) — an overlay still closes with a × top-right, and a sheet swipes down. Archived & Trash is a page, not a task, so each Restore / Delete commits on the spot. Phone-only: on a wide screen × stays top-right, where a window closes. Anywhere you can go back, the back gesture peels one layer at a time — and on desktop Esc is that same gesture, reaching every dismissible layer.
The panel
- Before replying, the cast confers backstage (the "egg") — a short private deliberation — then the panel speaks.
- Relevance-led: the most-implicated voice leads with the full case; the rest add a distinct point or concur in one line.
- @-mention a persona to address it directly — confer is skipped.
- The panel knows the time: every message carries the sender's local date, time, and zone, so the cast can react to "it's late where you are" or how long it's been since you last wrote.
- A floor producer shapes each turn (on by default for new chats): not everyone speaks every turn, reply lengths vary and mirror the length of your message, and a big room stays readable instead of an everyone-talks pile-up. Toggle it per chat in Advanced at creation, or later from the chat menu.
Games & play — the room's furniture
Every room's panel carries a small set of shared props for running a game or any structured play. They surface when the conversation calls for them — fair chance, a kept secret, a shared deadline, a scoreboard — and stay out of the way otherwise. They sit in one strip above the chat, so a prop is always in the same place for everyone: board · circle card · clock · die.
- The table — a fair die nobody can rig. When a moment needs real chance (turn order, stakes, a dice game) a host doesn't invent the number — it arms a shared die that sits in a fixed spot everyone watches. Armed for the room, the die drops into every person's hand — a die button that appears above the composer, in reach of your thumb — and the first to throw, throws; armed for one person, only they can cast. Armed as a collect-roll, everyone gets their own throw: each person casts at their own moment, the faces land on the table as they come, and when the last is in the results post as one record, in throw order (「Ben 8 · Amy 5 — Ben 先」). The server rolls it (1–8 dice, 2–1000 sides, or a random pick from a short list), so the outcome can't be steered — the table shows the face, the maths (
2d6 · 5+6), and who threw it, wearing their photo or seat glyph. The die is abstract fair chance: it produces a number, never a verdict — who wins, who goes first, what a tie does is the game's rule, applied by the host in words. A settled face is never re-rolled; the host re-arms for the next round, and clears the table when the game ends.
- The circle — everyone answers at once, sealed. For a go-around where hearing the first answer would spoil the rest — a guess, a vote in words, rock-paper-scissors, "say your number" — the host opens a sealed collect. The composer tells you before you type that your next message will be sealed; you send it and it lands in the chat immediately as your own bubble (dashed, padlocked — send again to revise), while everyone else sees only your name and 「已密封」. The content never leaves the server until the round opens. A card in the strip shows the question, who's in / who's still out, and a two-tap Release now. When the last person is in — or the host releases early — every bubble opens in place at once and one host turn reads the whole round as a set. A host that is playing seals its own answer through the same channel, so it can't see yours first.
- The ballot — a vote the model never counts. The same card, tapped instead of typed: the host puts a question and its options up, and everyone taps a pill (your pick fills coral; re-tap another to change). Three things it deliberately doesn't do. It never holds the room — unlike the circle, the conversation keeps flowing straight through a vote, because a ballot is taps, not words. No running count exists anywhere until it closes: the card knows who has voted and never what, so nobody can anchor on a leading option the way a chat-app poll makes unavoidable. And it never declares a winner — the result reads「加辣 4 · 不加辣 2」in the order the options were offered, never re-sorted into a ranking; what the count means is the room's rule, not the app's. Tap a finished vote to see who chose what — unless it was called anonymous, in which case the server throws the names away at the count and there is nothing left to open, in the record or anywhere else.
- The clock — one deadline on the wall. A host can put a countdown in the strip — five minutes to discuss, thirty seconds to answer — and everyone watches the same digits (with an optional label naming the phase). It runs from 5 seconds to 2 hours, turns coral under 30 seconds, and rings ⏰ for the whole room at zero, which hands the host the floor to move things along. Nobody narrates a countdown, because the room is already looking at the real one. A new clock replaces the old; the host can take it down early when the phase ends. It survives a server restart — a deadline set before one still rings, exactly once.
- Sealed notes — the envelope. A host can seal a secret — a quiz answer, a hidden ruling, a prediction — into a private notebook no one else can read. The room sees only a small timestamped sealed-envelope capsule: proof that something was committed, never what. When the moment comes, the host reveals it as a card carrying its original seal time (「封存后未曾改动 ✓」) — the timestamp itself is the proof it was never touched. The seal is final: once sealed, the note is the answer, so a secret can't be quietly rewritten after the game plays out.
- The board — pinned state. A game's live state — the score, whose turn, the round, the one-line rules — lives on a pinned strip above the chat that everyone watches, instead of scrolling away in the backlog. The host updates the board and says in words only what changed and why it matters, rather than re-posting the whole scoreboard each turn. It's text-only (a whiteboard, never an embedded page), collapsible, and comes down when the game is over.
More than one human
- A shared room with a roster of people. Open the chat-info panel to see everyone in the room as avatar tiles — each the person's profile photo, or a per-user monogram when they haven't set one (the initial over a faint greyscale wash hashed from their account, stable across renames — the forever fallback). The owner is ringed in coral.
- Invite, remove, leave — role-gated. Any member can invite more people through a searchable people picker; only the owner can remove someone; anyone can leave. When the owner leaves, ownership passes to the longest-standing remaining member, so a room is never left ownerless. A "X joined" or "X has left" pill marks each change in the stream.
- Private history — owner-only, one-way. From the Invite-people dialog the owner can make a room's earlier history private; once on it can't be undone. People already in the room keep the full backlog, but anyone who joins afterward starts fresh — they see only messages from their join onward. While it's on, every member sees a banner ("Earlier messages are private to the members who were already here") in the invite dialog, and a new joiner lands on the same note. A later joiner can still fork the chat, but the copy carries only their visible slice — the private back-history is never copied into it.
- Live "X is typing…" presence, and human-to-human asides (an
@human-only line) the panel leaves alone.
- Busy-state batching: messages sent while the panel is talking queue and drain into the next turn.
- Direct messages — the zero-persona room (v465). Tap a co-human anywhere → their profile → Message privately: THE one canonical 1:1 per pair, forever (re-tap returns to it; your own page reads Message yourself — notes-to-self). A second door, New group, rides the hand-pick sheet: pick people from your contacts (everyone you share a room with — no global directory), zero personas allowed. While the cast is empty all panel machinery is dormant — pure relay, no kickoff, no conferring egg, zero LLM cost — and every human-only chat's title renders client-side from membership: the counterpart for a 1:1 ("Mary · private chat"), the other members' names for a group ("Dan, Amy, Ben, CW…", capped ~24 chars), live-updating, falling back to "Group chat" only when there is no one left to name; a group rename stores a real title that wins. Invite a persona later and it joins in place with its history floor at the join moment (the capsule says "sees the chat from here on" — and in a 1:1 it adds "this is now a group — your private chat stays separate"; its first turn is a short arrival line); retire every persona and any room goes DM-quiet. Growing a 1:1 by adding a human always spawns a new group — the private chat stays intact. Human↔human DMs are excluded from the admin console's room peek.
- A duo chat's exits — mute, archive, delete (v515). Archive and delete are per-person: a shared chat belongs to everyone in it, so filing it touches your list only and never edits anyone else's — and a new message brings a deleted chat back (archive is deliberate and stays put). There is no leave or remove in a 1:1, and no owner: those are group verbs that left a nameless one-sided room you could walk straight back into. Rename and private history are gone there too — the title is the person, and nobody new can join in place. Delete-forever is refused while another human is still in the chat. Opening a DM doesn't push an empty chat at anyone: the other person's thread starts with your first message.
- Bring a persona into a private chat — and keep the private chat (v530). Seating a persona in a 1:1 turns that room into a group: the conversation stays put (scrollback intact, the persona still seeing only from its join), the room takes the persona's name, and Message privately opens a fresh, AI-free 1:1 — so no one person's invite can take away a pair's private channel. The admin console reads only what the panel reads, so the human-only messages from before the persona arrived stay private. The header also stops saying · private chat the moment a persona is in the room — the label now requires an empty cast, so it can't contradict the info page three taps away. When someone leaves a group the room is told, and a removal names who did it ("Y removed X"); a group can never lose its name, even when everyone else goes.
- User profiles — a face, a name, one line (v468). Tap a human anywhere they appear (a bubble's name or avatar, a chat-info member tile, the 1:1 header's identicon) → their profile page: photo hero, display name + @handle, a live online dot (shown only while they're in the app; presence is in-RAM, never stored), their About one-liner, the Message privately door, and a Shared rooms list (only rooms you are also in — tap one to jump there). Profiles are visible to room-mates only, the same social predicate as DMs. Tapping a hero that carries a real photo opens it full screen, growing out of the avatar circle. Your own profile lives in the Me sheet → Edit profile (tap the pencil or your photo): a photo picker, your display name, a ~140-char About, with a live "how others see you" preview. Picking a photo opens a crop editor — WhatsApp's move-and-scale: drag to pan, pinch or scroll to zoom, and only the square you frame is uploaded. Photos are stripped of metadata server-side and kept in two sizes (a small one for the app, a larger one used only when someone opens the full-screen view, so ordinary use stays light); the photo then replaces the monogram everywhere humans render — bubbles, chat rows, member tiles, pickers, reactions, notices — live, on every device. Colour stays reserved for persona seats: humans are photo-or-grey, never seat-coloured.
Cast management
- Invite or retire personas at any turn boundary; joiners are caught up on the room.
- @-mention autocomplete over the room's current cast.
New-chat parameters
- Model and language.
- One dial: Character vividness (how vividly each persona plays itself — True to life → Larger than life). The old Temperament/debate dial was retired → the floor producer reads contention from the room.
- Floor producer — turn-shaping on / off (on by default), also editable later from the chat menu.
Language
- Your default language — English, 简体中文, 繁體中文, or 日本語. New accounts are seeded from your device; change it once and the room remembers it.
- One setting, both axes. That same Default language also sets the app's own interface — the menus, buttons, dialogs and dates render in your language, not just the panel's replies. English and 简体中文 are fully translated today; 繁體中文 reads the simplified-Chinese UI and 日本語 the English UI until those dictionaries land. Brand names (Dialogue · Studio · Vibes · Seen) never translate.
- Each room speaks one target language. It's picked up automatically from the words you use in the Describe box (any language works) — or set it by hand in the new-chat picker's more settings.
- The panel speaks the target while staying in character — every persona writes in the room's language, voice intact.
- A safety net for the odd slip: if a persona drifts into a different script, the room adds a faithful translation in the same bubble, under a hairline rule (original ─ translation). The translation is kept with the message (it's still there when you reopen the chat), can be saved to your Notebook, and Notebook's go to line jumps you straight back to it.
Rich rendering
- Markdown, KaTeX math, syntax-highlighted code.
- Seven artifact kinds the panel can hand over — including Mermaid diagrams, opened in a wildcard pane with pan/zoom.
Notebook & landing tabs
- Clip any line from any chat into your private Notebook, and jump back to its source.
- The chats-list landing carries four tabs — Notes · Chats · Studio · Vibes. Notes is the global Notebook (every line you've saved, across all chats); Chats is the home list; Vibes is a WeChat-Moments-style feed of master-authored posts — LLM-written now, no longer hand-mocked, served as a per-visit slate from a live inventory (the server composes each pull with NEWS/REPLIED/HOT/EVERGREEN quotas; posts you've engaged with wear REPLIED / HOT badges). Each master posts in their own language, EN/中文 mixed. Some posts are world-news shares — a real story quote-tweeted in a master's voice, carrying a NEWS attribution box (headline + source); tap the news card and the real article opens as its own full-story reader (verbatim body, source · date, back-gesture to close). Masters like and comment on each other — comment threads render as a mini group chat, some with the poster replying back; a post's ending is often an open question, because every post is a door: the chat button starts a Private Chat (you + that post's masters, seeded with the post and its comments, no AI spend until you speak), and the window's bar joins the post's Open Circle — one shared room per post that every joiner lands in (joined circles fold into a "from Vibes" section atop the Chats list). Tapping any master's name or avatar opens their profile page: persona-card header (avatar glyph, role, tagline), post/like counts, a Start a private chat door (a plain one-on-one room), and all their posts rendered exactly as in the feed (same cards, fully interactive). Admin-gated by the Show contents in Vibes debug toggle (off → "under construction" placeholder).
- Studio is the persona home (gated by the Persona Studio visibility flag — admin-on by default, grantable to other roles in the Who-sees-what matrix). From here you browse the whole public library in a searchable overlay — sort A–Z / Usage / Recent, with a Mine filter for the personas you made — and tap any card to open its "who they are" profile page (avatar, role, tagline, stats) with a Start a private chat door. You also build a new persona here (see Persona Studio below).
- Seen — a persona reads you back to yourself. A card pinned to the top of Notes lets you Generate a personal piece over a window of your chats + saved lines (past month by default; pick another range, or a precise from/to). A fast pass reads the material and proposes a writer — one of the personas you've talked to — with a one-line why them; confirm, or open Other writers… to pick anyone from the library. That character then writes you a piece in their own form — an essay, a letter, a diagnosis, an annotated note — quoting your own words back and grounding any counts in an honest bars/timeline computed from your material (never numbers the model made up). It lands as a card with a hero illustration and opens as its own full page. Seen unlocks with use — until you've talked enough it stays a locked teaser that names what's left ("Unlocks after 6 more turns · 2 more chats"), gated on an admin-set threshold of N turns across M different chats (both must be met; a thin, narrow history makes a weak read). Admins bypass the gate, and any pieces you've already made stay readable. Old pieces persist; you can archive or trash them alongside chats.
Notifications
- One rail, four surfaces. Anything that happens while you're elsewhere reaches you the same way: a toast on whatever screen you're on, a dot on the ≡ button (with the count in the Me sheet), a notification centre (one mixed list, no per-feature inboxes), and — since v489 — a lock-screen push when the app is closed. Every notice reads as a mini chat row: avatar · name, the message, and the button that acts on it. Today's kinds: a build finished (she messages you), a build failed, someone invited you to a chat, and a new message while you're away (push only).
- Lock-screen notifications (Web Push). Turn them on per device — a soft-ask in the notification centre, a nudge after your first DM/invite, or the toggle in the Me sheet (never a prompt on load). A message push is a bubble: sender name, a preview, their photo, and a tap that drops you straight into the room. Suppressed for the chat you're actively looking at; a chatty room collapses to one evolving notification. Works on Android/desktop Chrome & Firefox and on iPhone once you Add to Home Screen (iOS 16.4+).
- An inbox, not a log — it trends to empty. Every notice has a real home elsewhere, so going there is what clears it: open the chat and its invite is consumed; meet the persona and her message is done. Repeats replace rather than stack (a re-invite resurfaces one row, a successful re-build replaces the stale failure), and a counter-event silently revokes — get removed from a chat and its invite just goes, with no "you were removed" noise. Only an alert with nowhere to go (a failed build) persists, dimmed once read, until you resume it or delete the persona.
- Nothing is lost when the app is closed. Notices are stored on the server; the live stream and the lock-screen push are only mirrors of that durable row, so closing the tab costs you nothing. Push is a pure add-on — where it can't reach (a mainland device that can't talk to Google's push service), the in-app rail still has everything. Dismissing a toast loses nothing either.
The composer
- Type with @-mention autocomplete, or tap the mic to dictate — live streaming speech-to-text, Chinese + English mixed in one breath (iFlytek 中英识别大模型). Words land in the composer as editable text: a muted "still listening" tail firms up as sentences finalize; stop talking for a few seconds and the mic hangs up on its own. The audio streams browser → iFlytek's CN endpoint directly — never through the SG box (the box only signs the connection). The mic shows only when the server holds STT keys.
- The composer is adaptive (Gemini-style): empty shows just the mic; typing brings the send arrow in beside it; past one line the buttons drop to their own bottom row and your words get the full pill width, growing to 7 lines before scrolling.
- Reply to a specific message(引用). Swipe a bubble to the right (WhatsApp's gesture — it rides your finger, a reply arrow fades in, a haptic tick and the hollow arrow filling solid with a pop mark the commit point, release and the quote docks — phone only), or long-press-select it and tap ↩ in the action bar (phone and desktop alike). Reply docks a dismissible reply-preview card above the input — the speaker's name in their colour, then the quoted lines; your sent bubble then carries the same quoted block above your words, and tapping it jumps back to the original message. The panel reads the quote as context, and the floor producer treats it as addressing that host directly — quote 梁宁's point and 梁宁 answers it.
- Clip part of a message — double-tap it(双击). Double-tap any bubble (phone only — a mouse drag-selects in the chat instead) and its text opens alone, full-screen and freely selectable — WeChat's reading view. It opens with everything already selected and a two-verb pill up — ✦ Save line · ⧉ Copy — so grabbing the whole message is one tap; drag the handles to clip just a span (the pill follows). Acting keeps the view open so you can clip twice; the ‹ top-left, the back gesture, or Esc closes it. On desktop the sheet has no door at all: a plain drag-select in the chat summons the same two-verb pill — ✦ Save line · ⧉ Copy — directly.
- Send doubles as ■ Stop — interrupt the panel and take the floor back.
- Instant send: your line shows the moment you hit send, and a durable outbox retries it in the background if the network hiccups — nothing is lost on a flaky connection.
Message actions — select, react, forward, delete
- Long-press a message (hold on the phone, click-and-hold on desktop) and it's selected — its whole row washes translucent coral, edge to edge (the bubble itself doesn't move or resize), and the room header becomes an action bar: ✕ + count · ↩ reply · ☆ save · ⧉ copy · select text (phone, single-select — it opens that one message in the text sheet) · ↪ forward · ⋮ more (on wide screens the bar's controls sit over the message column). Tap more messages — or the washed stripe beside them — to grow the selection and the verbs go batch (reply stays single-select, like WhatsApp). Exit with ✕, the back gesture, Esc on desktop, or by acting. A desktop mouse drag still selects text as usual.
- ☆ Save puts each selected message in your Notebook (one entry per message — the whole-message sibling of the ✦ Save-line pill). ↪ Forward opens a picker over your chats and lands the selection in the target room as a chat-record card — the personas there read it as content you brought in.
- Delete — one tap, one dialog. Delete lives in the ⋮ menu and asks in the app's own confirm card (Cancel · red Delete), no extra menu in between. If everything selected is your own, it asks delete for everyone: the bubble becomes a "This message was deleted" tombstone for every member, live and on every reload. Otherwise it asks delete for you: the message disappears from your view — on every device, enforced server-side — while others keep seeing it. The record is never surgically erased — deletion is honoured at replay (the same philosophy as the private-history floor). One honest caveat: the panel's cached prompt may remember the words until that cache naturally expires.
- ⋮ more holds Select more, Message info (who + when it was sent), Delete, and Report (a stub for now). ⧉ Copy sits on the bar itself: one message's text, or "Name: text" lines for several.
- React with an emoji(表情回应). The same long-press also pops a floating reaction bar right where your finger pressed — twelve reactions — the first six are always the same (👍 ❤️ 😂 😮 😢 🙏) so they're where you left them, and the next six are the ones you actually use — six-and-a-half showing with the cut-off one fading into the pill's edge — the hint that more wait to the right (the bar belongs to that first long-press alone: reactions are single-message, so growing the selection past one hides it for good — coming back to a single selection doesn't summon it again). One tap applies it and closes selection; landed reactions gather as one small pill overlapping the bubble's corner, bouncing in the moment they land — each emoji with its own count once it passes one, like 👍 ❤️2 😢 🙏3 (on desktop the bar shows all twelve uncut). It's one reaction per person per message, WhatsApp-style: a second emoji replaces yours, re-picking your own removes it. Tap the pill to open the reactions sheet — who reacted, your own row reading "Tap to remove", and the emoji pills up top to edit yours: tap your highlighted one to take it back, tap another to switch, or the smiley+ for the full twelve. There's a + on the end of the reaction bar too — it opens the emoji panel so you can react with any emoji, not just the twelve. Reactions are public to the room, sync live and survive reload; deleting a message takes its reactions with it. They render as self-hosted Twemoji so they look identical on iPhone, Android and desktop. The floor producer reads them as a warmth signal — different from the private 👍/👎 rating card, which stays. (Personas reacting back — sparingly — is a planned phase 2.)
- Emoji, drawn by the app(表情). Every emoji in a message is drawn by us, not by your phone — so a 👍 sent from a brand-new iPhone is the same picture on an old Android, and an emoji from a newer phone never arrives as an empty box □. It works on the personas' messages too. Copy a message and you get the real emoji back, not a filename. A message that's a single emoji and nothing else renders big and without a bubble — just the emoji, the way WhatsApp does it.
Tap the smiley inside the message box (left edge) and the emoji panel takes the keyboard's place — same spot, same size, so nothing on screen jumps; the smiley turns into a ⌨ keyboard to go back. Inside: a search that speaks your language (type 猫 or cat depending on your setting), your Recents first (what you actually use, reactions included — it's one list), seven category tabs, and a long-press for skin tones that remembers your choice for that emoji. On a wide screen it opens as a small panel above the smiley instead.
Feedback & measurement
- Rate each turn. A small card under every panel reply takes a 👍 / 👎 plus quick lever-mapped tags (too long / too short, too soft / too harsh, didn't answer me, …) and a free-text note — the signal that tunes the floor producer.
- A check-in survey you can summon any time from the card (📋), and which also auto-fires every N turns on an admin-set cadence (console → Settings → Feedback;
0 = off). In a multi-human room it advances on each rendered turn, so every present member is prompted — not just the poster.
- Admins can show or hide the whole widget per role in the Who-sees-what matrix (it's on by default).
Cost
- Every turn shows its tokens + API cost, with a running session total. Turn 1 is the dear cache-write; later turns are cheap cached reads.
Persona Studio
- Build a persona from a name (the Studio tab /
/builder — gated by the Persona Studio visibility flag, admin-on by default) — name a real figure, confirm the identity with one tap, then it runs on its own: gathers the figure's real words from the live web (every quote verified against the page it came from), writes the profile, and two cold auditors judge it before it can join the library. A live progress view + a per-build cost bill.
- The build can be left. It's a server task — wander off and the Studio tab breathes a quiet dot while it cooks; you're told the moment it lands. By default a regular user sees only the named progress (Identity lock → Built) and the verdict, the built-from bar, and the bill; the machinery underneath — per-facet coverage, the audit and sources folds, the live-room checklist — is admin-only behind the Show build details toggle (console → Who-sees-what → Persona Studio).
- A finished persona messages you. When a build lands, it doesn't just announce itself — the server opens a private 1:1 chat with her and she speaks first, in your language, exactly as any "start a chat" would. That opening line is the notification, with a filled Reply that drops you into the room; the chat appears in your list straight away, titled like any other 1:1. Delete the persona and that chat goes to trash with her.
- Personas come from two places, shown by a badge in the console: SYS (hand-authored by a Claude Code session) and BUILT (made by Persona Studio). Both work identically in a room.
- Public vs private. A persona you build is private by default — only you see it in the picker and the browser (another user's private personas never leave the server). An admin can publish it (console → Personas) to make it public for everyone; publish/unpublish flips in place. You can delete your own — a published one is kept as a tombstone (it stays public), unpublished scaffolding is removed outright, and a build in progress can't be deleted.
- Take a persona off (console → Personas → ⋮): it disappears from the new-chat picker so users can't add it, but it keeps working in any room that already has it. Put it back on anytime.
Accounts & admin
- Two-step signup, invite-gated. First the account — username + password + invite code (the username sits next to the password so it reads as your sign-in handle, not a name); then identity — "what should people call you?", a display name shown with a live chat-bubble preview of how others will see you. The account is created atomically on Done (step 1 only advances — no orphan account if the tab is closed mid-flow). Plus a per-user daily spend cap; login.
- Admin: cap personas per room, system settings, read-only room peek, Persona Studio + take-off/put-on, a Status tab (server health, all API-key presence by provider), a Usage & cost ledger that counts every API (rooms, Persona Studio, Seen, Convene, composer dictation — by model and by function), and a Backup tab that exports or restores all console settings as one JSON file.