Skip to content

tui: Ctrl+V paste silently does nothing on GNOME Wayland + Nix #61092

Closed

Description

@andycostintoma

Description

Ctrl+V (prompt.paste) does nothing on my machine — no paste, no toast, no log line — for both text and images. Ctrl+Shift+V (terminal paste) still works for text, so the prompt itself is fine.

The clipboard read returns status unsupported, and the TUI maps that to "nothing to paste":

  • packages/tui/src/clipboard.ts: read() maps the service statuses unsupported, empty, and cancelled to return undefined; only failed, timed-out, and limit-exceeded throw.
  • packages/tui/src/component/prompt/index.tsx: enqueuePaste shows toast.error only for thrown errors, so unsupported produces zero feedback. ~/.local/share/opencode/log/opencode.log stays clean as well.

Why the read is unsupported here: GNOME's mutter has no zwlr_data_control_manager_v1/ext_data_control_manager_v1, and the native clipboard library's core wl_data_device fallback is WSL-only; the X11 fallback dlopens libxcb.so.1, which a Nix-linked process cannot resolve (host /lib64 is invisible to Nix's loader). Verified with a bun harness against @opentui/core 0.8.1: createHostClipboard().read({ preferredTypes: ["image/png","text/plain"], selection: "clipboard" }) returns {status:"unsupported"} with either text or an image on the clipboard.

Making those X11 libs visible to the Nix-built binary (prepend Nix libxcb/libXau/libXdmcp to LD_LIBRARY_PATH) makes the same 2.2.1 binary paste both text and images correctly — so the only opencode-side defect is the silence. Related: #49895 reports the same silent-undefined symptom class on WSL with the old external-tools implementation.

Suggested fix: treat unsupported as visible feedback — a toast or at least a debug log line naming the status, so a dead clipboard key is diagnosable.

Plugins

opencode-secrets, rtk, sound-notify, @tarquinen/opencode-dcp

OpenCode version

2.2.1

Steps to reproduce

  1. Install opencode via Nix on a GNOME Wayland desktop (mutter without data-control protocols).
  2. Put text on the clipboard (wl-copy hello).
  3. Open the TUI, focus the prompt, press Ctrl+V.
  4. Nothing happens: no paste, no toast, no log entry.
  5. Control: Ctrl+Shift+V (terminal paste) inserts the text; images cannot be pasted at all.

Expected: either the paste works (environment permitting) or an error/toast explains why it cannot.

Screenshot

A silent failure produces nothing to screenshot — the keypress has zero visible effect.

Operating System

Fedora 44 host, Nix-managed packages; GNOME Shell 50.4 on Wayland (mutter, Xwayland available)

Terminal

Ghostty 1.4.0

Activity

  1. opencodejr commented on Nov 1, 2026

    @opencodejr
    Contributor

    Thanks for the detailed report and the root-cause analysis. I could reproduce the silent failure.

    The sandbox has no display, so the native clipboard read returns {status: "unsupported"}, the same status you get on GNOME Wayland with Nix. On @opencode/[email protected] I typed into the prompt and pressed Ctrl+V twice. Nothing was pasted and no toast or other feedback appeared. The recording and screenshot below show this, and the script below reproduces it. It still happens on the latest dev (8c750e37): read() in packages/tui/src/clipboard.ts still returns undefined for unsupported, and prompt.paste treats that as "nothing to paste".

    I didn't test the Nix packaging side. From reading nix/opencode.nix, the wrapper adds only wayland to LD_LIBRARY_PATH and not the X11 libraries (libxcb, libXau, libXdmcp), which fits your finding. I've passed both points on to the maintainers.

    Related:

    recording.mp4

    Screenshot

    Reproduction script (drive.ts)
    // Repro for anomalyco/opencode#61092: Ctrl+V (prompt.paste) gives no feedback
    // when the host clipboard reports `unsupported`.
    // The sandbox has no DISPLAY / WAYLAND_DISPLAY, so the native clipboard read
    // returns { status: "unsupported" }, the same status the reporter gets on
    // GNOME Wayland + Nix.
    import { Effect } from "effect"
    import { OpenCodeDriver } from "opencode-drive"
    
    export default OpenCodeDriver.use(
      {
        ...(process.env.OC_DEV ? { opencode: { dev: process.env.OC_DEV } } : {}),
        tui: { recording: true, keypressOverlay: true },
      },
      ({ ui }) =>
        Effect.gen(function* () {
          yield* ui.screenshot("01-home")
          yield* ui.type("before paste: ")
          yield* ui.screenshot("02-typed")
          // prompt.paste
          yield* ui.press("v", { ctrl: true })
          yield* Effect.sleep("2 seconds")
          yield* ui.screenshot("03-after-ctrl-v")
          const frame = yield* ui.capture()
          const text = JSON.stringify(frame)
          const toast = /clipboard|paste|unsupported/i.test(text.replace(/before paste/g, ""))
          yield* Effect.log(`toast/feedback visible after Ctrl+V: ${toast}`)
          yield* ui.press("v", { ctrl: true })
          yield* Effect.sleep("2 seconds")
          yield* ui.screenshot("04-after-second-ctrl-v")
        }),
    )

    Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.

  2. jimmyallinai commented on Nov 1, 2026

    @jimmyallinai
    Contributor

    I'll take a look at this. Plan: reproduce at the adapter level (a stubbed clipboard read returning unsupported currently resolves to undefined, so prompt.paste stays silent), then make unsupported surface through the existing error path in packages/tui/src/clipboard.ts so the paste command shows a toast instead of doing nothing, keeping empty/cancelled silent. I'll add a regression test to packages/tui/test/clipboard.test.ts and run the tui clipboard tests plus typecheck before opening a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions