Invalid entries written to settings.local.json when allowing Bash commands
Description
Claude Code CLI writes invalid entries to settings.local.json when users allow certain Bash commands, causing the entire settings file to be skipped with the error "Files with errors are skipped entirely."
Problem Cases
1. Shell parameter expansion fragments saved as separate entries
When a command containing shell parameter expansion like ${var%%pattern} or ${var##pattern} is allowed, fragments are incorrectly saved as separate entries:
Original command (in a for loop):
for device in "192.168.1.1:device1"; do
name="${device%%:*}"
ip="${device##*:}"
done
Incorrectly saved as:
"Bash(name=\"$device%%:*\")",
"Bash(ip=\"$device##*:\")"
These are not valid Bash commands and cause parser errors.
2. Regex patterns with .* cause parser confusion
Commands containing regex .* are saved as-is:
"Bash(... grep -E 'pattern.*here' ...)"
The parser then incorrectly interprets * as a wildcard pattern (expecting :* format) and reports:
"Use:*for prefix matching, not just*"
Impact
- Settings file becomes invalid and is skipped entirely
- Invalid entries accumulate over time as more commands are allowed
- Users must manually clean up the settings file
Expected Behavior
- Validate entries before writing to
settings.local.json - Reject or escape entries containing problematic patterns (
%%,##, standalone*) - Or: properly parse shell syntax to avoid fragmenting commands
Environment
- Claude Code CLI (latest)
- macOS
Workaround
Manually remove invalid entries from .claude/settings.local.json using:
import json, re
with open('.claude/settings.local.json', 'r') as f:
data = json.load(f)
data['permissions']['allow'] = [
item for item in data['permissions']['allow']
if not re.search(r'(?<![:])\*|%%|##', item)
]
with open('.claude/settings.local.json', 'w') as f:
json.dump(data, f, indent=2)This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗