Agent chat: Claude's hover rows under every message (read receipts, Pin, Read aloud)
Builds on #22675 (transcript-density's action rows, merged).
Problem
Leo (2026-10-20): the rows under chat messages should match Claude Code desktop.
- Hovering an answer drew a box around it with "6:29 PM" and Copy at the far right.
- Under a prompt there was only a lone bookmark icon, plus "Steered · the agent read it" under steers.
Change
- Under an answer (
TurnRows.tsxTurnFooter), at the answer's left edge:- Copy, Fork from here, Pin, Read aloud, then the answer's age ("43 minutes ago"; the exact date and time on hover).
- Fork's tooltip has Claude's second line: "Starts a new session from this point. This one stays as it is." (
data-tooltip-detailinui/titleTooltips.ts). - Retry moved to the prompt. The answer footer no longer draws a focus outline; focusing it shows its row instead.
- Under a prompt (
UserBubble.tsx), at the bubble's right edge:- the age, a read receipt, Copy, Edit, Retry (only on the last ended turn's prompt), Fork and Pin.
- The read receipt is ✓ "Delivered when the current step ends" while a steer waits (steer-default's wording; it drops its own waiting marker) and ✓✓ once the agent read it; hovering ✓✓ shows "Read by Claude Code" (the harness name).
- Hover only. Neither row shows until you hover or focus it. Each keeps its height, so nothing shifts when it appears. Hovering a prompt shows only the prompt's row, not its turn's footer too, so one row shows at a time.
- Removed:
SteerMark("Steering…" / "Steered · the agent read it"), the bookmark icon under prompts, and the always-on row for the latest prompt and turn. - Pin reuses the thread minimap's bookmarks. acpmux now also accepts a turn's
turn_resultseq, so answers can be pinned too (hub/bookmarks.rs).- Pinned prompts show in the minimap as before.
- Pinned answers aren't listed in the summary panel yet (follow-up).
- Read aloud uses the web view's
speechSynthesis(the macOS voice). It is one message at a time, and pressing it again stops. - New strings, in all 21 locales:
message.readBy,message.readByAgent,message.delivered,message.pin,message.unpin,message.readAloud,message.stopReading,turn.forkDetail. Removed the unusedsteer.*,message.readandmessage.unread.
Observed / Not run
- Ran
scripts/cmux-next/prepush-gate.py: no new violations. - Not run locally: web lint, typecheck, vitest and cargo. Cosmic-gray was at load 80, so CI runs these. Tests that pinned the old rows still need updating (in progress).
Changelog
- Changed: Chat messages show Claude-style hover action rows: Copy, Fork, Pin, Read aloud and the message's age under answers; age, read receipt, Copy, Edit, Retry and Fork under prompts.
Agent session: cosmic-gray
🤖 Generated with Claude Code
Summary by cubic
Matches Claude Code desktop's hover action rows under every chat message, on hover or focus only. Answers show Copy, Fork (with Claude's "starts a new session" tooltip), Pin, Read aloud and the message's age under their left edge; prompts show age, a read receipt, Copy, Edit, Retry, Fork and Pin under the bubble's right edge; another agent's message shows age, the receipt, Copy, Retry and Pin under its card, after its Reply. A Chief-sent prompt gets the same row as one the person sends. The receipt is one check while a steer waits and two once read ("Read by "). The Steered line, the lone bookmark icon and the always-on latest rows are gone, and no answer footer draws a focus box. This also reconciles with base's steer-as-one-turn, row-height-estimate, Reply placement and rewritten Retry model menu (RetryModelMenu.tsx) changes, which the prompt's row and a failed turn's footer now reuse; Copy reuses base's CopyButton (tooltip name, resetting check).
Bug Fixes
- Fixes the row-height estimate to reserve a line under a steer only while it waits.
- A pinned prompt or answer keeps its pin through a fork.
- The waiting receipt's tooltip gets its own locale key: base's
message.deliveredbelongs toMessageCard.