Claude Code's permission system has two layers: the permission mode sets the baseline, and allow/ask/deny rules provide fine-grained overrides. The right way to loosen up is to climb these two layers step by step — not to flip on bypassPermissions.
One-line answer
Answer
Four progressive steps: build an allowlist in default mode via "Yes, don't ask again" → switch to
acceptEdits to skip edit confirmations → move up to auto mode and let a classifier do background safety review; meanwhile use ask rules to keep a manual checkpoint on git push and deny rules to block sensitive files. Use bypassPermissions only inside an isolated container/VM — never day-to-day on your own machine.
Steps
- Start in default mode and let approvals settle into rules.OfficialDefault mode (called Manual in the UI) skips confirmation only for reads; Bash commands need approval on first use. When approving, pick "Yes, don't ask again" and the Bash rule is stored permanently in
.claude/settings.local.jsonat the repo root, taking effect for future sessions across the whole repo (including subdirectories and worktrees); approving a compound command (likegit status && npm test) saves it split into sub-commands. File-edit approvals last only until the session ends and are never persisted. After a day or two of use, your everyday commands have accumulated into a realistic allowlist. - Tidy the rules with
/permissions.Official/permissionslists every allow/ask/deny rule and its source file. Evaluation order is fixed: deny → ask → allow, first match wins, and specificity does not change the order (so a broad deny overrides a narrow allow). When hand-writing rules, mind the wildcard semantics:Bash(npm run *)matches commands starting withnpm run; the space inBash(ls *)is a word boundary — it matchesls -labut notlsof. To share with your team, move the rules into.claude/settings.jsonand commit it. - Switch to
acceptEditsand review after the fact.OfficialPressShift+Tabin a session to cycle through modes.acceptEditsauto-accepts file edits inside the working directory plus common filesystem commands (mkdir,touch,mv,cp,sed, etc.); other Bash commands still prompt as usual. It fits the "let it edit, then review everything at once withgit diff" workflow. To make it your default, put"permissions": {"defaultMode": "acceptEdits"}in~/.claude/settings.json. - Move up to auto mode: uninterrupted, but with a backstop.OfficialIn auto mode everything runs automatically while a separate classifier model reviews each action in the background, blocking high-risk operations by default —
curl | bash, force pushes, production deploys, sending secrets out of the repo; boundaries you state in the conversation (like "don't push yet") also count as blocking signals. Two caveats: entering auto mode temporarily revokes broad allow rules that grant arbitrary code execution, such asBash(*)(narrow rules likeBash(npm test)are kept); explicit ask rules still force a prompt. Auto mode requires your account to meet model and other conditions — if it doesn't, it simply won't appear in theShift+Tabcycle. What each mode skips confirmation for:Mode No confirmation needed for Best for default(Manual)Reads only Getting started, sensitive work acceptEditsReads + file edits + common filesystem commands Edit freely, review via diff planReads (when auto is available, classifier-approved commands pass too) Exploring before touching anything autoEverything, with background classifier review Long tasks, fighting confirmation fatigue dontAskOnly pre-approved tools; everything else auto-denied CI, locked-down script environments bypassPermissionsEverything, no review Isolated containers/VMs only - Hold the safety line — what never to allow.OfficialThe explicit official rules: use
bypassPermissionsonly in isolated environments (it even allows writes to protected paths like.gitand.claude, and refuses to start under root/sudo); to stay uninterrupted while keeping a manual checkpoint, add ask rules on push-type actions — the official recipe is"ask": ["Bash(git push *)", "Bash(gh pr create *)"], which forces a prompt even in auto mode; deny sensitive files, e.g.Read(.env),Read(~/.ssh/**). Our takeTwo more practical rules: never allow any download-and-execute command (curl | bash); and remember that Bash prefix rules match the command string — a deny onBash(rm *)won't stop/bin/rmorfind -delete, so when you need a hard guarantee use a PreToolUse hook or the sandbox (see D3 Permission modes & the sandbox). Also remember: permissions are enforced by Claude Code, while "don't do X" written in CLAUDE.md is guidance, not a boundary.
Copy-paste prompt
Upgrade this project's permission setup from "confirm every step" to "fewer interruptions, firm boundaries":
1. Read the allow rules accumulated in .claude/settings.local.json, pick out the
build/test/lint commands worth sharing with the team, and organize them into
permissions.allow in .claude/settings.json;
2. Add "Bash(git push *)" and "Bash(gh pr create *)" to permissions.ask,
keeping a manual checkpoint for pushes and PR creation;
3. Add permissions.deny rules for reading .env, secrets directories, and ~/.ssh;
4. Do not allow any deletion commands, download-and-execute commands (curl|bash),
or commands that change system configuration;
5. When done, explain what each rule does, and tell me how the deny → ask → allow
evaluation order affects this configuration.
Sources & last verified
- Officialpermissions (rule syntax / evaluation order / where rules are saved / managed settings), fetched 2026-08-05.
- Officialpermission-modes (the six modes / how to switch / auto mode's block list / protected paths), fetched 2026-08-05.
- Officialauto-mode-config (manual-checkpoint recipe / trusted infrastructure), fetched 2026-08-05.
- Last verified: 2026-08-05 · volatility:high (auto mode's availability conditions and block rules evolve quickly across versions; as of version 2.1.222).