---
title: Sender Run Cards (back-to-back messages become one quiet line that opens to a swipeable deck)
---

# Sender Run Cards

## What it is

A busy session gets bursts. A watcher fires three gate results; the lander reports twice; another
agent writes to this session two or three times while it works. Each one is its own message, so the
conversation grows a **wall of near-identical bubbles** — and on a phone every extra bubble costs a
screenful of scrolling.

**Sender Run Cards** collapses that burst. When two or more messages arrive **back to back**, the
conversation shows **one quiet line** — "5 agent messages · Scout #2, Fixer #3" — and clicking it
opens **one row holding a swipeable deck of cards**, one card per message. Swipe (on a phone) or use
the arrows (on desktop) to page through them.

Nothing is lost. The line always says how many messages are behind it and who sent them, every card
holds the real message exactly as it would have rendered on its own, the deck always tells you where
you are ("Card 2 of 4"), and **Show all** drops the deck into a plain vertical stack if you would
rather read the whole burst at once.

## Where to find it

### How to use it

You do not have to do anything. It is **on by default**.

- **To read the burst** — click the quiet line to open the deck, then swipe it or use the arrows
  beside the card counter.
- **To read it all at once** — press **Show all** and the deck becomes an ordinary vertical list.
- **To fold it back away** — click the line again; the deck collapses back to the one line.
- **To jump to a specific message** — search, the scroll buttons and deep links still work; the deck
  opens on the card you asked for rather than leaving it hidden off to one side.

To turn the whole thing off: **Settings → search "sender run cards"** and switch it off. The
conversation goes straight back to showing every message as its own bubble, exactly as it did before.

## How it behaves

### When a deck forms — and when it does not

A run forms only where it cannot mislead you:

- **Two or more messages.** A single message is just a message.
- **Any senders** — a run from Scout #2, Fixer #3 and Fixer #29 folds as one line. Each card still
  names the agent it came from, so a mixed run never hides who sent what. (Before 2026-09-21 a run
  required one sender, which meant a coordinator's inbox — almost always a mix — never folded at all.)
- **Nothing in between.** If the agent replied to the first message, the two never group: the reply
  stays where it happened, so a message can never appear after the answer it belongs to.
- **Nothing the deck would hide.** A message that carries something you must act on — a system
  marker, a divider, a note — breaks the run and renders on its own.

Messages **you** wrote are never folded. Neither is the agent's own writing; a deck only ever holds
messages that were **sent into** the session.

**The SENDING side folds too (2026-09-19).** A session that coordinates other agents sends one
"Sent to &lt;target&gt;" card per message, so an overseer's transcript stacks them the same way.
Several sends landing back to back now collapse into **one line** — "N messages sent" plus the last
send's time — which opens to the cards. An undelivered send ("Not delivered to …") always stays
visible on its own: it is the one card that wants an action from you.

**Identical repeats are handled separately and are unchanged.** When the same notice repeats word for
word — an account-capacity message re-emitting while you wait — you still get the familiar one-line
"Repeated 6 times" fold rather than a deck of six identical cards.

### Settings

| Setting field name (in `AppSettings`) | UI label         | Section        | Default |
| ------------------------------------- | ---------------- | -------------- | ------- |
| `senderRunCardsEnabled`               | Sender Run Cards | Lab / Features | **on**  |

### Where it goes wrong

- **A message that disappears.** Suppressing the rest of a run is only safe because a message joins a
  run _solely_ when its turn renders nothing but its own bubble. If that rule is ever loosened, the
  messages it lets through are not tidied — they are deleted from the conversation.
- **A row that resizes while you swipe.** The deck row takes one fixed height and paging never changes
  it. Letting it measure or animate itself re-anchors the conversation's scroll position, which is a
  known and repeatedly-seen class of bug.

## For agents

### Implementation pointers (for agents touching this code)

- The grouping rule: [src/renderer/src/features/sessions/sender-run-groups.ts](../../src/renderer/src/features/sessions/sender-run-groups.ts) —
  `computeSenderRuns` (the run walk), `rendersOnlyItsOwnPeerBubble` (the only turn shape that may
  join), `isLeadRendered` (the render-window rule).
- The quiet line: [SenderRunMarker.tsx](../../src/renderer/src/features/sessions/SenderRunMarker.tsx) —
  the count and the sender names, resolved with the arrival chip's own precedence through ONE store
  read for the whole run.
- The render: [TurnGroup.tsx](../../src/renderer/src/features/sessions/TurnGroup.tsx) takes an
  optional `senderRunMessages`; the run's lead paints the marker, and the deck only once the reader
  opens it. The followers render nothing.
- The wiring: [RealConversationList.tsx](../../src/renderer/src/features/sessions/RealConversationList.tsx) —
  the memoised pass behind the switch, plus the fall-through that renders a follower's own bubble
  when its lead was skipped by the render window.
- The deck itself is the **existing** [AgentCardDeck.tsx](../../src/renderer/src/components/ui/AgentCardDeck.tsx) —
  not a second deck implementation. Paging, the position label and Show all all come from it.
- Setting: `senderRunCardsEnabled`, default `true`, in the chat-ui settings slice; registered in
  [unreleased-features.ts](../../src/shared/unreleased-features.ts) as `in-development` with
  `defaultOn: true`, and read through `isUnreleasedFeatureVisibleInRenderer`.
- Tests: [sender-run-groups.test.ts](../../tests/unit/features/sessions/sender-run-groups.test.ts)
  (the run rules, including every refusal) and
  [sender-run-deck-render.test.tsx](../../tests/unit/features/sessions/sender-run-deck-render.test.tsx)
  (the render).
- Contracts: [.claude/memory/contracts/sender-run-cards-contract.md](../../.claude/memory/contracts/sender-run-cards-contract.md);
  map: [.claude/memory/sender-run-cards.md](../../.claude/memory/sender-run-cards.md).

## Related

- [agent-message-cards.md](../../.claude/memory/agent-message-cards.md) — the other card deck, where
  an AGENT splits its own long answer; this feature is about separate MESSAGES from one sender.
- [agent-message-display.md](agent-message-display.md) — how agent prose and tool activity render.
- [collapsed-exchange-contract.md](../../.claude/memory/contracts/collapsed-exchange-contract.md) —
  the other thing that quiets peer arrivals, by folding a notice and the agent's reply into one line.
