[BUG] Paste into prompt is inserted twice, concatenated byte-identically — doubled command is then EXECUTED on ! bash-input (2.1.220, macOS, tui: fullscreen)

Status Fixed / completed
Reported on v2.1.220
Maintainer reply None cached
Activity 3 comments · opened Jul 30, 2026 · closed Jul 31, 2026

Summary

Pasting into the prompt inserts the pasted text twice, concatenated with itself, byte-for-byte, with no separator. On ! bash-input lines the doubled string is then executed, so this is not a display artifact — it changes what runs.

Reproduced 7 times out of 7 in a single session (100%). Every affected input was a paste; every message typed by hand in the same session was unaffected.

Environment

  • Claude Code 2.1.220 (latest at time of report, autoUpdatesChannel: latest)
  • macOS 15 (Darwin 25.5.0), arm64
  • "tui": "fullscreen" in ~/.claude/settings.json ← the only non-default input-related setting
  • Shell: zsh; pbcopy present
  • No custom keybindings (~/.claude/keybindings.json absent)
  • Hooks configured: one UserPromptSubmit hook that only emits a <system-time> block and never touches the prompt (verified — it is a cat <<EOF of date output)

Evidence

Extracted from the session transcript (~/.claude/projects/<project>/<session>.jsonl), checking whether each <bash-input> payload equals its own first half repeated:

7 bash-input entries

[1] 2026-07-30T18:30:53Z v2.1.220 len=426 exact-half-dup=True
[2] 2026-07-30T18:32:53Z v2.1.220 len=58  exact-half-dup=True
[3] 2026-07-30T18:38:48Z v2.1.220 len=586 exact-half-dup=True
[4] 2026-07-30T18:40:11Z v2.1.220 len=590 exact-half-dup=True
[5] 2026-07-30T18:42:58Z v2.1.220 len=590 exact-half-dup=True
[6] 2026-07-30T18:43:42Z v2.1.220 len=196 exact-half-dup=True
[7] 2026-07-30T18:54:55Z v2.1.220 len=390 exact-half-dup=True

exact-half-dup is a strict inner[:len//2] == inner[len//2:] comparison. All seven are exact. There is no newline, space, or any delimiter at the join.

Why this is more than cosmetic

The concatenation happens at the join point with no separator, so the boundary silently corrupts the command:

Case 1 — a command truncated into a different, failing command.
Pasted:

cd /path/to/repo && git commit -m "msg" && git push

Executed: ... && git pushcd /path/to/repo && git commit -m "msg" && git push
Result: git: 'pushcd' is not a git command. The commit ran; the push silently did not. The repo was left committed-but-unpushed while the visible output looked like a normal error at the end.

Case 2 — a quoted payload corrupted mid-string.
Pasted a python3 -c "...print('added'))" one-liner. The join produced ...print('added'))python3 inside the quoted program text, yielding SyntaxError: invalid syntax. Harmless here only because Python parses before executing — the same join inside a shell string would have run.

Case 3 — accidentally benign.
rm -rf /tmp/aios-update-check doubled to rm -rf /tmp/aios-update-checkrm -rf /tmp/aios-update-check, which rm read as two targets: a nonexistent path (silently ignored) plus the intended one. It did the right thing by luck. A different path or flag combination would not be so forgiving — this is the shape of the bug that worries me most, because a destructive command can double into a valid destructive command with different arguments.

Workaround

Ending every pasted command with a space and # makes the doubling harmless — the second copy lands after a comment marker:

<command> #

becomes <command> #<command> #, which the shell executes once. This works only for single-line pastes; in a multi-line block only the final line is protected, and earlier lines of the second copy still execute.

Suspected area

"tui": "fullscreen" is the only non-default input-related setting present, which points at bracketed-paste handling in the alt-screen renderer — as though the paste payload is consumed from both the bracketed-paste buffer and the raw key stream. I have not been able to confirm this by bisection (it requires interactive typing to test), so treat it as a lead rather than a diagnosis.

Possibly a common duplicated-emit path with #74214 (fullscreen TUI emits the same OSC 52 clipboard write twice, byte-identical) and #41954. Those duplicate a clipboard write rather than concatenating content, and #74214 is Linux-without-pbcopy, so this is a different symptom — but "fullscreen renderer emits the same payload twice" is the shared shape, and they may have one root.

Expected

Pasted text is inserted once.

View original on GitHub ↗

3 Comments

Pipena · 2 months ago

Follow-up with a negative result that narrows this.

tui: "fullscreen" is not the cause. I switched ~/.claude/settings.json from "tui": "fullscreen" to "tui": "default" as a controlled test and the doubling still reproduces on 2.1.220.

Two further details that may help isolate it:

  1. It reproduces from dictation software, not just ⌘V. Speech-to-text tools deliver their output by writing to the clipboard and issuing a paste, and the doubling fires there identically. So the trigger is the paste/insert path, not the keybinding.
  2. The two copies are concatenated with no separator — the text reads ...end of dictation.Start of the same dictation again..., with no newline and no space between them. That reads as a single insert event delivered twice, rather than two independent input events.

Impact is cosmetic for prose but not for commands: a pasted shell command is submitted twice and executes twice. The workaround we run locally is to terminate any handed-over command with a trailing # and keep it to one line, so the duplicate is consumed as a comment.

Pipena · 2 months ago

Closing this — Claude Code is not at fault, and I misfiled it. Posting the resolution rather than deleting, since the failure shape may still be useful to someone who lands here.

The doubling was real and reproduced 7/7, but the host was not a terminal emulator. Claude Code was running inside a custom Electron application that embeds its own xterm.js terminal. That application's renderer had a hand-rolled Cmd+V handler which read the clipboard and wrote it to the pty itself — while xterm's own native paste event fired as well. Two writes, byte-identical, no separator. It was fixed upstream in that application on 27 July; the machine reporting this was running the build from the day before.

Two things worth carrying, because both nearly sent me the wrong way:

  1. tui: fullscreen was a red herring and I reported it as a suspect. Switching to default changed nothing, which is what began pointing outward.
  2. The dictation detail in my previous comment has the same explanation — speech-to-text tools insert by simulating Cmd+V, so they hit the identical handler. It looked like a second, independent reproduction path and it was the same one.

Apologies for the noise. Nothing here needs action on Claude Code's side.

github-actions[bot] · 22 days ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.