Summary
Port cmux's "drop/paste image → file → inject path" feature to limux so images can be pasted or dropped into a terminal running an agent CLI (Claude Code, Codex, etc.), including over SSH.
Today a pasted screenshot is dropped or turned into garbage: image bytes can't ride a PTY, and a TUI like Claude Code can't receive them. cmux solves this by intercepting the paste/drop client-side, writing the PNG to a real file, and injecting the file path as plain text. The agent's file-read tool then opens a real local file. No image bytes ever travel through the terminal stream.
How cmux does it (reference)
limux current state
- File drag-drop from a file manager works:
DropTarget<FileList> in terminal.rs (~1830) pastes shell-escaped file paths via ghostty_surface_text.
clipboard_formats_include_image helper exists in terminal.rs (~979) but is only used in a test — never wired into paste/drop.
- No clipboard image paste handling, and no image byte drop handling (only
FileList).
- Nothing detects the foreground process / SSH target of a pane.
So the feature does not exist. This is a net-new port.
Proposed design
Milestone 1 — Local (small, ships independently)
- Paste: on the terminal paste path, if the clipboard offers an image format (reuse
clipboard_formats_include_image), read the GdkTexture, encode PNG, write /tmp/limux-drop-<uuid>.png, inject the shell-escaped path via ghostty_surface_text (same sink the file-drop already uses).
- Drop: extend the
terminal.rs DropTarget to also accept GdkTexture / image MIME types (currently FileList only); same write-file-and-inject path.
- Path injection mirrors
dropped_file_text (shell-escaping).
Works for agents running on the same machine as limux. Self-contained; good first PR.
Milestone 2 — SSH parity (the harder part)
Mirror cmux:
- Detect the pane's foreground process by TTY. Find the controlling pty of the ghostty surface, then the foreground process group leader; if it's
ssh, parse the target (user@host, -p port, -o opts, host alias). (limux already does /proc scanning in claude_session.rs::find_tab_claude_pid — same technique applies.)
- Upload over the existing connection.
scp/sftp the PNG to remote /tmp/limux-drop-<uuid>.png reusing the user's SSH ControlMaster socket so there's no re-auth. Likely requires limux to ensure ssh invocations use ControlMaster=auto + a known ControlPath (inject -o defaults, or document/config it).
- Inject the remote path as text.
- Fallback to local (Milestone 1) when the foreground process isn't ssh.
Integration points
rust/limux-host-linux/src/terminal.rs — paste handling + DropTarget (extend ~1830), reuse clipboard_formats_include_image, write-file helper, ghostty_surface_text injection.
- New helper module (or extend
claude_session.rs) for /proc foreground + ssh-target detection.
- Possibly
control_bridge if we want a CLI surface for it.
Open questions / risks
- PTY/TTY access: ghostty owns the pty; limux doesn't currently track the surface's child pid/tty. Need a way to get it (ghostty FFI accessor?
ghostty_surface_pwd exists for cwd — check for a pid/tty accessor, else derive). This is the main feasibility unknown for M2.
- ControlMaster: relies on the user's ssh using connection multiplexing; otherwise scp re-prompts/fails. Decide: inject
-o ControlMaster=auto -o ControlPath=~/.ssh/limux-%r@%h:%p into ssh, or require user config.
- Auth: agent forwarding / ControlMaster reuse so scp doesn't prompt.
- Security: writing to remote
/tmp; cleanup of stale drop files; size limits.
- Agent read access: the agent must be allowed to Read
/tmp/*-drop-*.png.
Plan
Once M1 lands and the M2 spike confirms feasibility, open PR(s). Upstreaming to am-will/limux after it works in dev.
Summary
Port cmux's "drop/paste image → file → inject path" feature to limux so images can be pasted or dropped into a terminal running an agent CLI (Claude Code, Codex, etc.), including over SSH.
Today a pasted screenshot is dropped or turned into garbage: image bytes can't ride a PTY, and a TUI like Claude Code can't receive them. cmux solves this by intercepting the paste/drop client-side, writing the PNG to a real file, and injecting the file path as plain text. The agent's file-read tool then opens a real local file. No image bytes ever travel through the terminal stream.
How cmux does it (reference)
/tmp/cmux-drop-<uuid>.png, injects the local path.scprouted through the existing SSH connection's ControlMaster multiplexing (no re-auth), writing to the remote box, and injects the remote path. The path resolves where the agent actually runs.limux current state
DropTarget<FileList>interminal.rs(~1830) pastes shell-escaped file paths viaghostty_surface_text.clipboard_formats_include_imagehelper exists interminal.rs(~979) but is only used in a test — never wired into paste/drop.FileList).So the feature does not exist. This is a net-new port.
Proposed design
Milestone 1 — Local (small, ships independently)
clipboard_formats_include_image), read theGdkTexture, encode PNG, write/tmp/limux-drop-<uuid>.png, inject the shell-escaped path viaghostty_surface_text(same sink the file-drop already uses).terminal.rsDropTargetto also acceptGdkTexture/ image MIME types (currentlyFileListonly); same write-file-and-inject path.dropped_file_text(shell-escaping).Works for agents running on the same machine as limux. Self-contained; good first PR.
Milestone 2 — SSH parity (the harder part)
Mirror cmux:
ssh, parse the target (user@host,-p port,-oopts, host alias). (limux already does /proc scanning inclaude_session.rs::find_tab_claude_pid— same technique applies.)scp/sftpthe PNG to remote/tmp/limux-drop-<uuid>.pngreusing the user's SSH ControlMaster socket so there's no re-auth. Likely requires limux to ensure ssh invocations useControlMaster=auto+ a knownControlPath(inject-odefaults, or document/config it).Integration points
rust/limux-host-linux/src/terminal.rs— paste handling +DropTarget(extend ~1830), reuseclipboard_formats_include_image, write-file helper,ghostty_surface_textinjection.claude_session.rs) for /proc foreground + ssh-target detection.control_bridgeif we want a CLI surface for it.Open questions / risks
ghostty_surface_pwdexists for cwd — check for a pid/tty accessor, else derive). This is the main feasibility unknown for M2.-o ControlMaster=auto -o ControlPath=~/.ssh/limux-%r@%h:%pinto ssh, or require user config./tmp; cleanup of stale drop files; size limits./tmp/*-drop-*.png.Plan
Once M1 lands and the M2 spike confirms feasibility, open PR(s). Upstreaming to am-will/limux after it works in dev.