claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

[BUG] Pipe operator (|) in quoted strings incorrectly interpreted as shell pipe in Bash tool

Open orgoj opened this issue 7 months ago • 6 comments

Environment

  • Platform (select one):
    • [x] Anthropic API
    • [ ] AWS Bedrock
    • [ ] Google Vertex AI
    • [ ] Other:
  • Claude CLI version: v1.0.43
  • Operating System: Linux (detected as Ubuntu-based from environment)
  • Terminal: vs code

Bug Description

Pipe operator (|) in quoted strings is incorrectly interpreted as shell pipe operation in Bash tool calls, causing commands to fail with generic "Error" instead of treating the pipe as a literal character within quotes.

Steps to Reproduce

  1. Open Claude Code and use the Bash tool
  2. Execute any command with | inside quoted strings, for example:
    • rg -n "^import|^from" /path/to/file.py
    • grep -E "pattern1|pattern2" file.txt
    • sed "s/old1|old2/new/" file.txt
  3. Observe the command fails with generic "Error" message

Expected Behavior

Pipe operator inside quoted strings should be treated as literal character (regex alternation, etc.), not as shell pipe operator. The same commands work correctly when executed directly in shell.

Actual Behavior

  • Commands fail with generic "Error" output
  • Using --trace with ripgrep reveals corrupted regex parsing with shell redirection artifacts (e.g., < /dev/null appears in parsed regex)
  • No meaningful error message is provided

Additional Context

This affects all commands expecting literal pipe characters in quoted arguments, including regex patterns with alternation. Debug trace shows the issue is in quote parsing/shell interpretation within the Bash tool environment. Workarounds include splitting into multiple commands or using internal tools (Grep, Glob, etc.) instead of Bash+external tools.

orgoj avatar Jul 05 '25 09:07 orgoj

Example from chat

Bash(rg --trace -n "^import|^from" /home/michael/work/wdt/mp2/mp2c/md/py/cli.py)
  ⎿  Error: rg: DEBUG|rg::flags::parse|crates/core/flags/parse.rs:97: no extra arguments found from configuration file
     rg: DEBUG|rg::flags::hiargs|crates/core/flags/hiargs.rs:1083: number of paths given to search: 1
     rg: DEBUG|rg::flags::hiargs|crates/core/flags/hiargs.rs:1094: is_one_file? true
     rg: DEBUG|rg::flags::hiargs|crates/core/flags/hiargs.rs:1269: found hostname for hyperlink configuration: cislo5
     rg: DEBUG|rg::flags::hiargs|crates/core/flags/hiargs.rs:1279: hyperlink format: ""
     rg: DEBUG|rg::flags::hiargs|crates/core/flags/hiargs.rs:174: using 1 thread(s)
     rg: DEBUG|ignore::gitignore|crates/ignore/src/gitignore.rs:393: opened gitignore file: 
     /home/michael/.config/git/ignore
     rg: DEBUG|globset|crates/globset/src/lib.rs:453: built glob set; 1 literals, 0 basenames, 0 extensions, 0 
     prefixes, 1 suffixes, 0 required extensions, 0 regexes
     rg: TRACE|grep_regex::matcher|/project/crates/regex/src/matcher.rs:66: final regex: "(?:(?:(?m:^)(?:import < 
     /dev/null ))|(?: (?m:^)(?:from)))"
     rg: TRACE|grep_regex::literal|crates/regex/src/literal.rs:75: skipping inner literal extraction, existing regex 
     is believed to already be accelerated

orgoj avatar Jul 05 '25 09:07 orgoj

Related #2859

orgoj avatar Jul 05 '25 13:07 orgoj

@claude This is a significant issue with Claude Code. It unnecessarily consumes tokens and causes confusing behavior, as Claude Code fails to identify the error from a simple issue and mistakenly attempts to use grep or find.

orgoj avatar Jul 07 '25 05:07 orgoj

It is still not repaired.

> Try this command: echo "A|B"

● Bash(echo "A|B")
  ⎿  A < /dev/null | B

● The command executed successfully, but the output shows that the pipe character | was
  interpreted as a shell pipe operator, creating a pipeline where:
  - A < /dev/null tried to read from null input
  - B was treated as a command (which doesn't exist)

  The shell expanded the command differently than expected. If you want to literally print
   "A|B", you can use single quotes:

● Bash(echo 'A|B')
  ⎿  A < /dev/null | B

● Interesting - even with single quotes, the output is being modified. This appears to be
  related to the bash environment configuration or the tool execution environment
  processing pipe characters. The literal string "A|B" is being transformed into "A <
  /dev/null | B".

orgoj avatar Jul 19 '25 10:07 orgoj

This seems fixed?

> Try this command: echo "A|B"

● Bash(echo "A|B")
  ⎿  A|B

● The command output A|B.

Does it work for you, now?

bukzor avatar Nov 24 '25 18:11 bukzor

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

github-actions[bot] avatar Dec 25 '25 10:12 github-actions[bot]