Audit Claude Permissions
Scan project-local Claude Code settings files, aggregate permission patterns, and recommend promotions to global configuration.
Workflow Overview
This audit runs in three phases, each as a separate task. Use TaskCreate at the start to create all three tasks, then work through them sequentially with user input via AskUserQuestion.
- Phase 1: Promote to Global — Requires user judgment. Present candidates, get decisions, apply to global config.
- Phase 2: Automated Redundancy Cleanup — Script-driven. After Phase 1 promotions, run cleanup script to remove local permissions now covered by global. Present for sanity-checking, then apply.
- Phase 3: Judgment Calls — Everything requiring user input: security hygiene, policy conflicts, one-off cruft, empty file deletion, moderate-risk items.
Initial Setup
- Check for symlinked global settings:
readlink -f ~/.claude/settings.json
If the global settings file is a symlink, note the real path. All writes to ~/.claude/settings.json must edit the symlink target, not create a new file that replaces the symlink.
-
Load user preferences from
~/.claude/cc-maintenance.local.md(if it exists). See User Preferences section below. Apply any configured defaults (risk tolerance, auto-cleanup preference). -
Read global CLAUDE.md from
~/.claude/CLAUDE.mdto identify tool preference policies for Phase 3 policy conflict detection. -
Run the discovery and extraction pipeline:
scripts/discover-settings.sh | xargs scripts/extract-permissions.py
-
Read the actual global settings from
~/.claude/settings.json— compare against the real allow list, not just the static examples in this skill. -
Create tasks for the three phases:
TaskCreate: "Review and promote permissions to global config"
TaskCreate: "Automated redundancy cleanup"
TaskCreate: "Judgment calls: security, policy, and cruft"
- Analyze the data and categorize permissions (see Categorization Rules below).
Phase 1: Promote to Global
Goal: Identify permissions worth adding to global config and get user approval.
Present Findings
Show a summary table of promotion candidates:
## Promotion Candidates
### Strong Recommendations (safe patterns, multiple projects)
| Permission | Projects | Suggested Global Pattern |
| ---------- | -------- | ------------------------ |
| ... | ... | ... |
### Moderate Recommendations (review carefully)
| Permission | Projects | Notes |
| ---------- | -------- | ----- |
| ... | ... | ... |
### Cross-Project File Patterns
[If any Read/Write/Edit permissions reference paths outside their project directory
and appear in multiple projects, flag them here. Example: multiple projects have
`Write(~/.config/some-tool/config.json)` - might indicate a shared config worth
adding globally.]
Get User Decision
Use AskUserQuestion to let the user decide:
Question: "Which permissions should I add to global settings?"
Options:
- "Add all strong recommendations"
- "Add strong + moderate recommendations"
- "Let me pick specific ones" (then list individually)
- "Skip - don't add any"
Apply Changes
If user approves additions:
- Add selected permissions to
~/.claude/settings.json(or symlink target) - Respect existing logical groupings (git, nix, gh, etc.)
- Sort alphabetically within groups
- Use space-syntax:
Bash(cmd *)notBash(cmd:*) - Mark Phase 1 task as completed
Phase 2: Automated Redundancy Cleanup
Goal: Remove local permissions now covered by global config. This is mechanical — the script identifies exact matches; user just sanity-checks the list.
Preview Cleanup
Run the cleanup script in dry-run mode:
scripts/discover-settings.sh | scripts/cleanup-redundant.py
Present Findings
Show what would be removed:
## Redundant Permissions
| File | Permissions to Remove | Remaining |
| --------- | --------------------- | --------- |
| project-a | 5 (ls _, grep _, ...) | 12 |
| project-b | 3 (gh api \*, ...) | 8 |
| ... | ... | ... |
**Total:** X permissions across Y files
The script also normalizes any remaining colon-syntax (Bash(cmd:*)) to space-syntax (Bash(cmd *)) when applying.
Get User Decision
If auto_cleanup_redundant: true in user preferences, skip the question and apply directly (still show the summary). Otherwise:
Question: "Should I remove these redundant permissions from local files?"
Options:
- "Yes, clean them up"
- "Show me the full list first"
- "Skip cleanup"
Apply Changes
If user approves:
scripts/discover-settings.sh | scripts/cleanup-redundant.py --apply
Mark Phase 2 task as completed.
Phase 3: Judgment Calls
Goal: Everything that requires real user judgment — security risks, policy conflicts, stale cruft, and cleanup opportunities. Present all categories together.
Category A: Security Hygiene
Flag permissions that match these patterns:
High Risk (recommend removal):
Bash(curl *),Bash(wget *)— network exfiltration riskBash(rm *)— can delete any fileBash(source *)— executes arbitrary scriptsBash(eval *)— arbitrary code execution
Moderate Risk (review):
Bash(git reset *),Bash(git checkout *)— can discard workBash(pkill *),Bash(kill *)— process terminationBash(python *),Bash(python3 *),Bash(node *)— arbitrary code (flag if user hasn't consciously chosen this)
Adjust what counts as "moderate" vs "high" based on the user's risk_tolerance preference if set.
Category B: Policy Conflicts
Read the user's global ~/.claude/CLAUDE.md for stated tool preferences. Flag local permissions that conflict with those policies.
How to detect: Look for patterns like "prefer X over Y", "use X instead of Y", "avoid Y". Then scan all local permissions for uses of the deprecated tool. For example:
If CLAUDE.md says "prefer tool X over built-in Y", flag all
Ypermissions across local settings as policy conflicts.
Present these as informational — the user may have valid reasons for specific overrides.
Category C: One-Off Cruft
- Hardcoded file paths (e.g.,
Bash(prettier --write /full/path/to/file.md)) - Incomplete shell constructs (
Bash(done),Bash(for file in *.rs)) - Very specific commands with no wildcards that look like debugging artifacts
- Duplicate entries
- Legacy colon-syntax permissions (
Bash(cmd:*)) that weren't caught by the cleanup script (e.g., ones without a global equivalent)
Category D: Cross-Project File Access
Read,Write, orEditpermissions for paths outside the project- Flag if the same external path appears in multiple projects (potential global candidate)
- Flag broad patterns like
Write(~/.config/*)as security concerns
Category F: MCP Tool Permissions
- Flag MCP tools with write/send/delete capabilities (message sending, data deletion, post creation) — these have side effects beyond the local environment
- Flag server-wide wildcards (
mcp__server__*) — convenient but auto-permits any future tools added to that server without review - Suggest consolidation: if all or most tools from a server are individually listed, suggest replacing with the server wildcard (with a note about the trade-off)
Category E: Empty File Deletion
After cleanup, identify settings files where:
- All permissions have been removed (empty allow list or no allow list)
- No other settings exist (no hooks, enabledPlugins, etc.)
Offer to delete these empty files entirely — they serve no purpose.
Present Findings
## Judgment Calls
### Security Hygiene
#### High Risk — Recommend Removal
| Permission | Project | Risk |
| -------------- | --------- | ----------------- |
| `Bash(curl *)` | proj