[FEATURE] Allow suppressing bash safety heuristic prompts via settings
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Claude Code's built-in bash safety heuristics trigger interactive "Do you want to proceed?" prompts on common, legitimate shell patterns — and unlike allowlist-based permission prompts, these cannot be permanently suppressed through permissions.allow rules, acceptEdits mode, or "don't ask again."
Patterns that trigger these prompts include:
$()command substitution (e.g.,git commit -m "$(cat <<'EOF'...)"— Claude's own recommended commit format)- Backtick command substitution (e.g., in
gh pr createbodies) - Newlines separating multiple commands (e.g.,
forloops, multi-step scripts) - Empty quotes before dashes ("potential bypass")
- Quote characters inside
#comments ("can desync quote tracking") - ANSI-C quoting ("can hide characters")
- Compound commands with
cdand output redirection
For power users running Claude Code interactively on their own machines, these prompts fire dozens of times per session on routine development commands. The prompts have no "don't ask again" option, so each one requires manual intervention — even when the command prefix is explicitly in the allowlist.
Proposed Solution
A setting to configure the behavior of individual safety heuristic categories. For example:
{
"bashSafety": {
"commandSubstitution": "allow",
"newlines": "allow",
"ansiQuoting": "allow",
"ambiguousSyntax": "prompt"
}
}
Or a simpler blanket setting:
{
"bashSafety": "allow"
}
When set to "allow", the heuristic check would still run but would auto-approve instead of prompting. This preserves the detection logic (it could still log warnings) while removing the interactive friction.
This is the complement to #28993, which proposes auto-deny so Claude reformulates. Both approaches want to eliminate the interactive prompt — this one for users who trust their local shell environment and want flow, #28993 for users who want stricter automatic enforcement.
Alternative Solutions
--dangerously-skip-permissions: Too broad — disables all permission checks, not just heuristics. Intended for containers, not interactive use.- PreToolUse hooks: As noted in #28993, users can write hooks to intercept these, but this requires reimplementing detection logic that Claude Code already has. A configuration toggle would be much simpler.
- Avoiding trigger patterns: Claude could use simpler commands (e.g., no heredocs in commits), but this sacrifices formatting quality and forces workarounds for standard shell patterns.
Priority
High - Significant impact on productivity
Feature Category
Configuration and settings
Use Case Example
- User has
Bash(git:*)in their allowlist andacceptEditsmode enabled - User asks Claude to commit changes
- Claude runs
git add file.php && git commit -m "$(cat <<'EOF' ... EOF)" - Despite the allowlist match, user gets prompted: "Command contains $() command substitution — Do you want to proceed?"
- User approves. Next commit, same prompt. And the next. Every single commit.
- With this feature, user sets
"bashSafety": "allow"and commits flow without interruption
Additional Context
- Related: #28993 (auto-deny direction of same problem)
- The heuristics appear to be a relatively recent addition — users who configured extensive allowlists previously experienced far fewer prompts
- The current behavior creates "ask fatigue" where users reflexively approve every prompt, undermining the security purpose
17 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Not a duplicate. #28993 proposes auto-deny (opposite direction — we want auto-allow). #30213 is specific to
cd && gitin worktrees. #30345 is the closest but is scoped to a single heuristic type and filed as a bug — this issue is a broader feature request for a setting to configure the behavior of all bash safety heuristics, encompassing #30345 and #30213 as specific cases.Also #27957 is related in that any tool which you configure claude to use that utilizes quoted cli commands (ie
beansfor me) will prompt every single change it wants to make. I too want the ability to disable or bypass enforcement of this check either globally or per permitted command. Claude has become unwieldy for me because I have to repeatedly hit Enter for every step of every agent.Same issue here.
allowBashCommandSubstitution: trueis set in both global (~/.claude/settings.json) and project-level settings.local.json — still prompts every time. This is especially painful for git commits since Claude's own system prompt hardcodes the heredoc $() pattern.We run Claude Code headless as a persistent service with
dangerouslySkipPermissions: trueand layer safety on top via hooks instead of interactive prompts. IDE Agent Kit generates this config withinit --ide claude-code.The bash safety heuristics are the main blocker for unattended operation. Heredoc commits, command substitution in git messages, and similar patterns trigger prompts that can't be suppressed through
permissions.allow. For automated workflows, hook-based validation (pre-tool scripts that check the command before execution) is more flexible and doesn't require human presence.A settings flag to suppress specific heuristic categories while keeping the hook system for custom safety rules would make headless operation much more practical.
Same here. Good idea especially for casual users but we gotta have a way to disable these.
Worth noting that the first-party
/code-reviewplugin hits this hard. It spawns parallel subagents that generate bash commands with natural-language#comments (e.g.# Check "make docker build-all"), triggering the quote-tracking prompt dozens of times per run with no way to suppress it —permissions.allowdoesn't help and there's no "don't ask again." It makes/code-reviewessentially unusable in practice, which seems like a good signal for prioritizing a fix here.Adding another voice here. I'm hitting all five of these heuristic checks constantly during normal development on a Python/FastAPI project:
These fire even when the command prefix (curl, python3, while, etc.) is explicitly in my permissions.allow list. The permission system and the safety heuristics are completely orthogonal, which means there's no way to reduce friction for trusted local-only workflows.
A
bashSafetyconfig (granular or blanket) would be hugely appreciated. Even just being able to allow specific categories individually would cover most use cases.+1 this is super annoying. I understand it might have benefits but we need control over it.
Workaround — PreToolUse hook to auto-approve commands that trigger safety heuristics:
The safety heuristic prompts (quoted characters, pipes, redirects) can be bypassed with a PreToolUse hook that approves the command before the heuristic fires:
This runs before the built-in safety heuristic and returns
{"decision":"approve"}, which skips the interactive prompt entirely.npx cc-safe-setupincludes hooks that handle the most common false-positive patterns (cd+git compounds, comment stripping) while still blocking actually dangerous commands.A PreToolUse hook can override the safety heuristic by returning a permission decision:
The hook's
permissionDecision: "allow"bypasses the safety heuristic prompt. You control which commands skip it.For common patterns:
/tmp/gh-comment-30435.md
You can suppress these safety heuristic prompts with a PreToolUse hook that auto-approves commands matching the patterns you've described:
This specifically targets the patterns you listed:
$()command substitution in git commits → approved (git is the base command)gh pr create→ approved (gh is safe)forloops → approved if body commands are all safe#comments → stripped during normalizationThe hook fires before the safety heuristic, so
permissionDecision: "allow"bypasses the interactive prompt entirely.I am getting very tired of all these silly approves. I don't even know what they mean, and the command looks fine. Claude could run a python script to do any of these and as long as I have python allowed, it could perform these. I don't understand why I am getting warned about these commands. It did not used to be this way. Here is a list of all the commands I have found:
I have in my claude.md file imperatives to not use these commands, but claude ignores them. I would very much like to turn these off.
While I agree with the OP's proposal (do allow users to opt-into blanket overrides/disabling of specific safety heuristics), ideally we'd also just have the permission evaluation be smarter about command substitution and such:
"$(...)"should evaluate the substituted command for safety, but should otherwise treat the substitution the same as any string literal."$(cat ...)"is not risky (readonly) unless it's something like"$(cat /etc/shadow)"(sensitive information exposure).$(...), i.e. _without_ surrounding quotes, should be evaluated in terms of argument danger in the command it's passed to:echohas no real danger if given one or many args, soecho $(cat words)is going to be fine, butrm $(cat words)is dangerous due to argument splitting.Hello, the new "Auto Mode" does this evaluation. Since starting to use Auto Mode, I have not been asked to review any silly requests like this. I have a feeling Auto Mode may be doing more than just skipping these silly instances where permission is requested though.
Adding empirical data to support this feature request from systematic testing on Claude Code 2.1.143 (macOS, zsh).
Three-loop characterization of
--permission-modeagainst the "Contains brace with quote character (expansion obfuscation)" heuristic:| Permission mode | Dialog firing rate (n=invocations) |
|---|---|
|
default| 21/21 = 100% ||
acceptEdits| 6/6 = 100% ||
bypassPermissions| 0/6 = 0% |Test invocations included trivial blocks like
{ echo "Hello from T1"; } >> file— pure literal-string echoes with no shell expansion, no command substitution, no risk surface. These trigger the dialog at 100% rate under bothdefaultandacceptEdits.Confirming the OP's framing: the 200+
Bash(...)allow-patterns accumulated in mysettings.local.jsondo not suppress this class. The allow-list operates on exact-command-pattern matches; the heuristic fires on syntactic shape (literal{+"), a different layer.Operator-side mitigation is empirically binary: live with the dialogs (scaling to hundreds per multi-phase scripted cycle in my use case) or run with
bypassPermissionsand accept the platform's intentional sandbox-only trust gate. The intermediateacceptEditsmode does not help with this heuristic class.Why this matters for the proposed
"bashSafety": "allow"setting: The current binary surface forces users with bounded-blast-radius repos (single-user dev environments) to choose between "rubber-stamp 100+ dialogs per session" — which produces ask-fatigue and undermines the heuristic's safety purpose — and "disable all permission checks entirely." The proposed setting would allow heuristic-aware users to preserve allow-list discipline while suppressing the over-broad syntactic class.Strongly support this feature request. Happy to share full diagnostic transcripts if useful for engineering investigation.