FIG 01 · HERO

Talk to tmux peer agents and generate images — six fixed tools, zero tool-budget creep

One Rust binary gives Claude Code a single outbound layer: message whatever runs in another tmux pane (Codex CLI, another Claude, a shell) and generate or edit images, all through six fixed MCP tools. Drivers plug in underneath, so new channels never inflate your tool listing.

/plugin marketplace add XBlueSky/cc-uplink
/plugin install cc-uplink@cc-uplink

v0.2.1 · one static Rust binary · MIT

tmux:%1 — claude
$ claude

Transcript: you ask codex, running in the pane next door, to review your diff via channel_send. cc-uplink delivers the request as one injected line in codex's terminal, carrying the exact reply command to run. Codex reviews three files, notes that retry.rs:41 swallows the error cause, and runs the reply command verbatim. The reply — "LGTM — one nit: retry.rs:41 swallows the error cause" — lands back in your own pane, correlation id matching the one you sent.

FIG 02 · SIGNAL JOURNEY

signal journey [4/4]

tmux:%1 — claude (you)
$ claude
> ask codex to review my diff
⏺ channel_send(to: "tmux:%3", message: "review my diff")
  ⎿ delivered · id:6b3b20e6 · injection verified
[reply id:6b3b20e6] LGTM — one nit: retry.rs:41 swallows the error cause
tmux:%3 — codex (peer)
▌idle
[uplink from:claude pane:%1 id:6b3b20e6] review my diff (reply: run `tmux send-keys -t %1 -l '[reply id:6b3b20e6] <your answer>' \; send-keys -t %1 Enter`)
> reading the envelope… reviewing 3 files
> retry.rs:41 swallows the error cause
$ tmux send-keys -t %1 -l '[reply id:6b3b20e6] LGTM — one nit: retry.rs:41 swallows the error cause' \; send-keys -t %1 Enter

A peer, in the pane next door

Whatever runs in another tmux pane — the Codex CLI, another Claude, a plain shell — is addressable. You ask in plain words; channel_send wraps it into an envelope. The peer installs nothing.

The notification is the message itself

cc-uplink injects one plaintext line into the peer's terminal — that line IS the notification. Its tail carries the exact command to reply with: a correlation id and a tmux send-keys back to your pane.

The peer answers by running what it was handed

codex does the review, then runs the reply command verbatim. No SDK, no webhook, no queue — the envelope was the protocol.

The reply lands in your pane, not in a queue

The [reply id:…] line arrives in your own pane, correlation id matching the one you sent. channel_recv stays an audit log — nothing to poll, ever.

FIG 03 · IMAGES

Same six tools, a completely different channel

Images go through the same fixed surface: one channel_invoke call. The image:codex driver shells out to Codex CLI's built-in imagegen under your ChatGPT login — no OpenAI API key anywhere — and hands back a file path on disk.

tmux:%1 — claude
> generate a hero image of a lighthouse for the README
⏺ channel_invoke(channel: "image:codex", op: "generate",
      args: { prompt: "a lighthouse in watercolour" })
  ⎿ codex exec → built-in imagegen (via your ChatGPT login — no API key)
  ⎿ paths: ["~/project/lighthouse.png"]
Watercolour lighthouse generated by the image:codex channel
fig. 3b — generated by image:codex

FIG 04 · TOOLS

Adding a driver adds zero tools

Drivers plug in underneath a fixed surface. However many ways Claude can reach the outside world, the tool listing stays exactly this long.

LISTDESCRIBESENDINVOKERECVDOCTORTMUXOPENAICODEX+ NEXT
  • channel_list
  • channel_describe
  • channel_send
  • channel_invoke
  • channel_recv
  • channel_doctor

fixed surface — 6 tools

  • tmux
  • image:openai
  • image:codex
  • …the next one

FIG 05 · DOCS

Read the contracts

The parts most tools hide are the parts this one documents.

FIG 06 · INSTALL

/plugin marketplace add XBlueSky/cc-uplink
/plugin install cc-uplink@cc-uplink

v0.2.1 · MIT · github.com/XBlueSky/cc-uplink