If you use Claude Code or Codex CLI for more than a few minutes, you hit the same wall: either you approve every single ls and npm test by hand, or you flip on the "just do everything" mode and hope nothing goes wrong. Neither is great.
Both tools have a middle ground. You can tell them which commands are always fine, which ones always need a check, and which files they should never touch. This guide walks through how to set that up in each tool, plus a starter config you can copy.
Flags and setting names do change between releases, so run claude --help and codex --help to confirm what your version supports.
The idea: allow the boring stuff, block the scary stuff
Most agent commands fall into three groups:
-
Safe and frequent: reading files, running tests, linting,
git status,git diff. Approving these by hand is pure friction. -
Worth a look: installing packages,
git push, anything that hits the network or changes files outside the project. -
Never: reading
.envor credential files,rm -rfoutside the repo, deploying to production.
The goal is to auto-approve the first group, keep prompts for the second, and hard-block the third.
Claude Code: permission rules
Claude Code reads permission rules from settings files:
-
~/.claude/settings.jsonfor your personal defaults across every project -
.claude/settings.jsonin the repo, which you can commit for your team -
.claude/settings.local.jsonfor personal overrides in one repo (keep it out of git)
Rules go in allow, ask, and deny lists. Deny wins over everything else. A starter project file might look like this:
{
"permissions": {
"allow": [
"Bash(npm run test:*)",
"Bash(npm run lint)",
"Bash(git status)",
"Bash(git diff:*)",
"Bash(git log:*)"
],
"ask": [
"Bash(git push:*)",
"Bash(npm install:*)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(curl:*)"
]
}
}
A few things that help:
-
Use prefix matches for commands.
Bash(npm run test:*)coversnpm run testwith any arguments after it. Be careful with very broad prefixes likeBash(npm:*), since that also coversnpm publish. - Add rules from the prompt. When Claude asks to run something, choosing the "don't ask again" option writes an allow rule for you. After a week of normal work, open the file and prune anything too broad.
-
Check what's active with
/permissions. It lists every rule and which settings file it came from, which is the fastest way to debug "why did it ask me again?"
Permission modes
On top of rules, Claude Code has modes you can cycle with Shift+Tab during a session:
- Default: asks the first time it wants to use each tool.
- Accept edits: file edits go through without a prompt, but shell commands still follow your rules.
- Plan mode: read-only. Claude explores and writes a plan but doesn't change anything. This is a great first step for any big task.
There's also --dangerously-skip-permissions, which skips every prompt. Only use it inside a throwaway container or VM with no credentials in it, because the name is accurate.
Codex CLI: sandbox plus approval policy
Codex splits the problem into two separate settings.
Sandbox mode controls what commands can physically do:
-
read-only: can read files, can't write or use the network. -
workspace-write: can write inside the project folder, and network access is off by default. -
danger-full-access: no sandbox at all.
On macOS, Codex enforces this with the system's built-in sandbox (Seatbelt), so it isn't just an honor system. A command that tries to write outside the workspace actually fails.
Approval policy controls when Codex stops to ask you:
-
untrusted: asks before anything that isn't on its short list of known-safe read commands. -
on-request: runs inside the sandbox and asks only when it needs to go beyond it. -
never: never asks. Failures just come back to the model.
You can set both per session:
codex --sandbox workspace-write --ask-for-approval on-request
--full-auto is a shortcut for roughly that same pair. Or set defaults in ~/.codex/config.toml:
approval_policy = "on-request"
sandbox_mode = "workspace-write"
[sandbox_workspace_write]
network_access = false
Inside a session, the /approvals command lets you switch levels without restarting, which is handy when you move from exploring to letting it run a long refactor.
A setup that works for most projects
Here's what I'd start with in both tools:
-
Start big tasks read-only. Plan mode in Claude Code,
read-onlysandbox in Codex. Let the agent read the code and propose a plan before it touches anything. -
Then allow edits inside the repo only. Accept-edits mode in Claude Code,
workspace-writewithon-requestin Codex. - Auto-approve your test, lint, and read-only git commands. These are the bulk of what agents run.
-
Hard-deny secrets. Block
.envfiles and credential folders explicitly, even if you think the agent wouldn't look. -
Keep network and publish commands behind a prompt.
git push,npm publish,curl, and deploy scripts should always need your OK. - Do anything fully unattended in a container. If you want zero prompts, give the agent a disposable environment rather than your real laptop.
Commit the shared project rules so everyone on the team gets the same guardrails, and keep personal preferences in your home directory or local settings file.
One side effect worth knowing
Once you stop approving every command, sessions run a lot longer on their own. That's the point, but it also means an agent can burn through a big chunk of your plan limits or API budget while you're getting coffee. It's worth keeping an eye on usage when you first loosen the rules, so you notice if a loop of failing tests is eating tokens.
Disclosure: I built TokenBar, a $15 Mac menu bar app that shows your Claude and Codex usage and cost at a glance: https://tokenbar.site
What allow and deny rules have you settled on? I'd love to see other people's configs in the comments.
Top comments (0)