Skip to content

bug(terminal): cannot copy/paste from the zellij session terminal — no clipboard wiring in XtermTerminal #305

@neversettle17-101

Description

@neversettle17-101

Bug

Text cannot be copied from (or reliably pasted into) the in-app session terminal that attaches to zellij. The xterm.js surface is constructed with several addons but no clipboard integration is wired anywhere in the frontend, so a user has no working path to copy the agent/terminal output.

Source: reported via /bug-triage | Analyzed against: 73b166a (origin/main)
Platform observed: macOS (Darwin) — cross-platform impact flagged below
Confidence: High (mechanism traced); Medium on the exact failing interaction (see Open Questions)

Reproduction

  1. Open a worker/session and focus the embedded terminal (XtermTerminal, attached via /mux to zellij attach).
  2. Drag the mouse to select text → no selection appears (the drag is consumed by zellij).
  3. Try Cmd/Ctrl+C to copy, or Cmd/Ctrl+V to paste → nothing is copied to the system clipboard.

Root Cause

frontend/src/renderer/components/XtermTerminal.tsx loads FitAddon, Unicode11Addon, WebLinksAddon, SearchAddon, and the WebGL/Canvas renderer — but no clipboard handling:

  • xterm.js does not copy-on-select and does not bind Cmd/Ctrl+C to copy by default. The embedding app must do it (e.g. term.attachCustomKeyEventHandler + navigator.clipboard.writeText(term.getSelection()), a copy-on-select handler, or @xterm/addon-clipboard). None of these exist anywhere in frontend/src (grep for navigator.clipboard, attachCustomKeyEventHandler, addon-clipboard, getSelection → no matches). @xterm/addon-clipboard is not in frontend/package.json.
  • xterm.js selection is an internal model rendered to canvas, not a DOM selection, so the OS/Electron default "Copy" never captures it. frontend/src/main.ts also defines no custom application Menu, so there are no explicit copy/paste roles either.
  • Selection itself is blocked by design: the PTY runs zellij attach, a full-screen alt-buffer app with SGR mouse tracking enabled (see the scrollback: 0 comment, XtermTerminal.tsx:119-125). With mouse reporting on, a plain mouse drag is sent to zellij as mouse events rather than used for local selection. xterm.js only forces local selection on Shift+drag, which is undiscoverable and still copies nothing without the wiring above.

This appears to be a port gap: the component header notes it was "ported from yyork's terminal architecture," and per DESIGN.md the renderer clones the agent-orchestrator web app — the reference terminal almost certainly wires clipboard handling that wasn't carried over.

Fix

In XtermTerminal.tsx, wire clipboard handling on the constructed Terminal. Recommended minimal approach:

  • term.attachCustomKeyEventHandler to handle Cmd/Ctrl+C (and Cmd/Ctrl+Shift+C) → if term.hasSelection(), navigator.clipboard.writeText(term.getSelection()) and swallow the event; otherwise let it pass through to the PTY (so Ctrl+C still sends SIGINT when there's no selection).
  • Handle paste → navigator.clipboard.readText() then term.paste(text) / forward via onData, or rely on xterm's built-in paste DOM event (verify it fires under Electron on all platforms).
  • Consider a copy-on-select option and/or a right-click context menu, and document that Shift+drag is required to select while zellij mouse mode is active.

Cross-platform: verify on Windows/Linux — there is no default Electron menu bar there, so any reliance on native Edit-menu accelerators will not exist; explicit key handling is required regardless.

Impact

  • Users cannot copy command output, errors, URLs, or diffs out of the session terminal — a basic and frequently-needed terminal interaction in a terminal-centric app.
  • No workaround beyond external screen-scraping; Shift+drag selects but still cannot be copied.

Related

  • #280 — "Codex Terminal is sort of clipped. can't write, can't scroll." (same terminal subsystem)
  • #294 — "Add a reload shell button" (terminal UX)

Open Questions

  • Which interaction(s) specifically fail for the reporter: copy, paste, or both? (Assumed both.)
  • Exact OS/build where observed (assumed macOS from the reporting environment).

Metadata

Metadata

Labels

bugSomething isn't workingpriority: mediumFix when convenient

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions