Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion packages/opencode/src/cli/cmd/tui/util/clipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,34 @@ import clipboardy from "clipboardy"
import { lazy } from "../../../../util/lazy.js"
import { tmpdir } from "os"
import path from "path"
import fs from "fs"

/**
* Writes text to clipboard via OSC 52 escape sequence.
* This allows clipboard operations to work over SSH by having
* the terminal emulator handle the clipboard locally.
*
* Writes to /dev/tty directly to bypass terminal multiplexers
* (Zellij, tmux, screen) that intercept OSC52 on stdout.
*/
function writeOsc52(text: string): void {
if (!process.stdout.isTTY) return
const base64 = Buffer.from(text).toString("base64")
const osc52 = `\x1b]52;c;${base64}\x07`
const passthrough = process.env["TMUX"] || process.env["STY"]
const sequence = passthrough ? `\x1bPtmux;\x1b${osc52}\x1b\\` : osc52
process.stdout.write(sequence)

// Write to /dev/tty directly to bypass terminal multiplexers.
// SSH_TTY is set when connected via SSH, otherwise use /dev/tty.
const ttyPath = process.env["SSH_TTY"] || "/dev/tty"
try {
const fd = fs.openSync(ttyPath, "w")
fs.writeSync(fd, sequence)
fs.closeSync(fd)
} catch {
// Fallback to stdout if /dev/tty is unavailable (e.g., Windows)
process.stdout.write(sequence)
}
}

export namespace Clipboard {
Expand Down
Loading