Claude Code: permission denied
Claude Code's permission system blocked a tool or command. This is by design — but you can configure exactly which tools and commands are allowed without prompting via .claude/settings.json.
Where the error appears
# In Claude Code's UI or logs:
"Claude needs permission to run this command.
Bash: npm run test
[Allow] [Deny] [Allow Always]"
# Or in automated/CI contexts:
"Error: Permission denied for tool: Bash
Command: git push origin main"
Settings file locations
| File | Scope | Git |
|---|---|---|
.claude/settings.json |
Project (current directory) | Commit it |
.claude/settings.local.json |
Project, personal override | Gitignore it |
~/.claude/settings.json |
User (all projects) | Personal |
Minimal settings.json to allow tools
// .claude/settings.json
{
"allowedTools": [
"Bash",
"Read",
"Write",
"Edit",
"Glob",
"Grep"
],
"allowedCommands": [
"npm run test",
"npm run build",
"npm run lint",
"git status",
"git diff",
"git log"
]
}
Committing this file into your repo means everyone on the project gets the same permission policy — great for CI and team consistency.
Full settings.json reference
// .claude/settings.json — all available permission fields
{
// Allow specific named tools without prompting
"allowedTools": [
"Bash",
"Read",
"Write",
"Edit",
"Glob",
"Grep",
"WebFetch",
"WebSearch"
],
// Allow specific bash commands (exact match or glob pattern)
"allowedCommands": [
"npm run *", // any npm run script
"git *", // any git command
"python -m pytest",
"cargo test"
],
// Block specific tools (overrides allowedTools)
"blockedTools": [
"Bash" // never allow bash, even if asked
],
// Permission mode: "default" | "acceptEdits" | "bypassPermissions"
// bypassPermissions skips all confirmation prompts (use in CI only!)
"permissions": {
"mode": "default"
}
}
bypassPermissions mode skips ALL permission checks. Only use it in isolated CI environments — never on a shared machine or with production credentials.CI / non-interactive environments
In CI pipelines where prompts can't be answered, pass the permission flag:
# Allow all tools without prompting (CI mode)
claude --dangerously-skip-permissions "run the test suite and report results"
# Or set via environment variable
CLAUDE_SKIP_PERMISSIONS=1 claude "..."
# Recommended: use a project settings.json instead (more surgical)
# .claude/settings.json with specific allowedTools + allowedCommands
claude "run tests" # uses project settings, no interactive prompts
Permission prompt options explained
# When Claude asks: "Allow running: npm test?"
[Allow] → allow this one time, prompt next time
[Allow Always] → add to allowedCommands permanently (updates settings.json)
[Deny] → block this time, Claude adapts its approach
[Stop] → abort the current task
Clicking "Allow Always" is the fastest way to populate your allowedCommands — Claude updates settings.json for you.
FAQ
Why does Claude keep asking even after I click "Allow Always"?
Check that
.claude/settings.json was actually updated. Sometimes the file write fails if the directory doesn't exist — create .claude/ manually and retry.Can I allow all bash commands at once?
Yes — add
"Bash" to allowedTools without any allowedCommands restriction. This allows any bash command. For production or team repos, be more surgical with specific patterns.Do MCP tool permissions work the same way?
Yes — MCP tool names follow the pattern
mcp__server-name__tool-name. Add them to allowedTools the same way.How do I reset permissions to default?
Delete or empty
.claude/settings.json and ~/.claude/settings.json. Claude will start fresh with default (prompt-on-demand) behavior.