settings.local.json auto-append corrupts JSON with complex Bash commands
Bug
When a user approves a Bash command in Claude Code's permission prompt, the exact command string is auto-appended to .claude/settings.local.json. Complex commands containing heredocs, nested quotes, escaped parentheses, or multi-line strings produce entries that fail JSON parsing on the next session startup.
Reproduction
- Start a Claude Code session in any project
- Have Claude run a complex Bash command, e.g.:
```bash
gh release create v1.0.0 --title "v1.0.0" --notes "$(cat <<'EOF'
## Release notes
- Feature (with parens)
EOF
)"
```
- Approve the permission prompt
- Close the session, start a new one
- Result: Settings Error on startup — the saved entry can't be parsed back
Error shown on startup
Settings Error
C:\Users\...\settings.local.json
└ permissions
└ allow
└ "Bash("/c/Program Files/GitHub CLI/gh
└ exe" release create v0
└ 1
└ 0 --title "v0
...
The :* pattern must be at the end.
Additional issue: redundant appends when wildcards exist
Even when .claude/settings.json (the committed, non-local file) already contains a matching wildcard pattern like Bash(git *), approving a git commit command still causes an append to settings.local.json with the exact command string. This means:
settings.local.jsongrows indefinitely across sessions- Wildcard patterns in
settings.jsondon't suppress the auto-append behavior - Users have to periodically clean
settings.local.jsonmanually
Expected behavior
- Complex command strings should be safely serialized to JSON, or simplified to a wildcard pattern before saving
- If a wildcard in
settings.jsonalready matches the command, no entry should be appended tosettings.local.json - At minimum, entries that would produce invalid JSON should not be written
Workaround
Pre-populate .claude/settings.json (committed, not auto-modified) with broad wildcard patterns:
{
"permissions": {
"allow": [
"Bash(git *)",
"Bash(bash *)",
"Bash(gh *)"
]
}
}
This reduces (but doesn't fully eliminate) the auto-append behavior, since Claude Code doesn't need to prompt for commands matching these patterns.
Environment
- Claude Code CLI (latest as of 2026-02-10)
- Windows 11 + Git Bash
- Also likely reproducible on macOS/Linux with any complex Bash command containing heredocs
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗