skills/settings-clean/SKILL.md
Clean a bloated .claude/settings.local.json by removing redundant, stale, and junk permission entries and ensuring hook-redirected skills are allowed. Use when the user says "clean settings", "prune settings", "settings cleanup", or invokes /settings-clean; also proactively when settings.local.json exceeds ~30 entries. Only touches settings.local.json (gitignored), never settings.json (committed).
npx skillsauth add paulnsorensen/dotfiles settings-cleanInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Prune bloated .claude/settings.local.json files by removing permission entries that are redundant, stale, or junk — and ensure that skills referenced by hooks are actually allowed.
Claude Code's permission system only appends to permissions.allow — it never prunes — so these files grow unbounded. Meanwhile, hooks block legacy tools and redirect to skills that may not be in the allow list, creating a broken redirect loop.
LOCAL: .claude/settings.local.json (in the current project root)
GLOBAL: ~/.claude/settings.json (user-wide settings)
HOOKS: claude/hooks/*.js (PreToolUse hooks — for hook-blocked detection)
SKILLS: skills/*/SKILL.md (available skills — for missing skill detection)
If the local file doesn't exist or has no permissions.allow, skip to Step 6 (skill additions may still apply).
Walk through every entry in the local permissions.allow array. Classify each into exactly one category, checking in this order (first match wins):
These entries are bugs or nonsense. They never match real commands.
| Pattern | Why it's junk |
|---|---|
| Contains __NEW_LINE_ | Claude Code serialization bug for multi-line commands |
| Bash(done), Bash(fi), Bash(then), Bash(else) | Shell keywords, not commands |
| Bash(cd:*) | Shell builtin, doesn't go through Bash tool |
| Bash(for *), Bash(if *), Bash(while *) | Shell keywords captured mid-compound-command |
| Exact duplicate of another entry in the same file | Redundant |
An entry is "covered" when a broader permission already exists, either in global settings or elsewhere in the same local file.
Global coverage — check if the local entry's command prefix matches a global wildcard:
Bash( as the prefixBash(prefix:*), the local entry adds nothingExamples:
Bash(git stash:*) + Global Bash(git:*) → coveredBash(which rustup:*) + Global Bash(which:*) → coveredBash(npm install:*) + Global Bash(npx:*) → NOT covered (different prefix)Same-file coverage — also applies to Bash and Read entries within the local file:
Read(//path/subdir/**) is covered by Read(//path/**)Bash(cargo check:*) is covered by Bash(cargo:*)Bash(python3 -c:*) is covered by Bash(python3:*)For non-Bash entries: check for exact match in global (e.g., local Edit + global Edit → covered).
These are commands the user ran once during a session. They accumulate fast and will never be reused.
| Pattern | Example |
|---|---|
| Hardcoded absolute home path (/Users/, /home/, or ~/) | Bash(bash /Users/paul/Dev/dotfiles/agents/mcp/sync.sh ...) |
| Pipe chains (\|) | Bash(... 2>&1 \| grep -i ...) |
| Command joiners (;, &&, \|\|) | Bash(command -v cargo && cargo --version) |
| Stderr redirects (2>&1, 2>/dev/null) | Debug output capture |
| Bash(bash -x ...) | Debug tracing |
| Bash(find ...) with specific paths | Bash(find ~/Dev/dotfiles/claude -type f ...) |
| Bash(python3 -c ...) with inline code | One-off test snippets |
| Specific PR numbers or commit SHAs | Bash(gh pr merge 395 --rebase ...) |
Exception: Don't flag entries that are just a clean wildcard (e.g., Bash(python3:*), Bash(grep:*)). The patterns above target verbose, specific command strings — not clean tool:* patterns.
Everything else stays:
Skill(*) entries — user enabled these deliberatelymcp__serena__* — intentional (symbol-intelligence MCP)Bash(toolname:*) wildcards not covered by global or same-file — project-specificBash(toolname arg:*) patterns that don't match one-off patternsmcp__* entries not in globalWebFetch(domain:*) entries — intentional domain allowlistsRead() entries not covered by a broader ReadAlways start with dry-run output, regardless of whether the user said --apply.
Format a table grouped by category (see example in Step 7).
Suggest permissions.deny entries that reinforce hook blocks. These act as belt-and-suspenders — if Claude's interactive approval re-adds a blocked command to allow, the deny list catches it.
Recommended deny entries (reinforces hook blocks):
Legacy tools (use dedicated tools instead):
"Bash(grep:*)" → Grep tool or /scout
"Bash(egrep:*)" → Grep tool or /scout
"Bash(fgrep:*)" → Grep tool or /scout
"Bash(sed:*)" → easy-cheese:cheez-write or Edit
"Bash(awk:*)" → easy-cheese:cheez-write or Edit
"Bash(find:*)" → Glob tool or /scout (fd)
Package installs (require per-use approval):
"Bash(npm install:*)" → approve individually
"Bash(pnpm add:*)" → approve individually
"Bash(pnpm install:*)" → approve individually
"Bash(yarn add:*)" → approve individually
"Bash(pip install:*)" → approve individually
"Bash(pip3 install:*)" → approve individually
"Bash(cargo add:*)" → approve individually
"Bash(go get:*)" → approve individually
Hooks redirect blocked commands to skills, but those skills need Skill(name) in the allow list or Claude will prompt for permission — defeating the smooth redirect.
Scan available skills: Read skills/*/SKILL.md to find all skill names. If the skills directory doesn't exist in the current project, check ~/Dev/dotfiles/skills/ (the canonical source).
Map hook redirects to required skills: Each hook block implies a skill that should be allowed:
| Hook blocks | Required skill |
|---|---|
| grep, egrep, fgrep | Skill(scout) |
| sed, awk | Skill(chisel) |
| find | Skill(scout) |
| python3 -c tests | Skill(test-sandbox) |
| dep cache grep, doc+grep | Skill(lookup), Skill(fetch) |
| find+grep chains | Skill(trace), Skill(lookup) |
| cd && git | Skill(wt-git) |
| gh pr create --body | Skill(gh) |
Missing skills — hook-critical (redirect won't work without these):
+ Skill(scout) ← grep/find hooks redirect here
+ Skill(chisel) ← sed/awk hooks redirect here
+ Skill(test-sandbox) ← python3 -c hook redirects here
+ Skill(lookup) ← dep cache/doc grep hooks redirect here
+ Skill(fetch) ← dep cache/doc grep hooks redirect here
+ Skill(trace) ← find+grep chain hook redirects here
Missing skills — available but not allowed:
+ Skill(diff)
+ Skill(de-slop)
+ Skill(make)
+ Skill(self-eval)
...
Combine all recommendations:
Settings Clean: .claude/settings.local.json
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
REMOVALS:
JUNK: 5 entries
HOOK-BLOCKED: 2 entries
COVERED: 10 entries
ONE-OFF: 37 entries
─────────────────────────
Total removed: 54 entries
KEPT: 33 entries
DENY (recommended): 12 entries (reinforces hooks)
SKILLS (recommended): 20 entries (7 hook-critical, 13 available)
Net: 87 allow → 33 allow + 20 skills + 12 deny
The user must explicitly say --apply, "apply", "do it", "clean it", or similar.
When applying:
Backup the current file:
mkdir -p ~/.local/state/dotfiles/backups
cp .claude/settings.local.json ~/.local/state/dotfiles/backups/settings.local.json.$(date +%Y%m%d-%H%M%S)
Write the cleaned file, preserving:
permissions keys (sandbox, hooks, enabledMcpjsonServers, etc.)Report the result:
Backed up to: ~/.local/state/dotfiles/backups/settings.local.json.20260319-143022
Wrote: .claude/settings.local.json
allow: 53 entries (33 kept + 20 skills added, was 87)
deny: 12 entries (new)
settings.json (the committed project settings). Only settings.local.json.tools
Reconstruct what a past coding-agent session was doing so you can resume it — goal, files touched, last verified state, and the next step — by querying the session logs. Use when the user says "what was I working on", "recover that session", "reconstruct where I left off", "resume my last session", "what did that session change", "rebuild context from logs", or invokes /work-recovery. Report-only — it never scores or judges. Do NOT use for usage scoring (that is /skill-improver, /tool-efficiency, /prompt-analytics) or one-off interactive log queries (that is /session-analytics).
development
Curate this repo's hallouminate wiki (.hallouminate/wiki/, the repo:dotfiles:wiki corpus) — add or update architecture pages, per-harness docs, and gotchas. Use when the user says "update the wiki", "document this in the wiki", "refresh the harness docs", "add a wiki page", "curate the wiki", "the wiki is stale", or invokes /wiki-curator. Also use at session end to write back a non-obvious decision or gotcha worth preserving. Grounds the existing wiki first, follows one-topic-per-file conventions, verifies every external doc URL before writing, and reindexes. Do NOT use for general code search (that is cheez-search) or for editing AGENTS.md command reference.
tools
Audit how a tool, command, or MCP server is actually used across coding-agent sessions and produce calibrated recommendations — tool-vs-task fit, error forensics, fix recommendations, permission friction, MCP health, and token economics. Use when the user says "tool efficiency", "am I using X efficiently", "audit tool usage", "why does X keep failing", "how do I fix this error", "what should I change", "permission friction", "is this MCP worth it", "tool error rate", "fix recommendations", or invokes /tool-efficiency. Do NOT use for auditing a skill or agent definition (that is /skill-improver) or for one-off interactive log queries (that is /session-analytics).
tools
Analyze how prompts and skill routing behave across coding-agent sessions and produce calibrated recommendations — prompt-pattern analysis, routing accuracy, and knowledge gaps. Use when the user says "analyze my prompts", "prompt patterns", "is routing working", "which skill should have fired", "knowledge gaps", "what do I keep asking", or invokes /prompt-analytics. Do NOT use for auditing a single skill/agent definition (that is /skill-improver), tool/MCP efficiency (that is /tool-efficiency), or one-off interactive log queries (that is /session-analytics).