Motivation
Copying a file in GoLand (or Finder) and pressing ⌘V over a Runner terminal inserts nothing. Every native terminal — Terminal.app, iTerm2, Ghostty — inserts the file's POSIX path instead, which is how you hand an agent a file without typing its path.
A file copy puts no text on the clipboard: it writes public.file-url / NSFilenamesPboardType to NSPasteboard, and native terminals read those flavors explicitly. Across the WKWebView boundary the paste arrives as a File in DataTransfer with unusable text/plain, so xterm.js's default paste inserts nothing.
Runner already intercepts paste for this exact class of problem — RunnerTerminal.tsx:749 handles image paste by shipping bytes to Rust to restore the NSPasteboard flavor (#79). A non-image file falls through: inferPasteImageMime returns null, the loop continues, and the handler returns without preventDefault. The gap is one branch wide.
The web layer can't close it alone — DataTransfer withholds filesystem paths (File.name is only the basename, and WKWebView exposes no file.path), so the path must come from the native pasteboard.
Scope
- ⌘V over a terminal pane with file references on the clipboard inserts the absolute path at the cursor, shell-quoted; multiple files insert space-separated.
- Text and image pastes keep today's behavior exactly.
- Out of scope: drag-and-drop of files onto a pane (different Tauri mechanism, its own spec), directory contents, cwd-relative rewriting.
Key decisions
- Read paths in Rust via NSPasteboard —
commands/session.rs:144-165 already has the plumbing and objc2-app-kit is already a dependency.
- Branch inside the existing
onPaste handler; empty native result falls through untouched.
- Prefer the native read over
text/uri-list, whose presence is inconsistent across source apps.
- Quote unconditionally (
' → '\\'') — spaces in project paths are common.
- Insert as text, never submit — a pasted path is mid-sentence, so no
inject_paste/Enter.
- No cwd-relative rewriting; absolute paths always resolve.
Implementation phases
- Native pasteboard read — command returning
Vec<String> of file-URL paths; quoting helper unit tests.
- Frontend branch — extend
onPaste (RunnerTerminal.tsx:749-781), inject via injectStdin; component tests for image / file / text pastes.
- Validation —
cargo test --workspace, tsc --noEmit, lint, pnpm test, manual list.
Spec: docs/features/55-paste-file-paths.md
Motivation
Copying a file in GoLand (or Finder) and pressing ⌘V over a Runner terminal inserts nothing. Every native terminal — Terminal.app, iTerm2, Ghostty — inserts the file's POSIX path instead, which is how you hand an agent a file without typing its path.
A file copy puts no text on the clipboard: it writes
public.file-url/NSFilenamesPboardTypeto NSPasteboard, and native terminals read those flavors explicitly. Across the WKWebView boundary the paste arrives as aFileinDataTransferwith unusabletext/plain, so xterm.js's default paste inserts nothing.Runner already intercepts paste for this exact class of problem —
RunnerTerminal.tsx:749handles image paste by shipping bytes to Rust to restore the NSPasteboard flavor (#79). A non-image file falls through:inferPasteImageMimereturns null, the loop continues, and the handler returns withoutpreventDefault. The gap is one branch wide.The web layer can't close it alone —
DataTransferwithholds filesystem paths (File.nameis only the basename, and WKWebView exposes nofile.path), so the path must come from the native pasteboard.Scope
Key decisions
commands/session.rs:144-165already has the plumbing andobjc2-app-kitis already a dependency.onPastehandler; empty native result falls through untouched.text/uri-list, whose presence is inconsistent across source apps.'→'\\'') — spaces in project paths are common.inject_paste/Enter.Implementation phases
Vec<String>of file-URL paths; quoting helper unit tests.onPaste(RunnerTerminal.tsx:749-781), inject viainjectStdin; component tests for image / file / text pastes.cargo test --workspace,tsc --noEmit, lint,pnpm test, manual list.Spec:
docs/features/55-paste-file-paths.md