[BUG] Ctrl-G external editor does not disable bracketed paste mode before launching terminal editors

Resolved 💬 3 comments Opened Feb 9, 2026 by gslin Closed Mar 31, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When opening an external terminal editor (e.g., neovim) via Ctrl-G, Claude Code does not disable bracketed paste mode (\x1B[?2004l) before launching the editor. This causes the editor to receive raw ^[[200~ / ^[[201~ sequences when pasting, which are interpreted as keystrokes/commands instead of being recognized as bracketed paste delimiters.

Ink (the TUI framework Claude Code uses) enables bracketed paste mode on the terminal by writing \x1B[?2004h when entering raw mode. When Ctrl-G is pressed, the editor launch function (EmA in the bundled cli.js) does the following:

  1. Calls suspendStdin(), which calls process.stdin.setRawMode(false) but does not write \x1B[?2004l to disable bracketed paste mode on the terminal.
  2. Writes escape sequences before launching the editor:

\x1B[?1049h (alternate screen)
\x1B[?1004l (disable focus reporting)
\x1B[0m (reset attributes)
\x1B[?25h (show cursor)
\x1B[2J (clear screen)
\x1B[H (cursor home)

  1. Launches the editor via execSync(editor, { stdio: "inherit" }).

Note that focus reporting (\x1B[?1004l / \x1B[?1004h) is correctly disabled/re-enabled around the editor launch, but bracketed paste mode (\x1B[?2004l / \x1B[?2004h) is not.

After the editor exits, the restore sequence is:
\x1B[?1049l (exit alternate screen)
\x1B[?1004h (re-enable focus reporting)
\x1B[?25l (hide cursor)

Again, no \x1B[?2004h to re-enable bracketed paste (because it was never disabled).

There is a similar code path for the "thinkback" player (ZV6 function) that has the same issue.

What Should Happen?

Bracketed paste mode should be disabled before launching the terminal editor and re-enabled after it exits, consistent with how focus reporting is already handled:

- process.stdout.write("\x1B[?1049h\x1B[?1004l\x1B[0m\x1B[?25h\x1B[2J\x1B[H");
+ process.stdout.write("\x1B[?1049h\x1B[?1004l\x1B[?2004l\x1B[0m\x1B[?25h\x1B[2J\x1B[H");

- process.stdout.write("\x1B[?1049l\x1B[?1004h\x1B[?25l");
+ process.stdout.write("\x1B[?1049l\x1B[?1004h\x1B[?2004h\x1B[?25l");

Error Messages/Logs

No error messages. The symptom is that when pasting inside the editor launched via Ctrl-G, the `^[[200~` and `^[[201~` bracketed paste delimiter sequences appear as literal text or are interpreted as editor commands (e.g., in neovim normal mode, `~` toggles character case, `0` moves to beginning of line, etc.) instead of being silently consumed as paste boundaries.

Steps to Reproduce

  1. Set $EDITOR to a terminal-based editor (e.g., nvim)
  2. Launch Claude Code (claude)
  3. Press Ctrl-G to open the external editor
  4. In the editor, paste text from the clipboard (e.g., via terminal paste or Ctrl-Shift-V)
  5. Observe that ^[[200~ appears as literal text or is interpreted as commands rather than being handled as a bracketed paste sequence

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.37 (Claude Code)

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Other

Additional Information

Terminal/Shell: WezTerm/zsh

This bug was discovered and the root cause analysis was performed using Claude Code itself — by having it read and trace through the minified cli.js bundle to identify the missing escape sequences. This bug report was also written with assistance from Claude Code.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗