Skip to content

feat(remote): paste clipboard images into remote terminals#140

Open
matej21 wants to merge 2 commits into
mainfrom
feat/remote-image-paste
Open

feat(remote): paste clipboard images into remote terminals#140
matej21 wants to merge 2 commits into
mainfrom
feat/remote-image-paste

Conversation

@matej21

@matej21 matej21 commented Jun 15, 2026

Copy link
Copy Markdown
Member

Problem

Pasting a clipboard image into a remote-backed terminal was broken. TerminalPane::handle_paste wrote the image to the client's temp dir and sent that client-local path over the wire to the server's PTY — so the server-side process (e.g. Claude Code) got a path to a file that doesn't exist on it. Claude Code reads images by path, so this silently failed.

Local image paste already worked this way (write temp file → send_paste(path)); only the remote case was wrong.

Approach

Route remote image pastes over HTTP so the file is materialised where the terminal's process runs:

  1. Client captures the clipboard image (GPUI ClipboardEntry::Image) and, when the terminal is remote, uploads the bytes to POST /v1/terminals/{id}/paste-image instead of writing a local temp file.
  2. The server writes the bytes to its own temp dir and bracketed-pastes that path into the terminal — mirroring the local paste path, just across the wire — so the focused TUI's own paste handler attaches it.

Scope: remote desktop client (okena desktop connected to a remote okena server). Web/mobile clients are unchanged for now; they'd reuse the same endpoint via an onPaste handler.

Changes

  • okena-views-terminal: ActionDispatch::upload_remote_paste_image (default no-op); handle_paste short-circuits to it for remote terminals.
  • action_dispatch: strip the remote:{cid}: prefix and delegate to the connection manager.
  • okena-remote-client: RemoteConnectionManager::upload_paste_image — fire-and-forget HTTP upload, mirrors send_action.
  • remote server: new authenticated paste-image route (20 MiB body limit, overriding the global 1 MiB cap; clipboard PNGs routinely exceed 1 MiB) + RemoteCommand::PasteImageensure_terminal + send_paste on the GPUI thread.
  • enable tokio fs feature for the async temp-file write.

Testing

  • cargo clippy --workspace --all-targets -- -D warnings clean, cargo test green, CI passing.
  • New unit tests for the MIME→extension mapping (param tolerance + default).

Notes

  • Second commit (fix(lint)) is unrelated to this feature: the rust-toolchain.toml bump to 1.95.0 turned new clippy lints (collapsible_match, unnecessary_sort_by) into CI errors, which had already made main red. Mechanical, no behavior change — included here so this branch's CI is green; can be cherry-picked to main separately to un-red it sooner.
  • TLS parity caveat: the upload mirrors send_action, which builds an http:// URL with a plain reqwest::Client (no cert pinning). So like every other action, image upload won't work over a TLS connection with a self-signed pinned cert — a pre-existing limitation of the action transport, not a new regression. Happy to fix both in a follow-up.

🤖 Generated with Claude Code

matej21 and others added 2 commits June 13, 2026 14:21
Pasting an image into a remote-backed terminal wrote the image to the
client's temp dir and sent that client-local path to the server's PTY,
so the server-side process (e.g. Claude Code) couldn't find the file.

Route remote image pastes over HTTP instead: the desktop client uploads
the bytes to POST /v1/terminals/{id}/paste-image, the server writes them
to its own temp dir and bracketed-pastes that path into the terminal —
mirroring the local image-paste path, just across the wire.

- okena-views-terminal: ActionDispatch::upload_remote_paste_image (default
  no-op); TerminalPane::handle_paste short-circuits to it for remote terminals
- action_dispatch: strip the remote prefix, delegate to the manager
- okena-remote-client: RemoteConnectionManager::upload_paste_image (HTTP,
  mirrors send_action)
- remote server: paste-image route (20 MiB body limit) + RemoteCommand::PasteImage
  -> ensure_terminal + send_paste on the GPUI thread
- enable tokio "fs" feature for async temp-file writes

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The rust-toolchain.toml bump to 1.95.0 turned several new clippy lints
into CI errors (`cargo clippy --all-targets -- -D warnings`), failing the
Build workflow on main independently of any one change. Apply the
mechanical fixes:

- collapse nested `if let` into the outer `match` arm (collapsible_match)
- `sort_by(|a, b| b.k.cmp(&a.k))` -> `sort_by_key(|x| Reverse(x.k))`
  (unnecessary_sort_by)

No behavior change. Pre-existing on main; unrelated to the remote
image-paste feature on this branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant