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
- 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.
- As a Wayland user, I want the error to name wl-clipboard instead of X11 tools, so that I install the right package.
- As a headless server user, I want to know clipboard needs either a display or OSC52, so that I stop reinstalling xclip pointlessly.
- 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.
- 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.
- As a tmux user, I want the error to mention
set -g allow-passthrough on, so that I fix the actual blocker.
- As an iTerm2 user, I want the error to mention the clipboard-access preference, so that I enable it.
- As a VSCode Remote user, I want copy to work or fail loudly, so that I am not misled by a success toast.
- As a code-server user, I want the documented Shift-select fallback, so that I can still copy when native integration is unavailable.
- As a Docker user, I want headless guidance (xvfb or OSC52), so that I know the supported paths.
- As a WSL2 user, I want the Windows-side clipboard to receive copies, so that paste works outside the terminal.
- As a macOS user copying
hello${variable}world, I want the literal text copied, so that code survives the clipboard.
- As a macOS user doing multiline selection, I want no system alert sound and no appended duplicates, so that copy feels native.
- As a user with a slow or overshooting mouse drag, I want the selected text (not a stale buffer) copied, so that retry works.
- 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.
- As a user who wants mouse tracking fully off, I want a documented toggle, so that standard terminal selection works.
- As a contributor, I want pure unit-testable helpers for mode, SSH detection, and hints, so that regressions are caught without a TUI harness.
- As a contributor, I want the existing clipboard test file extended rather than replaced, so that prior coverage is preserved.
- As a developer on this sandbox VM, I want dependency installs to succeed, so that tests can run.
- As a developer, I want the workspace on the mounted 150GB volume, so that work survives reboots and tmpfs pressure.
- 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.
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:
/tmpis 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
pbcopyon 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
set -g allow-passthrough on, so that I fix the actual blocker.hello${variable}world, I want the literal text copied, so that code survives the clipboard.Implementation Decisions
autodefault,native,osc52) and detects SSH sessions from standard SSH environment markers.${...}sequences and broke on newlines and quotes. AppleScript remains only as a legacy fallback./tmp/opencodeto 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/datawith fail-safe mount options, and the workspace relocates there.Testing Decisions
Out of Scope
Further Notes
work/opencode/evidence/4283-comments.txt(1321 lines); fix verified via standalone assertion run (17 checks) since the full harness needs dependency install.mkfsmust never run before the empty-volume check.oci-block-volto 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./setup-matt-pocock-skills); spec saved locally instead.