# How Nodeterm Handles System Clipboard Integration with Tmux

> Discover how Nodeterm integrates with tmux for system clipboard access. Learn about OSC 52 escape sequences and Electron's IPC for seamless copy-paste functionality.

- Repository: [eneskirca/nodeterm](https://github.com/eneskirca/nodeterm)
- Tags: how-to-guide
- Published: 2026-08-26

---

**Nodeterm achieves seamless clipboard integration by configuring tmux to emit OSC 52 escape sequences, which the renderer intercepts and forwards to the native system clipboard via Electron's IPC layer.**

Nodeterm is an Electron-based terminal manager that relies on tmux for session persistence. According to the `eneskirca/nodeterm` source code, the application solves cross-environment copy-and-paste by leveraging the **OSC 52** terminal protocol. This mechanism captures text selections from any tmux-backed terminal—local or remote—and writes them directly to the host operating system's clipboard.

## Configuring Tmux for Clipboard Emission

Nodeterm programmatically configures every tmux session to announce clipboard capabilities. When the **Pty manager** spawns a new terminal node, it injects configuration directives that enable OSC 52 emission.

### Pty Manager Setup in src/main/pty-manager.ts

The `spawnTmuxSession` function in [`src/main/pty-manager.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/main/pty-manager.ts) generates a tmux configuration containing two critical settings:

```typescript
await spawnTmuxSession({
  nodeId,
  cwd,
  tmuxConfig: `
    set -g set-clipboard on
    set -as terminal-features ",*:clipboard"
  `,
});

```

- **`set -g set-clipboard on`** enables tmux's internal clipboard support.
- **`set -as terminal-features ",*:clipboard"`** declares clipboard capability to the terminal client.

These settings are required for **tmux 3.2 and later**. They instruct tmux to generate an OSC 52 payload whenever a user selects text in copy mode, rather than storing the selection only in an internal buffer.

## The OSC 52 Protocol Mechanism

**OSC 52** (Operating System Command 52) is an escape sequence that allows terminal applications to write text to the system clipboard. When a user drag-selects text, tmux copies the selection internally and simultaneously emits this sequence to the attached client.

### Remote SSH Session Support in src/shared/ssh.ts

For remote sessions, the same mechanism applies without modification. A code comment in [`src/shared/ssh.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/shared/ssh.ts) clarifies the architecture:

> “Copy goes out as OSC 52, which the client’s handler writes to the **LOCAL** clipboard – this is the only thing that ever made copying work over SSH. It needs `terminal‑features ",*:clipboard"`."

Because the OSC 52 sequence travels from the remote tmux server to the local terminal emulator, the clipboard write always targets the user's local machine, bypassing the need for remote clipboard forwarding.

## Parsing and Writing Clipboard Data

The renderer process handles the incoming OSC 52 payload, decodes the base64-encoded text, and triggers the clipboard write through an Electron IPC channel.

### OSC 52 Parsing in src/renderer/terminal/osc52.ts

The `parseOsc52` function extracts the payload using a specific regex pattern that matches the OSC 52 structure:

```typescript
// src/renderer/terminal/osc52.ts
export function parseOsc52(payload: string): string | null {
  // Payload looks like: "\x1b]52;c;<base64>\x07"
  const m = /\x1b]52;(?<selection>c|p);(?<b64>[^?]*?)\x07/.exec(payload);
  if (!m?.groups?.b64) return null;
  return atob(m.groups.b64);   // Decode base64 → plain text
}

```

The function supports both the clipboard (`c`) and primary selection (`p`) targets, though Nodeterm primarily uses the clipboard target.

### Clipboard Write API in src/renderer/terminal/useCopyFeedback.ts

After parsing, the renderer invokes the clipboard write method exposed through the window context:

```typescript
// src/renderer/terminal/useCopyFeedback.ts
import { clipboard } from 'window.nodeTerminal';

// After receiving the OSC 52 text:
const text = parseOsc52(oscPayload);
if (text) {
  clipboard.writeText(text);   // Electron main process writes to OS clipboard
}

```

This call traverses the Electron **context bridge** to reach the main process, where the actual OS clipboard manipulation occurs.

## Main Process Integration

The main process registers IPC handlers to receive clipboard write requests from the renderer and executes them using Electron's native APIs.

### IPC Handler Registration in src/main/index.ts

The main entry point sets up a listener for `clipboard:write` events:

```typescript
// src/main/index.ts
ipcMain.on(IPC.clipboardWrite, (_e, text: string) => {
  if (typeof text === 'string') {
    clipboard.writeText(text);   // Electron API
  }
});

```

This handler validates the input and delegates to Electron's `clipboard.writeText`, which updates the system clipboard on macOS, Linux, and Windows.

### macOS File References in src/main/clipboard-files.ts

On macOS, Nodeterm extends clipboard support to file references through a separate IPC channel. The [`src/main/clipboard-files.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/main/clipboard-files.ts) module implements `clipboard:write-files` handling, allowing the terminal to copy file paths as native clipboard objects that Finder and other applications can recognize.

## Summary

- **Tmux configuration** in [`src/main/pty-manager.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/main/pty-manager.ts) enables OSC 52 emission via `set-clipboard on` and `terminal-features`.
- **OSC 52 parsing** occurs in [`src/renderer/terminal/osc52.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/terminal/osc52.ts), where base64-encoded text is decoded.
- **Clipboard writing** uses Electron IPC to bridge from renderer to main process, ensuring secure, native OS integration.
- **SSH compatibility** is inherent because OSC 52 sequences travel to the local terminal client, not the remote host.
- **File support** on macOS is handled separately in [`src/main/clipboard-files.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/main/clipboard-files.ts).

## Frequently Asked Questions

### How does nodeterm copy text to the system clipboard?

Nodeterm captures text selections by parsing OSC 52 escape sequences emitted by tmux. The renderer decodes the base64 payload and sends it to the main process via IPC, which then calls Electron's `clipboard.writeText` to update the native clipboard.

### Does nodeterm clipboard integration work over SSH?

Yes. Because tmux on the remote server emits OSC 52 sequences to the connected client, the local Nodeterm instance receives the text and writes it to the **local** system clipboard. This works without requiring X11 forwarding or remote clipboard synchronization.

### What is OSC 52 and why does nodeterm use it?

**OSC 52** is an ANSI escape sequence that allows terminal applications to write text to the system clipboard. Nodeterm uses it because it is the only protocol that reliably bridges clipboard data across SSH connections without additional configuration or network dependencies.

### Where is the clipboard handling code located in the nodeterm repository?

Key files include [`src/main/pty-manager.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/main/pty-manager.ts) for tmux configuration, [`src/renderer/terminal/osc52.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/terminal/osc52.ts) for sequence parsing, [`src/renderer/terminal/useCopyFeedback.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/terminal/useCopyFeedback.ts) for the renderer API, and [`src/main/index.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/main/index.ts) for the main process IPC handler that interfaces with Electron's clipboard module.