Why Qwen Code keeps asking for permission after you chose "Always allow"
Qwen Code's default approval mode is Auto, which sends tool calls to a classifier instead of asking about each one; the prompt in front of you may be Auto's fallback rather than a plain rule miss. "Always allow" is not one setting. On a shell command, an MCP tool, or a web fetch, the choice writes an allow rule to a settings file. MCP here is the Model Context Protocol; Qwen reads its servers from mcpServers in its settings, and a rule for one of their tools is written mcp__server__tool. On a file edit, "Yes, allow always" switches the session to Auto-Edit instead and writes no rule. Only the shell, MCP and web choices leave a rule behind for the next session.
Run qwen --version first. The details here are from commit 32f6713 (27 October 2026), one commit before the v0.26.2 tag; permission handling changed during 2026, so an older install may not match.
Checked against Qwen Code's documentation and source on 27 October 2026.
Status, 27 October 2026: a multi-line heredoc is still split at newlines when shell rules are matched, so a rule saved for python does not cover the body (#9381, open, updated 18 August 2026).
What each "Always allow" writes#
The two rule-writing choices name the scope in the option. "Always allow in this project" appends a rule to .qwen/settings.json; "Always allow for this user" appends it to ~/.qwen/settings.json. The settings documentation lists both locations. In either case Qwen Code also updates the running session immediately, so the new rule can take effect without a restart.
| Dialog | What the choice stores | How long it lasts |
|---|---|---|
| Yes, allow once | Nothing | That call |
| Always allow in this project | An allow rule in .qwen/settings.json | Until you remove it |
| Always allow for this user | An allow rule in ~/.qwen/settings.json | Until you remove it |
| Yes, allow always, on a file edit | No rule; switches the session to Auto-Edit | Until the session ends |
A web fetch saves the hostname, so WebFetch(example.com) covers every URL on that host. An MCP rule is for one tool, written as mcp__server__tool, not for every tool on that server.
The file-edit row is the odd one. "Yes, allow always" on an edit does not write permissions.allow. It changes the approval mode to Auto-Edit, which auto-approves edit, write_file and notebook_edit for the rest of the session. The approval mode documentation describes the mode. After a restart the mode is whatever your settings say, usually Auto, so an edit outside Auto's fast path can prompt again.
Shell rules are built from the command, not from the exact line you approved. Qwen Code takes the root command, keeps a known subcommand, and replaces the remaining arguments with *. The label on the button is a useful disclosure: "Always allow run 'python3 *' commands in this project" means the saved rule is Bash(python3 *).
Some examples:
npm testbecomesBash(npm test). That coversnpm testandnpm test -- --watch.python3 -c "..."becomesBash(python3 *). That covers everypython3command, not just that one-liner.
The rule is broader than the exact command you approved. That is why a later, different python3 command can pass without a prompt, and why a rule for one root command does nothing for another.
Why a command that looks the same can ask again#
A compound command is judged in pieces. Qwen Code splits an unquoted &&, ||, ;, | or background & before it applies Bash(...) rules, and every piece has to be covered. If you allowed npm test earlier and now run npm test | tee test.log, the first piece is allowed but tee test.log is not, so the call prompts. Choosing Always allow there saves rules for both pieces; the next npm test | tee other.log should pass.
A multi-line heredoc is still split. A command such as python - <<'PY'... PY contains newlines, and the permission matcher treats those newlines as command separators. The body lines are evaluated as separate commands, so a saved Bash(python *) rule does not cover the whole call. This is the open report above. Keep long scripts in a file and run the file if you want the saved rule to apply.
A different root command is a different rule. npm test, pnpm test, yarn test and npx vitest do not share a rule. Neither does sudo npm test. The rule is a prefix with word boundaries, not a search for a familiar word anywhere in the line.
An ask rule outranks an allow rule#
Qwen Code evaluates rules in a fixed order: deny first, then ask, then allow, and finally the tool's default or the approval mode. The first matching rule in that order wins. The permissions section of the settings documentation states the same precedence.
This produces the most confusing result. You have a saved allow rule, but a matching ask rule also exists, so the call still prompts. You click Always allow again, but Qwen Code does not even show that option when an explicit ask rule is the reason for the prompt. It hides the button because an allow rule cannot override the ask rule. Check the Ask tab in /permissions; a project rule, a user rule, or an operator's system rule can all put you here.
There is one more source of a hard ask. A PreToolUse hook, a script that runs before a tool call, can return permissionDecision: "ask". Qwen Code then shows a confirmation for that call, and no permission rule or approval mode, including YOLO, overrides it. The hooks documentation says this confirmation takes the place of the usual one, and it has no Always allow. If a prompt has no Always allow and no matching ask rule, check /hooks for a PreToolUse entry.
Auto mode is the default, and it takes some allow rules away#
A normal Qwen Code session starts in Auto unless you choose another mode, or the folder is untrusted. Auto is not the same as Ask Permissions, the mode that asks before edits and shell commands. It sends the calls that are not obviously safe to a model classifier; safe calls run, risky ones are blocked, and a classifier failure or a run of repeated blocks falls back to a manual confirmation.
Three Auto behaviors can produce the "Always allow did not stick" report.
First, the fallback confirmation hides the Always allow choices. The point of that prompt is to review one call that the classifier could not clear, so it offers "Yes, allow once", "Switch to Default Mode and allow once (recommended)" when the classifier itself is unavailable, and "No, suggest changes (esc)" — not a standing grant. If you are in Auto and wondering why the option is missing, this is the likely answer. Switch to Ask Permissions with /approval-mode default and the project and user choices return. To make that the default for new sessions, set tools.approvalMode to default in settings.json.
Second, entering Auto temporarily removes broad allow rules that would let the model bypass the classifier. The list includes a bare Bash, Bash(*), interpreter wildcards such as Bash(python *), package-runner rules such as Bash(npm run *), and any Agent or Skill allow rule. When you switch into Auto, Qwen Code prints a notice listing them. It keeps the rules in memory and restores them when you leave Auto; it does not edit settings.json. A rule can therefore be on disk, absent from the active set, and working again the moment you switch modes.
Third, Auto re-checks a call through the classifier when it writes to a protected path, even if a specific allow rule matches. The protected set includes Qwen Code's own settings, QWEN.md, hooks, skills, MCP configuration, and persistence files such as package.json or .git/. An allow rule is not the last word there.
The strip list matters because Always allow often saves exactly those broad rules. python3 *, node *, bash *, npx * and npm run * are all on the strip list; a concrete Bash(npm test) is not. If your saved rule is an interpreter or package-runner wildcard, Auto is not using it. This is a guardrail: check it first when an earlier rule seems to have vanished.
YOLO is not a persistence fix. /approval-mode yolo auto-approves tool calls for the session, or as a saved default with --project or --user, but it writes no rule. Some tools still require a user decision, so it does not remove every prompt either.
Folder trust can hide the persistent choices#
Folder trust is a separate gate. The trusted folders documentation says the feature is disabled by default. When it is off, the current folder counts as trusted. When it is on and the folder is untrusted, Qwen Code does not load the project's .qwen/settings.json, forces the session out of Auto, Auto-Edit or YOLO into Ask Permissions (Plan is left alone), and hides the Always allow rows in tool confirmations. For an ordinary tool call, only Allow once is offered.
That means a project-scope rule you saved in one checkout can appear to do nothing in another checkout, or in a folder that Qwen Code now treats as untrusted. The rule is in the repository's settings file, but the file is not being read. A user-scope rule lives in your home directory and is not tied to the project, though the untrusted folder still changes the mode.
Run /trust to open the folder trust dialog. The saved decision is in ~/.qwen/trustedFolders.json. If you want to know whether the feature is enabled at all, look for security.folderTrust.enabled in your user settings.
Plan mode is a mode, not a standing permission#
Plan mode is one of the five approval modes. Enter it with /plan, /plan <task>, the mode cycle, or tools.approvalMode: "plan". /plan exit restores the mode you came from. It keeps Qwen Code to read-only work: it refuses non-read-only tools, and for shell it blocks commands it classifies as state-changing. A command it cannot classify needs a one-off confirmation, and that confirmation has no Always allow.
Approving the plan at the end is also not a permission grant. The choices are to restore the previous mode, to auto-accept edits in a trusted folder, or to approve edits manually. They change the approval mode; they do not add a rule. Treat Plan as a review mode, not a sandbox: it controls what Qwen Code may call, not what an already-running process or your own terminal may do.
Check the real state#
Do not ask the model which rule is active. It cannot see the merged permission manager reliably. Use the surfaces:
/permissionsopens the rule manager. The Allow, Ask and Deny tabs list the active rules, and the Workspace tab manages additional workspace directories. Remove a stuck rule here or add an ask rule deliberately.cat.qwen/settings.jsonandcat ~/.qwen/settings.jsonshow what was written. Look underpermissions.allow,permissions.askandpermissions.deny./approval-modeshows the current mode and lets you change it. The status bar shows the mode during a session./trustopens the folder trust dialog, and~/.qwen/trustedFolders.jsonrecords the answer./hooksshows registered hooks. APreToolUsehook is worth checking when a prompt has no Always allow and no matching ask rule.- Changes made through
/permissionsapply to the running session. After editing a settings file by hand, start a new session so it is loaded.
The permissions.allow key is pure auto-approval. It does not remove tools or restrict what is registered, and adding a tool name there does not restrict any other tool. If you need a hard block, use permissions.deny; if you need a review step, use permissions.ask.
Where to go next#
- Qwen Code guides — the rest of the set.
- Gemini CLI permissions — if you came from Gemini CLI. Qwen Code is a fork, but its permission model is not the Gemini policy engine: there is no policy list to inspect, rules are
permissions.allow,askanddenyinsettings.json, and the mode names are Plan, Ask Permissions, Auto-Edit, Auto and YOLO. - Claude Code permission prompts — the same question for Claude Code.