[BUG] Wrong command is reported in "don't ask again for" in "This command requires approval"
Status Closed — not planned
Reported on v2.1.50
Maintainer reply None cached
Activity 10 comments · opened Feb 21, 2026 · closed Mar 25, 2026
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
When executing bash with a pipe, where the first pipe argument should be auto-allowed, but the second isn't, like this:
Bash command
hyprctl clients -j | python3 -c "import sys,json; [print(f'at=({c[\"at\"][0]},{c[\"at\"][1]})') for c in json.loads(sys.stdin.read()) if 'popup' in c.get('title','')]"
Check popup position after manual move
Do you want to proceed?
❯ 1. Yes
2. Yes, and don’t ask again for: hyprctl clients:*
3. No
Esc to cancel · Tab to amend
It asks to allow hyprctl clients:*, even though hyprctl clients:* is allowed:
> \cat .claude/settings.local.json
{
"permissions": {
"allow": [
"mcp__web-search-prime__webSearchPrime",
"mcp__web-reader__webReader",
"Bash(head:*)",
"Bash(tail:*)",
"Bash(tail *)",
"Bash(flutter pub get)",
"Bash(flutter build linux --release)",
"Bash(grep:*)",
"Bash(grep *)",
"Bash(flutter build:*)",
"Read(//home/username/.pub-cache/hosted/pub.dev/**)",
"Bash(flutter clean)",
"Bash(cmake *)",
"Bash(dart analyze *)",
"Bash(hyprctl clients:*)",
"Bash(hyprctl monitors:*)"
]
}
}
Python is not allowed, so the Bash tool call is probably blocked because of python, not because of hyprctl clients.
What Should Happen?
TUI should display the correct prompt:
Bash command
hyprctl clients -j | python3 -c "import sys,json; [print(f'at=({c[\"at\"][0]},{c[\"at\"][1]})') for c in json.loads(sys.stdin.read()) if 'popup' in
c.get('title','')]"
Check popup position after manual move
Do you want to proceed?
❯ 1. Yes
2. Yes, and don’t ask again for: python3:*
3. No
Esc to cancel · Tab to amend
Error Messages/Logs
Steps to Reproduce
- Start in a new project
- Ask it to run a piped command of your liking, where both parts will not be allowed
- Allow the first one
- Ask it to rerun this command
- The first command will still be there, even though it is allowed.
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.50 (Claude Code)
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
Other
Additional Information
OS: Arch Linux, EndeavourOS flavor, super custom but I don't think that it should matter.
Terminal: kitty
Default shell: zsh
Sorry if it's a dupe, I searched but couldn't find the similar issue.
10 Comments
Found 2 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Possible duplicates are not relevant. The second command is not executed and the first one seems related but is closed.
There's also an inconsistency about spaces vs colons that happens in these cases.
I have
Bash(git log *)in myallowlist. Claude has no trouble with simplegit log ...commands.But if Claude tries to do
it raises this permissions check:
https://github.com/anthropics/claude-code/blob/main/plugins/plugin-dev/skills/command-development/references/frontmatter-reference.md suggests the colon, which is consistent with the message, but it doesn't explain what the colon means. Is it a case of
bash -cseparating the command from the arguments?Root Cause Analysis
I reproduced this bug by analyzing how
tree-sitter-bash(the parser Claude Code uses for bash command analysis) builds the AST for compound commands.Why It Happens: Bash Operator Precedence in the AST
The key insight is that
|(pipe) has higher precedence than||and&&in bash. This meanstree-sitter-bashparses:as:
But for commands with redirects + logical operators + pipe:
the AST becomes:
The Bug
The prefix extraction algorithm appears to search for the first direct child of type
commandinside apipelinenode — without recursing into wrapper nodes likeredirected_statementorlist.Since
redirected_statementis not acommandtype, it gets skipped. The algorithm then findshead(ortail,grep,python3) — which is the right side of the pipe — and uses that as the prefix.Verified with tree-sitter-bash
I confirmed this AST structure using
web-tree-sitter@0.24.7+tree-sitter-wasms:| Command | Prefix shown | Should be |
|---------|-------------|-----------|
|
wg show 2>/dev/null \|\| cmd 2>&1 \| head -5|head:*|wg:*||
bun init -y 2>/dev/null && bun add ... 2>&1 \| tail -5|tail:*|bun:*||
cat file 2>/dev/null \| head -5|head:*|cat:*||
ls -la 2>&1 \| grep pattern|grep:*|ls:*||
git log ... \| while read ...(from @jamesarosen's comment) |while:*or similar |git:*|Suggested Fix
When traversing a
pipelinenode, if a direct child is not acommand/declaration_command, the algorithm should recurse into it rather than skip it. This wayredirected_statement→list→commandchains are properly followed, and the first real command in the pipeline is found.Pseudocode:
TDD Validation
I built a test suite (13 tests,
node:test+ realweb-tree-sitterparser) comparing the current behavior vs the fixed algorithm. All 13 pass — the fix resolves the bug without breaking simple commands,&&/||lists, semicolons, ordeclaration_command(export,local). Happy to share the repo if helpful.TDD test suite for this bug (13 tests, all green): https://gist.github.com/fedosov/b155ad5b0fe016375dcd65322147dd2a
Tests use
web-tree-sitter+tree-sitter-bashto parse real bash commands and compare the current algorithm (reproduces the bug) vs the fixed one.I'm seeing the opposite thing, for example
somecmd | tail -n 3will keep asking me to allowtaileven thoughtailis already allowed. It's very very frustrating because claude keeps bothering me incessantly. I'm not sure if it's becausesomecmdisn't allowed or what, but over and over again, with many different commands that| tail ...will ask to be allowed (and also commonly forgrep).<img width="1125" height="398" alt="Image" src="https://github.com/user-attachments/assets/8643de9c-77f8-4316-9fbb-7d3591158120" />
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
The bug is still there. See the comment above for a solution. Please reopen the issue.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.