Skip to content

Spec: truthful clipboard copy (fix #4283) + durable workspace storage #53926

Description

@Bearmancer

Spec: Truthful clipboard copy in opencode TUI + durable workspace storage

Problem Statement

Selecting text in the opencode TUI shows a "Copied to clipboard" toast, but nothing reaches the system clipboard (#4283, 140 comments). The toast lies in every failure mode: Linux without a clipboard backend installed, SSH sessions where local tools cannot work, terminals without OSC52 support, and tmux without passthrough enabled. Users across Ubuntu, Mint, Arch, NixOS, WSL2, macOS, VSCode Remote, code-server, and Docker all report the same symptom with different root causes. Separately, development work on this fix is blocked by environment storage: /tmp is a 5.9GB tmpfs that filled to 80%, failing dependency installs with disk-quota errors.

Solution

Make clipboard copy truthful and single-pathed: copy via native OS tools on local sessions and via OSC52 on SSH sessions (never both by default), surface an actionable error naming the missing piece instead of a false success, keep the user's selection on failure so manual copy still works, prefer pbcopy on macOS to fix interpolation bugs, fix the tmux passthrough duplication, and add an explicit override. Document the full support matrix. For storage: relocate work off the tmpfs onto disk-backed storage and mount the 150GB OCI block volume as the durable workspace.

User Stories

  1. As an Ubuntu X11 user without xclip installed, I want the copy error to tell me the exact install command, so that one command fixes it.
  2. As a Wayland user, I want the error to name wl-clipboard instead of X11 tools, so that I install the right package.
  3. As a headless server user, I want to know clipboard needs either a display or OSC52, so that I stop reinstalling xclip pointlessly.
  4. As an SSH user, I want copy to go over OSC52 without attempting local xclip, so that remote copy works when my terminal supports it.
  5. As an SSH user whose terminal lacks OSC52, I want the error to name the terminal requirement plus a probe command, so that I can verify support myself.
  6. As a tmux user, I want the error to mention set -g allow-passthrough on, so that I fix the actual blocker.
  7. As an iTerm2 user, I want the error to mention the clipboard-access preference, so that I enable it.
  8. As a VSCode Remote user, I want copy to work or fail loudly, so that I am not misled by a success toast.
  9. As a code-server user, I want the documented Shift-select fallback, so that I can still copy when native integration is unavailable.
  10. As a Docker user, I want headless guidance (xvfb or OSC52), so that I know the supported paths.
  11. As a WSL2 user, I want the Windows-side clipboard to receive copies, so that paste works outside the terminal.
  12. As a macOS user copying hello${variable}world, I want the literal text copied, so that code survives the clipboard.
  13. As a macOS user doing multiline selection, I want no system alert sound and no appended duplicates, so that copy feels native.
  14. As a user with a slow or overshooting mouse drag, I want the selected text (not a stale buffer) copied, so that retry works.
  15. As a user who prefers terminal-native copy, I want a setting to disable copy-on-select, so that Shift-select plus Ctrl+Shift+C works.
  16. As a user who wants mouse tracking fully off, I want a documented toggle, so that standard terminal selection works.
  17. As a contributor, I want pure unit-testable helpers for mode, SSH detection, and hints, so that regressions are caught without a TUI harness.
  18. As a contributor, I want the existing clipboard test file extended rather than replaced, so that prior coverage is preserved.
  19. As a developer on this sandbox VM, I want dependency installs to succeed, so that tests can run.
  20. As a developer, I want the workspace on the mounted 150GB volume, so that work survives reboots and tmpfs pressure.
  21. As an operator, I want the volume mounted with fail-safe options, so that a detached volume never blocks boot.

Implementation Decisions

  • The TUI clipboard module is the single owner of copy strategy. It now resolves an explicit mode from environment (auto default, native, osc52) and detects SSH sessions from standard SSH environment markers.
  • Automatic routing is exclusive, not dual: SSH sessions use OSC52 only; local sessions use the native tool only. The previous always-both behavior caused duplicated/appended copies and alert sounds, and the maintainer already flagged it as wrong.
  • The copy operation keeps its existing async contract but now rejects with an actionable error (naming the missing tool, the install command, or the terminal prerequisite plus docs link) instead of silently succeeding. All existing success/error toast call sites become truthful with no interface change.
  • On macOS the native backend prefers the stdin-based clipboard setter over AppleScript string interpolation, which dropped ${...} sequences and broke on newlines and quotes. AppleScript remains only as a legacy fallback.
  • The tmux multiplexer wrapper now sends only the passthrough-wrapped sequence (previously it sent the raw sequence plus the wrapped one, producing double copies). Screen handling is unchanged in shape.
  • Selection-clearing moves into the success path: the user's highlight is preserved on failure so terminal-native copy remains possible.
  • New pure helpers (mode resolution, SSH detection, hint text, tool selection) are exported for unit testing; the cached tool probe gains a reset for test isolation.
  • Troubleshooting documentation gains the SSH/OSC52 checklist: terminal support table, tmux passthrough setting, iTerm2 preference, the one-line OSC52 probe, and the override variable.
  • Storage: the working trees move from the tmpfs-backed /tmp/opencode to disk-backed /home/ubuntu/work/opencode (done). The 150GB volume (currently Available, same availability domain as the instance) is attached via console to this instance, connected over iSCSI, verified empty via block inspection before any format, formatted once, mounted at /mnt/data with fail-safe mount options, and the workspace relocates there.

Testing Decisions

  • Only external behavior is tested, not implementation details: given an OS, tool availability, and session type, the right backend is chosen and failures name the remedy.
  • The existing clipboard test module is extended (prior art for tool-selection tests); new suites cover mode resolution, SSH-marker edge cases (including empty-string markers), and hint content.
  • An adversarial pass deliberately attacks the fix: empty SSH variables masking real ones, missing-backend silence, double-send duplication, interpolation payloads, and selection loss on failure. Findings from that pass are fixed before merge.
  • Integration coverage for the async copy operation uses environment manipulation plus cache reset; UI copy handlers are covered with fake renderer/toast/clipboard doubles asserting toast truthfulness and selection retention.
  • Full package tests and type checks run once dependencies install in the relocated workspace; the manual OSC52 probe matrix across terminals is recorded as evidence.

Out of Scope

  • The maintainer's long-term generalized copy routine in the UI framework.
  • A right-click context menu on selection.
  • Automatic detection of terminal OSC52 capability (terminals do not reliably advertise it).
  • Fixing OSC52 support inside third-party terminals.
  • Changes to clipboard image paths on any platform.
  • Migrating anything beyond the working trees to the new volume.

Further Notes

  • Evidence: all 140 issue comments reviewed and saved at work/opencode/evidence/4283-comments.txt (1321 lines); fix verified via standalone assertion run (17 checks) since the full harness needs dependency install.
  • Residual risks: a terminal that silently drops OSC52 still looks like success (undetectable programmatically); very long selections may truncate per terminal limits; mkfs must never run before the empty-volume check.
  • Open actions: user attaches oci-block-vol to this instance in console and shares the iSCSI details; dependency install then full test suite in the relocated workspace; reviewer briefs 17/18/20 plus verify index after work completes.
  • Tracker publishing pending: no write access to the upstream tracker and no triage vocabulary configured (run /setup-matt-pocock-skills); spec saved locally instead.

Activity

  1. opencode-agent commented on Oct 8, 2026

    @opencode-agent
    Contributor

    Thanks for putting this together! This reads as an AI-generated implementation spec rather than a bug report. Part of it (the tmpfs, the OCI block volume, iSCSI, mkfs) is about your own development VM and isn't something OpenCode can act on.

    To look into the clipboard problem, could you tell us briefly, in your own words:

    • Your OpenCode version (opencode --version)
    • Your OS, your terminal, and whether you're running locally, over SSH and/or inside tmux/screen
    • What you did, what you expected, and what actually happened (for example, the toast says "Copied to clipboard" but pasting gives old content), with any error message

    You can reply here with the details, or edit the issue. If you edit it, please also leave a comment saying you've updated it, so we know when you're done.

    These existing issues and PRs look closely related, ordered from most to least likely to cover your problem:

  2. opencode-agent commented on Oct 11, 2026

    @opencode-agent
    Contributor

    We're closing this issue for now because we haven't heard back. To work on the clipboard problem we needed your OpenCode version, your OS, terminal and session type (local, SSH or tmux), and a short description in your own words of what happened. The storage and VM parts of the spec are outside OpenCode, so we can't act on them here.

    The false "Copied to clipboard" toast is already tracked in #4283 and #41470, and the SSH/OSC52 case in #46377. You can follow those or add your details there. If your problem is different, feel free to open a new issue with the details above. Thanks!

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions