Skip to content

Why Cinch

Most modern terminals support clipboard sharing via OSC 52 escape sequences. For interactive SSH sessions in a cooperating terminal, it works well.

But the escape sequence approach breaks in a surprisingly large number of real-world situations:

ScenarioOSC 52 status
Interactive SSH in iTerm2 / GhosttyWorks
SSH inside tmuxBroken — tmux intercepts the sequence
SSH inside GNU screenBroken
Docker exec / docker attachBroken — no terminal escape passthrough
CI/CD runner (GitHub Actions, etc.)Broken — non-interactive, no PTY
Older SSH servers (OpenSSH < 7.2)Broken — clipboard support not enabled
Nested SSH hopsBroken at the first hop
VS Code Remote SSHWorks sometimes, broken in others

Cinch doesn’t use terminal escape sequences at all. It’s just HTTP:

  1. cinch push sends the clip to a relay server over HTTPS.
  2. The relay holds the clip in SQLite until it is pulled.
  3. cinch pull (or cinchd) retrieves it over WebSocket for real-time delivery.

Because it’s HTTP, it works everywhere:

  • In non-interactive shells (no PTY required)
  • Inside Docker containers (just needs outbound HTTPS)
  • In CI runners (GitHub Actions, GitLab CI, etc.)
  • Across tmux, screen, and any multiplexer
  • Through any number of SSH hops

OSC 52 is push-only. Cinch supports both directions:

Terminal window
cinch push # local → relay → remote
cinch pull # relay → local clipboard

Push from a script running on a remote box. Pull the result on your laptop. Or the reverse — push from your laptop, pull inside a container.

Cinch is designed to be self-hosted. The relay is a single Go binary (or a Docker image) you run on any server. Your clips never leave infrastructure you control unless you opt into the hosted relay.

The protocol is documented in Relay Protocol. Anyone can inspect what the relay stores and for how long.