Short version: update Claude Code first, because recent versions start in auto mode, where a classifier reviews actions instead of you. Then add allow rules for your test and lint commands, an ask rule for git push, deny rules for secrets, and enable the sandbox with /sandbox. Keep --dangerously-skip-permissions for throwaway containers.

Why Claude Code asks

In Manual mode (config value default), the docs give this table of what needs approval:

Tool typeAsks first?If you choose "don't ask again"
File reads, GrepNo, inside the working directoryNot applicable
Bash commandsYes, except a built-in read-only setSaved permanently, per repository and command
File editsYesLasts until the session ends
Web fetchYes, except preapproved documentation domainsSaved permanently, per repository and domain
Web searchYesSaved permanently, per repository

The read-only set includes ls, cat, grep, find, diff and read-only forms of git; those run without a prompt. A permanent approval is saved as a rule in .claude/settings.local.json.

Check your version first

As of 2 October 2026 the docs say that with Claude Code v2.1.283 or later, auto mode is the built-in starting permission mode for interactive terminal sessions on every plan. If you are approving every command, you may be on an older version (claude --version, then claude update), on a model auto mode doesn't support, in an organisation that disabled it, or have defaultMode pinned in a settings file. This area has changed quickly, so check the docs if your version behaves differently.

Permission modes

ModeRuns without asking
default (Manual)Reads only
acceptEditsReads, file edits, and common filesystem commands such as mkdir, mv and cp
planReads; edits stay blocked until you approve a plan
autoEverything, with background safety checks by a classifier model
dontAskReads and pre-approved tools; anything that would prompt is denied
bypassPermissionsEverything

Press Shift+Tab to cycle default, acceptEdits, plan; auto joins the cycle when it is available. Start in a mode with claude --permission-mode acceptEdits, or set permissions.defaultMode in a settings file. auto and bypassPermissions do not take effect from a project's settings files; set them in ~/.claude/settings.json.

Auto mode's classifier blocks things like curl | bash, force pushes, production deploys and sending sensitive data to external endpoints. After three blocks in a row it goes back to prompting you. The docs are direct about its limits: it "reduces permission prompts but does not guarantee safety".

Allow, ask and deny rules

Rules layer on top of whichever mode you use and are the precise tool. In .claude/settings.json:

{
  "permissions": {
    "allow": [
      "Bash(npm run test *)",
      "Bash(npm run lint *)",
      "Bash(git commit *)"
    ],
    "ask": [
      "Bash(git push *)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)"
    ]
  }
}

What the docs say about the syntax:

  • A rule is Tool or Tool(specifier). In Bash rules * matches any text, and a trailing * also matches the bare command.
  • The :* suffix is an equivalent way to write that trailing wildcard, so Bash(npm run test:*) is the same rule as Bash(npm run test *). The space counts: Bash(ls *) does not match lsof, Bash(ls*) does. By that logic neither form covers a script named test:unit; give it its own rule, Bash(npm run test:unit *).
  • Put the * after the subcommand. Bash(git *) allows every git command, push included.
  • Order is deny, then ask, then allow. The first match wins regardless of how specific a rule is, so an allow can't carve an exception out of a deny.
  • Claude Code understands &&, | and ;. Each part of a compound command must match a rule on its own.
  • Bash deny rules match the command text, so Bash(curl *) does not stop /usr/bin/curl. The docs say such rules are not a security boundary. Read deny rules cover the file tools and commands like cat, but not a script that opens the file itself.

Inside a session, /permissions lists every rule with the settings file it came from and lets you add or remove rules while Claude is working.

Where the rules live

  • User: ~/.claude/settings.json, for you in every project.
  • Shared project: .claude/settings.json, committed for the team. Its allow rules apply only after you accept the workspace trust dialog.
  • Project local: .claude/settings.local.json, for you in this project. "Don't ask again" writes here.
  • Managed: deployed by your organisation; nothing you set overrides it.

Precedence, highest first: managed, command-line flags, project local, shared project, user. Rule lists merge across files instead of replacing each other, and a deny at any level beats an allow at any other.

The sandbox

The built-in Bash sandbox confines shell commands at the operating-system level, so they need not be approved one by one. Run /sandbox and choose auto-allow. It works on macOS, Linux and WSL2; on Linux install bubblewrap and socat first (sudo apt-get install bubblewrap socat). Sandboxed commands can write only to the working directory and a temp directory, and the first use of each network domain prompts. Deny rules and specific ask rules such as Bash(git push *) still apply.

Know its limits. It covers shell commands only, not the file tools, MCP servers or hooks. By default it can still read most of the disk, including ~/.ssh, unless you configure sandbox.credentials. The docs call it "not a complete isolation boundary".

What --dangerously-skip-permissions does

The flag is equivalent to --permission-mode bypassPermissions. Tool calls run immediately, including writes to protected paths such as .git and .claude. The documented warning: "Only use this mode in isolated environments like containers, VMs, or dev containers without internet access, where Claude Code cannot damage your host system." The docs add that it "offers no protection against prompt injection or unintended actions" and point to auto mode instead.

Deny rules still block and explicit ask rules still prompt in this mode, and Claude Code refuses to start in it as root or under sudo on Linux and macOS. On your everyday machine, with your SSH keys and cloud credentials in reach, it is the wrong tool.

A sensible setup

  • Use auto mode if you have it; otherwise Manual, switching to acceptEdits while you review diffs in your editor.
  • Allow the read-only, test, lint and build commands you run constantly, each as its own narrow rule.
  • Add ask rules for git push and anything that deploys or deletes. Ask rules prompt even in auto mode.
  • Deny reads of .env files and secret directories.
  • Turn on the sandbox, and keep prompts for whatever writes outside the project or touches the network.

Common questions

How do I disable Claude Code permission prompts completely? claude --dangerously-skip-permissions, but only inside an isolated container or VM. Everywhere else, use auto mode or the sandbox.

How do I skip the permissions prompt for one command? Choose "Yes, and don't ask again" when it appears, or add an allow rule such as Bash(npm run build *).

Why does Claude Code still ask after I allowed a command? Usually a compound command with one part no rule covers, a deny or ask rule that also matches, or project allow rules in a folder you haven't trusted yet.

Is there a shortcut to switch modes? Shift+Tab.

The prompts you keep

Some prompts should stay, and the real cost of those is an agent sitting blocked while you are away. Claude Code can ring the terminal bell or send a desktop notification when it pauses for permission. With Remote Control turned on, the Claude mobile app can push when a permission prompt is waiting. The phone options are compared here. If you work over SSH to your own machine, Melta (coming soon for iPhone and Android) sends a push when an agent is blocked and shows Allow / Deny buttons on the question.

Sources