I've been running Claude Code in auto mode for a while. In auto mode, Claude doesn't stop to ask before every routine action. A separate classifier model looks at each action and blocks the risky ones.
You can tell that classifier about your setup in ~/.claude/settings.json, under autoMode. I had done that. I wrote down who I am, what's normal for my work, and what must never leave my machine.
This week I printed that block to check it. One of my lines still said this:
Source control: GitHub personal account GITHUB_ACCOUNT_HERE; repositories under it are trusted.
It had been a placeholder since the day I wrote the config. The classifier never knew which GitHub account was mine.
Below is how I found it, and the two checks I'd now run on any auto mode config.
What the autoMode block is
The autoMode block has four lists, and each one is plain English, not patterns:
-
environment: context about your setup. Who you are, which repos and domains you trust. -
allow: exceptions. Things the classifier would normally block, but that are fine for you. -
soft_deny: things to block unless you clearly asked for them. -
hard_deny: things to block no matter what.
By default, the classifier trusts only the repo you're working in and its configured remotes. Anything else, like your other repos on the same account, is "outside" until you say otherwise in environment.
That's exactly what my placeholder line was supposed to do.
Check 1: does every list you set still have "$defaults"?
This is the one that can actually hurt you.
Each list ships with built-in rules. If you set a list and include the literal string "$defaults", your entries are added to the built-in ones. If you set a list without it, your entries replace the built-in ones.
The docs are blunt about what that means:
-
soft_denywithout"$defaults"drops every built-in soft block, including force pushes,curl | bash, production deploys, and auto mode bypass. -
hard_denywithout"$defaults"drops the built-in data exfiltration rule. -
allowwithout it drops the built-in exceptions. That's not dangerous, but you'll get more prompts. -
environmentis the exception. If you generate it with/auto-mode-setup, it's written without"$defaults"on purpose, because the draft spells out the built-in entries itself.
To see what you wrote, print your autoMode block:
jq '.autoMode' ~/.claude/settings.json
My soft_deny, hard_deny, and environment all started with "$defaults". That's also where I saw the placeholder.
Check 2: what is the classifier actually using?
Your settings file is what you wrote. It isn't necessarily what the classifier reads, because entries from different scopes are combined.
This prints the effective config, your settings merged with the defaults:
claude auto-mode config
To confirm the built-in force-push rule is still there:
claude auto-mode config | grep -c 'Git Destructive'
Anything above 0 means it's in effect.
To check the line I cared about:
claude auto-mode config | grep 'Source control'
After I replaced GITHUB_ACCOUNT_HERE with my real account name, this showed two lines. One is the built-in default, saying it trusts the current repo and its remotes. The other is mine, naming my account.
Two more commands worth knowing
claude auto-mode critique sends your custom entries to a model and flags ones that are ambiguous, redundant, or likely to cause false positives.
claude auto-mode defaults prints the built-in rules. Read these before you ever write a list without "$defaults".
If you don't want to open a terminal, /permissions inside a session has an Auto mode tab where you can view and edit the same entries.
Why I missed it
I wrote the config once, it looked complete, and nothing broke loudly. Auto mode is a judgment call by a model, so a missing piece of context doesn't produce an error. At most, it makes the classifier a little more cautious than it needs to be.
That's the same pattern as every other silent failure I've hit with AI tools: the output looks finished, and nothing tells you otherwise until you check.
One rule from the Claude Code best practices page fits here. Auto mode is a classifier, not a hard rule, and it can be wrong. So the things that must never happen still belong in permissions.deny or hooks. The autoMode block is for context, not for guarantees.
The two-minute check
If you use auto mode, run these once:
jq '.autoMode' ~/.claude/settings.json # what you wrote
claude auto-mode config | grep -c 'Git Destructive' # built-in blocks still on?
claude auto-mode config # what the classifier really reads
Then read your environment lines one more time, looking for anything that still looks like a template.
Disclaimer: The config lines in this post are from my own setup. English isn't my first language, so I use an AI assistant to help draft and edit the writing.
Top comments (0)