Claude Code, the easy way
Sep 2, 2026
6 min read

Permissions: stop clicking Allow all day (safely)

How Claude Code decides when to ask, which permission mode to pick, and a starter allow, ask and deny list you can paste into a content or ops project today.

Every permission prompt is Claude Code asking a fair question: may I do this? The trouble starts when it asks forty times an afternoon and you start pressing Enter without reading. A prompt you don't read is worse than no prompt at all, because it feels like safety and isn't.

The fix isn't to switch the checks off. It's to answer the boring questions once, in writing, so the prompts that remain are the ones worth reading.

How a prompt happens

Claude Code sorts everything Claude wants to do into kinds of action. Reading and searching files inside your project folder (your "working directory") needs no approval. Running shell commands, editing files, fetching web pages and searching the web do, unless something has already approved them. A built-in set of read-only commands, such as ls, cat, grep and read-only git, also runs without asking.

A prompt usually offers yes once, yes and don't ask again, or no. "Don't ask again" on a shell command or a web domain is saved as a rule in .claude/settings.local.json at the root of your project, so it sticks for future sessions. Approvals for file edits last until the session ends.

One small trick: move to Yes or No and press Tab to attach a note. "No, put that in drafts/ instead" saves a round of back and forth.

Pick a permission mode

A permission mode is the baseline for how much Claude can do without asking. Rules (next section) adjust it.

ModeWhat runs without askingUse it for
default (labeled Manual)Reads onlySensitive work, unfamiliar folders
acceptEditsReads, file edits, and basic file commands like mkdir, mv and cp in your folderDrafting sessions you'll review
planReads, while Claude works out a plan before changing anythingThinking before acting
autoMost things, with a second model (the "classifier") checking riskier actions against your requestLong tasks where you trust the direction
dontAskOnly what your rules pre-approve; everything else is refusedScripts and unattended runs
bypassPermissionsNearly everythingThrowaway containers or virtual machines only

In the terminal, press Shift+Tab to cycle modes; the status bar shows which one is on. To start in a mode, pass it as a flag:

claude --permission-mode acceptEdits

In the desktop app, use the mode selector under the prompt box. Plan mode has its own post: Plan mode: think before it types.

Recent versions of Claude Code start terminal and VS Code sessions in auto mode where it's available. If you're drowning in prompts, check the status bar: you're probably in Manual mode, or auto mode isn't available on your plan, model or organization. Anthropic is clear that auto mode "reduces permission prompts but does not guarantee safety," so treat it as a convenience for work you understand, not a replacement for review.

To change the mode your sessions start in, set defaultMode in your user settings at ~/.claude/settings.json:

{
  "permissions": {
    "defaultMode": "acceptEdits"
  }
}

auto and bypassPermissions only take effect from your user settings (or the command line), not from a project's settings files. That's deliberate: a folder you downloaded can't switch your safety off.

Rules: allow, ask, deny

Rules are where the real time savings live. There are three lists:

  • allow: run without a prompt
  • ask: always prompt, even in auto mode
  • deny: never run

Claude Code checks deny first, then ask, then allow, and the first match wins. A narrow allow can't punch a hole in a broad deny. Deny rules hold in every mode, including bypassPermissions.

Every rule is either a tool name or a tool name with a specifier in brackets:

RuleWhat it matches
Bash(git commit *)Any command starting git commit. The * stands for any text
Bash(npm run build)Exactly that command, nothing else
Edit(/drafts/**)Edits anywhere under drafts/ in the project
Read(./.env)Reading the .env file
WebFetch(domain:docs.stripe.com)Fetching pages from that domain
mcp__notion__*Every tool from an MCP server you named notion
WebSearchEvery web search

Three details that trip people up:

  1. Put the star after the subcommand. Bash(git log *) allows only git log. Bash(git *) allows every git command, including push.
  2. Use Edit, not Write, for paths. Path rules written as Write(...) are accepted but never match. Edit(...) covers every tool that changes files, including creating new ones.
  3. Path anchors matter. In a project settings file, a leading / means "from the project folder". Use ~/ for your home folder and // for an absolute path. ** means any depth.

Claude Code also understands shell operators. An allow rule for Bash(git status *) won't approve git status && rm -rf notes, because every piece of a compound command has to be allowed on its own.

Which file your rules live in

FileWho it affectsGood for
~/.claude/settings.jsonYou, in every projectPersonal rules, your default mode
.claude/settings.jsonEveryone who uses this folder (commit it)Shared project rules
.claude/settings.local.jsonYou, in this project onlyPersonal exceptions; where "don't ask again" lands

Organizations can also push managed settings that override all three. Rules from every file combine, and a deny anywhere wins. Allow rules in a project's committed .claude/settings.json only apply after you accept the trust dialog for that folder, so a cloned repo can't quietly grant itself access.

Run /permissions at any time to see every rule, which file it came from, and to add or remove one.

A starter list for a content or ops project

Picture a folder with drafts/, research/, published/, a .env with API keys, and git for version history. Here's a sensible first pass:

.claude/settings.json
{
  "permissions": {
    "allow": [
      "Edit(/drafts/**)",
      "Edit(/research/**)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "WebSearch",
      "WebFetch(domain:code.claude.com)",
      "WebFetch(domain:docs.stripe.com)"
    ],
    "ask": [
      "Bash(git push *)",
      "Edit(/published/**)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Bash(curl *)",
      "Bash(wget *)"
    ]
  }
}

What it does, line by line:

  • Claude can edit drafts and research freely, commit its work, search the web and read the docs sites you name.
  • Pushing to a shared remote and touching published work always asks first.
  • Claude's file tools can't read your secrets, and the obvious ways of sending data out through the shell (curl, wget) are off. Claude can still fetch pages through its own web tool, which you control per domain.

Swap the domains for the ones you actually use, and add exact rules for your own scripts, like Bash(npm run build). Want a head start? The built-in /fewer-permission-prompts skill scans your past sessions for common read-only commands and proposes an allowlist for .claude/settings.json. Read what it suggests before you accept it.

What never to auto-allow

Some rules look like time savers and are really blank cheques:

  • Bash on its own, or Bash(*). That's every shell command.
  • Interpreters and runners with a wildcard, like Bash(python *), Bash(node *) or Bash(npx *). They run whatever comes after them. Auto mode drops broad rules like these when it starts, which tells you how Anthropic rates them.
  • Bash(git *), which includes push and history rewrites.
  • Deletes, like Bash(rm *). Keep these on a prompt.
  • MCP tools that send, pay or publish: email sends, refunds, social posts. Allow the read tools by name; keep the write tools on ask. More in MCP in plain English.
  • bypassPermissions on your real machine. Anthropic's docs say to use it only in isolated environments like containers or VMs.

Start narrow and widen as you learn what you actually approve. It's much easier to add a rule than to undo what a loose one allowed.

Sandboxing: a fence, not a guard

Rules match the text of a command, so they aren't a wall. A deny on Bash(rm *) doesn't stop /bin/rm, and a deny on curl doesn't stop sh -c 'curl ...'. For an actual boundary, turn on the sandbox by typing /sandbox in a session, or set sandbox.enabled to true in a settings file.

With the sandbox on, your operating system limits every shell command Claude runs: writes only inside your project folder and a temp folder, and network access only to domains you allow. It works on macOS out of the box; Linux and WSL2 need two small packages (bubblewrap and socat); native Windows isn't supported. In its auto-allow mode, sandboxed commands run without prompts, because the fence does the job the prompt was doing.

Your five-minute setup

  1. Check which mode your sessions start in, and set defaultMode if you want a different one.
  2. Paste the starter list into .claude/settings.json, adjust the folders and domains, and commit it.
  3. Keep personal extras in .claude/settings.local.json.
  4. Run /sandbox if you're on macOS, Linux or WSL2.
  5. Once a week, open /permissions and delete anything you don't recognize.

If you're new to Claude Code, start with your first hour. If you plan to run it unattended, read keeping agents cheap and safe before you loosen anything.

Sources