A coding agent keeps asking for permission when the action it wants isn’t covered by an allow rule: a command your rule doesn’t match exactly, a chain of commands where one part isn’t allowed, a file outside the project, or network access the sandbox blocks. The fix is a rule for the specific safe action, not the flag that turns all prompts off.
Most “it keeps asking” reports come down to five causes. They hit every tool, in slightly different ways.
The five causes
| Cause | What you see | Fix |
|---|---|---|
| Rule doesn’t match | You allowed npm test, it asks for npm test -- --watch | Allow the family: npm test * |
| Chained command | npm install && npm test asks although both are allowed | Every part must be allowed; allow each part |
| Outside the project | Reads or writes in another folder ask every time | Add the folder as a working directory |
| Sandbox boundary | Codex asks for anything that needs the network | Turn on network for the sandbox, or allow the command |
| ”Allow” didn’t stick | You clicked allow, and it asks again tomorrow | The approval was for this session only; write a rule |
Where the rules live, and what “don’t ask again” really saves:
| Tool | Rules file | ”Don’t ask again” saves to |
|---|---|---|
| Claude Code | .claude/settings.json (project), ~/.claude/settings.json (you) | .claude/settings.local.json, for commands and web fetches; edit approvals last only for the session |
| Codex | ~/.codex/rules/default.rules, ~/.codex/config.toml | ~/.codex/rules/default.rules; restart Codex to load it |
| OpenCode | opencode.json (project), ~/.config/opencode/opencode.json | Nothing: “always” lasts for the session |
| Copilot CLI | Startup flags; saved approvals | ~/.copilot/permissions-config.json, per repository |
| VS Code (Copilot) | settings.json | ”Always Allow” is saved; “in this Session” is not |
| Cursor | Settings → Agents → Approvals & Execution, or .cursor/permissions.json | The allowlist |
Claude Code
In Manual mode, Claude Code reads files in the project without asking and runs a fixed set of read-only commands (ls, cat, grep, find, diff, read-only git) without asking. Everything else asks: other commands, edits, web fetches.
Since v2.1.283 the built-in default is auto mode, where a classifier model approves routine actions. If you see ⏸ manual mode on in the status bar, you or your settings chose Manual.
The causes that catch people:
- Exact match.
Bash(npm test)matches onlynpm test. WriteBash(npm test *). And mind the space:Bash(ls*)also matcheslsof. - Chains. With
&&,||,;,|or a newline, every part must be allowed. A command that ends in&&can’t be parsed and always asks. - Wrappers.
npx,docker execanddevbox runaren’t stripped before matching, soBash(eslint *)doesn’t covernpx eslint. - Read-only commands that still ask: an unquoted glob on a command that can write (
find,sed,git),cdcombined withgit, or a redirect to a path outside the project or starting with~. - Other folders. Start with
claude --add-dir ../shared, run/add-dir, or add the folder topermissions.additionalDirectories. - A stricter rule elsewhere. An
askrule in the project or managed settings beats your own allow rule. Allow rules in a committed.claude/settings.jsononly apply after you accept the workspace trust dialog.
A rule set that removes most routine prompts:
{
"permissions": {
"allow": [
"Bash(npm test *)",
"Bash(npm run build)",
"Bash(npm run lint *)",
"Bash(git add *)",
"Bash(git commit *)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Bash(git push --force *)"
]
}
}
Run /permissions to see every rule and which file it came from.
On Windows, “Yes, don’t ask again” saves the rule next to .claude/settings.json in the folder you started Claude in, not at the repository root. Start Claude Code from a subfolder and the rule seems to vanish next time. Also on Windows: paths on a network share (\\server\share) always ask, whatever your rules say; map the share to a drive letter and add it with --add-dir.
Codex
Codex works differently. Instead of a list of rules, it has a sandbox and an approval policy. With the usual setup, workspace-write plus on-request, Codex runs commands freely inside the sandbox and asks only when something needs to leave it.
So when Codex keeps asking, it’s almost always the sandbox:
-
Network.
workspace-writehas no network.npm install,pip installandgit fetchfail in the sandbox, and Codex asks to rerun them outside. Turn network on in~/.codex/config.toml:sandbox_mode = "workspace-write" [sandbox_workspace_write] network_access = true -
Other folders. Add them to
writable_rootsin the same section, or pass--add-dir ../shared. -
Protected paths.
.git,.codex,.agentsand.awsstay read-only even inside the workspace. Anything that writes to.git, such as a commit, needs approval. -
Untrusted folders. Codex can start in
read-onlyuntil you trust the folder, and folders without version control default toread-only.
For single commands, Codex has rules, written in ~/.codex/rules/default.rules:
prefix_rule(pattern = ["npm", "run", ["build", "test", "lint"]], decision = "allow")
prefix_rule(pattern = ["git", "push"], decision = "prompt")
The pattern is an exact prefix of the arguments. When several rules match, the strictest wins. Test a rule before you rely on it:
codex execpolicy check --pretty --rules ~/.codex/rules/default.rules -- npm run test
Run /status to see your approval policy and writable folders, and /debug-config to see whether a managed config overrides yours.
Several open GitHub issues report Codex asking although Full Access is on, mostly in the desktop app, in older or branched chats, and on Windows with “blocked by policy” errors. Update first: releases from late October 2026 fix permissions getting lost when you resume or fork a chat. If it still asks, it’s a bug, not your config.
On Windows, a lot depends on which sandbox Codex uses. The recommended one, MXC, needs Windows 11 24H2 or 25H2 with a recent update and no admin setup. The older elevated sandbox needs an admin setup step; a declined UAC prompt during that step is a common reason commands keep failing. Test a command in the sandbox with codex sandbox windows <command>.
OpenCode
OpenCode rarely asks at all. By default, it runs commands and edits files without asking. It asks only for files outside the project, for .env files, and when it repeats the same tool call three times in a row.
If it keeps asking, your config or a plugin set ask. Find the rule under permission in opencode.json or ~/.config/opencode/opencode.json. Remember that the last matching rule wins:
{
"permission": {
"bash": {
"*": "ask",
"npm test *": "allow",
"git status *": "allow"
}
}
}
Here "*" comes first, and the specific allows override it. In the other order, "*": "ask" would win every time.
Clicking always in the prompt only lasts until you close OpenCode. Write the rule into the config to keep it.
GitHub Copilot
Copilot CLI asks before every tool that changes or runs something. A plain Yes is one-time. Choose Yes, and approve TOOL for the rest of the running session, or allow commands at startup:
copilot --allow-tool='shell(npm test)' --allow-tool='shell(git:*)' --deny-tool='shell(git push)'
Deny rules win over allow rules. Two more reasons it asks: you didn’t pick Yes, and remember this folder at the trust prompt, so it asks again on every start, and folders outside the trusted one need /add-dir. Flags last only for the session, so put your usual set in a shell alias.
VS Code agent mode decides per subcommand with chat.tools.terminal.autoApprove:
{
"chat.tools.terminal.autoApprove": {
"npm test": true,
"/^git (status|diff|log)\\b/": true,
"rm": false
}
}
The
falsetrap:falsedoesn’t block a command, it means “always ask”. And a chain is approved only if every part matchestrue, so one unknown command in a pipe brings the prompt back.
Cursor
Cursor’s run mode is under Settings → Cursor Settings → Agents → Approvals & Execution. If Cursor asks before every command, you’re probably in Allowlist with an empty list. That’s what users of the old Ask Every Time mode were moved to. Add your safe commands, or switch to Auto-review, the default for new users, where a model reviews commands that aren’t on the list.
If .cursor/permissions.json contains "terminalAllowlist": [], the allowlist is empty, and your list in Settings is ignored. Remove the key or fill it.
Some prompts stay on purpose: File-Deletion Protection, External-File Protection and Browser Protection ask even in auto modes, and risky recursive deletes always ask.
What should keep asking?
Make the routine work quiet, not everything. Keep these as prompts in every tool:
git push, and anything that rewrites history- Deleting files, and
sudo - Installing packages, which runs install scripts from the internet
- Network calls you didn’t expect
- Anything touching
.env, keys, or your shell profile
If you answer five prompts a day and read all five, the setup works. If you click “yes” fifty times without reading, you don’t have more safety, only more clicks. That’s the moment people reach for YOLO mode.
Contenox
Contenox comes with rules for this split. The default permission set reads freely and runs builds, tests, linters and read-only git commands without asking. Edits ask; rm, mv, sudo and redirects always ask; SSH keys and cloud credentials are blocked. For your own machine there’s a set that allows everything not named, and still asks before risky commands and history changes. Each rule is visible under Permissions in the sidebar. See built-in tools and permissions.
Related guides
- YOLO mode in Claude Code, Codex, Copilot and Cursor: what the off switch turns off in each tool
- —dangerously-skip-permissions: Claude Code’s flag and the Codex equivalent
- AI agent permissions: a starting rule set for any agent
- How to sandbox AI coding agents: when rules aren’t enough