> permissions & tools
Permissions are how Claude Code stays safe while still being autonomous: a permission mode sets the baseline for what runs without asking, and allow/deny rules layer specific exceptions on top. This section covers choosing a mode (default, acceptEdits, plan, dontAsk, bypassPermissions), the flags that pre-approve or deny individual tools for a run, and the persistent rules you keep in settings.json. Deny always beats allow, and rules merge across every settings scope.
// permissions & tools
4 commands$ claude --permission-mode plan$ claude --dangerously-skip-permissions$ claude -p "run the tests and fix failures" --allowedTools "Bash,Read,Edit"$ { "permissions": { "allow": ["Bash(npm run test:*)"], "deny": ["Read(./.env)"] } }// faq
What are the permission modes and what does each allow?
default reads files only and asks before edits or commands; acceptEdits also writes files and auto-approves common filesystem commands like mkdir and mv; plan is read-only and writes a plan before touching anything; dontAsk allows only pre-approved tools (good for locked CI); bypassPermissions allows everything except protected directories, for containers only. Cycle them with Shift+Tab or start in one with --permission-mode.
Is --dangerously-skip-permissions safe to use?
Only in a disposable sandbox. It runs every tool call, shell command, and file write with no confirmation, which is the point for containers and throwaway VMs but a real hazard on your main machine — a bad command can delete files or leak data unchallenged. Never point it at untrusted code.
How do I stop a headless run from pausing on permission prompts?
Pre-approve the tools it needs with --allowedTools "Bash,Read,Edit", or set a baseline mode like --permission-mode acceptEdits or dontAsk. Entries use permission-rule syntax, so Bash(git diff *) allows any git diff command — mind the space before * or it also matches git diff-index.
Why is a command still blocked after I allowed it?
Permission rules merge across all settings scopes, and deny always overrides allow. A deny rule in a project, local, or managed-policy settings file — possibly one you didn't write — can block a command your allow rule matched. Run /permissions to inspect the effective rules and find the deny that's winning.