Bash tool still escapes `!` to `\!` in non-interactive shell (v2.1.79)
Preflight
- [x] I have searched existing issues for duplicates
- [x] I am reporting a single bug
- [x] I am using the latest version of Claude Code
What's Wrong?
The Bash tool escapes ! to \! before passing commands to the shell. Since Claude Code runs bash non-interactively (bash -c), history expansion is disabled and ! has no special meaning — the backslash becomes a literal character that breaks downstream tools.
This was reportedly fixed in v2.1.75 ("Fixed Bash tool mangling ! in piped commands"), but the issue persists on v2.1.79.
What Should Happen?
! should be passed through unescaped to non-interactive bash, since history expansion is off by default in that context.
Steps to Reproduce
- Ask Claude Code to run a
jqcommand containing!= - Observe that the Bash tool escapes it to
\!= - The command fails with a jq syntax error
Error Messages/Logs
● Bash(nix-shell -p jq --run 'jq -r "[.[] | select(.httpRequest != null and .timestamp >= \"2026-03-19T10:04:00\" and .timestamp <= \"2026-03-19T10:08:00\")] | group_b…)
⎿ Error: Exit code 3
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting ';' or ')' at <top-level>, line 1, column 28:
[.[] | select(.httpRequest \!= null and .timestamp >= "2026-03-19T10:04:00" and .timestamp <= "2026-03-19T10:08:00")] | group_by(.httpRequest.status) | map({status: .[0].httpRequest.status, count:
length})
^
jq: 1 compile error
The != in the jq filter was mangled to \!=, which jq rejects as INVALID_CHARACTER.
Claude Code Version
2.1.79
Is this a regression?
Yes — the v2.1.75 changelog states "Fixed Bash tool mangling ! in piped commands", but the fix appears incomplete.
Last Working Version
_Unknown — the bug predates v2.1.75; that version claimed to fix it but didn't fully._
Platform
Other
Operating System
Linux (NixOS on WSL2, kernel 6.6.87.2-microsoft-standard-WSL2)
Terminal/Shell
Bash tool uses /bin/bash non-interactively (user's login shell is fish, but not relevant here)
Additional Information
Related issues: #23740, #24979, #2941, #10335, #7387.
The root cause appears to be the shell-quote library's quote() function, which escapes ! unconditionally without considering whether the target shell runs interactively. Since Claude Code spawns bash -c (non-interactive), history expansion is off and the escaping is both unnecessary and harmful.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗