Bash command with 2>&1 causes ~12min spinner hang with token usage climbing during the stall
Summary
A Bash tool command containing 2>&1 triggers a ~12-minute hang on the spinner, and token usage increments continuously during the hang — implying a model-reinvocation loop rather than an idle wait. No tool work is produced during the stall; the command eventually executes and returns normally.
Environment
- Claude Code (Opus 4.8, 1M context)
- macOS, project uses a
PreToolUsepermission allowlist + custom hooks in.claude/settings.json
What happened
A single turn whose entire work was: one Read, then two Bash calls. Both Bash calls used 2>&1:
git commit -m "..." 2>&1 | tail -3
...
git push 2>&1 | tail -3
The turn hung ~12 minutes on the spinner. The commands DID eventually run and return correct output (commit + push succeeded), consistent with a long stall that finally resolved — not 12 minutes of actual compute.
Smoking gun
Token usage ticked up continuously while the spinner sat. A command blocked on permission evaluation should draw zero tokens. Usage climbing during the hang implies something is actively re-invoking the model in a loop (retry / re-send context / re-evaluate) during the stall. This is the user-visible cost spike — bill grows while nothing is accomplished.
Suspected cause
The permission engine splits Bash commands on shell operators including &. The & inside 2>&1 fragments the command into segments that are validated independently. The hypothesis: that fragmentation drops the command into a permission-evaluation path that loops/retries against the model instead of erroring or waiting idle.
Repro candidate
Run a Bash tool command of the shape:
<some-git-or-cli-command> 2>&1 | tail -3
in a project that has a PreToolUse permission allowlist. Watch for: spinner hang + usage incrementing during the hang.
Expected
A command blocked/queued in permission evaluation should be idle (zero token draw), and should resolve in well under a second for an allowlisted command — not loop for minutes consuming tokens.
Workaround
Avoid 2>&1 / &> entirely; use 2>/dev/null or split into separate Bash calls. This sidesteps the &-fragmentation path.
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗