xiaohongshu
xiaohongshu
configuring-permissions
Use when adding allow/deny rules to Claude Code, granting project permissions, troubleshooting "permission denied" errors, "skill requires approval" prompts, or setting up shared team permissions. Also use when working with git worktrees and permissions aren't being inherited.
Full skill instructions
Before using this skill: Check .state file — if missing or last_evaluated > 7 days ago, warn user and research current CC issues before proceeding.
find ~/.claude/plugins -path "*/claude-code/skills/configuring-permissions/.state" 2>/dev/null | head -1
Full procedure: freshness-check.md
Claude Code permissions control which tools/skills can run without prompting. Core principle: prompt grants update memory immediately; manual edits require restart.
Before modifying project settings: Check if changes affect a team (git shortlog -sne --all | head -10). User-level Skill(*) won't help teammates — team projects need project-level config.
Full decision flow: team-detection.md
| Method | Restart? | Why |
|---|---|---|
| Prompt grant | No | Updates file AND in-memory simultaneously |
| Manual settings.json edit | Yes | File only read at startup |
When manually editing settings.json, tell user:
Restart Claude Code for the new permission to take effect.
Common mistake: Using marketplace name instead of plugin name.
| Plugin Identifier | Correct Pattern | Wrong Pattern |
|---|---|---|
superpowers@superpowers-marketplace | Skill(superpowers:*) | Skill(superpowers-marketplace:*) |
hookify@claude-plugins-official | Skill(hookify:*) | Skill(claude-plugins-official:*) |
The format is Skill(plugin-name:skill-name), NOT Skill(marketplace-name:skill-name).
To find the correct plugin name: Look at the part BEFORE the @ in the plugin identifier.
MCP permissions support three patterns (docs):
| Pattern | Matches |
|---|---|
mcp__server | All tools from server |
mcp__server__* | All tools (wildcard, equivalent) |
mcp__server__tool | Specific tool only |
Example:
{
"permissions": {
"allow": [
"mcp__serena",
"mcp__claude-in-chrome",
"mcp__effect-docs"
]
}
}
Fully qualified names (e.g., mcp__serena__find_symbol) only needed to allow specific tools while denying others from the same server.
Note: Issue #3107 (July 2025) claimed wildcards weren't supported, but current docs confirm both patterns are valid and equivalent.
Skill(*) is broken everywhere:
~/.claude/settings.json (user): buggy, sometimes ignored (#5140, #10833).claude/settings.json (project): doesn't work at all.claude/settings.local.json (project local): works, but see team workaround belowFor individuals: Use explicit patterns in user settings:
"Skill(plugin-name:*)"
Extract plugin names from enabledPlugins keys (the part before @).
For teams — Option A (simple, no personal overrides):
Commit .claude/settings.local.json with skill permissions. Tradeoff: team members can't have personal overrides without merge conflicts.
For teams — Option B (recommended, allows personal overrides): Use a SessionStart hook to sync baseline permissions:
.claude/settings.local.json.example (committed) with baseline permissions.claude/settings.local.json gitignored#!/bin/bash
# .claude/scripts/sync-local-permissions.sh
EXAMPLE=".claude/settings.local.json.example"
LOCAL=".claude/settings.local.json"
[[ ! -f "$EXAMPLE" ]] && exit 0
if [[ ! -f "$LOCAL" ]]; then
cp "$EXAMPLE" "$LOCAL"
echo "Created $LOCAL from example. Restart CC for permissions to take effect."
exit 0
fi
CURRENT=$(jq -S '.permissions.allow // [] | sort' "$LOCAL" 2>/dev/null || echo '[]')
BASELINE=$(jq -S '.permissions.allow // [] | sort' "$EXAMPLE" 2>/dev/null || echo '[]')
MERGED=$(jq -n --argjson a "$CURRENT" --argjson b "$BASELINE" '$a + $b | unique | sort')
if [[ "$CURRENT" != "$MERGED" ]]; then
jq --argjson allow "$MERGED" '.permissions.allow = $allow' "$LOCAL" > "$LOCAL.tmp" && mv "$LOCAL.tmp" "$LOCAL"
echo "Added baseline permissions. Restart CC for changes to take effect."
fi
Hook in .claude/settings.json:
{
"hooks": {
"SessionStart": [{ "hooks": [{ "type": "command", "command": ".claude/scripts/sync-local-permissions.sh" }] }]
}
}
Benefits: team gets baseline permissions, individuals can add extras without conflicts.
Tracking: #10833 — when fixed, move to settings.json and simplify.
| File | Scope | Committed? | Precedence |
|---|---|---|---|
~/.claude/settings.json | User (global) | No | Lowest |
.claude/settings.json | Project | Yes | Middle |
.claude/settings.local.json | Project local | Usually no | Highest |
Select "Yes, and don't ask again" → adds to appropriate settings file, no restart needed.
{
"permissions": {
"allow": ["Bash", "Skill(superpowers:*)"],
"deny": []
}
}
digraph team_permissions {
"Project permission needed" [shape=box];
"settings.local.json committed?" [shape=diamond];
"Works for user only" [shape=box];
"Share with team?" [shape=diamond];
"Add to settings.local.json" [shape=box];
"Override gitignore + commit" [shape=box];
"Project permission needed" -> "settings.local.json committed?";
"settings.local.json committed?" -> "Add to settings.local.json" [label="yes"];
"settings.local.json committed?" -> "Works for user only" [label="no"];
"Works for user only" -> "Share with team?";
"Share with team?" -> "Override gitignore + commit" [label="yes"];
"Share with team?" -> "Add to settings.local.json" [label="no"];
"Override gitignore + commit" -> "Add to settings.local.json";
}
Check: git ls-files .claude/settings.local.json
To share with team, override gitignore:
.claude/
!.claude/settings.local.json
Why commit: Team members get permissions automatically; worktrees don't inherit uncommitted files.
| Tool | Default | Notes |
|---|---|---|
| Bash | Ask | Shell commands |
| Edit | Ask | File modifications |
| Write | Ask | File creation/overwrite |
| MultiEdit | Ask | Batch file edits |
| NotebookEdit | Ask | Jupyter cell modifications |
| WebFetch | Ask | URL fetching |
| WebSearch | Ask | Web searches |
| Skill | Ask | Plugin/local skills |
No permission required: Glob, Grep, Read, NotebookRead, Task, TodoWrite
# TOOLS (bare = all uses)
Bash # All bash commands
Edit # All file edits
Write # All file writes
MultiEdit # All multi-edits
WebFetch # All web fetches
WebSearch # All web searches
# BASH (prefix matching, NOT regex)
Bash(npm run build) # Exact command
Bash(npm run test:*) # Commands starting with "npm run test:"
Bash(git *) # Commands starting with "git "
# FILE PATHS (gitignore-style globs)
Read(~/**) # Read files in home (recursive)
Read(/src/**) # Relative to settings file location
Read(//absolute/path/**) # Absolute filesystem path (note: //)
Edit(*.md) # Edit markdown files
Write(.claude/**) # Write to .claude directory
# SKILLS
Skill(plugin-name:*) # All skills from a plugin
Skill(plugin-name:skill-name) # Specific skill from plugin
Skill(local-skill-name) # Local skill (no colon)
# MCP SERVERS
mcp__server # All tools from server
mcp__server__* # All tools (wildcard, equivalent)
mcp__server__tool # Specific tool only
# WEB
WebFetch(domain:example.com) # Specific domain only
| Skill Location | Example | Permission Pattern |
|---|---|---|
~/.claude/skills/foo/ | User local skill "foo" | Skill(foo) |
.claude/skills/bar/ | Project local skill "bar" | Skill(bar) |
Plugin hookify@marketplace | Plugin skill "list" | Skill(hookify:list) or Skill(hookify:*) |
Key distinction: Local skills have NO colon. Plugin skills have plugin-name:skill-name.
Problem: CC doesn't properly handle symlinked ~/.claude/settings.json:
Impact: Dotfiles users (stow, chezmoi symlinks, custom scripts) can't sync settings.json normally.
Workaround: Don't symlink settings.json. Let CC own ~/.claude/settings.json at runtime.
For dotfiles ergonomics, create a reverse convenience symlink (gitignored) from your dotfiles repo to the runtime file:
# In dotfiles repo (gitignored):
ln -s ~/.claude/settings.json dotfiles/claude/settings.json
This lets you edit from your dotfiles workspace while CC owns the actual file.
Alternative tools:
| Prefix | Meaning | Example |
|---|---|---|
/path | Relative to settings file | /src/** → <settings-dir>/src/** |
//path | Absolute filesystem | //Users/me/code/** |
~/path | Home directory | ~/.config/** |
Common mistake: /Users/me/... is NOT absolute — use //Users/me/...
Skill(*) doesn't work reliably anywhere:
settings.json: doesn't work at allsettings.local.json: works but blocks personal overridesTeam workaround: Commit settings.local.json with explicit skill patterns. See Skill Permissions above.
Skills with allowed-tools in frontmatter don't actually grant permissions. The skill loads, reports correct allowedTools, but Bash commands are still denied.
Workaround: Add patterns to global allow list directly.
When plugins share a source directory, disabling one loads all skills anyway. enabledPlugins settings have no effect.
Impact: ~35-40k tokens wasted on unwanted skills.
~/.claude/settings.json permissions may not apply. Same rules work in project .claude/settings.local.json.
| Issue | Fixed | Description |
|---|---|---|
| #9814 | Oct 2025 | UI grant overwrites list |
| #8581 | Oct 2025 | Bash wildcards + env vars |
| #3107 | Jul 2025 | MCP wildcards not honored |
| #10093 | Jan 2026 | Plugin-scoped permissions (NOT_PLANNED) |
When scripts modify settings.json:
SETTINGS_FILE="$HOME/.claude/settings.json"
PERMISSION="Skill(hookify:*)"
# Check if already present (avoid duplicates)
if ! jq -e --arg p "$PERMISSION" '.permissions.allow | index($p)' "$SETTINGS_FILE" >/dev/null 2>&1; then
# Atomic write: tmp file + mv
jq --arg p "$PERMISSION" '.permissions.allow += [$p]' "$SETTINGS_FILE" > "$SETTINGS_FILE.tmp" \
&& mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
fi
.tmp, then mvjq -e ... | index($p) to avoid duplicatesjq empty "$SETTINGS_FILE" to verify valid JSONLOCK_FILE="$HOME/.claude/settings.json.lock"
exec 200>"$LOCK_FILE"
flock -n 200 || { echo "Settings locked"; exit 1; }
# ... do work ...
flock -u 200
* matches any characters; ** matches directory depthxiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience