15 KiB
Documentation Index
Fetch the complete documentation index at: https://vineetagarwal-code-claude-code.mintlify.app/llms.txt Use this file to discover all available pages before exploring further.
Permissions API
Reference for permission modes, allow/deny rule syntax, and configuration methods for controlling which tools Claude Code can use without prompting.
The permissions system controls whether Claude Code runs a tool immediately, prompts you for confirmation, or blocks the call entirely. You configure it through permission modes and rule lists that can be set globally, per project, or per session.
Permission modes
A permission mode sets the baseline behavior for all tool calls. Individual allow/deny rules can override this baseline for specific tools or commands.
| Mode | Description |
|---|---|
default |
Prompt for approval on potentially dangerous operations. Safe read-only tools run without prompting. |
acceptEdits |
Auto-approve all file edit operations (Write, Edit, MultiEdit). Bash commands still prompt. |
bypassPermissions |
Skip all permission checks. All tools run without prompting. Requires allowDangerouslySkipPermissions: true in settings. |
plan |
Read-only planning mode. No tool execution; Claude can only read files and explain what it would do. |
dontAsk |
Do not prompt the user. Deny any tool call that is not pre-approved by an explicit allow rule. |
Setting the permission mode
Pass `--permission-mode` to set the mode for a single invocation:```bash theme={null}
claude --permission-mode acceptEdits
claude --permission-mode bypassPermissions --dangerously-skip-permissions
claude --permission-mode plan
```
Set `defaultPermissionMode` in any Claude Code settings file to make it the default for all sessions in that scope:
```json theme={null}
{
"defaultPermissionMode": "acceptEdits"
}
```
Settings files load in this priority order (highest wins):
* `.claude/settings.local.json` — local overrides, not committed
* `.claude/settings.json` — project-level defaults
* `~/.claude/settings.json` — user-level defaults
Run `/permissions` inside a session to open the interactive permissions panel where you can view and edit allow/deny rules. Session-level changes are not persisted to disk.
```
/permissions
```
Change the permission mode programmatically via the control protocol:
```json theme={null}
{
"type": "control_request",
"request_id": "pm-1",
"request": {
"subtype": "set_permission_mode",
"mode": "acceptEdits"
}
}
```
Permission rules
Rules let you pre-approve or block specific tools and commands without changing the global permission mode. Rules are additive across settings scopes — allow rules from all files merge together.
Configuration format
{
"permissions": {
"allow": [
"Bash(git *)",
"Bash(npm run *)",
"Read",
"Write(src/**)",
"mcp__myserver"
],
"deny": [
"Bash(rm -rf *)",
"Bash(curl * | bash)",
"Write(/etc/**)"
]
}
}
Rule syntax
A rule is a string that matches a tool name, optionally with a parenthesized content pattern.
Tool name only — matches every call to that tool:
Read
Write
Edit
Bash
Tool name with content pattern — matches calls where the tool's primary input matches the glob:
Bash(git *)
Bash(npm run *)
Write(src/*)
Edit(*.ts)
For Bash, the pattern is matched against the full command string. For file tools (Write, Edit, Read, Glob), the pattern is matched against the file path argument.
MCP server — matches all tools from a specific MCP server:
mcp__myserver
MCP server wildcard — same as above, explicit wildcard form:
mcp__myserver__*
Specific MCP tool — matches one tool from a server:
mcp__myserver__query_database
Agent type — blocks or allows a specific subagent:
Agent(Explore)
Agent(CodeReviewer)
Pattern matching for Bash
Bash rule patterns use shell-style glob matching on the full command string.
{
"permissions": {
"allow": [
"Bash(git status)",
"Bash(git log *)",
"Bash(git diff *)",
"Bash(npm run test*)",
"Bash(make *)"
],
"deny": [
"Bash(rm *)",
"Bash(sudo *)",
"Bash(* | bash)",
"Bash(* | sh)"
]
}
}
Pattern matching for file tools
File path patterns are matched against the absolute path of the file being read, written, or edited.
{
"permissions": {
"allow": [
"Write(src/**)",
"Write(tests/**)",
"Edit(*.md)",
"Read"
],
"deny": [
"Write(/etc/**)",
"Write(~/.ssh/**)",
"Edit(.env*)"
]
}
}
Permission rule sources and priority
Rules are collected from multiple sources and evaluated in a defined order. When the same tool call matches rules from different sources, deny takes precedence over allow, and the most restrictive result wins.
| Source | Where configured | Editable |
|---|---|---|
policySettings |
Managed policy layer | No |
flagSettings |
CLI flags and SDK control requests | Per-session |
userSettings |
~/.claude/settings.json |
Yes |
projectSettings |
.claude/settings.json |
Yes |
localSettings |
.claude/settings.local.json |
Yes |
cliArg |
--allowedTools / --disallowedTools flags |
Per-invocation |
session |
/permissions command, SDK updates |
Per-session |
--allowedTools and --disallowedTools CLI flags
Pass comma-separated rule strings directly on the command line:
claude --allowedTools "Bash(git *),Read,Write" --print "Run the tests"
claude --disallowedTools "Bash,Write" --print "Summarize this project"
These map to the cliArg source and apply for the duration of the invocation.
Permission decisions
The permission engine evaluates each tool call through a pipeline and returns one of three outcomes.
| Decision | Meaning |
|---|---|
allow |
Tool runs immediately. |
ask |
User is prompted for confirmation. |
deny |
Tool call is blocked; Claude receives an error result. |
Decision pipeline
Claude Code evaluates tool calls in this order:
- Deny rules — if any deny rule matches, the call is blocked immediately.
- Ask rules — if any ask rule matches, the permission dialog is shown.
- Tool's own permission check — the tool's
checkPermissionsmethod runs (e.g., Bash checks individual subcommands). - Safety checks — paths inside
.git/,.claude/,.vscode/, and shell config files always prompt, even inbypassPermissionsmode. - Mode check —
bypassPermissionsand plan mode apply here. - Allow rules — if an allow rule matches, the call is approved.
- Default behavior — if no rule matched, prompt the user.
Working directories
By default, Claude Code restricts file operations to the current working directory and its subdirectories. You can grant access to additional directories.
Via CLI flag
claude --add-dir /path/to/extra/dir
Via settings
{
"permissions": {
"additionalDirectories": [
"/shared/data",
"/home/user/configs"
]
}
}
Via SDK control request
{
"type": "control_request",
"request_id": "dirs-1",
"request": {
"subtype": "apply_flag_settings",
"settings": {
"permissions": {
"additionalDirectories": ["/shared/data"]
}
}
}
}
Permission updates via the SDK
SDK hosts (IDEs, desktop apps) can respond to can_use_tool control requests and include permission updates to persist rule changes alongside their decisions.
PermissionUpdate object
{
"type": "addRules",
"rules": [
{ "toolName": "Bash", "ruleContent": "git *" }
],
"behavior": "allow",
"destination": "userSettings"
}
Permission decision response
When responding to a can_use_tool request, include updatedPermissions to persist rule changes:
{
"type": "control_response",
"response": {
"subtype": "success",
"request_id": "<request_id>",
"response": {
"behavior": "allow",
"updatedPermissions": [
{
"type": "addRules",
"rules": [{ "toolName": "Bash", "ruleContent": "git *" }],
"behavior": "allow",
"destination": "userSettings"
}
],
"decisionClassification": "user_permanent"
}
}
}
Hooks and permissions
PreToolUse and PermissionRequest hooks can inject permission decisions programmatically. See Hooks reference for details on permissionDecision output and hookSpecificOutput.decision.
The hook-based permission flow is especially useful for headless agents that cannot show interactive prompts. When shouldAvoidPermissionPrompts is true (background agent mode), Claude Code runs PermissionRequest hooks before falling back to auto-deny.
Safety recommendations
Use `bypassPermissions` only in isolated, short-lived environments where you control all inputs. Set explicit deny rules for destructive operations as a defense-in-depth measure:```json theme={null}
{
"defaultPermissionMode": "bypassPermissions",
"allowDangerouslySkipPermissions": true,
"permissions": {
"deny": [
"Bash(rm -rf *)",
"Bash(sudo *)",
"Bash(curl * | bash)"
]
}
}
```
Use `default` mode with allow rules for common safe operations. This minimizes interruptions while keeping you in control of destructive actions:
```json theme={null}
{
"defaultPermissionMode": "default",
"permissions": {
"allow": [
"Read",
"Glob",
"Grep",
"Bash(git status)",
"Bash(git log *)",
"Bash(git diff *)",
"Bash(npm run *)",
"Bash(make *)"
]
}
}
```
Use `plan` mode when you want Claude to reason about code without making any changes. Claude can read files and explain what it would do, but cannot write, edit, or run commands:
```bash theme={null}
claude --permission-mode plan "Explain the architecture of this codebase"
```
Use `dontAsk` mode combined with an SDK `PermissionRequest` hook to replace the interactive dialog with your own approval UI. The hook receives every tool call that would have prompted and can allow, deny, or forward it to a human reviewer:
```json theme={null}
{
"defaultPermissionMode": "dontAsk",
"permissions": {
"allow": [
"Read",
"Bash(git *)"
]
}
}
```
Any tool call not matching an allow rule is sent to your `PermissionRequest` hook handler instead of being auto-denied.
Built with Mintlify.