Shell variable expansion fails in piped commands ($VAR expands to empty with |)
Description
Shell variable expansion ($VAR) produces empty strings when the Bash tool command contains a pipe (|). The same variable expands correctly without a pipe. This affects all environment variables, not just specific ones.
Reproduction
All of these can be run directly in Claude Code's Bash tool:
# Works (no pipe):
echo "$HOME"
# → /home/jason
# Fails (with pipe):
echo "$HOME" | cat
# → (empty)
# Fails (with pipe):
echo "$HOME" | wc -c
# → 1 (just the newline — $HOME expanded to empty)
# Works (no pipe):
printf "%s" "$HOME"
# → /home/jason
# Fails (with pipe):
printf "%s" "$HOME" | cat
# → (empty)
# Works (redirect instead of pipe):
echo "$HOME" > /tmp/test.txt && cat /tmp/test.txt
# → /home/jason
# Process env IS correct:
printenv HOME | wc -c
# → 12 (printenv reads from process env directly — correct)
Key observations
$VARexpands correctly without a pipe$VARexpands to empty string with a pipeprintenv VAR(reads process env directly) works correctly even in pipes$(printenv VAR)works as a workaround:echo "$(printenv HOME)" | wc -c→12bash -c 'echo "$HOME"' | catworks (single-quoted, so inner bash expands from inherited env)- File redirects (
>) work correctly — only|pipes are affected declare -p HOMEshowsdeclare -x HOME="/home/jason"— the variable IS declared and exported in the shell
Impact
This is a critical issue for AI agent workflows that use curl with auth tokens piped to jq/python3 -m json.tool for parsing:
# This sends an EMPTY Authorization header:
curl -s -H "Authorization: Bearer $API_KEY" "$API_URL/endpoint" | jq .
# This works:
curl -s -H "Authorization: Bearer $API_KEY" "$API_URL/endpoint"
In our case, this caused a Paperclip AI agent orchestration system to have cascading authentication failures — the agent's JWT token expanded to empty in every piped curl command, causing checkout conflicts, wrong author identity, and ownership errors. Non-piped commands from the same session worked perfectly.
Environment
- Claude Code version: 2.1.58
- OS: Ubuntu on WSL2 (Linux 6.6.87.1-microsoft-standard-WSL2)
- Shell: bash 5.2.21
- The Bash tool uses
bash -c "source <snapshot> && eval '<command>' < /dev/null"execution pattern
Workaround
Replace $VAR with $(printenv VAR) in any command that includes a pipe.
Root cause hypothesis
The Bash tool wraps commands via eval 'COMMAND' < /dev/null. When the COMMAND string contains a pipe, variable expansion behaves differently than without a pipe. Direct bash -c testing of the same eval pattern works correctly, so the issue may be in how Claude Code constructs or passes the command string to bash, possibly related to quoting or escaping of the command before it reaches eval.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗