Bash tool unescapes backslashes inside a quoted heredoc
What happened
In the Claude Code Bash tool, a quoted heredoc (<<'EOF') applies one level of backslash-unescaping to the body before the shell sees it. POSIX requires a quoted delimiter to suppress all expansion and processing, so the body should arrive verbatim.
Reproduction
Run this as a single Bash tool call:
cat <<'EOF'
one: C:\Users
two: C:\\Users
EOF
Expected
one: C:\Users
two: C:\\Users
Actual
one: C:\Users
two: C:\Users
One backslash survives; two collapse to one. That is a single unescape pass in which \\ is a recognised escape and \U is not.
Why this is worth fixing
The failure is misattributed, which is the expensive part. Piped into Python:
python - <<'EOF'
s = "C:\\Users\\Scott"
print(s)
EOF
raises:
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
The traceback points at a source line the model never wrote. It reads as the model emitting bad Python rather than as a transport defect, so the natural response is to rewrite the Python, which cannot help. I hit it twice in one session before recognising the pattern.
On Windows this is not an edge case: every absolute path carries backslashes. Regexes with \\ and \d are affected the same way. A script written through a heredoc can silently differ from what was composed, and where it does not throw a syntax error it just runs with different semantics.
Workarounds
Both verified in the same session:
- Build the separator at runtime, e.g.
BS = chr(92), then concatenate. - Use the PowerShell tool with a single-quoted here-string (
@'...'@), which is unaffected, including for multi-line bodies containing backslash paths. - Forward slashes, where the consumer accepts them.
Environment
- Claude Code 2.1.246 (bundled in the desktop app, where this was observed). The CLI on PATH reports 2.1.251.
- Windows 11 Pro 26200
- Bash tool backed by Git Bash
I have not checked whether this reproduces on macOS or Linux. Backslashes are rarer in paths there, so the impact would be mostly regexes and escape sequences.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗