Every time Claude Code wants to do something that touches your machine — edit a file, run a command, fetch a URL — it asks. This is the single most important safety feature of the tool, and the single most common thing newcomers want to switch off. This lesson explains how the permission model works and, more importantly, when it's safe to loosen it.
Why permissions exist
Claude is fast, capable, and occasionally wrong. The combination is hazardous. An agent that can edit and delete files at the speed of thought is also an agent that can delete the wrong file at the speed of thought.
The permission system is the brake. It forces a tiny pause — long enough for you to glance at what Claude wants to do and make sure it's sensible. Most of the time you click approve and move on; the small fraction of the time you don't click is when the system earns its keep.
What you'll see
When Claude wants to use a tool that requires permission, a box appears in the terminal:
Claude wants to run this command: rm -rf node_modules [A] Approve once [B] Approve always for this command [N] No, don't run this
Three things to read carefully:
- The tool — is this an Edit, a Bash command, a WebFetch?
- The target — which file, which URL, which command exactly?
- The scope— is "always approve" really what you want, or just this one time?
rm is fine; rm -rf / is catastrophic. Make sure the path or argument matches what you actually intended.Approve-once vs. approve-always
Two different shortcuts, two different uses.
Approve oncemeans "let this one specific action through, ask me again next time." Use it for anything slightly unusual, anything that touches a file you care about, or anything you're still building trust in.
Approve alwaysadds the tool/command to an allowlist for the current project. Use it for commands you run constantly and that have low blast radius — running tests, listing files, checking git status. Don't use it for rm, git push, or anything that talks to production.
The settings file
Approvals are stored in .claude/settings.json inside your project (or, for global rules, in a similar file in your home folder). It looks roughly like:
{
"permissions": {
"allow": [
"Bash(npm run test)",
"Bash(git status)",
"Read",
"Glob"
],
"deny": [
"Bash(git push --force *)"
]
}
}Read and Glob being globally allowed is reasonable for almost everyone — they can't change anything. Specific Bash patterns are how you allowlist exact commands. And the denylist lets you guarantee certain dangerous patterns will never be auto-approved even if you accidentally click "always."
The "accept edits" mode
Edit operations get their own toggle: a mode where every file edit is automatically approved. You enter this mode with Shift + Tab(or via a menu). It's extremely useful once you trust Claude with a particular task — you stop having to click approve fifty times during a refactor — but it comes with the obvious trade-off: no checkpoint.
A good middle ground: use accept-edits mode for the bulk of a big task, but exit it before any irreversible step (commits, pushes, deletes).
Bypass-permissions mode
There's also a fully off switch — usually called bypass-permissions mode. Everything is auto-approved. No prompts. Claude becomes much faster and much more capable of catastrophe.
When is this OK?
- Inside a sandbox, container, or virtual machine where the blast radius is contained.
- On disposable folders where the worst case is "delete and start over."
- For specific automated workflows you've thoroughly tested.
When is it not OK?
- On your primary work machine, on real projects, on a normal day.
Per-project vs. global settings
Some permissions make sense globally (e.g., always allow Read); some are project-specific (e.g., allow the deploy command only in your deploy repo). Claude Code looks at both your project-level and your global settings; project settings win for overlapping rules.
A practical approach: a small global allowlist for the ubiquitously-safe stuff (Read, Glob, Grep), and per-project allowlists for the specific commands a given codebase runs all the time (its test runner, its build, its deploy script).
- Claude asks before doing anything that touches your machine. That's the safety brake; respect it.
- Read the target, not just the tool.
rmis fine;rm -rf important-folderis not. - Use approve-once for unusual things. Approve-always for the safe, repetitive ones.
.claude/settings.jsonrecords your approvals. You can also pre-allow or deny specific patterns there.- Bypass-permissions mode exists. Use it only in sandboxes you can afford to lose.