Is there a safe way for me to use opencode plugins, in order to maybe leverage opentui in order to copy texxt from opencodes terminal into and out of a bubblewrap container?
Is there a safe way for me to use opencode plugins, in order to maybe leverage opentui in order to copy texxt from opencodes terminal into and out of a bubblewrap container?
Let me fetch information about opencode's plugin system and security considerations.
<skill_content name="developing-opencode-meta">
# Skill: developing-opencode-meta
<essential_principles>
This skill covers building extensions for **OpenCode**, an open-source AI coding assistant. OpenCode's plugin system allows customizing agents, tools, hooks, and more.
**1. Plugins are the extension mechanism**
Everything in OpenCode is extended through plugins. A plugin is a TypeScript function that returns configuration for agents, tools, hooks, and other features. Plugins can be distributed via npm.
**2. Agents define AI behaviour**
Agents are configured AI assistants with specific prompts, models, and tool access. OpenCode has two modes: `primary` (main agent) and `subagent` (delegated tasks). Agent prompts are full TypeScript strings, giving complete control.
**3. Hooks intercept lifecycle events**
Hooks let plugins react to events like tool execution, session creation, context limits, and more. They enable features like auto-compaction, TDD enforcement, and context monitoring.
**4. Tools extend agent capabilities**
Custom tools give agents new abilities. Tools are defined with Zod schemas for parameters and can access the plugin context for session management, file operations, etc.
**5. Skills work differently in OpenCode**
OpenCode can load Claude Code skills, but also has its own skill system. Skills in OpenCode are simpler — markdown files that agents can invoke for domain knowledge.
</essential_principles>
<never_do>
- NEVER export non-plugin functions from main index.ts (OpenCode calls ALL exports as plugins)
- NEVER use blocking `task()` calls for explore/librarian agents (always use `background_task`)
- NEVER allow subagents to spawn subagents without explicit design (can cause runaway delegation)
- NEVER skip the `tool.execute.before` hook when modifying tool arguments
- NEVER hardcode models — always accept model as parameter with sensible defaults
</never_do>
<escalation>
Stop and ask the user when:
- Unclear whether feature needs plugi...Based on my understanding of opencode's plugin system, here's my assessment:
Yes, it can be done safely, but requires careful design:
Plugin Architecture: Opencode plugins can create custom tools that agents use. You could build a plugin that provides a bubblewrapCopy tool that explicitly manages the security boundary.
Security Considerations:
Safer Approach: Instead of automatic clipboard sync, create a plugin that:
copyToSandbox and copyFromSandbox toolsAlternative: Consider if you actually need clipboard integration, or if file-based workflow (writing to shared volume) would suffice without breaking the security boundary.
Would you like me to help design the plugin architecture for this, or explore if there's a simpler approach to your workflow?
Yes, and I mean the clipboard integration could just use the shared volumes. And I like the idea of a shared volume, or maybe a unique keybind is needed in order to complete the copy
Let me clarify a few things about your use case:
Questions:
Direction: Do you need bidirectional copy, or primarily one direction (e.g., copying output from opencode into the container)?
Shared Volume Location: Where would the shared volume be mounted?
~/.cache/opencode-bubblewrap/shared//shared/Trigger: You mentioned a keybind - would you prefer:
/copy-to-sandbox or similar)Content: What text needs to be copied?
Proposed Design:
Plugin Architecture:
├── Tool: copyToSandbox(text: string) → writes to shared volume
├── Tool: copyFromSandbox() → reads from shared volume
├── Hook: keyboard shortcut handler (if keybind approach)
└── Config: shared volume path, confirmation prompts
The plugin would use a simple file-based protocol - write to a known file in the shared volume, then your bubblewrap container can read from that same path.
What are your preferences on the questions above? This will help me design the exact interface.
What is the difference between wl-clipboards primary clipboard, and regular clipboard?
Also what is the safes set of options for setting on wl-copy and wl-paste
Title: Clipboard in Wayland (Sway Spin): How does it work?
Published Date: 2025-01-09T00:00:00.000Z
URL: https://discussion.fedoraproject.org/t/clipboard-in-wayland-sway-spin-how-does-it-work/141904
Text: Clipboard in Wayland (Sway Spin): How does it work? - Fedora Discussion
🍪This website uses cookies to function. The compliance people asked us to tell you.[More information.]
Fine.
[Skip to main content]
[![Fedora Discussion]]
Sign UpLog In
* * ![:party:] **Welcome to Fedora Discussion!**![:category_chat:]
Check out the our**[guide to navigation: tags, categories, and concepts] **, or add to our**[tips and tricks] **.
# [Clipboard in Wayland (Sway Spin): How does it work?]
[Ask Fedora]
[wayland]
You have selected**0**posts.
[select all]
[cancel selecting]
[Jan 2025]
2 / 2
Jan 2025
[Jan 2025]
## post by bonfireatnight on Jan 9, 2025
[![]]
[Kai] [bonfireatnight]
[Jan 2025]
Today I came across the “primary selection” / “clipboard selection” (in regard to Helix registers). I know it has its origin in X11 and it made me wonder whether my Wayland setup with the Sway Spin uses something like this, too. Which led me down a bit of a rabbit hole.
Things I came across:
* There is wl-clipboard (I think installed by default), which comes with two command:`wl-copy`and`wl-paste`. I think it’s no integral part of Wayland and just some CLI utility to access the system clipboard (among other tools with the same purpose).
* There is Clipman (I think installed by default), which is a “full” clipboard manager. Among other things, it allows for copied text to persist even if the source application closes.
* `ps aux`tells me that`wl-copy`,`wl-paste`and`clipman`are running.
* There are different ways to interact with the clipboard (or various clipboards).`wl-copy`and`wl-paste`are a CLI way to do it. Helix register commands another. Many applications have key combinations like`CTRL+C`and`CTRL+V`.
What I was not able to figure out:
* What application or kind of applicati
...Title: Securing Clipboard Privacy on Wayland and Hyprland with a Custom wl-paste Script
Author: Julien Turbide
Published Date: 2025-09-30T00:00:00.000Z
URL: https://www.julienturbide.com/blog/wayland-hyprland-secure-clipboard-privacy
Text: Securing Clipboard Privacy on Wayland and Hyprland with a Custom wl-paste Script
![]
[![π]]
Blog
# Securing Clipboard Privacy on Wayland and Hyprland with a Custom wl-paste Script[]
**> TL;DR
**> : Wayland/Hyprland clipboard managers can leak secrets.
> **> Solution
**> :> Lower history size.> Wipe history on reboot.> Use a secure watcher script to block sensitive data.Disable clipboard history entirely for maximum security.
![Securing clipboard data on Wayland]
I’ve been running Wayland for a while now, specifically with Hyprland, and overall I’m really happy with the switch from X11. The rendering feels smoother, the security model is much stronger, and the compositors are catching up fast in terms of features.
But along the way I stumbled on a subtle problem: clipboard privacy.
The issue isn’t Wayland itself. In fact, Wayland is designed to be more secure than X11, applications don’t have the same free-for-all access to your clipboard content. The problem comes from how most users (myself included, at first) integrate clipboard managers like cliphist, clipman, copyq, or clipse into their workflow.
If you follow the official[Hyprland wiki on Clipboard Manager] integration, you’ll often see something like this in your config:
```
`# cliphistexec-once=wl-paste--watchcliphist store# clipmanexec-once=wl-paste-ttext--watchclipman store --no-persist# clipvaultexec-once=wl-paste--watchclipvault store# clipseexec-once=clipse-listen# copyqexec-once=copyq --start-server# wl-clip-persistexec-once=wl-clip-persist--clipboardregular`
```
**It’s convenient**. Every piece of text you copy is automatically added to your clipboard history, and you can later search or browse it with tools like rofi, fuzzel, or tofi.
**The problem**? Sometime
...Based on the search results, here's what you need to know:
| Selection | Purpose | Trigger |
|---|---|---|
| PRIMARY | Currently selected/highlighted text | Middle-click paste, selection |
| CLIPBOARD | Explicit copy/paste | Ctrl+C, Ctrl+V, menu commands |
In Wayland, these are separate clipboards. PRIMARY is the traditional X11 "select-to-copy" behavior, while CLIPBOARD is the modern explicit copy.
For sandbox/container use:
wl-copy:
--foreground - Don't daemonize, stays in foreground (safer)--paste-once - Content only pasteable once--clear - Clear clipboard after use--type text/plain - Restrict MIME type--trim-newline - Remove trailing newlinewl-paste:
--watch with a handler script that clears sensitive data--no-newline for cleaner output--type text/plain - Only accept plain textSecurity Concerns:
/tmp temporarily (issue #51)Recommendation: For bubblewrap integration, I'd suggest avoiding direct clipboard access and instead using the shared volume approach we discussed - it's more secure and auditable.
Got it - bidirectional.
Still need answers on:
2. Shared Volume Location: Where should it be mounted?
~/.cache/opencode-bubblewrap/shared/ or somewhere else?/shared/ or /mnt/shared/?3. Trigger: Which approach?
/copy-to-sandbox)4. Content: What text gets copied?
Let me know these and I'll draft the plugin architecture.
Trigger can be a keybind,
content is text received into opentui and sent through to the clipboard through it
Let me explore the codebase to understand the current structure and how opentui is used:
task_id: ses_3bc2ab737ffevsNDdwyouXoJkU (for resuming to continue this task if needed)
<task_result>
</task_result>/home/jm/data/code/opencode/packages/opencode/src/cli/cmd/tui/util/clipboard.ts
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/opencode/src/cli/cmd/tui/util/clipboard.tsNo files found<file>
00001| import { $ } from "bun"
00002| import { platform, release } from "os"
00003| import clipboardy from "clipboardy"
00004| import { lazy } from "../../../../util/lazy.js"
00005| import { tmpdir } from "os"
00006| import path from "path"
00007|
00008| /**
00009| * Writes text to clipboard via OSC 52 escape sequence.
00010| * This allows clipboard operations to work over SSH by having
00011| * the terminal emulator handle the clipboard locally.
00012| */
00013| function writeOsc52(text: string): void {
00014| if (!process.stdout.isTTY) return
00015| const base64 = Buffer.from(text).toString("base64")
00016| const osc52 = `\x1b]52;c;${base64}\x07`
00017| const passthrough = process.env["TMUX"] || process.env["STY"]
00018| const sequence = passthrough ? `\x1bPtmux;\x1b${osc52}\x1b\\` : osc52
00019| process.stdout.write(sequence)
00020| }
00021|
00022| export namespace Clipboard {
00023| export interface Content {
00024| data: string
00025| mime: string
00026| }
00027|
00028| export async function read(): Promise<Content | undefined> {
00029| const os = platform()
00030|
00031| if (os === "darwin") {
00032| const tmpfile = path.join(tmpdir(), "opencode-clipboard.png")
00033| try {
00034| await $`osascript -e 'set imageData to the clipboard as "PNGf"' -e 'set fileRef to open for access POSIX file "${tmpfile}" with write permission' -e 'set eof fileRef to 0' -e 'write imageData to fileRef' -e 'close access fileRef'`
00035| .nothrow()
00036| .quiet()
00037| const file = Bun.file(tmpfile)
00038| const buffer = await file.arrayBuffer()
00039| return { data: Buffer.from(buffer).toString("base64"), mime: "image/png" }
00040| } catch {
00041| } finally {
00042| await $`rm -f "${tmpfile}"`.nothrow().quiet()
00043| }
00044| }
00045|
00046| if (os === "win32" || release().includes("WSL")) {
00047| const script =
00048| ...Found 89 matches
/home/jm/data/code/opencode-trees/capnweb-session-transport/bun.lock:
Line 302: "@opentui/core": "0.1.77",
Line 303: "@opentui/solid": "0.1.77",
Line 328: "opentui-spinner": "0.0.6",
Line 1277: "@opentui/core": ["@opentui/core@0.1.77", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.77", "@opentui/core-darwin-x64": "0.1.77", "@opentui/core-linux-arm64": "0.1.77", "@opentui/core-linux-x64": "0.1.77", "@opentui/core-win32-arm64": "0.1.77", "@opentui/core-win32-x64": "0.1.77", "bun-webgpu": "0.1.4", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-lE3kabm6jdqK3AuBq+O0zZrXdxt6ulmibTc57sf+AsPny6cmwYHnWI4wD6hcreFiYoQVNVvdiJchVgPtowMlEg=="],
Line 1279: "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.77", "", { "os": "darwin", "cpu": "arm64" }, "sha512-SNqmygCMEsPCW7xWjzCZ5caBf36xaprwVdAnFijGDOuIzLA4iaDa6um8cj3TJh7awenN3NTRsuRc7OuH42UH+g=="],
Line 1281: "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.77", "", { "os": "darwin", "cpu": "x64" }, "sha512-/8fsa03swEHTQt/9NrGm98kemlU+VuTURI/OFZiH53vPDRrOYIYoa4Jyga/H7ZMcG+iFhkq97zIe+0Kw95LGmA=="],
Line 1283: "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.77", "", { "os": "linux", "cpu": "arm64" }, "sha512-QfUXZJPc69OvqoMu+AlLgjqXrwu4IeqcBuUWYMuH8nPTeLsVUc3CBbXdV2lv9UDxWzxzrxdS4ALPaxvmEv9lsQ=="],
Line 1285: "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.77", "", { "os": "linux", "cpu": "x64" }, "sha512-Kmfx0yUKnPj67AoXYIgL7qQo0QVsUG5Iw8aRtv6XFzXqa5SzBPhaKkKZ9yHPjOmTalZquUs+9zcCRNKpYYuL7A=="],
Line 1287: "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.77", "", { "os": "win32", "cpu": "arm64" }, "sha512-HGTscPXc7gdd23Nh1DbzUNjog1I+5IZp95XPtLftGTpjr...<file>
00001| import { createMemo } from "solid-js"
00002| import { useSync } from "@tui/context/sync"
00003| import { Keybind } from "@/util/keybind"
00004| import { pipe, mapValues } from "remeda"
00005| import type { KeybindsConfig } from "@opencode-ai/sdk/v2"
00006| import type { ParsedKey, Renderable } from "@opentui/core"
00007| import { createStore } from "solid-js/store"
00008| import { useKeyboard, useRenderer } from "@opentui/solid"
00009| import { createSimpleContext } from "./helper"
00010|
00011| export const { use: useKeybind, provider: KeybindProvider } = createSimpleContext({
00012| name: "Keybind",
00013| init: () => {
00014| const sync = useSync()
00015| const keybinds = createMemo(() => {
00016| return pipe(
00017| sync.data.config.keybinds ?? {},
00018| mapValues((value) => Keybind.parse(value)),
00019| )
00020| })
00021| const [store, setStore] = createStore({
00022| leader: false,
00023| })
00024| const renderer = useRenderer()
00025|
00026| let focus: Renderable | null
00027| let timeout: NodeJS.Timeout
00028| function leader(active: boolean) {
00029| if (active) {
00030| setStore("leader", true)
00031| focus = renderer.currentFocusedRenderable
00032| focus?.blur()
00033| if (timeout) clearTimeout(timeout)
00034| timeout = setTimeout(() => {
00035| if (!store.leader) return
00036| leader(false)
00037| if (!focus || focus.isDestroyed) return
00038| focus.focus()
00039| }, 2000)
00040| return
00041| }
00042|
00043| if (!active) {
00044| if (focus && !renderer.currentFocusedRenderable) {
00045| focus.focus()
00046| }
00047| setStore("leader", false)
00048| }
00049| }
00050|
00051| useKeyboard(async (evt) => {
00052| if (!store.leader && result.match("leader", evt)) {
00053| leader(true)
00054| ...Found 3 matches
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/opencode/src/cli/cmd/tui/app.tsx:
Line 175: onCopySelection: (text) => {
Line 202: // Wire up console copy-to-clipboard via opentui's onCopySelection callback
Line 203: renderer.console.onCopySelection = async (text: string) => {<file>
00001| import { render, useKeyboard, useRenderer, useTerminalDimensions } from "@opentui/solid"
00002| import { Clipboard } from "@tui/util/clipboard"
00003| import { TextAttributes } from "@opentui/core"
00004| import { RouteProvider, useRoute } from "@tui/context/route"
00005| import { Switch, Match, createEffect, untrack, ErrorBoundary, createSignal, onMount, batch, Show, on } from "solid-js"
00006| import { Installation } from "@/installation"
00007| import { Flag } from "@/flag/flag"
00008| import { DialogProvider, useDialog } from "@tui/ui/dialog"
00009| import { DialogProvider as DialogProviderList } from "@tui/component/dialog-provider"
00010| import { SDKProvider, useSDK } from "@tui/context/sdk"
00011| import { SyncProvider, useSync } from "@tui/context/sync"
00012| import { LocalProvider, useLocal } from "@tui/context/local"
00013| import { DialogModel, useConnected } from "@tui/component/dialog-model"
00014| import { DialogMcp } from "@tui/component/dialog-mcp"
00015| import { DialogStatus } from "@tui/component/dialog-status"
00016| import { DialogThemeList } from "@tui/component/dialog-theme-list"
00017| import { DialogHelp } from "./ui/dialog-help"
00018| import { CommandProvider, useCommandDialog } from "@tui/component/dialog-command"
00019| import { DialogAgent } from "@tui/component/dialog-agent"
00020| import { DialogSessionList } from "@tui/component/dialog-session-list"
00021| import { KeybindProvider } from "@tui/context/keybind"
00022| import { ThemeProvider, useTheme } from "@tui/context/theme"
00023| import { Home } from "@tui/routes/home"
00024| import { Session } from "@tui/routes/session"
00025| import { PromptHistoryProvider } from "./component/prompt/history"
00026| import { FrecencyProvider } from "./component/prompt/frecency"
00027| import { PromptStashProvider } from "./component/prompt/stash"
00028| import { DialogAlert } from "./ui/dialog-alert"
00029| import { ToastProvider, useToast } from "./ui/toast"
00030| import { Exit...Found 12 matches
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/sdk/openapi.json:
Line 8449: "KeybindsConfig": {
Line 9508: "$ref": "#/components/schemas/KeybindsConfig"
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/sdk/js/src/v2/gen/types.gen.ts:
Line 960: export type KeybindsConfig = {
Line 1641: keybinds?: KeybindsConfig
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/sdk/js/src/gen/types.gen.ts:
Line 772: export type KeybindsConfig = {
Line 1184: keybinds?: KeybindsConfig
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/opencode/src/config/config.ts:
Line 916: ref: "KeybindsConfig",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/opencode/src/cli/cmd/tui/context/keybind.tsx:
Line 5: import type { KeybindsConfig } from "@opencode-ai/sdk/v2"
Line 81: match(key: keyof KeybindsConfig, evt: ParsedKey) {
Line 91: print(key: keyof KeybindsConfig) {
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx:
Line 14: import type { KeybindsConfig } from "@opencode-ai/sdk/v2"
Line 25: keybind?: keyof KeybindsConfig<file>
00956|
00957| /**
00958| * Custom keybind configurations
00959| */
00960| export type KeybindsConfig = {
00961| /**
00962| * Leader key for keybind combinations
00963| */
00964| leader?: string
00965| /**
00966| * Exit the application
00967| */
00968| app_exit?: string
00969| /**
00970| * Open external editor
00971| */
00972| editor_open?: string
00973| /**
00974| * List available themes
00975| */
00976| theme_list?: string
00977| /**
00978| * Toggle sidebar
00979| */
00980| sidebar_toggle?: string
00981| /**
00982| * Toggle session scrollbar
00983| */
00984| scrollbar_toggle?: string
00985| /**
00986| * Toggle username visibility
00987| */
00988| username_toggle?: string
00989| /**
00990| * View status
00991| */
00992| status_view?: string
00993| /**
00994| * Export session to editor
00995| */
00996| session_export?: string
00997| /**
00998| * Create a new session
00999| */
01000| session_new?: string
01001| /**
01002| * List all sessions
01003| */
01004| session_list?: string
01005| /**
01006| * Show session timeline
01007| */
01008| session_timeline?: string
01009| /**
01010| * Fork session from message
01011| */
01012| session_fork?: string
01013| /**
01014| * Rename session
01015| */
01016| session_rename?: string
01017| /**
01018| * Delete session
01019| */
01020| session_delete?: string
01021| /**
01022| * Delete stash entry
01023| */
01024| stash_delete?: string
01025| /**
01026| * Open provider list from model dialog
01027| */
01028| model_provider_list?: string
01029| /**
01030| * Toggle model favorite status
01031| */
01032| model_favorite_toggle?: string
01033| /**
01034| * Share current session
01035| */
01036| session_share?: string
01037| /**
01038| * Unshare current session
01039| */
01040| session_unshare?: string
01041| /**
01042| * Inte...Found 17 matches
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/zht.ts:
Line 56: "ui.textField.copyToClipboard": "複製到剪貼簿",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/zh.ts:
Line 56: "ui.textField.copyToClipboard": "复制到剪贴板",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/th.ts:
Line 53: "ui.textField.copyToClipboard": "คัดลอกไปยังคลิปบอร์ด",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/ru.ts:
Line 52: "ui.textField.copyToClipboard": "Копировать в буфер обмена",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/da.ts:
Line 52: "ui.textField.copyToClipboard": "Kopier til udklipsholder",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/pl.ts:
Line 52: "ui.textField.copyToClipboard": "Skopiuj do schowka",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/bs.ts:
Line 48: "ui.textField.copyToClipboard": "Kopiraj u međuspremnik",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/no.ts:
Line 55: "ui.textField.copyToClipboard": "Kopier til utklippstavlen",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/br.ts:
Line 52: "ui.textField.copyToClipboard": "Copiar para área de transferência",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/ko.ts:
Line 52: "ui.textField.copyToClipboard": "클립보드에 복사",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/ja.ts:
Line 52: "ui.textField.copyToClipboard": "クリップボードにコピー",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/fr.ts:
Line 52: "ui.textField.copyToClipboard": "Copier dans le presse-papiers",
/home/jm/data/code/opencode-trees/capnweb-session-transport/packages/ui/src/i18n/es.ts:
Line 52: ...Based on my exploration, I now understand the architecture. Here's my assessment:
The codebase already has:
clipboard.ts) - uses wl-copy/wl-paste on LinuxKeybindsConfig type with leader-key support app.tsx for Ctrl+Y copyingPlugin Approach (not needed - can integrate directly):
Since this is opencode itself, we can add the feature directly:
Architecture:
├── KeybindsConfig: Add `copy_to_sandbox` keybind
├── New util: shared-volume.ts (file-based IPC)
├── Modify: app.tsx - add keybind handler
└── Config: Shared volume path (~/.cache/opencode/shared/)
Flow:
<leader>cs)~/.cache/opencode/shared/clipboard.txtSecurity:
Questions for you:
~/.cache/opencode/shared/ or do you prefer elsewhere?<leader>cs (copy to sandbox), <leader>ps (paste from sandbox)?/shared/ or do you want it configurable?Should I proceed with implementing this?
No, but I will save it. Thank you mate :)
No worries! Save the notes for when you're ready.
Just a quick summary of what we'd build:
<leader>cs / <leader>ps (copy/paste to sandbox)~/.cache/opencode/shared/clipboard.txtFeel free to come back when you want to implement it!