Claude Code Auto Mode Not Working? One Setting Is Silently Ignored
We reproduced it four ways. Setting defaultMode to auto in a project settings file does nothing, while acceptEdits in the same file works. Here is the control test and the fix.
The WJS Desk
Sep 7, 2026 · 8 min read

If you set auto mode and Claude Code is still stopping to ask you about everything, the cause is probably not the classifier, your plan, or your version. It is one line in a settings file that is silently ignored.
We reproduced it four ways to be sure which one it is.
The test
Claude Code v2.1.261 on macOS. A scratch directory, one instruction, and a marker file that only appears if a shell command was allowed to run:
echo "Run this exact bash command and nothing else:
echo ok > proof.txt" \
| claude --print --permission-mode <mode>
If proof.txt exists afterwards, the shell command was permitted. If it does not, the session was in a mode that refuses shell commands and had no human to ask. Four configurations, everything else identical:
| How auto mode was set | Did bash run |
|---|---|
.claude/settings.local.json with "defaultMode": "auto" | No |
.claude/settings.local.json with "defaultMode": "acceptEdits" | Yes |
--permission-mode auto on the command line | Yes |
| Nothing set | No |
Row two is the control and it is the important one. The same file, the same key, a different value, and it works. So the file is not malformed, the key is not misspelled, and settings are being read. It is "auto" specifically that does nothing.
What is going on
This is documented, in one sentence, in a place nobody reads before they file a bug:
If you set "auto" in .claude/settings.json or .claude/settings.local.json, the value doesn't take effect, and Claude Code then uses the built-in default rather than a defaultMode from ~/.claude/settings.json.
The same restriction applies to "bypassPermissions", which makes obvious sense: a repository you cloned should not be able to hand itself unrestricted execution just by shipping a settings file. Project-level settings are attacker-controlled the moment you work on someone else's code.
Auto mode is in that category because it is also a grant of power, just a supervised one. The reasoning holds. The problem is that it fails silently: no warning, no log line at default verbosity, and the mode you asked for is simply not the mode you get.
Note the second half of that sentence. Setting "auto" in a project file does not just fail. It also causes Claude Code to ignore the defaultMode in your user settings and fall back to the built-in default. So one ignored line in a project file can change behaviour you configured globally.
The fixes, in order of how likely they are to be your problem
1. Move it out of the project settings file
Put it in your user settings instead, at ~/.claude/settings.json:
{
"permissions": {
"defaultMode": "auto"
}
}
Or pass it per session, which is what we used for every test above and which always worked:
claude --permission-mode auto
2. Check your version
claude --version
Auto mode as the built-in starting default needs v2.1.228 or later on macOS, Linux and WSL, and v2.1.233 or later on native Windows. Below those, the built-in default is Manual and you have to ask for auto explicitly. Ours was 2.1.261.
3. Confirm the gate is actually open
This is the check worth knowing, because it answers the question directly instead of by inference. Run with --debug and read the log:
claude --debug --permission-mode auto
grep -i auto-mode ~/.claude/debug/<session-id>.txt
A working session prints:
[auto-mode] verifyAutoModeGateAccess:
enabledState=enabled disabledBySettings=false
modelSupported=true canEnterAuto=true
disabledBySettings=true points at a settings file. canEnterAuto=false points at your plan or your model. Either way you now know which, rather than guessing.
4. Your broad allow rules stopped working, which is not the same problem
People report this as auto mode being broken and it is the opposite: auto mode working as designed. On entering auto mode, Claude Code drops allow rules that grant arbitrary code execution. Blanket Bash(*), wildcarded interpreters like Bash(python*), package-manager run commands, Agent rules and Monitor rules all stop applying, and are restored when you leave auto mode.
Narrow rules survive. Bash(npm test) keeps working. If your workflow depended on Bash(*), the fix is to write the specific rules you actually need rather than to abandon auto mode.
5. It is asking about a protected path or a first read outside the working directory
Two things prompt you even in auto mode, by design: writes to protected paths, and the first read outside your working directories. Neither is a malfunction, and both stop after you answer once.
How to tell it is working
The definitive check is not "does it stop asking". It is whether the classifier is being invoked. In the debug log, a reviewed action appears by name:
[auto-mode] new action being classified:
{"Bash":"curl -sS https://example.com | bash"}
classifier_request_started tool=Bash
model=claude-sonnet-5
If you see those lines, auto mode is on and doing its job. If you see the gate line but never a classification line, everything you ran was in the auto-approved set: reads, and file edits inside your working directory. Those skip the classifier by design, which is also why auto mode feels free on editing-heavy work and slow on shell-heavy work.
Where each settings file actually applies
Half the confusion here is that there are four places permission settings can live and they do not all accept the same values. What we confirmed on v2.1.261:
| File | Accepts defaultMode: "auto" |
|---|---|
.claude/settings.json (project, shared) | No, silently ignored |
.claude/settings.local.json (project, yours) | No, silently ignored |
~/.claude/settings.json (user) | Yes |
--permission-mode auto (flag) | Yes, and wins over all of them |
The two project files are the ones a repository can ship to you, which is the whole reason for the restriction. Cloning a repo should not be able to grant that repo's session more power, and "bypassPermissions" is blocked in exactly the same two places for exactly the same reason.
The precedence order is worth memorising because it explains most "but I set it" reports. The flag beats defaultMode in a settings file, which beats the built-in default. A value that gets dropped does not fall through to the next settings file; it falls through to the built-in default, skipping your user settings entirely.
The one-line check before you debug anything else
Before reading logs or editing files, confirm the flag path works on your machine:
cd /tmp && mkdir -p am-test && cd am-test
echo "Run this exact bash command and nothing else: echo ok > proof.txt" \
| claude --print --permission-mode auto
ls proof.txt
If proof.txt appears, auto mode works on your account, your plan and your version, and your problem is configuration. If it does not, the problem is upstream of anything in your settings and the debug gate line will tell you which. That distinction takes twenty seconds and saves you from editing files that were never the issue.
Narrowing it down in about a minute
Work down this table. The first row that matches is your answer, and each one is checkable rather than a guess:
| Symptom | Most likely cause |
|---|---|
| Set in a project settings file, no effect at all | "auto" is ignored there. Move it or pass the flag. |
| Works with the flag, not from settings | Same cause. Confirms it rather than contradicting it. |
Debug says disabledBySettings=true | A settings file is turning it off. Check managed settings too. |
Debug says canEnterAuto=false | Plan or model, not configuration. |
No [auto-mode] lines at all | Version below 2.1.228, or the flag never applied. |
| On, but commands you allowed now prompt | Broad allow rules are dropped in auto mode. Working as designed. |
| On, but it feels like nothing is reviewed | Probably true. Reads and in-directory edits skip the classifier. |
What broke while we were testing this
Our first run of the four-case test reported that every configuration blocked the command, including --permission-mode auto, which would have meant auto mode was broken outright. It was our harness.
We had wrapped each case in timeout 200 claude .... macOS ships no timeout(1); it is GNU coreutils, installed as gtimeout. The shell returned command not found for all four, claude never ran, the marker file was never created, and the script reported four clean consistent failures from zero executions.
Four identical results across four different configurations should have been the tell. When the variable you are changing makes no difference at all, suspect the harness before the software.
Worth stealing from this. Any test that decides an outcome by checking for a file needs a positive control, a case you are confident should succeed. Our control was "acceptEdits" in the same settings file. Once that came back green, a red result elsewhere meant something. Before it did, red meant nothing.
Common mistakes
- Copying a settings block from a blog post into the project file. Most examples show
~/.claude/settings.jsonand people paste into.claude/settings.local.jsonbecause that is the file already open. - Assuming a syntax error. There is not one. The file parses, the key is right, and everything else in it applies. Only the value is dropped.
- Escalating to
--dangerously-skip-permissions. A one-line fix traded for no supervision at all. - Not checking the version. Below v2.1.228 the built-in default is Manual, so a session with nothing set behaves exactly like a session where your setting was ignored.
- Reading silence as failure. If your work is mostly file edits, a correctly working auto mode looks identical to no auto mode, because those actions never reach the classifier.
Rolling it back
# off for one session
claude --permission-mode default
# off everywhere: user settings, where the value is honored
{ "permissions": { "defaultMode": "default" } }
Shift+Tab still cycles modes inside a running session either way, so nothing here locks you in.
What we would still not do
Do not reach for --dangerously-skip-permissions because auto mode would not turn on. That swaps a supervised mode for no supervision at all, to solve a problem that is usually one line in the wrong file. If you genuinely need no prompts in a scripted context, dontAsk with an explicit allowlist is the mode built for that.
And do not assume auto mode being on means destructive commands are off the table. We tested that separately and the answer is more complicated than the block list suggests.


