Claude Permissions Optimizer
Claude Permissions Optimizer
Section titled “Claude Permissions Optimizer”Find safe Bash commands that are causing unnecessary permission prompts and auto-allow them in settings.json — evidence-based, not prescriptive.
This skill identifies commands safe to auto-allow based on actual session history. It does not handle requests to allowlist specific dangerous commands. If the user asks to allow something destructive (e.g., rm -rf, git push --force), explain that this skill optimizes for safe commands only, and that manual allowlist changes can be made directly in settings.json.
Pre-check: Confirm environment
Section titled “Pre-check: Confirm environment”Determine whether you are currently running inside Claude Code or a different coding agent (Codex, Gemini CLI, Cursor, etc.).
If running inside Claude Code: Proceed directly to Step 1.
If running in a different agent: Inform the user before proceeding:
“This skill analyzes Claude Code session history and writes to Claude Code’s settings.json. You’re currently in [agent name], but I can still optimize your Claude Code permissions from here — the results will apply next time you use Claude Code.”
Then proceed to Step 1 normally. The skill works from any environment as long as ~/.claude/ (or $CLAUDE_CONFIG_DIR) exists on the machine.
Step 1: Choose Analysis Scope
Section titled “Step 1: Choose Analysis Scope”Ask the user how broadly to analyze using the platform’s blocking question tool (question in Claude Code, request_user_input in Codex, ask_user in Gemini). If no question tool is available, present the numbered options and wait for the user’s reply.
- All projects (Recommended) — sessions across every project
- This project only — sessions for the current working directory
- Custom — user specifies constraints (time window, session count, etc.)
Default to All projects unless the user explicitly asks for a single project. More data produces better recommendations.
Step 2: Run Extraction Script
Section titled “Step 2: Run Extraction Script”Run the bundled script. It handles everything: loads the current allowlist, scans recent session transcripts (most recent 500 sessions or last 30 days, whichever is more restrictive), filters already-covered commands, applies a min-count threshold (5+), normalizes into Bash(pattern) rules, and pre-classifies each as safe/review/dangerous.
All projects:
node <skill-dir>/scripts/extract-commands.mjsThis project only — pass the project slug (absolute path with every non-alphanumeric char replaced by -, e.g., /Users/tmchow/Code/my-project becomes -Users-tmchow-Code-my-project):
node <skill-dir>/scripts/extract-commands.mjs --project-slug <slug>Optional: --days <N> to limit to the last N days. Omit to analyze all available sessions.
The output JSON has:
green: safe patterns to recommend{ pattern, count, sessions, examples }redExamples: top 5 blocked dangerous patterns{ pattern, reason, count }(or empty)yellowFootnote: one-line summary of frequently-used commands that aren’t safe to auto-allow (or null)stats:totalExtracted,alreadyCovered,belowThreshold,patternsReturned,greenRawCount, etc.
The model’s job is to present the script’s output, not re-classify.
If the script returns empty results, tell the user their allowlist is already well-optimized or they don’t have enough session history yet — suggest re-running after a few more working sessions.
Step 3: Present Results
Section titled “Step 3: Present Results”Present in three parts. Keep the formatting clean and scannable.
Part 1: Analysis summary
Section titled “Part 1: Analysis summary”Show the work done using the script’s stats. Reaffirm the scope. Keep it to 4-5 lines.
Example:
## Analysis (systematic)
Scanned **24 sessions** for this project.Found **312 unique Bash commands** across those sessions.
- **245** already covered by your 43 existing allowlist rules (79%)- **61** used fewer than 5 times (filtered as noise)- **6 commands** remain that regularly trigger permission promptsPart 2: Recommendations
Section titled “Part 2: Recommendations”Present green patterns as a numbered table. If yellowFootnote is not null, include it as a line after the table.
### Safe to auto-allow| # | Pattern | Evidence ||---|---------|----------|| 1 | `Bash(bun test *)` | 23 uses across 8 sessions || 2 | `Bash(bun run *)` | 18 uses, covers dev/build/lint scripts || 3 | `Bash(node *)` | 12 uses across 5 sessions |
Also frequently used: bun install, mkdir (not classified as safe to auto-allow but may be worth reviewing)If redExamples is non-empty, show a compact “Blocked” table after the recommendations. This builds confidence that the classifier is doing its job. Show up to 3 examples.
### Blocked from recommendations| Pattern | Reason | Uses ||---------|--------|------|| `rm *` | Irreversible file deletion | 21 || `eval *` | Arbitrary code execution | 14 || `git reset --hard *` | Destroys uncommitted work | 5 |Part 3: Bottom line
Section titled “Part 3: Bottom line”One sentence only. Frame the impact relative to current coverage using the script’s stats. Nothing else — no pattern names, no usage counts, no elaboration. The question tool UI that immediately follows will visually clip any trailing text, so this must fit on a single short line.
Adding 22 rules would bring your allowlist coverage from 65% to 93%.Compute the percentages from stats:
- Before:
alreadyCovered / totalExtracted * 100 - After:
(alreadyCovered + greenRawCount) / totalExtracted * 100
Use greenRawCount (the number of unique raw commands the green patterns cover), not patternsReturned (which is just the number of normalized patterns).
Step 4: Get User Confirmation
Section titled “Step 4: Get User Confirmation”The recommendations table is already displayed. Use the platform’s blocking question tool to ask for the decision:
- Apply all to user settings (
~/.claude/settings.json) - Apply all to project settings (
.claude/settings.json) - Skip
If the user wants to exclude specific items, they can reply in free text (e.g., “all except 3 and 7 to user settings”). The numbered table is already visible for reference — no need to re-list items in the question tool.
Step 5: Apply to Settings
Section titled “Step 5: Apply to Settings”For each target settings file:
- Read the current file (create
{ "permissions": { "allow": [] } }if it doesn’t exist) - Append new patterns to
permissions.allow, avoiding duplicates - Sort the allow array alphabetically
- Write back with 2-space indentation
- Verify the write — tell the user you’re validating the JSON before running this command, e.g., “Verifying settings.json is valid JSON…” The command looks alarming without context:
If this fails, the file is invalid JSON. Immediately restore from the content read in step 1 and report the error. Do not continue to other files.
Terminal window node -e "JSON.parse(require('fs').readFileSync('<path>','utf8'))"
After successful verification:
Applied N rules to ~/.claude/settings.jsonApplied M rules to .claude/settings.json
These commands will no longer trigger permission prompts.If .claude/settings.json was modified and is tracked by git, mention that committing it would benefit teammates.
Edge Cases
Section titled “Edge Cases”- No project context (running outside a project): Only offer user-level settings as write target.
- Settings file doesn’t exist: Create it with
{ "permissions": { "allow": [] } }. For.claude/settings.json, also create the.claude/directory if needed. - Deny rules: If a deny rule already blocks a command, warn rather than adding an allow rule (deny takes precedence in Claude Code).