cmux NEXT chat: shared chat faces (author, who's here, typing, answered by), render only
Leo, 2026-10-26, on hearing that Chief multiplayer is Lawrence's: "we can still do the regular chat multiplayer". Earlier: "also chief chats we need multiplayer".
Design: manaflow-ai/cmuxterm-hq#4389 (plans/cmux-next/chat-multiplayer/DESIGN.md).
What this adds (render only)
One set of components, multiplayer/Faces.tsx, for several people in one chat. It serves both the regular agent chat and Chief chats:
- Author chip: the author's face (their picture, else initials on their own hue) and name over each teammate's prompt. The reader's own prompts draw as before.
- Presence: who else has the chat open, as a stack of up to 3 faces with +N in the chat header.
- Typing: "Ana is typing…" over the composer, with a three-dot wave. It is a moving wave like a spinner, never a pulsing dot, and reduced motion stills it.
- Answered by: "Answered by X" on a permission receipt.
An adapter feeds it plain fields: participants.ts reads acpmux records in hb-acpmux's agreed shapes (person_message provenance, answeredBy {id, name} and _acpmux/presence). Names lose hidden and bidi characters and are capped at 64 characters; ids are kept whole. Home's adapter (chiefAdapter.ts) and the Chief mount come in the next PR, to keep this one under 800 lines.
No acpmux on base sends these fields yet, so a live chat renders exactly as today. The sync PRs light it up. Avatar pictures come from Home's avatar service when one is mounted; otherwise the face shows initials.
Gallery
Two entries, both on synthetic data:
agent-pane.shared-chat: the whole pane. Variantsshared,crowdedandalone(aloneis the before).agent-pane.multiplayer-looks: three looks plus two people typing at once. Variantspicked,names,facesandtwo-typing.
The pick is picked: face and name over the prompt, overlapping faces in the header, and face + words + dot wave for typing.
Real app (cmux NEXT, fleet build, Blacksmith macOS)
Real captures of the agent chat with the showcase mock daemon, before (36b8f277c12d, the base) and after (ffb62262fc02, this PR's head). The real app has no teammate yet, so no author chip, face or typing line can show here. These captures show that a chat with nobody else draws exactly as before. The shared-chat look is in the gallery captures below; the live two-person capture over cmux host share follows once presence (#25303, #25375) is on the base.
Before (36b8f277c12d)
After (ffb62262fc02)
| Light | Dark | |
|---|---|---|
| Before | ![]() | ![]() |
| After | ![]() | ![]() |
Captures (Linux Chromium, synthetic data, head 6316d03)
Before is alone, the same chat with nobody else. It renders exactly as base does today, since no field is set. After is shared, where three teammates are in the chat, and crowded, where four are here and two are typing.
before (alone) | after (shared) | after (crowded) | |
|---|---|---|---|
| dark | ![]() | ![]() | ![]() |
| light | ![]() | ![]() | ![]() |
Looks (agent-pane.multiplayer-looks). The pick is picked:
| picked | names | faces | two typing | |
|---|---|---|---|---|
| dark | ![]() | ![]() | ![]() | ![]() |
| light | ![]() | ![]() | ![]() | ![]() |
Risk
Low. Render only, behind fields that nothing sets on base.
- Touches
App.tsxin three places (author chip, header stack, typing line over the composer), each rendering only when its field is set. - Adds
AUTHOR_HEIGHTto the user row estimate only whenauthoris set. - No timers or observers. The typing dots are a CSS animation under
prefers-reduced-motion: no-preference. The only effect isuseAvatarPicture's existing subscription, cleaned up on unmount.
Tests
multiplayer/participants.test.ts: an author comes only fromperson_message;answeredByis a person, not a device or session; presence leaves out the reader by its own id; names lose hidden characters and are bounded, while ids stay whole; only inline pictures are used; graphemes.multiplayer/Faces.test.tsx: the chip; the stack with +N and the screen-reader label; nothing shown when alone; typing wording for one, two and several people.- Ran on huge-blue:
vp fmt,vp lint(0 warnings),tsc --noEmit, and the tests above.gallery-coverageandpane-englishfail the same way on base; nothing in those failures is from this change.
Agent session: cosmic-gray
🤖 Generated with Claude Code

















