← Back to all free guides

The Claude
Code Safety
Hack

Too scared to let Claude Code run on its own? Write an allow list and a deny list once. The safe stuff runs without asking, and the dangerous stuff stays blocked in every mode. Here’s exactly how, plus my lists to copy.

If you use Claude Code, you’ve hit this wall. You want it to just run, building, testing and fixing, without stopping to ask about every step. The scary shortcut is bypass permissions mode, where Claude can run almost anything with no prompts.

There’s a smarter middle built right in. You tell Claude Code ahead of time which commands are always fine, which ones need your OK, and which ones it is never allowed to run. Set it up once and you stop babysitting.

Quick Note

This is for Claude Code, the version of Claude that runs commands and edits files on your computer (in the terminal, the desktop app or VS Code), not the regular chat app. "Permissions" are the rules for what it can do on your machine.

Three Lists Beat One Scary Switch

Claude Code checks every action against three kinds of rules. (Anthropic’s permissions docs)

01

Allow: green light

Commands on your allow list run without a pop-up. Put the boring stuff you do a hundred times a day here, like starting your app, running tests or saving work with git. Simple reads like ls, cat and git status already run without asking, so you don’t need to list those.

02

Deny: hard wall

Commands on your deny list are blocked. This is for the truly dangerous stuff, like bulk-deleting folders, force-pushing over your code, or anything with sudo. Rules are enforced by Claude Code itself, so Claude can’t argue its way past them in the chat.

03

Ask: your call

Commands on your ask list always stop and check with you first, even in bypass mode. Use it for anything that goes live, like pushing code or deploying.

04

Deny always wins

Claude Code checks deny first, then ask, then allow, and the first match decides. An allow rule can’t carve an exception out of a deny rule, and Anthropic says deny rules block in every mode, including bypass permissions. (Permission modes)

Anything not on a list behaves normally for whatever mode you’re in.

My Allow + Deny List

Here’s a safe starting point for a typical web project. It lets the everyday commands run, blocks the destructive ones, and asks before anything goes live or deletes a file. Swap the npm lines for the commands your project actually uses.

permissions block for .claude/settings.json
{ "permissions": { "allow": [ "Edit", "Bash(npm run dev)", "Bash(npm run build)", "Bash(npm test *)", "Bash(npm install)", "Bash(mkdir *)", "Bash(git add *)", "Bash(git commit *)", "Bash(git pull)", "Bash(git switch *)", "Bash(git stash *)" ], "deny": [ "Bash(rm -rf *)", "Bash(rm -fr *)", "Bash(rm -r *)", "Bash(sudo *)", "Bash(git push --force *)", "Bash(git push -f *)", "Bash(git reset --hard *)", "Bash(git clean *)", "Bash(chmod 777 *)", "Bash(curl *)", "Bash(wget *)", "Bash(mkfs *)", "Bash(dd *)", "Read(./.env)", "Read(./.env.*)", "Read(**/.env)", "Read(./secrets/**)", "Read(~/.ssh/**)" ], "ask": [ "Bash(rm *)", "Bash(git push *)", "Bash(git checkout *)", "Bash(npm publish *)", "Bash(npm run deploy *)", "Bash(vercel *)", "Bash(netlify deploy *)" ] } }

How To Read These Rules

Each rule is a tool name with the command in parentheses. A * means "anything here," so Bash(npm test *) covers npm test and npm test --watch. The older :* ending, like Bash(ls:*), still works the same way. A bare name like Edit covers the whole tool. Settings files are strict JSON. A comment or a trailing comma makes Claude Code flag the file as broken.

I left npx, node and python off the allow list on purpose. Those run whatever comes after them, so allowing them is close to allowing everything. Allow your exact scripts instead.

Let Claude Write Yours

Don’t want to guess which commands your project uses? Open Claude Code in your project folder and paste this. It reads your project, drafts all three lists and explains each rule before it saves anything.

Build My Permission Lists
You are my Claude Code safety reviewer. Your job is to write the permission rules for this project so I can work fast without risking my files. Step 1. Look around this project without changing anything. Read package.json (or requirements.txt, Makefile, or whatever this project uses), the README, and any existing .claude/settings.json and .claude/settings.local.json. Note the commands I run all the time (dev server, build, tests, installs) and anything that deploys, publishes, deletes, or touches secrets. Step 2. Sort those commands into three lists: - allow: everyday commands that only build, test, or save work locally - ask: anything that goes live, publishes, pushes, deletes single files, or switches branches - deny: anything that bulk-deletes, force-pushes, wipes uncommitted work, runs as sudo, downloads from the internet in the shell, or reads secret files (.env, keys, a secrets folder) Step 3. Show me the result as one strict JSON "permissions" block (no comments, no trailing commas) using the Claude Code rule format, like Bash(npm run build) or Bash(git push *) or Read(./.env). Step 4. Under the JSON, give me a short table: each rule, which list it is on, and one plain-English line on why. Rules for you: - Do not put broad runners in allow, like Bash(npx *), Bash(node *), Bash(python *), or plain Bash. Allow the exact scripts instead. - If you are unsure about a command, put it in ask, not allow. - Do not write or edit any settings file until I say "save it". Then merge into .claude/settings.json without deleting rules that are already there.
Now Put It To Work

01

The easy way: use the menu

In Claude Code, type /permissions and hit enter. You can see every rule, which file it came from, and add or remove rules without editing anything. Every time Claude asks to run a command you know is safe, pick "Yes, and don’t ask again." That saves an allow rule for this project, so your list builds itself around how you work.

02

The paste way: settings file

In your project folder, open or create .claude/settings.json and paste the block above. Rules there apply to this project for you and anyone you share it with. Want them in every project? Put them in ~/.claude/settings.json in your home folder. If you already have a settings file, add the permissions section inside it instead of pasting a second set of braces. Run /status afterward to confirm the file loaded.

03

Test the wall

Ask Claude to run something harmless that’s on your deny list, like "run sudo ls." Watch it get blocked. Then ask it to push to git and watch it stop and ask. Once you’ve seen both, you’ll trust the setup.

The Honest Part

A deny rule matches the command the way Claude usually writes it. Anthropic is clear that it isn’t a security boundary around the program, so Bash(curl *) won’t catch /usr/bin/curl or a command tucked inside sh -c. If you need a hard wall, turn on Claude Code’s sandbox, which limits files and network at the operating-system level.

Newer versions of Claude Code start in auto mode, where a background check reviews risky actions before they run. Your deny and ask lists still apply on top of it. Press Shift+Tab to switch modes, and save bypass permissions for a container or test machine, which is what Anthropic recommends.

And keep your work in git so anything can be undone. The lists do the heavy lifting. You stay the adult in the room.