settings.local.json accumulates invalid permission entries (heredocs, shell fragments)

Resolved 💬 3 comments Opened Feb 12, 2026 by hyperpolymath Closed Feb 16, 2026

Bug Description

settings.local.json (both global ~/.claude/ and project-level .claude/) accumulates invalid and malformed permission entries over time. This causes /doctor to report "Invalid Settings" errors and the file grows with junk entries that should never have been persisted.

Reproduction

  1. Use Claude Code normally over several sessions
  2. Run /doctor
  3. Observe "Invalid Settings" errors from malformed permission entries

What gets persisted incorrectly

1. Heredoc content saved as permission patterns

When a user approves a Bash command that contains a heredoc, the entire heredoc content (potentially hundreds of lines) gets saved as a single permission entry. Examples from my settings file:

"Bash(/tmp/test_hnsw.rs << 'ENDTEST'\nuse hnsw_rs::prelude::*;\nuse hnsw_rs::hnsw::Hnsw;\n...100+ lines of Rust code...\nENDTEST)"
"Bash(git commit -m \"$(cat <<''EOF''\nfeat(hir): wire concurrency expressions through HIR lowering\n...50+ lines of commit message...\nEOF\n)\")"

These are one-off commands that will never match again. They bloat the file and can trigger validation errors (e.g., when the heredoc content happens to contain patterns like :* that confuse the permission parser).

2. Shell fragments saved as standalone permissions

Parts of bash loops/conditionals get split out and saved as individual permission entries:

"Bash(then)",
"Bash(else)",
"Bash(fi:*)",
"Bash(done)",
"Bash(do:*)",
"Bash(while:*)",
"Bash(1)"

These are not valid standalone commands - they're fragments of multi-line shell constructs.

3. Shell conditional fragments

"Bash(then echo \"$repo\")",
"Bash(else echo \"✗ $repo (missing)\")",
"Bash(then has_sec=\"\")",
"Bash(! grep -q \"rsr-template-repo\" STATE.scm)",
"Bash(! test -d .machines_readable)"

Specific /doctor error

The entry that triggered the validation failure:

Invalid Settings
/var/mnt/eclipse/repos/.claude/settings.local.json
 └ permissions
   └ allow
     └ "Bash(/tmp/test_hnsw.rs << 'ENDTEST'
       ...
       ENDTEST)": The :* pattern must be at the end.

Expected Behavior

  1. Heredoc commands should either not be persisted as permission patterns, or should be normalized to just the command prefix (e.g., Bash(cat <<EOF:*) or just not saved)
  2. Shell fragments (then, else, fi, done) should not be saved as standalone permission entries - they should be recognized as parts of a compound command and either the full compound command should be saved or nothing
  3. Permission entries should be validated before being written to the settings file to prevent entries that will later fail /doctor validation

Frequency

This happens repeatedly — multiple times per day in heavy usage sessions. The file grows continuously with these junk entries and periodically one of them triggers an actual validation error.

Environment

  • Claude Code: 2.1.39 (native)
  • OS: Fedora 43 (Atomic/Silverblue)
  • Platform: Linux x86_64

Workaround

Manually edit settings.local.json to remove the offending entries.

View original on GitHub ↗

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