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

  1. Start a Claude Code session in any project
  2. Run a command that uses subshell syntax, e.g. kill $(lsof -ti:8080)
  3. When prompted, approve and save the permission ("Always allow")
  4. Inspect .claude/settings.local.json — the saved rule will have :* misplaced
  5. Restart Claude Code in that project — Settings Error appears

Environment

  • Claude Code CLI on macOS
  • Observed repeatedly across multiple projects over several weeks

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗