[BUG] Bash tool escapes ! to \! inside JSON strings in single-quoted arguments (regression 2.1.87)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
The Bash tool escapes ! to \! when it appears inside double-quoted strings ("...") within single-quoted arguments ('...'). Single quotes should protect all characters — no escaping should occur.
This breaks any CLI command that passes JSON with ! as an inline argument.
What Should Happen?
! inside single-quoted arguments should be passed as-is to the subprocess, with no escaping.
Error Messages/Logs
# ! inside "..." gets escaped
$ python3 -c "import sys; print(repr(sys.argv[1]))" '{"range":"Feuille 1!A11"}'
'{"range":"Feuille 1\\!A11"}'
# ! outside "..." is fine
$ python3 -c "import sys; print(repr(sys.argv[1]))" 'hello!world'
'hello!world'
Steps to Reproduce
- Open Claude Code 2.1.87
- Ask Claude to run:
````
python3 -c "import sys; print(repr(sys.argv[1]))" '{"key":"val!ue"}'
- Output shows
\\!instead of! - Any CLI tool parsing that JSON (e.g.
serde_json,json.loads) fails with "invalid escape"
Real-world impact: Google Workspace CLI (gws) uses --params '<JSON>' for API calls. Google Sheets A1 notation requires ! to specify a sheet name (e.g. Sheet1!A1:B2). Every Sheets API call targeting a named tab fails:
gws sheets spreadsheets values get --params '{"spreadsheetId":"...","range":"Feuille 1!A11"}'
# → "Invalid --params JSON: invalid escape at line 1 column 84"
Workaround: Write JSON to a temp file and use "$(cat /tmp/file.json)" — heredocs with quoted delimiters bypass the escaping.
Is this a regression?
Yes, this worked in a previous version.
Last Working Version: 2.1.86
Environment
- Claude Code Version: 2.1.87
- Platform: Anthropic API
- OS: macOS (Darwin 25.3.0, aarch64)
- Terminal: Terminal.app
- Shell: zsh
- Install: Standalone installer (
~/.local/share/claude/versions/) - Model: Opus
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗