[FEATURE] A standard text-editing model for the prompt input: selection, cut/copy/paste, word navigation (built on OSC 52, bracketed paste, kitty keyboard protocol)

Status Open
Maintainer reply None cached
Activity 1 comment · opened Sep 28, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Preflight

I searched existing issues. The closest ones, as they looked when I checked:

  • #23396 — Shift+Arrow selection, Ctrl+X/C/V (closed as duplicate)
  • #27561 — click-to-position, selection, standard editing (closed)
  • #63058 — word-jump cursor actions (closed as not planned / stale)
  • #68935 — shortcut to copy the input buffer (tracked in the meta issue #81472)

These keep being filed and closed one key at a time. This request is different in scope: it asks for one coherent editing model (selection + clipboard + navigation), says exactly which terminal protocol carries each piece, and points out that most of the machinery already exists elsewhere in Claude Code. If it should be folded into an existing canonical issue, please point me to it.

Problem

The prompt is the one text field every Claude Code user types into for hours a day, and it is the only text field on my machine where I cannot select a piece of text, cut it, copy it, or paste over it.

| Operation | Today | Expected (HTML <textarea>, Far Manager / far2l) |
|---|---|---|
| Select by character / line | ✗ | Shift+←/→/↑/↓ |
| Select by word | ✗ | Ctrl+Shift+←/→ |
| Select to line start / end | ✗ | Shift+Home/End |
| Select all | ✗ (Ctrl+A = line start) | Ctrl+A / Cmd+A |
| Move by word | Alt+B/F only (macOS: needs "Option as Meta") | Ctrl+←/→, Alt+←/→ |
| Cut / copy selection | ✗ (only the kill-ring: Ctrl+K/U/W) | Ctrl+X / Ctrl+C / Ctrl+Insert / Shift+Delete / Cmd+X/C |
| Paste over a selection | ✗ | Ctrl+V / Shift+Insert / Cmd+V |
| Typing / Backspace replaces or deletes the selection | ✗ | yes |
| Delete word right | Alt+D only | Ctrl+Delete |

The pieces already exist, just not in the prompt in normal mode:

  • Vim mode has a selection (v/V, y, d, p) — so the input widget already has selection state.
  • Fullscreen mode has selection:extendLeft/Right/Up/Down/LineStart/LineEnd on Shift+arrows / Shift+Home/End, a selectionBg theme token, and selection:copy (Cmd+C / Ctrl+Shift+C) that reaches the system clipboard — evidently via OSC 52.
  • There is a kill-ring (Ctrl+K/U/W, Ctrl+Y, Alt+Y), /copy, and chat:undo.

But the Chat context in keybindings.json exposes no cursor, selection or clipboard actions, so none of this can be reached or remapped (cf. #63058). Three unrelated selection models, none of them available to a user in default mode.

There are also deliberate conflicts that a proposal has to resolve rather than ignore:

  • Ctrl+V is chat:imagePaste.
  • Ctrl+X is a chord prefix (Ctrl+X Ctrl+E, Ctrl+X Enter, …).
  • Ctrl+A / Ctrl+E are readline line-start/end.
  • Shift+arrows and Ctrl+Home/End are already used by the Scroll context in fullscreen.

Why this is feasible now: what the terminal can actually carry

1. Selection and word navigation need no protocol negotiation at all. The xterm modifier scheme (parameter = 1 + Shift·1 + Alt·2 + Ctrl·4 + Meta·8) is old and widely implemented:

Shift+Left        ESC [ 1 ; 2 D        Ctrl+Left         ESC [ 1 ; 5 D
Ctrl+Shift+Left   ESC [ 1 ; 6 D        Shift+End         ESC [ 1 ; 2 F
Ctrl+Insert       ESC [ 2 ; 5 ~        Shift+Insert      ESC [ 2 ; 2 ~
Shift+Delete      ESC [ 3 ; 2 ~

Phase 1 below is therefore doable with today's input parser, on almost every terminal.

2. What the legacy encoding cannot express — Ctrl+Shift+<letter> (arrives as plain Ctrl+<letter>), Cmd/Super+<key>, Ctrl+Enter, and Ctrl shortcuts under non-Latin layouts — is exactly what the kitty keyboard protocol fixes: push flags CSI > 5 u (disambiguate + report alternate keys), query CSI ? u, pop CSI < u; key events arrive as CSI code ; modifiers u, with super as bit 8. "Report alternate keys" delivers the base-layout key, which is what makes Ctrl+С on a Russian layout behave as Ctrl+C. Support is broad (kitty, Ghostty, WezTerm, iTerm2, Alacritty, foot, Windows Terminal, xterm.js, …), and detection is CSI ? u followed by DA1. Claude Code already uses it (the docs describe kitty-based layout matching and Super detection), and upstream Ink exposes it (render(..., {kittyKeyboard}), key.super). Fallbacks: xterm modifyOtherKeys (CSI > 4 ; 2 m), and on Windows win32-input-mode (CSI ? 9001 h) which delivers full KEY_EVENT_RECORDs from ConPTY / Windows Terminal.

3. Writing to the clipboard = OSC 52: ESC ] 52 ; c ; <base64> ST (p for PRIMARY). Widely supported (kitty, iTerm2, WezTerm, Alacritty, foot, Konsole, Windows Terminal, tmux, far2l …), not by GNOME Terminal/VTE or macOS Terminal.app. tmux ignores applications' OSC 52 under its default set-clipboard external; it needs set-clipboard on or passthrough. Claude Code already emits OSC 52 for /copy and selection:copy, so what remains is making it reliable (see "Known clipboard bugs" below) and using it from the prompt. Native tools (pbcopy, wl-copy, xclip, clip.exe) are the local fallback; over SSH only OSC 52 works.

4. Pasting = bracketed paste, and this is the easy half. With CSI ? 2004 h the terminal wraps pastes in ESC[200~ … ESC[201~. Every terminal-initiated paste (Ctrl+Shift+V, Cmd+V, right-click, middle-click, usually Shift+Insert) arrives this way, with no permission prompt, no clipboard read, and it works over SSH. Ink's usePaste does exactly this.

5. Application-initiated paste (the app's own Ctrl+V) is the hard half: the app must read the clipboard. Options: (a) native tools on a local session (already done for images); (b) kitty's OSC 5522 type=read (permission-gated; probe with CSI ? 5522 $ p); (c) OSC 52 query ? — usually disabled or gated, so it must have a short timeout. Proposed order is local native → 5522 → 52-query → a one-line hint: "use your terminal's paste (Ctrl+Shift+V / Cmd+V)". Nothing else in the design depends on this half.

6. far2l is the UX reference — and its terminal extensions are not far2l-only. far2l ships a layered set of TTY backends (TTY, TTY|X, TTY|Xi, TTY|k for the kitty protocol, TTY|F for its own extension protocol) precisely because no single terminal feature is guaranteed: it probes what is available and degrades gracefully. Far/far2l editing (Shift+arrows selection, Ctrl+Ins/Shift+Ins/Shift+Del, Ctrl+←/→) is the CUA layout, which never conflicts with terminal signals.

The far2l terminal extensions (a private APC channel that carries full key events and the clipboard) are also implemented by other software:

  • KiTTY (the PuTTY fork at https://www.9bis.net/kitty/ — unrelated to Kovid Goyal's kitty, despite the name) and other PuTTY forks;
  • f4 (https://github.com/unxed/f4), a Go TUI file manager that speaks the extensions with its host terminal and also answers the handshake for programs run in its built-in terminal — so Claude Code launched there sees an extension-capable terminal.

I am not asking for a bespoke integration in phases 1–3. I am asking for the same probe-and-degrade discipline, and that the existing OSC 52 / bracketed-paste / kitty paths keep working in these terminals. Treating the extension channel as one more optional capability (a possible phase 4) would give their users desktop-grade keys and clipboard even over a remote connection.

Proposed solution

Phase 1 — one selection model in the prompt (no negotiation).

  • Anchor + cursor in the input buffer; render with the existing selectionBg. Share the model with vim VISUAL and, where sensible, with selection:*.
  • Textarea semantics: typing, Backspace, Delete and paste replace/delete the selection; unshifted ←/→ collapse it to its start/end; Shift+↑/↓ preserves the visual column in multi-line input.
  • New bindable actions in the Chat context, e.g. chat:cursorWordLeft/Right, chat:selectLeft/Right/Up/Down, chat:selectWordLeft/Right, chat:selectLineStart/End, chat:selectAll, chat:copy, chat:cut, chat:paste, chat:deleteWordRight — with defaults on the non-conflicting keys above (Shift/Ctrl+arrows, Shift+Home/End, Ctrl+Insert, Shift+Insert, Shift+Delete, Ctrl+Delete).
  • Conflicts, resolved deliberately:
  • Ctrl+C copies only while a selection exists; otherwise it keeps today's interrupt behaviour (the convention in Windows Terminal, VS Code, JetBrains).
  • Ctrl+X cuts only while a selection exists; otherwise it stays the chord prefix.
  • Ctrl+V: image if the clipboard has one, text otherwise.
  • Ctrl+A stays line-start by default; select-all is Cmd+A / Ctrl+Shift+A where the terminal can report them, and Ctrl+A in an opt-in "standard" flavour (e.g. editorMode: "standard").
  • The prompt must take precedence over Scroll for Shift+arrows while it has focus.
  • A [Pasted text #N] placeholder must be atomic under selection, and copying it must copy the underlying content.

Phase 2 — clipboard and keyboard capability layer.

  • Push kitty flags 1|4 on start; pop them on exit and around every child process (Ctrl+G external editor, ! shell mode, suspend), or $EDITOR will receive CSI u it cannot parse.
  • Probe with CSI ? u + DA1; Cmd+C/X/V/A/Z via super; modifyOtherKeys and win32-input-mode fallbacks.
  • The clipboard read/write layering from points 3–5.
  • Pasted text replaces the selection, and one paste is one undo step.

Phase 3 — mouse in the prompt (fullscreen only, where mouse reporting is already on): click to position, drag to select, double-click for a word, triple-click for a line, Shift+click to extend. In non-fullscreen mode the terminal keeps the mouse.

Known clipboard bugs this should not step on

#66098 (OSC 52 corrupts multi-byte UTF-8, e.g. Cyrillic), #79482 (/copy writes Latin-1), #57654 (OSC 52 should set both CLIPBOARD and PRIMARY), #63061 (OSC 52 regression under tmux), #67576 (OSC 52 does not reach RDP clipboard redirection), #73098 (vim mode: unbracketed paste turns newlines into j). Most of them are fixed by one UTF-8-correct OSC 52 writer.

Alternatives considered

  • Vim mode — great for those who use it; not a substitute for muscle memory built on every other text field.
  • Ctrl+G external editor — heavyweight for a one-word fix.
  • Terminal-native selection — unreliable: the prompt sits under an alt-screen or mouse capture, the > gutter and hard wraps come along (#81472).
  • Kill-ring only — deletes, doesn't select or copy, and can't paste from outside.
  • Minimum fallback if the full model is too big: at least expose chat:cursorWordLeft/Right and chat:deleteWordRight as bindable actions and make Ctrl+←/→ work by default.

Acceptance tests

The sequences above are deterministic, so this can be tested headlessly by feeding bytes into the input component and asserting buffer, selection and emitted OSC 52:

  • ESC[1;6D × 2 selects two words to the left.
  • ESC[200~foo\nbar ESC[201~ over a selection replaces it, inserts the newline literally, doesn't submit, and is undone in one step.
  • ESC[99;5u (Ctrl+C) with a selection emits ESC]52;c;<base64(utf-8)>; without one, it interrupts as today.
  • Cyrillic text round-trips through copy/paste.
  • Kitty flags are popped before spawning $EDITOR and restored afterwards.

Priority

High — significant impact on productivity. It is a daily-friction item for everyone who edits multi-line prompts.

Feature category

Interactive mode (TUI)

References

Priority

Medium - Would be very helpful

Feature Category

CLI commands and flags

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗