Skip to main content

OSC 52: How to use `pbcopy` over SSH

Keep GitHub credentials off a remote machine while letting an AI agent copy a PR body into your local pasteboard.

· 4 min read

TL;DR

A remote pbcopy cannot reach the local pasteboard. OSC 52 sends Base64-encoded clipboard data through the terminal stream, so an agent can prepare a PR body remotely while GitHub access stays local.

On this page

The Remote PR Body Problem

I sometimes work in a repository that lives on a remote machine, with an interactive agent such as Claude Code, Codex, or pi running beside the code. The agent can inspect a diff, run the test suite, and write a probably better pull-request description than I could be bothered to come up with nowadays, using the templates enforced by my repositories. There are however security scenarios in which giving the remote host access to my GitHub credentials is undesirable.

In those cases, the remote machine can prepare a PR body while the GitHub CLI (gh), its authentication, and the final review step stay local. I only need the agent to put its Markdown in my local pasteboard, ready to paste into GitHub or a local gh pr create command.

The usual commands you’d use to copy data to the paste buffer, like pbcopy, fall short on SSH. Though I didn’t think much about it at first, this fails for a fairly obvious reason. A command running through SSH can only reach the clipboard of the remote host. Most servers have no graphical pasteboard at all, and installing an equivalent command there would not create a path back to my Mac.

OSC 52 Clipboard Path

Click a stage to follow one PR body from a remote agent to the local pasteboard. The clipboard boundary stays at the terminal emulator.

remote host

The agent can inspect the repository and compose Markdown, but it has no GitHub credential and no access to the local Mac pasteboard.

The Terminal Is the Bridge

OSC means “Operating System Command”, a family of terminal control sequences. OSC 52 is the member that carries clipboard data. Its shape is compact:

ESC ] 52 ; c ; <Base64 payload> BEL

c means the standard clipboard. The payload is Base64, not encryption. It gives the terminal a text-safe representation of arbitrary UTF-8 bytes, which avoids control characters accidentally ending the sequence. When the terminal emulator receives the complete sequence, it decodes the payload and writes it to the local clipboard.

This works over SSH because the terminal stream is already the path between the remote process and the local emulator. The sequence is just another set of bytes travelling alongside prompts, colours, and command output. The remote machine never calls a macOS API; the local terminal performs the clipboard write after receiving the sequence.

xterm’s control-sequence reference defines OSC 52 as selection manipulation with Base64 data that becomes available for pasting. Terminal emulators interpret the sequence as a request to write clipboard data. PowerShell makes the same distinction explicitly: its Set-Clipboard -AsOSC52 option targets the local host during an SSH session.

OSC 52 Frame Inspector

Edit the PR body to see the payload the remote helper sends. This widget shows printable escape names only. It never writes an OSC 52 sequence to your clipboard.

OSC 52 frame
ESC ] 52 ; c ; IyMgV2hhdCBjaGFuZ2VkCgpQcmV2ZW50IHRoZSByZXRyeSB3b3JrZXIgZnJvbSBzdGFydGluZyB0d2ljZSB3aGVuIHRoZSBwcm9jZXNzIHJlY2VpdmVzIHR3byBzdGFydHVwIHNpZ25hbHMuCgojIyBWZXJpZmljYXRpb24KCnBucG0gdGVzdA== BEL
Scroll to inspect the full frameend: YXRpb24KCnBucG0gdGVzdA==
136 UTF-8 bytes
184 Base64 characters

ESC ] opens an operating-system command.

52 ; c selects OSC 52 and the standard clipboard.

BEL terminates the command after the Base64 payload.

A Remote pbcopy That Writes to the Right Place

I use a small shell function on the remote host. It keeps the familiar pbcopy interface, but writes the OSC 52 sequence directly to the interactive SSH terminal named by $SSH_TTY.

~/.zshrc on the remote machine
pbcopy() {
  if [ -z "${SSH_TTY:-}" ]; then
    printf '%s\n' "pbcopy: OSC 52 needs an interactive SSH session" >&2
    return 1
  fi

  encoded=$(base64 | tr -d '\n') || return 1
  printf '\033]52;c;%s\007' "$encoded" > "$SSH_TTY"
}

Writing to $SSH_TTY matters. An agent runner may capture, annotate, or redirect a command’s ordinary stdout; the pseudo-terminal is the channel the human is actually watching. The function also refuses to run outside an interactive SSH session, rather than silently sending terminal control bytes into a log or a file.

After reloading the shell configuration, an agent can use a heredoc exactly as it would with macOS pbcopy:

Copy a generated PR body from the remote host
pbcopy <<'EOF'
## What changed

Prevent the retry worker from starting twice when the process receives two startup signals.

## Verification

pnpm test
EOF

The Markdown appears in the local pasteboard. I can review it, edit it, and paste it into GitHub without placing a GitHub token or gh configuration on the remote system.

When OSC 52 Fits

scp can bring a file home, but adds a manual retrieval step for a few lines of prose. X11 forwarding can expose a remote program to a display server, but it adds a graphical channel and broader permissions when the only requirement is one clipboard write. Installing gh remotely would let the agent create the PR directly, but removes the security separation that motivated the workflow.

This workflow fits when all of these are true:

  • The text originates in an interactive terminal session.
  • The local terminal emulator allows OSC 52 clipboard writes.
  • The remote host is trusted to ask for that write.
  • The clipboard should remain local, without forwarding a GUI session or remote GitHub credentials.

Ghostty, my favourite terminal emulator, supports OSC 52 and recognises the c clipboard target used above.