[BUG] Multi-line bash commands are fragmented when saved to settings.local.json
[BUG] Multi-line bash commands are fragmented when saved to settings.local.json
Description
Claude Code CLI incorrectly fragments multi-line bash commands when saving them to .claude/settings.local.json during runtime. This results in invalid permission entries that cannot be parsed correctly.
Environment
- Claude Code Version: 2.1.16
- OS: macOS (Darwin 25.1.0)
- Installation Method: native
- Observed in: Multiple projects (agents-sdk, user-story-agent-dev, dev-agent)
Steps to Reproduce
- Start Claude Code CLI in a project directory
- Run a multi-line bash command, for example:
``bash``
for f in docs/work/tickets/*/; do echo "=== $f ==="; done
- Check
.claude/settings.local.jsonafter the session - Observe fragmented entries in the
permissions.allowarray
Expected Behavior
The permission should be saved as a single entry that represents the complete command pattern, such as:
{
"permissions": {
"allow": [
"Bash(for *)"
]
}
}
Or the multi-line command should be normalized to a pattern that makes sense as a permission entry.
Actual Behavior
The multi-line command is incorrectly split into multiple invalid entries:
{
"permissions": {
"allow": [
"Bash(for dir in /Users/jflavigne/agents-sdk/docs/work/tickets/*/)",
"Bash(done)",
"Bash(while read f)",
"Bash({} ;)"
]
}
}
Evidence
From /Users/jflavigne/agents-sdk/.claude/settings.local.json (166 lines total):
{
"permissions": {
"allow": [
// ... other valid entries ...
"Bash(done)", // Line 32 - Fragment from loop
"Bash({} ;)", // Line 68 - Fragment
"Bash(while read f)", // Line 108 - Incomplete loop
"Bash(for dir in /path/to/tickets/*/)", // Line 151 - Loop start
// ... more entries ...
]
}
}
These entries trigger validation warnings:
Agent Parse Errors
└ Failed to parse 6 settings entries
Impact
High Severity - This bug causes:
- Immediate user-facing errors: "6 invalid settings" warnings appear when opening Claude Code
- Persistent corruption: Since
settings.local.jsonis treated as PROTECTED during updates, corrupted entries persist indefinitely - Propagation across projects: When using deployment scripts that copy
.claude/settings.local.json, the corruption spreads to new projects - Doctor command noise: Users see persistent validation warnings that cannot be easily resolved
Root Cause Analysis
Based on investigation:
- Claude Code modifies
.claude/settings.local.jsonat runtime to add permission entries for executed commands - When processing multi-line bash commands (loops, conditionals, complex pipes), the parser appears to split on shell keywords (
for,do,done,while, etc.) or delimiters - Each fragment is saved as a separate permission entry
- These fragments are syntactically invalid as standalone bash patterns
Propagation Chain
Work in project → Run multi-line bash → Fragmented entries saved
↓
settings.local.json corrupted
↓
Use project as deployment SOURCE
↓
deploy-agent.sh copies corrupted file
↓
Target project now corrupted
↓
Updates skip settings.local.json (PROTECTED)
↓
Corruption persists forever
Proposed Fix
Option 1: Don't save multi-line commands to permissions
- Detect multi-line bash commands (contain
\n,;,&&, etc.) - Skip adding them to
settings.local.json
Option 2: Normalize to patterns
- Extract the base command(s) and save as wildcards
- Example:
for f in *; do cat $f; done→["Bash(for *)", "Bash(cat *)"]
Option 3: Save complete command as single entry
- Escape/encode the full multi-line command
- Ensure it's valid JSON
Workaround
For users experiencing this:
- Manually clean
.claude/settings.local.json:
``bash``
# Remove malformed entries
# Keep only valid patterns like "Bash(command *)"
- Before deploying dev-agent to new projects, reset the source's settings.local.json:
``bash``
echo '{"permissions": {"allow": []}}' > .claude/settings.local.json
Additional Context
This bug was discovered while investigating recurring "6 invalid settings" warnings across multiple projects. The investigation revealed that:
- Fresh
composeoutput generates cleansettings.local.json - During runtime, Claude Code appends permission entries
- Multi-line commands get fragmented
- Deployment scripts copy the corrupted file to new projects
- PROTECTED file status prevents automatic fixes during updates
Related Files
.claude/settings.local.json- Affected filescripts/deploy-agent.sh- Propagates corruption via copy- Claude Code CLI runtime - Source of fragmentation
---
Reproduction Rate: 100% when running multi-line bash commands
User Impact: All users who:
- Run multi-line bash commands in Claude Code sessions
- Deploy dev-agent using active development directories as source
- Use worktree workflows with shared configurations
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗