Mindket

Claude Code settings.json: scopes, precedence and permission rules

A black banner titled "Claude Code advanced" over the line "Settings, headless runs, CI and the Agent SDK".

Claude Code reads settings from four places: managed policy, your ~/.claude/settings.json, the committed .claude/settings.json and the untracked .claude/settings.local.json. A --settings flag adds a fifth for one session. Managed wins, then the flag, then local, project and user. Lists such as permissions.allow merge, and deny rules beat ask rules, which beat allow rules.

In this lesson

  • A key set in several files resolves by one stack: managed, then --settings, then local, project and user. List keys such as permissions.allow merge instead of overriding.
  • Rules are checked deny first, then ask, then allow, and the first match decides. A narrow allow cannot reopen what a broad deny blocks.
  • Allow rules in a committed file wait until each teammate trusts the folder. Deny and ask rules take effect immediately.
  • Bash rules guard the usual form of a command and are not a security boundary. Pair them with the sandbox or a hook.
All courses
On this page
  1. Before you start
  2. Set up a team file and a personal override
  3. Which value wins when files disagree
  4. Deny, then ask, then allow
  5. Path rules and where they anchor
  6. What a deny rule does not stop
  7. Sharing a file with a team: trust and the keys that never travel
  8. How Claude Code's creator shares permission rules with his team
  9. Common mistakes
  10. Try it yourself
  11. Next: headless runs
  12. Check yourself
  13. Frequently asked questions
  14. Sources

Before you start

This lesson is for people who already use Claude Code every day. If you do not, take the beginner course first. You need a git repository to try the shared and local files.

Anthropic's docs tie several behaviors to a release. The local settings file lives at the repository root since v2.1.211, and bypassPermissions stopped working from project files in v2.1.257. Run claude --version if something here does not match your install. The facts below come from the settings guide and the permissions page, read on 4 November 2026 and checked again on 5 November.

Settings change faster than most of Claude Code, because a release ships most days. These four releases changed what a settings file can do, with their dates from GitHub and the changelog.

Settings changes in recent Claude Code releases
  1. v2.1.211: approvals save at the repository root

    "Always allow" rules go to the local file at the root, so a session in a git worktree keeps them.

    Source: Claude Code release v2.1.211 on GitHub (read November 5, 2026)

  2. v2.1.257: bypass mode leaves project files

    defaultMode: "bypassPermissions" in a project or local file is ignored, as auto already was.

    Source: Claude Code release v2.1.257 on GitHub (read November 5, 2026)

  3. v2.1.314: a block on writes outside the project

    permissions.blockWritesOutsideWorkingDirectories makes Write, Edit and NotebookEdit refuse paths outside the working directories in every mode.

    Source: Claude Code changelog (read November 5, 2026)

  4. v2.1.318: one dialog for /permissions

    Rule details and delete confirmations open in the standard dialog, and pressing Ctrl+C twice there goes back instead of quitting.

    Source: Claude Code changelog (read November 5, 2026)

Set up a team file and a personal override

A committed file for the team and an untracked file for you cover most projects. The block below is the permissions part of Anthropic's example team file, plus the schema line that gives your editor autocomplete and validation.

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm run *)"
    ],
    "ask": [
      "Bash(git push *)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)"
    ]
  }
}
  1. Save the block as .claude/settings.json at the top of the repository and commit it. Claude Code reads the shared file from the session's primary working directory, so start claude at the repository root.
  2. Create .claude/settings.local.json for your own exceptions. Claude Code keeps a file it writes itself out of git. If you create the file by hand, add it to .gitignore yourself.
  3. In the local file, set a key the team file also sets. Local sits above shared project, so only your sessions change. {"spinnerTipsEnabled": false} turns the tips under the spinner off for you alone.
  4. Run /status. The Setting sources line names each file Claude Code loaded, such as User settings or Project local settings. It confirms which files were read, not which file supplied a key.
  5. Run /permissions to list every rule and the file it comes from. Run claude doctor to list the entries Claude Code rejected.
  6. Edit a rule while a session runs. Claude Code watches the files and applies most edits, including permissions and hooks, without a restart.

Which value wins when files disagree

Claude Code uses the value from the highest level that sets a key. Managed settings sit on top, above even --settings, and nothing in your own files overrides a managed key.

Lists are the exception to winner takes all. When permissions.allow appears in several files, Claude Code combines the lists, so each file adds entries and removes none. Four model keys follow their own rules: fallbackModel, modelPicker, availableModels and modelSettings.

Environment variables are not a level. When a behavior has both a variable and a key, the pair decides. ANTHROPIC_MODEL exported in your shell beats the model key from any file, while ANTHROPIC_DEFAULT_MODEL applies only when no file sets model. An env block inside a settings file is an ordinary key that follows the table, and its values overwrite the same variable in your shell.

Settings precedence, highest first, from Anthropic's settings guide
LevelSourceApplies to
1Managed: managed-settings.json, an MDM policy or server-managed settingsEveryone your organization deploys it to
2Command line: --settings with inline JSON or a file pathOne session. It writes nothing to disk
3Project local: .claude/settings.local.jsonYou, in one project
4Shared project: .claude/settings.jsonEveryone who clones the repository
5User: ~/.claude/settings.jsonYou, in every project on this machine

Deny, then ask, then allow

Claude Code checks deny rules first, then ask, then allow. The first match decides, and a narrower rule does not win for being narrower. A deny on Bash(aws *) blocks aws s3 ls even when an allow rule names that exact command. A deny in any scope beats an allow in any other, in either direction.

The config below runs npm scripts and commits without asking and refuses git push. Rules reach past Bash, too. mcp__puppeteer__* matches every tool of one MCP server, and Agent(Explore) in deny turns one subagent off.

Permission rules are enforced by Claude Code, not by the model.

Anthropic, Claude Code documentation · Claude Code docs: Configure permissions (read November 4, 2026)
{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(git commit *)"
    ],
    "deny": [
      "Bash(git push *)"
    ]
  }
}
  • Put the * after the subcommand. Bash(git log *) allows only git log commands, while Bash(git *) allows every git command. Claude Code warns at startup about an allow rule with a * before the subcommand, such as Bash(git * main).
  • A trailing * with a space also matches the bare command, so Bash(ls *) matches ls. The space matters: Bash(ls*) matches lsof as well.
  • A compound command needs every part allowed. Bash(safe-cmd *) does not approve safe-cmd && other-cmd, and a deny or ask rule fires when any part matches.
  • Claude Code strips a fixed set of wrappers before matching, such as timeout, time, nice and nohup. It does not strip runners like npx, docker exec or devbox run, so a rule for devbox run * allows whatever follows run.

Path rules and where they anchor

Read and Edit rules use gitignore syntax, and the leading slash trips most people. A single slash is not an absolute path. A rule that starts with / anchors at the settings source, so a /secrets rule in your user settings blocks the secrets folder under ~/.claude and leaves the one in your project alone. The block below lists the four anchors with Anthropic's examples.

Depth depends on the rule type. A one-segment directory pattern such as src covers only the src folder under the current directory as an allow rule, and a folder of that name at any depth as a deny or ask rule. To allow a name at any depth, start the pattern with a double star, as in the last line of the block.

//path   Read(//Users/alice/secrets/**)   absolute path from the filesystem root
~/path   Read(~/Documents/*.pdf)          from your home directory
/path    Edit(/src/**/*.ts)               under the primary working directory, in project settings
path     Read(*.env)                      relative to the current directory

allow    Edit(src/**)                     only the src folder under the current directory
deny     Read(secrets/**)                 a secrets folder at any depth
any      Edit(**/src/**)                  a src folder at any depth

A path rule written for Write, NotebookEdit or Glob is accepted and never matches. Use an Edit rule in place of Write and a Read rule in place of Glob.

What a deny rule does not stop

A Bash rule matches the command text Claude writes, after Claude Code splits compound commands and strips wrappers. The same program called another way is a different string, so the rule covers the usual form and nothing more. Anthropic's table shows three examples.

Files have the same gap. Read(./.env) stops cat .env and the file tools, and it does not stop grep -r run over the directory or a script that opens the file itself. When a limit must hold, the permissions page points to two tools. Sandboxing enforces filesystem and network limits at the OS level, and a PreToolUse hook can inspect the whole command, as in the hooks lesson. A hook that exits 2 blocks the call before any allow rule is read.

Rules in deny or ask and what slips past them, from the permissions page
RuleStopsDoes not stop
Bash(curl *)curl https://example.com/usr/bin/curl https://example.com and sh -c 'curl https://example.com'
Bash(rm *)rm -rf build//bin/rm -rf build/ and bash -c 'rm -rf build/'
Bash(git push *)git push origin maingit -C . push origin main and git 'push' origin main

Sharing a file with a team: trust and the keys that never travel

A committed file cannot grant capability by itself. permissions.allow and permissions.additionalDirectories in .claude/settings.json apply only after each teammate accepts the workspace trust dialog for that folder. Deny and ask rules apply at once, because they only restrict. We would fill the committed file with secret-file denies first and convenience allows second, since the denies protect from the first session.

Non-interactive runs skip the dialog. claude -p and SDK sessions never show it, so project allow rules go unused and Claude Code prints a this workspace has not been trusted warning to stderr. Hooks and the env block from the repository still run. Before you run claude -p in a repository you did not write, pass --setting-sources user, or start with --bare, which the next lesson covers.

Some keys never take effect from a repository file at all.

  • permissions.defaultMode set to auto or bypassPermissions. Set it in your user settings, or pass --permission-mode for one session.
  • The OpenTelemetry exporter variables in an env block, apart from a few values that turn telemetry off. Set them in managed or user settings.
  • Any key whose Scope in the settings reference reads User, User or managed, User, local, or managed, Managed or Global config.

How Claude Code's creator shares permission rules with his team

Boris Cherny created Claude Code and works on Claude at Anthropic. His thread of customizing tips is on X, and tip 5 starts from the defaults. Claude Code pre-approves a small set of safe commands, you add more through /permissions, and the rules go into the team's settings.json. His examples are a Bash rule for bun run and an Edit rule for a docs folder, both in this lesson's wildcard syntax. The Edit rule starts with a slash, so in the team file it anchors at the project. Pasted into your user file, it would point at ~/.claude/docs instead.

Five minutes later, tip 12 said the same about every setting. He counted 37 settings and 84 environment variables that day and suggested the env field over wrapper scripts. Treat those counts as a February snapshot. The settings reference lists every key today.

Each "Yes, and don't ask again" writes one more rule into .claude/settings.local.json, so your own approvals pile up there. After a week of work, open /permissions, move the rules every teammate would approve into the shared file, and commit it.

When you do customize, check your settings.json into git so your team can benefit, too.

Boris Cherny, Creator of Claude Code, at Anthropic · X (read November 5, 2026)
Boris Cherny (@bcherny) on X, 11 February 2026, tip 12 of his thread: Claude Code is built to work great out of the box. When you do customize, check your settings.json into git so your team can benefit, too. We support configuring for your codebase, for a sub-folder, for just yourself, or via enterprise-wide
Boris Cherny on X, 11 February 2026

A screenshot of X's own embed of the post, taken on 5 November 2026, with the time in UTC. X cuts the post short with Show more. Select it to open the post on X.

Common mistakes

  • A trailing comma or a // comment in a settings file. The files are strict JSON, and Claude Code shows a Settings Error at the next start. A -p run shows no dialog and skips the broken file, so run claude doctor after a run that ignored a setting.
  • Trying to carve an exception out of a deny. An allow rule cannot reopen what a deny blocks. Narrow the deny instead.
  • Reading /status as a trace of each key. It lists loaded files and not the file behind each value. /permissions shows where each rule comes from.
  • Writing Windows paths as Windows writes them. Claude Code normalizes C:\Users\alice to /c/Users/alice before matching, so a rule for that drive starts with //c/.
  • Expecting "Yes, and don't ask again" to beat a project rule. That choice saves an allow rule to your local file, and an allow there does not outrank an ask rule from a project or managed file.

Try it yourself

  • Add Read(./.env) to the project file's deny list, ask Claude to read .env, then open /permissions and find the file that rule comes from.
  • Put Bash(git push *) in ask in the team file and the same rule in allow in your local file. Predict whether Claude Code prompts, then ask it to push and check.
  • Set spinnerTipsEnabled to false in your user file, then start one session with claude --settings '{"spinnerTipsEnabled": true}'. The tips return for that session only.
  • Run /status, then claude doctor, and write down what each one tells you that the other does not.

Next: headless runs

Settings decide what a session may do. In the next lesson, headless runs, claude -p runs where nobody can answer a prompt, so the rules from this lesson become the whole safety model.

Hooks, from an earlier lesson, run your own commands at set points of a session. Standing instructions still belong in a CLAUDE.md file, which settings do not replace.

Check yourself

  1. Your user settings deny Bash(npm run deploy *) and the committed project file allows Bash(npm run *). What happens to npm run deploy prod?

    Show answer

    B. It is blocked, because a deny in any scope beats an allow Claude Code checks deny rules first, then ask, then allow, across every scope, and the first match decides.

  2. Which file holds your own overrides for one project and stays out of git?

    Show answer

    C. .claude/settings.local.json Project local settings apply only to you in one project and sit above the shared project file in the precedence stack.

  3. You commit "defaultMode": "auto" in .claude/settings.json. What do your teammates get?

    Show answer

    A. Nothing, because auto does not take effect from project or local settings The values auto and bypassPermissions only take effect from user or managed settings, or from --permission-mode for one session.

  4. Which protection still holds when Claude runs /usr/bin/curl instead of curl?

    Show answer

    C. A sandbox network allowlist A Bash rule matches the command text as written, while the sandbox restricts network access at the OS level whatever the command looks like.

Frequently asked questions

Where is the Claude Code settings.json file?

There are four sources: ~/.claude/settings.json for you in every project, .claude/settings.json committed with a project, .claude/settings.local.json for you in one project, and a managed file or policy your organization deploys. Installing Claude Code creates none of them. On Windows, ~/.claude means %USERPROFILE%\.claude.

Where does "Yes, and don't ask again" save my choice?

In .claude/settings.local.json, as an allow rule that only you get. It outranks the shared file, and Claude Code keeps the local file out of git when it creates it.

How do I stop Claude Code from reading my .env file?

Add Read(./.env) and Read(./.env.*) to permissions.deny. Claude Code then excludes matching files from discovery and search, and blocks Edit and Write on those paths. A command that never names the file, such as grep -r over the folder, still gets through, so turn on the sandbox when the file must stay unreadable.

Why is my permission rule ignored?

Start with /status. A higher level may set the same key, or a project allow rule may still wait for workspace trust. Other causes are auto or bypassPermissions in a project file, an invalid entry that Claude Code skipped, and a Write or Glob path rule, which never matches. claude doctor lists what it rejected.

Do I need to restart Claude Code after editing settings?

Usually not. Claude Code reloads user, project, local and managed files when they change, including permissions, hooks and credential helpers. A few keys load once at session start, and removing permissions.blockReadsOutsideWorkingDirectories mid-session keeps the block until you restart each session.

Can I set the permission mode for a whole project?

Yes for default, acceptEdits, plan and dontAsk, through permissions.defaultMode in .claude/settings.json. The values auto and bypassPermissions take effect only from user or managed settings, or from --permission-mode for one session.

Can an admin stop developers from changing these settings?

Yes. Managed settings sit above every other level, and allowManagedPermissionRulesOnly makes them the only source of permission rules. permissions.disableBypassPermissionsMode set to "disable" removes bypass mode, and a developer can see the policy in /status.

Sources

  1. Claude Code docs: Settings files and precedence (read November 5, 2026)https://code.claude.com/docs/en/settings
  2. Claude Code docs: Configure permissions (read November 5, 2026)https://code.claude.com/docs/en/permissions
  3. Claude Code docs: Example settings files (read November 4, 2026)https://code.claude.com/docs/en/settings-example
  4. Claude Code docs: Settings reference (read November 4, 2026)https://code.claude.com/docs/en/settings-reference
  5. Claude Code release v2.1.211 on GitHub (read November 5, 2026)https://github.com/anthropics/claude-code/releases/tag/v2.1.211
  6. Claude Code release v2.1.257 on GitHub (read November 5, 2026)https://github.com/anthropics/claude-code/releases/tag/v2.1.257
  7. Claude Code changelog (read November 5, 2026)https://code.claude.com/docs/en/changelog
  8. Boris Cherny on X: pre-approve common permissions (read November 5, 2026)https://x.com/bcherny/status/2021700332292911228
  9. Boris Cherny on X: customize all the things (read November 5, 2026)https://x.com/bcherny/status/2021701636075458648

Share this lesson

Kits made for Claude Code

A Mindket kit is a zip of plain text files you unzip into a project. Browse the ones made for Claude Code.

Browse kits

This lesson as Markdown · Claude Code advanced course · All courses