Skip to content

feat(desktop): quote selected terminal output into the composer - #58420

Merged
Brendonovich merged 2 commits into
betafrom
terminal-quote
Oct 23, 2026
Merged

Brendonovich merged 2 commits into
betafrom
terminal-quote

Conversation

@Brendonovich

@Brendonovich Brendonovich commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Brings timeline quoting (#55664) to the integrated terminal. Selecting output in a terminal shows the same floating Quote toolbar; clicking it adds a quote chip to the composer and focuses the prompt, and Alt/⌥-click opens the quote's comment editor instead.

Terminal side:

  • The terminal draws to a canvas, so the toolbar is placed from ghostty-web's selection position and cell metrics. One-line selections get it above, taller ones below their end, pinned to the terminal's bottom when neither fits. It follows scrolling, resizes and new output, and hides on a press or on typing (Cmd/Ctrl shortcuts such as copy keep it).
  • Same 20k character limit and "Selection too long" state as the timeline. Leading blank rows and trailing whitespace are trimmed.
  • The chip shows a terminal icon and "Terminal"; the model reads "The user quoted the following from the terminal:" and the > prefixed lines.

API: quotes become a proper composer part instead of something only the timeline can add.

  • ComposerQuote in the extension SDK: { type: "quote", commentID, text, comment?, source: { label, icon, subject } }. Composer.attach accepts it next to files and notes.
  • Composer.quotable(): false in child sessions and in shell mode, matching the timeline.
  • Composer.focus(commentID?): focuses the prompt, or opens an attached quote's comment editor.
  • Quotes carry an optional source through drafts, message metadata, revert and fork. Chips and the comment editor use its icon and label. Quotes without a source keep today's "from earlier in the conversation" wording, so existing drafts and messages are unchanged.

No keyboard shortcut yet: mod+L would be Ctrl+L (clear screen) on Windows and Linux.

Recording

Selecting build output in the terminal, quoting it, and asking about it from the composer.

terminal-quote.webm

How did you verify your code works?

  • bun typecheck in app, gui-extensions and session-ui, plus typecheck:tsc in gui-extensions. script/sdk-docs.ts passes, and oxlint and Prettier are clean on every changed file.
  • Extended the quote case in request.test.ts to cover a quote with a source (model text and sent metadata).
  • New case in the terminal keeper terminal-input.spec.ts: drag-select output, the Quote toolbar shows, clicking it adds a "Terminal" chip and focuses the prompt. The whole suite passes (10).
  • Not yet checked by hand in the desktop build; the recording is the dev web app against the mocked PTY.

Added by the opencode bot (AI-generated).

Related: #43758

Public API: adds ComposerQuote, Composer.quotable() and Composer.focus() to the extension SDK, and Composer.attach accepts quotes (backwards compatible)

@Brendonovich
Brendonovich requested a review from Hona as a code owner October 23, 2026 10:40

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find anything that should block this. I read the full diff, ran request.test.ts (it passes) and ran tsc -b in app, gui-extensions and session-ui (all clean). I couldn't try the terminal toolbar itself: it's in the desktop app's canvas terminal, which I can't drive here. Since the description says it hasn't been checked by hand yet, could you add a short video or before/after screenshots? Please cover where the toolbar appears for one-line and multi-line selections, Alt-click opening the comment editor, and how the chip looks in the composer and in the sent message.

Public API (extension SDK, packages/gui-extensions/src/sdk/host-apis.ts), all additions:

  • New ComposerQuote type: { type: "quote", commentID, text, comment?, source: { label, icon, subject } }.
  • Composer.attach(part) now also accepts ComposerQuote.
  • New Composer.quotable(): boolean, which is reactive.
  • New Composer.focus(commentID?).

The quote metadata stored with messages and drafts gains an optional source field. Quotes saved without it keep today's "from earlier in the conversation" wording. Existing extensions, drafts and messages are unaffected, so this is backwards compatible.

The code looks sound. source is carried through drafts, the submit snapshot, revert/fork, the model text and every place a quote chip is drawn. quotable() uses the composer's existing check for child sessions and shell mode, and terminals in hidden tabs don't show the toolbar.

Related: #43758

@Brendonovich
Brendonovich merged commit e335832 into beta Oct 23, 2026
10 of 15 checks passed
@Brendonovich
Brendonovich deleted the terminal-quote branch October 23, 2026 10:50

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new commit only adds the end-to-end case in terminal-input.spec.ts, and it's fine. It's small, checks what matters (one "Terminal" chip, the toolbar hidden, the prompt focused) and uses Playwright's auto-waiting rather than sleeps. I couldn't run it because Playwright browsers aren't installed here. Type-checking the e2e folder shows no errors in this file. The recording in the description covers the manual walkthrough I asked for last time. The public API is unchanged from my earlier review, and I have no new concerns.

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.

1 participant