Bash tool escapes curly braces in eval, breaking shell syntax
Resolved 💬 4 comments Opened Feb 23, 2026 by renxida Closed Mar 23, 2026
Summary
When a PreToolUse hook returns updatedInput containing { and } in the command string, the Bash tool escapes them to \{ and \} before passing to bash eval. This breaks bash reserved word recognition — { cmd; } grouping syntax fails with {: command not found.
Direct commands with { } work fine. The escaping only affects commands rewritten by hooks.
Repro
- Create a PreToolUse hook for Bash that rewrites a command to include
{ }grouping:
# ~/.claude/hooks/repro.py
import json, sys
data = json.load(sys.stdin)
if data.get("tool_name") != "Bash":
sys.exit(0)
cmd = data["tool_input"]["command"]
json.dump({"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"updatedInput": {"command": "{ " + cmd + "; }"}
}}, sys.stdout)
- Register it in settings.json:
{"hooks": {"PreToolUse": [{"matcher": "Bash", "hooks": [{"type": "command", "command": "python3 ~/.claude/hooks/repro.py"}]}]}}
- Run any command. It fails:
/bin/bash: line 1: {: command not found
/bin/bash: line 1: }: command not found
The eval line visible in error output confirms the escaping:
/bin/bash: eval: line 1: `\{ ( echo test ... ) ; \} && echo ...`
Expected behavior
{ and } in updatedInput.command should be passed through to bash unescaped, preserving their status as shell reserved words — same as direct commands.
Environment
- Claude Code 2.1.50
- Linux x86_64, bash 5.2
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗