Analyze permission prompts and auto mode denials, then generate permission rules and autoMode entries that cut prompt fatigue. Use when prompts keep interrupting, auto mode falls back to prompting, or after sessions with many denials.
Reduce permission prompts by fixing their causes, not by piling up rules.
Use when:
allow cannot override it.Bash(*), wildcarded interpreters like Bash(node *), package-manager run commands, Agent, and Monitor.Rules merge across scopes, so check every file that exists, not only the user file. /permissions shows the rules Claude Code actually loaded, and claude auto-mode config shows the effective autoMode (the classifier ignores autoMode in .claude/settings.local.json).
for f in ~/.claude/settings.json .claude/settings.json .claude/settings.local.json; do
[ -f "$f" ] && jq --arg f "$f" '{file: $f, mode: .permissions.defaultMode, allow: (.permissions.allow|length), ask: (.permissions.ask|length), deny: (.permissions.deny|length), autoMode: (.autoMode != null)}' "$f"
done
claude auto-mode config
ls -t ~/.claude/projects/*/*.jsonl | head -20 | xargs grep -ho '"toolDenialKind":"[^"]*"' | sort | uniq -c | sort -rntoolDenialKind values seen in transcripts (undocumented, may change): permission-rule (rule or hook), automode-blocked (classifier), automode-parsing-error and automode-unavailable (no verdict, not tunable), user-rejected (you said no).
| Symptom | Fix |
|---|---|
| Prompt on something you always approve | Remove or narrow the ask rule |
permission-rule on a harmless command | Fix the hook false positive or narrow the deny rule |
| Classifier blocks work in your own repos, registries, local services | Add an autoMode.environment entry |
| Classifier blocks one routine pattern | Add an autoMode.allow entry |
| Want outward actions only when you asked | Add an autoMode.soft_deny entry |
| Want a human check every time | Keep a short permissions.ask rule |
{
"permissions": {
"allow": [
"Bash(git status)",
"Bash(npm test)",
"Bash(npm run lint)"
],
"ask": [
"Bash(git push --force*)",
"Bash(git push * main)",
"Bash(git push * main *)",
"Bash(git push *:main)",
"Bash(git push *:main *)",
"Bash(git push * master)",
"Bash(git push * master *)",
"Bash(git push *:master)",
"Bash(git push *:master *)",
"Bash(gh pr merge *)",
"Bash(npm publish*)"
],
"deny": [
"Bash(rm -rf *)",
"Read(**/.env)",
"Read(**/.env.*)"
]
},
"autoMode": {
"environment": [
"$defaults",
"Source control: repositories under github.com/your-org are trusted; feature-branch pushes are routine."
],
"allow": ["$defaults"],
"soft_deny": [
"$defaults",
"Merging a pull request needs the user's approval for that specific merge."
]
}
}autoMode only takes effect in ~/.claude/settings.json, managed settings, or --settings. Keep "$defaults" in each list. Check the result with claude auto-mode config and review custom rules with claude auto-mode critique.
PERMISSION TUNER REPORT
Mode: [mode] Rules: [X] allow, [Y] ask, [Z] deny autoMode: [yes/no]
Denials: [n] permission-rule, [n] classifier, [n] no verdict, [n] you rejected
Remove (ask rules you always approve):
- Bash(...) -- approved [n]x
Add to autoMode.environment:
+ "..." -- clears [n] blocks
Add to autoMode.allow / soft_deny:
+ "..."
Fix hooks:
! [script] blocked [n] harmless commands
Keep asking:
~ force push, merge, publish, deploy
Estimated prompts saved per session: ~[N]autoMode entries over new ask rulesautoMode into project settings86d5f27
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.