Permission rules with subshell syntax $() generate malformed :* patterns
Resolved 💬 3 comments Opened Apr 4, 2026 by jaybna Closed Apr 8, 2026
Bug
When a user approves a Bash tool call containing subshell syntax like kill $(lsof -ti:8080), Claude Code auto-saves a permission rule to .claude/settings.local.json with the :* wildcard placed inside the subshell instead of at the end of the pattern.
Examples of malformed rules generated
"Bash(kill $(lsof:*)" // unbalanced parens, :* inside subshell
"Bash(kill $(lsof:*))" // :* inside subshell, not at end
Expected
Either:
- Skip auto-saving rules for commands containing
$((since the prefix pattern can't represent them correctly) - Or generate a valid prefix like
Bash(kill:*)by truncating before the subshell token
Impact
One malformed rule causes the entire settings.local.json file to be skipped on next launch. The error message is:
Settings Error
/Users/user/Projects/myproject/.claude/settings.local.json
└ permissions
└ allow: Invalid permission rule "Bash(kill $(lsof:*))" was skipped:
The :* pattern must be at the end. Move :* to the end for prefix matching,
or use * for wildcard matching
Files with errors are skipped entirely, not just the invalid settings.
This means all 100+ valid permission rules in the file are also lost, causing permission prompts for every previously-approved command until the malformed rule is manually found and removed.
Reproduction
- Start a Claude Code session in any project
- Run a command that uses subshell syntax, e.g.
kill $(lsof -ti:8080) - When prompted, approve and save the permission ("Always allow")
- Inspect
.claude/settings.local.json— the saved rule will have:*misplaced - Restart Claude Code in that project — Settings Error appears
Environment
- Claude Code CLI on macOS
- Observed repeatedly across multiple projects over several weeks
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗