Skip to content

Commit bb348fd

Browse files
committed
fix: centralize OSC 52 clipboard support for SSH sessions (resolves #2773)
1 parent f8dc1a6 commit bb348fd

File tree

4 files changed

+16
-20
lines changed

4 files changed

+16
-20
lines changed

packages/opencode/src/cli/cmd/tui/app.tsx

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,6 @@ function App() {
200200
renderer.console.onCopySelection = async (text: string) => {
201201
if (!text || text.length === 0) return
202202

203-
const base64 = Buffer.from(text).toString("base64")
204-
const osc52 = `\x1b]52;c;${base64}\x07`
205-
const finalOsc52 = process.env["TMUX"] ? `\x1bPtmux;\x1b${osc52}\x1b\\` : osc52
206-
// @ts-expect-error writeOut is not in type definitions
207-
renderer.writeOut(finalOsc52)
208203
await Clipboard.copy(text)
209204
.then(() => toast.show({ message: "Copied to clipboard", variant: "info" }))
210205
.catch(toast.error)
@@ -627,11 +622,6 @@ function App() {
627622
}
628623
const text = renderer.getSelection()?.getSelectedText()
629624
if (text && text.length > 0) {
630-
const base64 = Buffer.from(text).toString("base64")
631-
const osc52 = `\x1b]52;c;${base64}\x07`
632-
const finalOsc52 = process.env["TMUX"] ? `\x1bPtmux;\x1b${osc52}\x1b\\` : osc52
633-
/* @ts-expect-error */
634-
renderer.writeOut(finalOsc52)
635625
await Clipboard.copy(text)
636626
.then(() => toast.show({ message: "Copied to clipboard", variant: "info" }))
637627
.catch(toast.error)

packages/opencode/src/cli/cmd/tui/routes/session/index.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -697,11 +697,6 @@ export function Session() {
697697
return
698698
}
699699

700-
const base64 = Buffer.from(text).toString("base64")
701-
const osc52 = `\x1b]52;c;${base64}\x07`
702-
const finalOsc52 = process.env["TMUX"] ? `\x1bPtmux;\x1b${osc52}\x1b\\` : osc52
703-
/* @ts-expect-error */
704-
renderer.writeOut(finalOsc52)
705700
Clipboard.copy(text)
706701
.then(() => toast.show({ message: "Message copied to clipboard!", variant: "success" }))
707702
.catch(() => toast.show({ message: "Failed to copy to clipboard", variant: "error" }))

packages/opencode/src/cli/cmd/tui/ui/dialog.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,6 @@ export function DialogProvider(props: ParentProps) {
141141
onMouseUp={async () => {
142142
const text = renderer.getSelection()?.getSelectedText()
143143
if (text && text.length > 0) {
144-
const base64 = Buffer.from(text).toString("base64")
145-
const osc52 = `\x1b]52;c;${base64}\x07`
146-
const finalOsc52 = process.env["TMUX"] ? `\x1bPtmux;\x1b${osc52}\x1b\\` : osc52
147-
/* @ts-expect-error */
148-
renderer.writeOut(finalOsc52)
149144
await Clipboard.copy(text)
150145
.then(() => toast.show({ message: "Copied to clipboard", variant: "info" }))
151146
.catch(toast.error)

packages/opencode/src/cli/cmd/tui/util/clipboard.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,21 @@ import { lazy } from "../../../../util/lazy.js"
55
import { tmpdir } from "os"
66
import path from "path"
77

8+
/**
9+
* Writes text to clipboard via OSC 52 escape sequence.
10+
* This allows clipboard operations to work over SSH by having
11+
* the terminal emulator handle the clipboard locally.
12+
*/
13+
function writeOsc52(text: string): void {
14+
if (!process.stdout.isTTY) return
15+
const base64 = Buffer.from(text).toString("base64")
16+
const osc52 = `\x1b]52;c;${base64}\x07`
17+
// tmux and screen require DCS passthrough wrapping
18+
const passthrough = process.env["TMUX"] || process.env["STY"]
19+
const sequence = passthrough ? `\x1bPtmux;\x1b${osc52}\x1b\\` : osc52
20+
process.stdout.write(sequence)
21+
}
22+
823
export namespace Clipboard {
924
export interface Content {
1025
data: string
@@ -123,6 +138,7 @@ export namespace Clipboard {
123138
})
124139

125140
export async function copy(text: string): Promise<void> {
141+
writeOsc52(text)
126142
await getCopyMethod()(text)
127143
}
128144
}

0 commit comments

Comments
 (0)