Skip to content

feat(gpui): copy a whole thread as Markdown - #118

Merged
tee8z merged 1 commit into
mainfrom
feat/gpui-copy-thread
Nov 4, 2026
Merged

tee8z merged 1 commit into
mainfrom
feat/gpui-copy-thread

Conversation

@tee8z

@tee8z tee8z commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #95.

Problem

The GPUI app can copy one message or its link, but not a whole thread. To share a thread with a person or an agent, a developer must paste each message, take screenshots, or run buzz messages thread with their private key. Copied text also loses agent state such as "Could not finish" and remote session banners.

Change

The root message's More message actions menu in the thread panel now has Copy thread, under Copy message. It puts this Markdown on the clipboard:

# Thread in #general · buzz://message?channel=<uuid>&id=<root-id>

> Older replies were not loaded.
> The session has ended.

**blu** · 2026-10-29 11:22:30 UTC
@Augustus ping

**Augustus** (agent) · 2026-10-29 11:23:42 UTC
@blu pong

> Activity: Augustus — Could not finish: sandbox restarted
Part Source
Heading Channel name (or "a direct message") and the root's buzz:// link
Notes Unloaded older or later replies, the history limit, an unavailable root, and the text of every registered thread banner (for example, remote workspace session state)
Messages Root, then loaded replies sorted by time. Author display name, (agent) for agents, UTC time, body as written (mentions stay @Name), then attachment URLs. Undelivered messages are marked not sent.
Activity Each agent's status on a message, with the same states as the activity bubble

The copy uses only what the panel has loaded and shows. It contains no keys, tokens, or telemetry payloads.

Implementation

  • message_copy::thread formats a LoadedThread. It is a pure function, so it is unit tested without the app.
  • ThreadPanel::copy_text builds the LoadedThread from the thread snapshot, the thread banner registry, and the agent activity observer.
  • Hooks::copy_thread and Actions::copy_thread show the menu entry only on pages that can copy a thread. Media comments also set in_thread, so in_thread is not used for this gate.
  • bubble::status gives an agent's status as text, consistent with the bubble.

Validation

  • cargo test -p buzz-gpui --features voltage-sandbox: new tests cover time order, the heading and link, notes, attachments, agent suffix, activity lines, an unavailable root, an unsent reply, name escaping, and the menu gate (root only, and only when the page provides the hook).
  • cargo clippy -p buzz-gpui --all-targets --locked --features voltage-sandbox -- -D warnings and cargo fmt --all --check pass.
  • Human-tested in a debug build (--features voltage-sandbox, Linux) on an #engineering agent thread: the copy had the heading and link, messages in time order with UTC times, (agent) suffixes, and tables and Markdown kept as written.

Limits

  • The thread header has no menu of its own. The header is the shared tab strip, so adding a menu there is a separate change.
  • The root message's menu in the channel view does not offer Copy thread, because the channel view has not loaded the replies.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a Copy thread option to eligible message menus. It copies the thread as Markdown, including messages, links, attachments, and available activity details.
    • Thread links now retain their thread context when copied.
  • Improvements
    • Activity bubbles show clearer status text, including “Working,” “Status unknown,” and “Could not finish” with an available error reason.

Adds "Copy thread" to the root message's menu in the thread panel. It
copies the loaded thread with the root's link, notes about unloaded
replies and thread banners, each message in time order with author and
UTC time, and each agent's activity status.

Closes #95

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tee8z <tee8z@protonmail.com>
@coderabbitai

coderabbitai Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Explain Change →

Caution

Review failed

The pull request is closed.

Walkthrough

Adds a Copy thread action to eligible message menus. The thread panel provides Markdown generated from loaded thread content, including message links, notes, attachments, and observed agent activity.

Changes: Thread copy

Layer / File(s) Summary
Copy thread action and dispatch
apps/buzz-gpui/crates/app/src/ui/message.rs, apps/buzz-gpui/crates/app/src/ui/message_actions.rs, apps/buzz-gpui/crates/app/src/external_plugins/message_view.rs, apps/buzz-gpui/crates/app/src/ui/channel.rs, apps/buzz-gpui/crates/app/src/ui/media/comments.rs
Adds the CopyThread command, an action flag, and an optional callback. The menu shows the action when enabled on a root message. The command copies callback text and shows a success notice when text is returned. Other hook initializers set the callback to None.
Thread Markdown formatting
apps/buzz-gpui/crates/app/src/ui/message_copy.rs, apps/buzz-gpui/crates/app/src/ui/agent_activity/bubble.rs, apps/buzz-gpui/crates/app/src/ui/markdown.rs
Adds a renderer for thread Markdown, with links, notes, ordered replies, message content, attachments, and activity. Adds helpers for author bylines, UTC timestamps, escaping, and quoting. Tests cover output content and ordering.
Thread panel content provider
apps/buzz-gpui/crates/app/src/ui/thread.rs
Adds a callback that builds Markdown from loaded thread content, channel details, member names, history notes, applicable banners, and observed agent statuses. It returns no text when the snapshot has no root or replies.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant MessageMenu
  participant MessageActions
  participant ThreadPanel
  participant MessageCopy
  participant Clipboard
  User->>MessageMenu: Select Copy thread
  MessageMenu->>MessageActions: Dispatch CopyThread
  MessageActions->>ThreadPanel: Request Markdown
  ThreadPanel->>MessageCopy: Render loaded thread
  MessageCopy-->>ThreadPanel: Return Markdown
  ThreadPanel-->>MessageActions: Return copy text
  MessageActions->>Clipboard: Copy text
Loading

Possibly related PRs

  • voltagecloud/buzz#56: Adds thread-scoped remote-session banners and recovery state, which the copied Markdown can include.

Suggested reviewers: thebrandonlucas

Merge Risk: Low · up to 5ce7c

Copying a thread opened from a reply can link to the reply and omit a registered thread banner. This is a bounded issue, but the root ID should be corrected.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@tee8z
tee8z marked this pull request as ready for review November 4, 2026 18:05
@tee8z
tee8z merged commit 995e579 into main Nov 4, 2026
46 of 47 checks passed
@tee8z
tee8z deleted the feat/gpui-copy-thread branch November 4, 2026 18:10
@tee8z

tee8z commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Action not completed

Pull request is closed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@tee8z

tee8z commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator Author

Native runtime verification completed for 5ce7c3a using the actual Linux GPUI client and an isolated local relay.

  • Opened a thread containing its root and two replies.
  • Activated Copy thread with the pointer, then with keyboard menu selection and Enter.
  • Read the actual system clipboard after each action. Both copies contained one root, both replies in order, UTC timestamps, and the exact root link.
  • Confirmed Copy message still copies only the selected message.
  • Resolved the copied deep link through the live relay CLI and recovered the same three messages.

Reviewed the diff against #95 and the activity vision. No blocking correctness, security, or agreed-contract findings. Minimalism 9/10; elegance 9/10; correctness 9/10. The declared root-menu-only scope remains explicit. Agent testing does not attest human app acceptance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copy a whole thread as Markdown from the Buzz app

2 participants