Bash tool: shell-quote mangles { }, heredoc markers, and $ in piped commands

Resolved 💬 4 comments Opened Mar 10, 2026 by bukzor Closed Apr 8, 2026

Related: #4711 (fixed 2>&1 mangling in v1.0.74). These are further edge cases in the same shell-quote reconstruction path.

Bug Description

The Bash tool's shell-quote library doesn't understand several shell constructs. When pipes are present, token reconstruction mangles them. Three related symptoms:

1. Brace groups { } quoted as literals

# Works — no pipe
{ echo inside braces; }
# Output: inside braces

# Fails — with pipe
true | true; { echo inside braces; }
# set -x trace shows: '{' echo inside braces
# Error: /bin/bash: line 1: {: command not found

2. Heredoc markers containing hyphens are split

# Fails — hyphens in heredoc marker
bash <<'MY-MARKER'
echo hi | cat
MY-MARKER
# Error: syntax error near unexpected token `<'
# Reconstructed as: bash < < MY-MARKER echo hi ...

Markers using only [A-Za-z0-9_] survive reconstruction by accident — shell-quote treats them as simple word tokens.

3. $ expansion broken in pipes (likely related to #29298)

# Works
echo "PID=$$"
# Output: PID=12345

# Fails
true | true; echo "PID=$$"
# Output: PID=

Root Cause

All three stem from shell-quote not recognizing these as shell syntax during tokenization. When the command contains a pipe, shell-quote parses and reconstructs the token stream, and the reconstruction:

  • Quotes { and } as literal strings
  • Splits <<'MARKER' into separate < < tokens when the marker contains non-word characters
  • Escapes or drops $ in variable references

Workaround

Wrap commands in a heredoc so shell-quote only sees bash and a simple redirect. The heredoc marker must use only [A-Za-z0-9_] characters:

bash <<'BASH_SAFE'
true | true; { echo inside braces; }
BASH_SAFE

This can be automated via a PreToolUse hook (we have one at ~/.claude/hooks/bash-preamble.py).

Environment

  • Claude Code: 2.1.72
  • Platform: linux
  • Shell: bash

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗