Problem
Claude Code security pre-checks flag commands with patterns like:
- Backticks inside single-quoted strings (e.g.
git commit -m 'fix \encoding` issue'`)
#-prefixed lines after quoted newlines (e.g. --body '## Summary ...')
$() command substitution (even safe patterns like $(cat <<'EOF' ...))
These pre-checks override allow rules entirely (by design, see anthropics/claude-code#11932).
The approve_safe_commands.py PermissionRequest hook was created to auto-approve safe commands, but it cannot override all pre-check types. For example, the "quoted newline followed by #-prefixed line" check still prompts the user even when the hook returns {"behavior": "allow"}.
Current state
approve_safe_commands.py handles some cases via PermissionRequest hook
- AIRULES.md rule 8 instructs agents to use single-quoted multiline strings
- Some pre-checks still bypass the hook
Options considered
PreToolUse hook
Runs before all pre-checks and can bypass the entire permission system with permissionDecision: "allow". However, this also bypasses deny rules, making the hook a single point of trust for command safety. Too powerful for comfort.
Ideal solution
Related upstream issues
Problem
Claude Code security pre-checks flag commands with patterns like:
git commit -m 'fix \encoding` issue'`)#-prefixed lines after quoted newlines (e.g.--body '## Summary ...')$()command substitution (even safe patterns like$(cat <<'EOF' ...))These pre-checks override allow rules entirely (by design, see anthropics/claude-code#11932).
The
approve_safe_commands.pyPermissionRequest hook was created to auto-approve safe commands, but it cannot override all pre-check types. For example, the "quoted newline followed by #-prefixed line" check still prompts the user even when the hook returns{"behavior": "allow"}.Current state
approve_safe_commands.pyhandles some cases via PermissionRequest hookOptions considered
PreToolUse hook
Runs before all pre-checks and can bypass the entire permission system with
permissionDecision: "allow". However, this also bypasses deny rules, making the hook a single point of trust for command safety. Too powerful for comfort.Ideal solution
Related upstream issues
*does not match multiline commands (missingsflag in RegExp)