Configure auto mode
Teach the auto mode classifier which repositories, buckets and domains you trust, adjust its block and allow rules, and inspect or reset the result.
Auto mode removes routine permission prompts by sending each tool call past a classifier that blocks anything irreversible, destructive or headed outside your environment. Deny rules and explicit ask rules still run first. This page is about tuning that classifier so it stops tripping over your normal internal work.
The out-of-the-box classifier is deliberately cautious: it trusts only the working directory and the repository's configured remotes. Pushing to another repository in your GitHub organisation, writing to the team's artefact bucket or calling an internal API all look "external" until you say otherwise. That is what the autoMode settings block is for.
Auto mode works on every provider: the Anthropic API, Claude Platform on AWS, Bedrock, Vertex AI, Foundry and signed-in Claude apps gateway sessions. If it shows as unavailable, check the model and organisation requirements on the permission modes page, which also covers switching in and out of auto mode.
What is allowed by default
Pushing to any branch of the repository you are working in (including the default branch) and opening pull requests are allowed. Branches whose names mark them as deployment or publishing targets, such as production, release or gh-pages, are judged separately and may be treated as a production deploy. The content of a push is still inspected, so force pushes, secrets entering a commit, or changes that would leak secrets when CI runs them are blocked regardless.
Adding a human checkpoint
If you want to see pushes and PRs before they happen while leaving auto mode on for everything else, add ask rules. An explicit, content-scoped ask rule always prompts, even in auto mode:
{
"permissions": {
"ask": [
"Bash(git push *)",
"Bash(gh pr create *)",
"Bash(gh release create *)"
]
}
}
These rules match commands that start with those words. git -C ../other push would slip past. If that matters to you, inspect the full command in a PreToolUse hook.
How firm do you need the boundary to be?
| You want | Use | In auto mode |
|---|---|---|
| A prompt before it happens | permissions.ask | Always prompts on a match; the classifier cannot approve it |
| It never to happen | permissions.deny | Blocked before the classifier runs; nothing overrides it |
| A boundary for this session only | Say it: "don't push until I've reviewed" | The classifier honours it, but compaction can drop the message, so it is not durable |
Where the classifier gets its configuration
The classifier reads the same CLAUDE.md content as Claude, so "never force push" in a project's CLAUDE.md steers both. That is the right place for project conventions.
For things that apply across projects, use autoMode. It is read from:
| Scope | Location | Typical use |
|---|---|---|
| You | ~/.claude/settings.json | Your own trusted infrastructure |
| Organisation | Managed settings | Trusted infrastructure for everyone |
| One run | --settings or the Agent SDK | Automation overrides |
It is not read from .claude/settings.json or .claude/settings.local.json. Those sit inside the repository, so a cloned repo or a build step could otherwise inject its own allow rules. If you have an autoMode block in a local project file, move it to your user settings.
Scopes combine. A developer can add to environment, allow, soft_deny and hard_deny but cannot remove managed entries. Note that a personal allow entry can still carve an exception out of an organisational soft_deny; this is additive guidance, not a hard wall. For anything that must never run, use permissions.deny in managed settings.
Describing your environment
For most teams, autoMode.environment is the only field worth touching. It defines what counts as "inside", which in turn defines what counts as exfiltration.
Entries are plain English, not patterns. Write them as you would brief a new starter. Run claude auto-mode defaults to see the built-in entries, which fall into three groups:
Context slots describe the organisation so the classifier can interpret everything else. They are: Organization; Primary use of Claude Code (default: software development); Cloud provider(s); Repository visibility (assumed private unless the remote host and name, or something the classifier itself reads earlier in the conversation such as your own message, show otherwise; command output like gh repo view does not reach it); Internal sharing / snippet hosting (public paste and gist sites are outside until named); Org-specific CLIs; Secrets management; CI/CD deploy targets; Network posture; Host containment; Protected deployment namespaces / environments; and Data retention / declassification.
Host containment (v2.1.257+) defaults to an ordinary laptop or CI runner with open internet. If Claude runs in a locked-down container, VM or pod, name the permitted hosts, whether the cloud metadata endpoint should be reachable, and which cloud project, cluster or registry the work uses and under what identity. Until you do, requests for the host's own credentials are blocked.
Trust slots say what is inside your boundary: Trusted repo, Source control, Trusted internal domains, Trusted cloud buckets, Key internal services, Internal package registry. The first two default to the working repository and its remotes; everything else starts empty. Visibility only governs confidential material: a private repo is a fine home for confidential work, but privacy never clears secrets or personal data into it, and content brought in from outside the working repo is not treated as that repo's own work.
Sensitivity slots say what deserves extra protection: Sensitive data locations & audiences, Sensitive remote targets, Protected IaC scopes. Until you fill them, broad heuristics apply (for example, anything with prod or production in the name is a sensitive remote target). Naming concrete targets replaces the heuristic with your list.
Keeping the defaults and adding yours
Include the literal string "$defaults" and the built-in entries are spliced in at that position. Here is roughly what I set up for a client running on Azure DevOps and GCP:
{
"autoMode": {
"environment": [
"$defaults",
"Organization: Northwind Logistics. Primary use: software development and data pipelines",
"Source control: dev.azure.com/northwind and every project under it",
"Cloud provider(s): Google Cloud",
"Trusted cloud buckets: gs://northwind-build-cache, gs://northwind-dev-exports",
"Trusted internal domains: *.northwind.internal, api.northwind.dev",
"Internal package registry: europe-west2-npm.pkg.dev/northwind/npm",
"Sensitive remote targets: the GKE namespaces prod-eu and prod-us",
"Sensitive data locations & audiences: BigQuery dataset customer_pii, internal finance team only"
]
}
}
Then run claude auto-mode config to confirm your entries appear.
A good environment section usually names: the organisation and what Claude Code is used for; every source control org people push to; cloud providers and trusted buckets; internal domains; CI, artefact stores and incident tooling; the internal package registry (so installs that bypass it get blocked); where sensitive data lives and who may see it; what counts as production; which infrastructure needs an explicit, named change to apply or destroy; and any regulatory context.
You do not need all of it on day one. Start with source control and key internal services, which clear the commonest false positives, then add domains and buckets, then fill the rest as blocks show up.
Drafting entries with /auto-mode-setup
/auto-mode-setup asks Claude Code to draft environment entries (and sometimes rules) from your project and recent sessions, and on acceptance writes them to ~/.claude/settings.json. It needs a Pro, Max or Team plan, v2.1.228 or later (v2.1.233 on native Windows) and feature-flag fetching enabled. It does not run in cloud sessions.
If you already have autoMode entries, it first asks whether to add to or replace the environment list, keeping your rules either way. It then asks how you use the project and offers two optional scans. It always reads:
- the project's
CLAUDE.md,README.md, config files and git remotes; - your
autoModeandpermissions.allowsettings; - hosts, buckets and command names from commands Claude ran in recent sessions here (never your messages).
The optional scans add the first word of each command in your shell history, and the remote hosts and names of repositories under your home directory.
You accept or discard the draft as a whole. On accept, the environment list is written without "$defaults" (the draft spells out the defaults it kept), "$defaults" is added to any allow, soft_deny or hard_deny list it touches (unless you already had an allow list without it), and you are offered the chance to remove permissions.allow rules auto mode ignores, such as Bash(*), or that auto-approve destructive commands.
After auto mode has blocked several actions and you still have no environment entries, a "Teach auto mode about your environment?" dialog offers to run it. Don't show again silences the offer. To remove both the offer and the command:
{ "skillOverrides": { "auto-mode-setup": "off" } }
It is a built-in command rather than a bundled skill, so disableBundledSkills does not affect it, but skillOverrides does.
Changing the block and allow rules
Three more lists replace or extend the classifier's built-in rules, again written as prose:
hard_deny: absolute boundaries.soft_deny: destructive actions that user intent can clear.allow: exceptions to soft blocks.
Inside the classifier, precedence runs: hard_deny blocks no matter what; then soft_deny blocks; allow carves exceptions out of soft_deny; and finally, explicit user intent clears any remaining soft block. Explicit means the user's message specifically describes the exact action. "Tidy up the repo" does not authorise a force push; "force-push this branch" does.
Loosen with allow when a routine pattern keeps getting flagged. Tighten with soft_deny for risks specific to you, or hard_deny for lines that must never be crossed. For pattern-based blocks that run before the classifier, use permissions.deny.
{
"autoMode": {
"environment": ["$defaults", "Source control: dev.azure.com/northwind"],
"allow": [
"$defaults",
"Running dbt against the dev BigQuery project is fine: it is rebuilt from scratch every night"
],
"soft_deny": [
"$defaults",
"Do not edit anything under pipelines/release/: release pipeline changes need a reviewer"
],
"hard_deny": [
"$defaults",
"Never upload source files to online formatters, pastebins or AI review sites"
]
}
}
Warning: Leaving
"$defaults"out of any of the four lists replaces the built-in list for that section entirely. Without it insoft_denyyou lose every built-in soft block, including force push,curl | bash, production deploys and auto mode bypass. Without it inhard_denyyou lose the built-in data exfiltration rule.
Sections are independent, so setting only environment leaves the three rule lists at their defaults. Only drop "$defaults" if you mean to own the whole list: print the built-ins with claude auto-mode defaults, copy them in, and review each one.
Editing from /permissions
From v2.1.246, /permissions has an Auto mode tab (shown when auto mode is available) for viewing and editing rules and environment entries. Managed and --settings entries are read-only there; your edits go to ~/.claude/settings.json.
Sending every shell command to the classifier
Narrow allow rules such as Bash(pnpm test) normally keep working in auto mode and are resolved before the classifier sees anything (unless the command carries per-command allowed domains). Broad rules that grant arbitrary execution, like Bash(*) or wildcarded interpreters, and every rule that names the Monitor tool, are suspended. The gap: a narrow rule can still wave through a destructive argument its prefix did not anticipate.
To close it, suspend every Bash and PowerShell allow rule while auto mode is on:
{ "autoMode": { "classifyAllShell": true } }
Every shell command then waits for a classifier decision (and counts as a classifier call), except critical-path removals. Outside auto mode your allow rules behave normally.
The auto-mode subcommands
| Command | Does |
|---|---|
claude auto-mode defaults | Prints the built-in environment, allow, soft_deny and hard_deny lists as JSON |
claude auto-mode defaults --label 'Git Destructive' | Prints only rules whose label starts with that text, case-insensitive (v2.1.208+) |
claude auto-mode config | Prints the effective lists with your settings applied |
claude auto-mode critique | Reviews your custom entries and flags ambiguous, redundant or false-positive-prone ones |
claude auto-mode reset | Removes autoMode from your user settings after a confirmation (v2.1.212+); --yes skips the prompt. Managed and --settings rules still apply. |
Each rule in the output is a prose string that starts with a label such as Git Destructive or Test Artifacts.
Working through denials
/permissions has a Recently denied tab. Select an action and press r to mark it for retry; when you close the dialog Claude is told it may try again. If the classifier returned no verdict at all (a separate safety check refused its request, or the response did not parse), the action is denied but not listed there.
To see what was blocked, find the tool call in the conversation; if it is folded into a summary like Ran 3 shell commands, press Ctrl+O for the transcript viewer. The notice near the input (for example bash denied by auto mode · [Data Exfiltration] · /permissions) gives the reason but not the command. A PermissionDenied hook receives the exact input as tool_input if you want to log it.
Under the call:
- Text about the classifier itself failing (
is temporarily unavailable, a classifier error) means there was no verdict. That is an availability problem, not a configuration one. Denied by auto mode classifierwith a reason such as[Production Deploy]means it was judged unsafe. The bracketed text names the matched rule; look it up with--label.
Then choose a fix:
- A destination needed throughout the work (a registry, internal domain or repository host): add it to
environment. - A command you want to run without review from now on: add an
allowrule. - A one-off you genuinely meant: say so in your next message and let Claude retry.
If the same destination keeps getting denied, the classifier is missing context. Add it to environment or run /auto-mode-setup, then confirm with claude auto-mode config.