vim editor mode: pasted line breaks become literal 'j' when paste isn't bracketed
Description
When editorMode is set to vim in ~/.claude/settings.json, pasting multi-line text into the prompt sometimes turns every line break into a literal j character instead of a newline.
Environment
- Claude Code version: 2.1.198
- OS: Debian devcontainer on WSL2 (Linux 6.6.87.2-microsoft-standard-WSL2)
- Terminal multiplexer: tmux 3.5a
- TERM: xterm-256color
~/.claude/settings.json:"editorMode": "vim"
Steps to reproduce
- Set
"editorMode": "vim"in~/.claude/settings.jsonand start Claude Code. - In tmux, generate some multi-line output in one pane (e.g. run a command that prints several lines).
- Select/copy that multi-line output via tmux (e.g. mouse drag-select, or copy-mode) so the paste is not delivered to Claude Code as a single atomic bracketed-paste event, but arrives as individual keystrokes instead.
- With the Claude Code prompt in vim Normal mode (i.e. before pressing
i), paste the copied text into the prompt.
Expected behavior
The pasted text is inserted verbatim, preserving line breaks - regardless of whether the paste arrives as one atomic bracketed-paste blob or as a stream of individual keystrokes, and regardless of the current vim mode (Normal vs Insert). This is how real Vim itself handles bracketed paste: it detects the \e[200~ ... \e[201~ wrapper and inserts the content literally even when triggered from Normal mode.
Actual behavior
Every line break in the pasted text is replaced with a literal j character in the prompt.
Suspected root cause
This looks like two compounding issues:
- Claude Code's terminal input handling doesn't reliably treat certain pastes (relayed through tmux) as a single bracketed-paste event, so the pasted bytes get processed by the normal per-keystroke handler.
- In vim Normal mode, the per-keystroke handler apparently maps
<CR>/newline to the same action asj(move down one line, which is standard vim behavior for<CR>in Normal mode) - but instead of just moving the cursor, it inserts the literal characterjinto the buffer. That insertion is the actual bug: a plain cursor-navigation command should never write a character into the text.
Workaround
Press i to enter Insert mode before pasting, or temporarily disable vim mode (/vim, or set "editorMode": "default" in ~/.claude/settings.json) before doing a large multi-line paste.
Example of corrupted paste
(redacted/genericized - original was multi-line CLI output copied from a package registry login command)
example.com/repo/some-internal-feedjLogin expires in 12 hours at 2026-07-03j 00:13:32+10:00j>> token renewedjSuccessfully configured package manager to use internal registryj https://example.com/some-internal-feedj Login expires in 12 hours at 2026-07-03 00:13:33+10:00j>> token renewedj