Permission allow-list captures entire literal commands instead of extracting command patterns

Resolved 💬 4 comments Opened Jan 30, 2026 by karptonite Closed Feb 28, 2026

Description

When approving Bash commands to add to the permission allow-list, Claude Code captures the entire literal command instead of extracting a sensible command pattern. This results in:

  1. Malformed/bloated settings files
  2. Permission rules that will never match future commands
  3. Multi-line commands getting split into nonsensical individual entries

Reproduction Steps

Case 1: Simple command with complex arguments

  1. Run a command like gh issue create --title "..." --body "$(cat <<'EOF'...EOF)"
  2. Approve it for the allow-list
  3. Check .claude/settings.local.json

Expected: Bash(gh issue create:*) or similar pattern
Actual: The entire literal command including the full heredoc body is stored verbatim (~2KB of text in one permission rule)

Case 2: Multi-line bash constructs

  1. Run a for-loop or similar multi-line bash construct
  2. Approve it

Actual result in settings:

"Bash(for i in {1..15})",
"Bash(do)",
"Bash(if tail -5 /tmp/claude/ng-serve.log)",
"Bash(then)",
"Bash(break)",
"Bash(fi)",
"Bash(done)"

These are fragments of a for-loop, not valid standalone commands.

Environment

  • Claude Code Version: 2.1.25
  • OS: macOS Darwin 25.2.0

View original on GitHub ↗

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