Repository navigation
Description
Summary
Fenced code blocks render, but there is no way to copy one directly. No copy button on the block, no "copy code" in the message action menu. The only route is highlight-then-copy, which works but is imprecise: it is easy to over-select into surrounding message text or miss the last line, and on wrapped lines the selection can carry soft line breaks into a command that then has to be cleaned up before it runs.
This is a minor papercut in a generic chat app. It is a more frequent one in Buzz specifically, because agents hand humans shell commands as a routine interaction, so the same imprecise selection gets repeated many times a day.
Steps to reproduce
-
Have an agent post a message containing a fenced code block — in practice this happens constantly, e.g. an agent proposing a fix:
bash ~/.buzz/.scratch/clean-buzz-agents.sh -
Try to get that command onto the clipboard.
Actual: no copy control on the block, and no "copy code" entry in the message action bar. Highlight-and-copy is the only route.
Expected: a copy control on the block (hover-revealed, corner-positioned) that copies the fence contents exactly — no language tag, no surrounding message text, no leading prompt characters.
Why this one matters more than usual here
Buzz's premise is agents as workspace members rather than bots. In practice a large share of agent output is a command or snippet the human is meant to run, so this selection dance repeats constantly — and a mis-selected shell command is worse than a mis-selected sentence, because it either fails confusingly or does something slightly different from what was intended. Slack, Discord, GitHub and ChatGPT all ship a copy button on code blocks; its absence is more noticeable in a product where the code is usually addressed to you, to run now.
It also interacts with an existing quirk: agents sometimes emit literal \n (#4891), so a hand-selected copy is not always faithful to what the agent meant to send.
Suggested scope
Smallest useful version:
- Copy control on fenced code blocks in the desktop message list, revealed on hover, consistent with the existing
MessageActionBarinteraction pattern. - Copies the fence contents verbatim; excludes the info string and any surrounding markdown.
- Brief "Copied" confirmation, matching whatever the existing clipboard call sites already do.
Deliberately out of scope for a first pass: inline code (`like this`), mobile (mobile code rendering already diverges — see #5257), and any execute affordance.
A wider version, if it's interesting
The narrow fix above is a chat-app table stake. The more Buzz-shaped question is whether an agent-authored command deserves a first-class treatment rather than being plain markdown that happens to contain a command — copy, and possibly "run in terminal" behind a confirmation, given the agent proposing it is already an identified workspace member with an audit trail.
That is a design conversation rather than a bug, and I would not want it to block the copy button. Raising it because a platform built on agents-as-teammates is a place where it might actually make sense.
Environment
- Buzz Desktop 0.5.8, macOS 26 (arm64)
- Self-hosted relay
- Verified against current
mainby code search: no copy-on-code-block affordance present
Activity
TheSeydiCharyyev commentedon Aug 10, 2026
The per-block copy control already exists in
main, and it matches the scope described here.MarkdownCodeBlockindesktop/src/shared/ui/markdown/CodeBlock.tsxrenders a button in the corner of the block. It is hidden at rest and appears on hover or keyboard focus (opacity-0plusgroup-hover:opacity-100/group-focus-within:opacity-100). Its accessible name isCopy code block, its tooltip saysCopy code, and it copies the fence contents throughcopyCodeBlockToClipboard.There is also a regression test:
desktop/tests/e2e/messaging.spec.ts, "copy a rendered code block and paste it back as code". It posts a fenced block in a channel, asserts the button goes fromopacity: 0toopacity: 1on hover, clicks it, and asserts the clipboard holds exactly the code — no language tag and no surrounding message text.CodeBlock.tsxlast changed on 8 July, so this is in 0.5.8 as well.So something else is going on in your case. Two paths in the code would show no control:
Markdowntakes aninteractiveprop. It defaults totrueand the message list uses the default. When it isfalse, theprerenderer returns a plain<span>(desktop/src/shared/ui/markdown.tsx), so there is no block wrapper and no copy control. Today that is the inbox list pane, the drafts panes, the project issues / pull request / readme panels, the persona catalog dialog, and the agent details in a profile.If the message body carries a literal
\ninstead of real newlines — the [Bug] buzz-acp agents can still publish literal \n after #2121 #4891 you mention — the fence never closes into a block. The text renders as an inline code chip, and an inline chip has no per-block control.Two questions, so this lands in the right place:
If it is case 1, the useful change is giving the non-interactive markdown surfaces the same control, which is a different piece of work from what this issue currently describes.