settings.local.json fragility: multi-line bash commands corrupt permissions array
Summary
When users approve complex bash commands (especially heredocs, multi-line shell scripts, or commands with nested parentheses), Claude Code splits them into individual entries in settings.local.json's permissions.allow array. This creates entries with mismatched parentheses that fail Claude Code's own validation, causing the entire settings file to be skipped at startup.
Steps to Reproduce
- During a session, approve a bash command containing a heredoc, e.g.:
``bash``
gh api repos/owner/repo/branches/main/protection -X PUT -H "Accept: application/vnd.github+json" --input - <<'JSON'
{
"required_pull_request_reviews": {
"dismiss_stale_reviews": true
}
}
JSON
- Claude Code auto-saves this as multiple separate permission entries:
``json``
"Bash(1 <<'JSON'",
"{",
" \"required_pull_request_reviews\": {",
...
"JSON)"
- On next startup, the parenthesis validator rejects
"Bash(1 <<'JSON'"(unmatched opening paren) and"JSON)"(unmatched closing paren) - The entire
settings.local.jsonis skipped, losing ALL permissions
Actual Results
Settings Error
/var/home/hyper/.claude/settings.local.json
└ permissions
└ allow
├ "Bash(1 <<'JSON'": Mismatched parentheses
└ "JSON)": Mismatched parentheses
Files with errors are skipped entirely, not just the invalid settings.
User loses all 1000+ permission patterns because of 2 bad entries.
Expected Results
At minimum:
- Skip only invalid entries, not the entire file
- Ideally, don't split multi-line commands into separate array entries in the first place
Additional Context
This is a recurring issue. Other patterns that leak into the permissions array include:
- Markdown text from GitHub issue bodies (
## Summary,**System:**, etc.) - Shell control flow fragments (
then,else,fi,done) - Heredoc delimiters (
EOF),<<'EOF') - Bug report prose that happened to be in a bash command's arguments
Over time, the permissions array grows to 1000+ entries, many of which are invalid non-permission junk. A single bad entry with mismatched parens makes the entire file unusable.
Suggested Improvements
- Skip individual bad entries instead of rejecting the whole file
- Validate entries before persisting - check parenthesis balance before writing
- Don't split multi-line commands - store the full command as one entry, or use a hash/pattern rather than the literal command text
- Periodic self-cleanup - prune entries that are clearly not valid permission patterns
Workaround
I wrote a jq-based cleanup script that runs at boot and shell startup to catch and remove invalid entries before Claude Code sees them. Happy to share if useful.
Environment
- Claude Code v2.1.37
- Fedora Kinoite 43 (Linux 6.18.8)
- Bash shell
- Power user with 500+ repos (permissions list grows rapidly)
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗