[BUG]
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Claude Code's auto-approval permission system stores literal multi-line command arguments as approval patterns instead of using wildcards.
When a user approves a bash command containing a long heredoc (for example git commit -m "$(cat <<'EOF' ... EOF)"), the entire literal command text (including 400+ lines of commit message content) is saved as an auto-approval rule and embedded into every conversation's system prompt, consuming ~26,000 tokens before any work begins.
Impact:
- Performance: Wastes 13% of token budget (26k out of 200k) before user does any work
- Cost: Higher API costs due to inflated input tokens on every conversation start
- UX: Slower conversation starts, reduced available context window
- Scope: Affects any workflow using heredocs (git commits, inline scripts, JSON/YAML, multi-line configurations)
What Should Happen?
Auto-approval rules should use wildcard patterns rather than literal command text.
Instead of storing:
Bash(git commit -m "$\(cat <<''EOF''...[400+ line literal message]...EOF\)")
Approval rules should use:
Bash(git commit -m:*)
or:
Bash(git commit:*)
This would prevent large command arguments from being embedded into future system prompts and avoid unnecessary token consumption.
Error Messages/Logs
Example from debug log (~/.claude/debug/[session-id].txt):
2026-01-28T13:21:27.182Z [DEBUG] Applying permission update: Adding 26 allow rule(s) to destination 'localSettings': ["Bash(git commit -m \"$\\(cat <<''EOF''...[massive literal text]...EOF\\)\")"]
The literal command text is stored in:
- Session JSONL files (.claude/projects/[project-path]/*.jsonl)
- Debug logs (.claude/debug/*.txt)
- Loaded into system prompt on every conversation start
- Token consumption visible at conversation startup (26,000+ tokens before any user work)
Steps to Reproduce
- Execute a git commit with a large heredoc message:
``bash``
git commit -m "$(cat <<'EOF'
[... 400+ lines of commit message ...]
EOF
)"
- Approve the command when prompted by Claude Code
- Start a new conversation in the same project directory
- Observe ~26k–27k tokens consumed immediately during initial context load due to auto-approval rules being injected into the system prompt
Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.0.76
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
iTerm2
Additional Information
Environment:
- Claude Code Version: 2.0.76
- OS: macOS (Darwin 25.2.0)
- Model: claude-sonnet-4-5-20250929
- Installation: CLI
Related Issues:
This issue is related to several existing bugs but adds a critical new dimension:
- #16462 - Permission parser corrupts settings when approving heredoc commands
- #15742 - Multi-line bash permission patterns corrupt settings.json
- #11932 - Auto-approve patterns don't match multiline commands
While the above issues focus on settings corruption and pattern matching failures, this report quantifies the token consumption impact that occurs even when the permission system doesn't corrupt files. The literal command storage creates measurable performance and cost degradation.
Suggested Fix:
- Pattern matching logic: When storing approval rules, detect and convert literal arguments to wildcards (especially for heredocs, command substitution, and other multi-line constructs)
- Retroactive cleanup: Provide a way to clean/reset permission rules without losing all session history
- UI/validation: Warn users or auto-convert when approval patterns exceed reasonable size (e.g., >500 chars)
- Command structure vs arguments: The permission system should distinguish between command structure (what should be pattern-matched for approval) and command arguments (which should be wildcarded)
Current Workaround:
Delete the entire project session directory:
rm -rf ~/.claude/projects/[project-path]/
This clears permissions but also loses all conversation history for the project.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗