Claude Code permission modes can no longer be set by the repository you happen to be working in, and if you were relying on that, nothing will tell you it stopped.
Claude Code now ignores defaultMode: "bypassPermissions" in a project’s .claude/settings.json. It ignores it in .claude/settings.local.json too. The session starts in Manual mode instead, with no warning. The documented reason is short and worth reading twice: it prevents projects from forcing bypassPermissions on developers who clone them.
That sentence is the whole story, and it belongs to a pattern this site has been tracking for a month. We wrote about an AI coding agent’s git config, about an LLM proxy whose authentication failed open, about credentials sitting in AI tooling and about CI credentials in the npm supply chain. Every one of those is a version of the same question: how much authority should arrive with the code?
This is the first time in that series where the answer was fixed by taking a capability away.
What changed in claude code permission modes
The mechanics, precisely, because the precision is what makes it actionable.
Still works. bypassPermissions set in your own user settings at ~/.claude/settings.json. The --permission-mode bypassPermissions flag at launch. Managed settings deployed by an administrator.
Now ignored. bypassPermissions in .claude/settings.json inside a project. The same in .claude/settings.local.json, which is the file people assume is personal because it is gitignored by convention. The auto mode is ignored in project settings as well, for the same reason.
What happens instead. The session starts in Manual mode. You get permission prompts. There is no error, no warning line, and no note that a setting was discarded.
That last part is the operational problem. A silent downgrade to a safer state is the correct security decision and a miserable debugging experience. The failure presents as "Claude Code started asking me to approve things again," which reads like a regression rather than a policy change, and the first instinct is to go looking for what broke rather than to check a changelog.
Why a settings file is a trust boundary
The reason this matters more than a configuration tweak is that .claude/settings.json is a file that arrives with the repository.
Clone a client project, open it, and that file is already on your disk before you have read a line of it. If it could set the permission mode, then cloning would be enough to disarm the approval prompts on your machine, for an agent with your credentials, in your shell. Nobody has to be malicious for that to go wrong. A well-meaning lead who got tired of approving the same commands in a monorepo commits the setting once, and then every contractor, every new hire and every agency brought in for six weeks inherits it silently.
.claude/settings.local.json being covered too is the part most write-ups will miss, and it is the more interesting half. That file is conventionally gitignored, so the assumption is that it is yours. But conventions are not enforcement. A .gitignore can be changed, a file can be committed deliberately or by accident, and a scaffolding tool or template repository can write one during setup. Treating it as untrusted alongside the tracked file is the right call precisely because its trustworthiness depends on a convention rather than a mechanism.
Compare this with what the surrounding series has been describing. In the Langflow and LiteLLM cases, the failure was an authorization check that let the wrong request through. Here the fix is upstream of that: the authorization decision is simply not delegated to a party who should not hold it. Removing a capability is a better outcome than hardening it, and it is rarer, because it breaks somebody’s workflow.
What this breaks, and who should care
Three setups are affected, in descending order of how likely you are to hit them.
Shared development containers and devcontainer images. If the image or the repo template ships a .claude/settings.json with the mode set so that everyone gets a frictionless environment, everyone now gets prompts. This is the most common case in agency work, because the whole point of a shared container is that nobody configures anything.
Continuous integration and scripted runs. Any pipeline that relied on a checked-in project setting to keep a headless run from stalling on an approval prompt will now stall. The fix is the flag, --permission-mode bypassPermissions, set in the job definition rather than in the repository, which also has the useful property of being visible in your CI configuration where somebody reviews it.
Onboarding docs that say "just clone and go." If your setup instructions assume the repo configures the agent, they are now wrong, and the person following them will not know why.
For a team serving nonprofits, associations or public-sector clients, there is a second-order point worth making to a client rather than keeping internal. If a vendor hands you a repository, the permission posture of the tools you point at it is now yours to set and cannot be quietly set for you. That is a small, real improvement in the security story you can tell about subcontracted development work.
What else in a repository can still change how the agent behaves
The permission mode is now off limits to a project. Plenty of other things are not, and the useful exercise is knowing which is which.
The distinction that actually matters is not tracked versus gitignored. It is read automatically from the working directory versus pointed at deliberately.
Read automatically. Project settings, skills and slash commands defined in the project, hooks configured for it, and MCP server definitions it carries. These are picked up because you opened the directory.
Pointed at deliberately. A plugin folder you pass with --plugin-dir, an MCP server you add yourself, managed settings an administrator deployed. These require an act on your part.
Within the first group, several surfaces can still change agent behavior in ways worth knowing about.
Skill and command frontmatter can choose a model. A model: line in a skill’s or a slash command’s frontmatter works in interactive sessions and applies for that turn. An effort: line sets the effort level, and it now applies even on models whose default effort is otherwise pinned. That is not a permission escalation, and it is a behavior change that arrives with the code.
Hooks can intercept a model switch. PreModelSwitch fires before Claude Code applies a switch you or a client requested, and it can block that switch outright by returning a deny decision. PostModelSwitch fires after the model changes, including changes Claude Code makes on its own. Useful for logging or for handing a new model extra context, and worth knowing that a hook can refuse.
Subagent model selection has a precedence order. CLAUDE_CODE_SUBAGENT_MODEL sets a default model for subagents, taking aliases, full model IDs, or inherit. The order runs: a per-invocation model parameter first, then the subagent definition’s own model: frontmatter, then the environment variable, then the main conversation’s model as a fallback. There is also a force variant that overrides everything except forks. Worth setting deliberately if your main session runs an expensive model and spins up many subagents, because the default is that they follow the main conversation.
A plugin folder loads everything in it. Pointing --plugin-dir at a parent folder loads every subfolder containing a manifest as its own plugin, and in interactive sessions it picks up additions and removals without a restart. That is a convenience, and it also means the contents of that folder are the actual scope, not the plugin you were thinking of.
None of these is a flaw. They are the configuration surface of a tool that is meant to be configured. The point is that the trust boundary moved in exactly one place, and the inventory of everything else has not changed. When you audit an unfamiliar repository before pointing an agent at it, the settings file is now the least of it.
What to do this week
Search your repositories. Anywhere you set claude code permission modes at the project level is now dead configuration. Look for defaultMode in any .claude/settings.json or .claude/settings.local.json across the projects you maintain. Anything that sets bypassPermissions or auto there is now inert and should be removed rather than left to confuse the next person.
Move the setting to where it belongs. If a person genuinely wants to run without prompts, that is their decision to make in ~/.claude/settings.json on their own machine, or with the launch flag. It should be a choice each developer makes knowingly, which is exactly what the change is designed to force.
Put the flag in your CI configuration, not your repo. A job definition is reviewed, versioned and owned by the team that runs the pipeline. A settings file in the project is inherited by everyone who clones it. Those are different risk profiles for the same effect.
Check managed settings if you are the administrator. Managed settings still work and still override, which is the supported route for an organization that needs a consistent posture across machines. If you have been achieving that by convention through project files, this is the moment to do it properly.
Update your onboarding docs. The step that used to be implicit is now explicit, and a one-line note saves the next person an afternoon.
And read the pattern, not just the fix. Two of the four posts linked at the top of this piece describe an authorization check that failed open. This one describes an authorization decision that was being delegated to whoever wrote a file in a repository. As agent tooling accumulates configuration surfaces, a settings file, a hook, an MCP server definition, a skill, a plugin manifest, the question to keep asking is which of those can change what the agent is permitted to do, and which of them arrive with code you did not write.
Frequently Asked Questions
What exactly changed?
Claude Code now ignores `defaultMode: “bypassPermissions”` when it appears in a project’s `.claude/settings.json` or `.claude/settings.local.json`. The session starts in Manual mode instead.
Does it warn me?
No. The setting is ignored silently, which means the symptom is simply that permission prompts have returned.
Where can bypassPermissions still be set?
In your own user settings at `~/.claude/settings.json`, with the `–permission-mode bypassPermissions` flag at launch, or through managed settings deployed by an administrator.
Is `.claude/settings.local.json` really covered?
Yes. It is conventionally gitignored, but a convention is not a guarantee, so it is treated as untrusted for this purpose alongside the tracked settings file.
Is any other mode affected?
Yes. The `auto` permission mode is also ignored in project-level settings.
Why did Anthropic do this?
The documented rationale is to prevent projects from forcing bypassPermissions on developers who clone them.
What breaks in CI?
Any headless run that relied on a checked-in project setting will now stop at approval prompts. Move the setting into the job definition using the launch flag instead.
What about shared devcontainers?
Same problem, same fix. The image or the developer’s own user settings is the right place for it, not the repository.
Do project settings still control anything?
Yes, project settings remain useful for plenty of configuration. What they can no longer do is raise the permission posture of the session beyond what the person running it has chosen.
Is this a security vulnerability being patched?
No. There is no CVE and no evidence of exploitation. It is a design change that removes a capability which could have been misused, which is a different and generally better kind of fix.
Should I now trust repository config more or less?
Less, in general, and this change is a reason to feel slightly better rather than worse. A tool that refuses to let a cloned repository change its own permission posture is behaving correctly.
Where do I check which of the claude code permission modes I am actually in?
The session reports its permission mode, and if you expected no prompts and are getting them, a project-level setting being ignored is now the first thing to check rather than the last.