Claude Code settings.json: file locations and reference
Updated 24 October 2026
Claude Code reads its settings from several JSON files, and the one you edit decides who the change applies to: just you, everyone on the project, or your whole organization. Most “my setting does nothing” problems are a setting in the wrong file, a file that didn’t parse, or another file overriding it. Here’s where each file lives on every OS, which one wins, what goes where, and the keys you’ll actually use.
The short answer
| File | Path | Applies to | Commit it? |
|---|---|---|---|
| User | ~/.claude/settings.json | You, in every project on this machine | No |
| Project | .claude/settings.json | Everyone who works in the repository | Yes |
| Local | .claude/settings.local.json | You, in this project only | No |
| Managed | managed-settings.json in a system directory, MDM or the claude.ai console | Everyone your organization deploys it to | No |
Not on the list: ~/.claude.json. It sits next to the .claude folder, not inside it, and it isn’t a settings file. More on that in section 3.
1. Where each settings file lives
Installing Claude Code doesn’t create any settings file. Claude Code writes ~/.claude/settings.json the first time you change something in /config that belongs there, and .claude/settings.local.json the first time you choose “Yes, and don’t ask again” on a permission prompt. Otherwise, create the file yourself.
- User settings:
~/.claude/settings.jsonon macOS, Linux and WSL. On Windows,~means%USERPROFILE%, so it’s%USERPROFILE%\.claude\settings.json. If you setCLAUDE_CONFIG_DIR, Claude Code uses that directory instead of~/.claude. - Project settings:
.claude/settings.jsonin the directory you start Claude Code from. To use a file committed at the repository root, start Claude Code at the root. - Local settings:
.claude/settings.local.json. In a git repository, Claude Code reads and writes it at the repository root even if you start in a subdirectory (since v2.1.211), and in a worktree it uses the main checkout’s file. The first time Claude Code writes it, it adds**/.claude/settings.local.jsonto your global git excludes. If you created the file by hand, add it to.gitignoreyourself.
Managed settings paths
| OS | File-based managed settings |
|---|---|
| macOS | /Library/Application Support/ClaudeCode/managed-settings.json |
| Linux and WSL | /etc/claude-code/managed-settings.json |
| Windows | C:\Program Files\ClaudeCode\managed-settings.json |
A managed-settings.d/ folder next to that file is merged in too, after managed-settings.json, in alphabetical order, so separate teams can own 10-telemetry.json and 20-security.json. Claude Code no longer reads the old Windows path C:\ProgramData\ClaudeCode\managed-settings.json.
The same keys can arrive other ways: a macOS configuration profile for the com.anthropic.claudecode domain, a Settings string value under HKLM\SOFTWARE\Policies\ClaudeCode on Windows (or HKCU, which has the lowest priority), or server-managed settings from the claude.ai admin console. By default Claude Code uses the highest-ranked of these that has a policy and ignores the rest: server-managed, then MDM or registry, then files, then HKCU.
2. Which file wins
When the same key is set in more than one place, the highest one wins:
- Managed settings. Nothing you set overrides them.
- Command line:
claude --settings <file-or-json>, for that session only. - Local:
.claude/settings.local.json - Project:
.claude/settings.json - User:
~/.claude/settings.json
Rules that change the picture:
- Lists merge.
permissions.allow,denyandaskfrom every file are combined, not replaced. Hooks merge across files the same way, so a project hook doesn’t knock out your user hooks. - Permission rules go by type, not by file. Deny is checked first, then ask, then allow. An
allowin your local file doesn’t beat anaskin the project file. - Some values are refused from project files.
permissions.defaultModeset toautoorbypassPermissionshas no effect in.claude/settings.jsonorsettings.local.json. Put those in your user file. - Some keys wait for trust. In a committed project file,
permissions.allow,additionalDirectoriesand mostenvvalues only apply after you accept the workspace trust dialog. Deny and ask rules apply right away. - Environment variables aren’t a level. Whether a shell variable or a settings key wins is decided per pair.
ANTHROPIC_MODELin your shell beats themodelkey in any file, and--modelbeats both.
Example: you set "spinnerTipsEnabled": false in your user file, but the team’s .claude/settings.json sets it to true. You’ll see tips in that project. Put false in that project’s .claude/settings.local.json and they go away for you without changing anything for your teammates.
3. settings.json vs CLAUDE.md vs .mcp.json vs ~/.claude.json
| File | What goes in it | Where |
|---|---|---|
settings.json | Behavior Claude Code enforces: permissions, hooks, env, model, sandbox, status line, plugins | ~/.claude/, .claude/, managed directory |
CLAUDE.md | Instructions for Claude in plain Markdown: build commands, conventions, where things live | ~/.claude/CLAUDE.md, ./CLAUDE.md or ./.claude/CLAUDE.md, ./CLAUDE.local.md for personal notes |
.mcp.json | MCP servers shared with the team, under an mcpServers key | Repository root, not inside .claude/ |
~/.claude.json | App state Claude Code writes itself: account, personal and per-project MCP servers, trust decisions, a few /config toggles | Your home directory |
The rule of thumb from Anthropic’s docs: CLAUDE.md is guidance, settings are guarantees. “Never touch the migrations folder” in CLAUDE.md is a request Claude will usually follow. "deny": ["Edit(./migrations/**)"] in settings.json is enforced.
MCP servers you add with claude mcp add go to ~/.claude.json by default (local scope, this project only). --scope user also stores them there, for every project. --scope project writes .mcp.json. You rarely need to edit ~/.claude.json by hand. If it gets corrupted, Claude Code keeps backups in ~/.claude/backups/.
Managed instructions exist too: CLAUDE.md in the same system directories as managed-settings.json.
4. The settings keys worth knowing
There are well over a hundred keys. These are the ones people actually set. Every one of them works in any of the four settings files unless noted.
| Key | What it does |
|---|---|
permissions.allow | Tool uses that run without a prompt, such as "Bash(npm run *)" |
permissions.ask | Tool uses that always prompt, even in auto and bypass modes |
permissions.deny | Tool uses that are blocked, such as "Read(./.env)" |
permissions.defaultMode | Starting permission mode: default (or manual), acceptEdits, plan, auto, dontAsk, bypassPermissions |
permissions.additionalDirectories | Extra directories Claude can work in, like --add-dir |
permissions.disableBypassPermissionsMode | "disable" blocks --dangerously-skip-permissions |
model | Model new sessions start with, as an alias or full model ID |
env | Environment variables for every session and the commands it runs |
hooks | Your own commands on events like PreToolUse, PermissionRequest, Notification and Stop |
disableAllHooks | true turns off hooks and any custom status line |
statusLine | A command whose output becomes the status line below the prompt |
preferredNotifChannel | How Claude Code alerts you: auto, terminal_bell, iterm2, kitty, ghostty, notifications_disabled and others |
sandbox.enabled | true runs Bash commands in the OS sandbox (macOS, Linux, WSL2) |
attribution | Change or hide the Co-Authored-By trailer and PR line; false hides both (v2.1.281+). Replaces the deprecated includeCoAuthoredBy |
cleanupPeriodDays | Days to keep session transcripts; default 30, minimum 1 |
enabledPlugins | Turn plugins on or off, keyed by plugin-name@marketplace-name |
enableAllProjectMcpServers | Approve every server in a project’s .mcp.json without asking |
apiKeyHelper | A command that prints the API credential, instead of storing a key |
theme | auto, dark, light and colorblind or ANSI variants |
editorMode | vim for vim key bindings in the prompt |
language | Have Claude reply in another language, such as "japanese" |
alwaysThinkingEnabled | false turns extended thinking off; no effect on models that always think |
autoUpdatesChannel | stable to follow a release about a week old instead of latest |
skipDangerousModePermissionPrompt | Skip the bypass-mode warning; user, local or managed settings only |
A reasonable starting user file:
~/.claude/settings.json{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test *)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)"
]
},
"preferredNotifChannel": "terminal_bell",
"cleanupPeriodDays": 90
}
The full list, with defaults and which files each key is allowed in, is on Anthropic’s settings reference. Look at the Scope column before committing a key: keys marked User, Managed or Global config do nothing in a project file.
5. Environment variables in settings
The env key sets variables for every session and every command Claude runs from it. Values must be strings:
~/.claude/settings.json{
"env": {
"BASH_DEFAULT_TIMEOUT_MS": "300000",
"DISABLE_AUTOUPDATER": "1"
}
}
- A value in
envoverwrites the same variable exported in your shell. To cancel a shell export, set it to"". - From a project file, most
envvalues apply only after you trust the folder. Some variables can’t be set from project or local files at all, includingCLAUDE_CONFIG_DIR,HOME,TMPDIRand theXDG_*family. Claude Code drops them and logs a warning you’ll see withclaude --debug. - Values here are plain text and reach every subprocess. Don’t put API keys in a committed file; use
apiKeyHelperfor credentials. - When the Claude desktop app starts the session, variables it already sets win over
env.
6. /config, /status and one-off overrides
/configopens a menu with a short list of personal options: theme, editor mode, verbose output and so on. It isn’t a view of yoursettings.json. Most choices save to~/.claude/settings.json; a few, like Show tips, go to.claude/settings.local.json; global options go to~/.claude.json. To set one directly:/config verbose=true. It’s terminal only; the VS Code panel and desktop app don’t open it./statusshows aSetting sourcesline listing every file that loaded, plus the managed source if there is one. It doesn’t tell you which file supplied a given key.--settingsapplies JSON for one session without touching your files:
Terminalclaude --settings '{"model": "claude-opus-5-5"}'
--setting-sources user loads your user file and skips project and local settings (managed settings still apply), which is handy for checking whether a repository’s settings are causing a problem.
You don’t need to restart after editing. Claude Code watches the files and applies most changes, including permissions and hooks, to the running session. model and effortLevel are read at startup only; use /model and /effort mid-session.
7. The $schema line and validating your JSON
Add this as the first key in any settings file:
.claude/settings.json{
"$schema": "https://json.schemastore.org/claude-code-settings.json"
}
VS Code, Cursor and other editors that understand JSON Schema then autocomplete key names and underline wrong values. The schema can lag behind new releases, so a warning on a key that was added recently doesn’t always mean it’s wrong.
Settings files are strict JSON. A // comment or a trailing comma makes the whole file invalid. Check a file before you start a session:
Terminalpython3 -m json.tool ~/.claude/settings.json
claude doctor
python3 -m json.tool prints the file if it parses and the line and column of the error if it doesn’t; jq . ~/.claude/settings.json works too. claude doctor reads your settings files without starting a session and lists problems under Invalid settings, such as “Invalid or malformed JSON” or an unknown hook event name.
What happens to a broken file depends on how bad it is. Invalid JSON shows a Settings Error dialog when an interactive session starts, and you can fix it, exit, or continue without that file. A single bad entry, like a malformed permission rule, is a Settings Warning: that entry is skipped and the rest of the file applies. A claude -p run shows no dialog and silently skips the broken parts, so run claude doctor after a headless run that ignored a setting.
8. Common mistakes
Two "hooks" keys in one file. This is the classic one, and it happens when you paste a second hook snippet below the first. The JSON still parses, so there’s no error, but only the last "hooks" block survives and the first one silently disappears. claude doctor doesn’t flag it either. Keep one "hooks" object and put each event inside it (say is macOS text-to-speech; use any command you like):
~/.claude/settings.json{
"hooks": {
"Notification": [
{ "matcher": "", "hooks": [{ "type": "command", "command": "say 'Claude needs you'" }] }
],
"Stop": [
{ "hooks": [{ "type": "command", "command": "say 'Claude is done'" }] }
]
}
}
The same goes for a second "permissions" or "env" key. The other usual suspects:
- Settings in
~/.claude.json.permissions,hooksandenvthere are ignored. They belong in~/.claude/settings.json, inside the folder. - MCP servers in
settings.json. AnmcpServerskey in a settings file is ignored without any warning. Use.mcp.jsonat the repository root orclaude mcp add. A.mcp.jsoninside.claude/, or one that uses VS Code’sserverskey, doesn’t load either. - A separate hooks file. There’s no standalone
hooks.jsonfor user or project config (only plugins have one). Hooks go under"hooks"in a settings file. - Matcher typos. Matchers are case-sensitive strings:
"Bash", not"bash". To match several tools use"Edit|Write", not an array. An array matcher is reported as invalid, and underPreToolUseorPermissionRequestit stops the rest of that file’s hooks loading too. - Forgetting the local file exists. A value in
.claude/settings.local.jsonbeats the same key in.claude/settings.jsonand your user file. Claude Code writes allow rules there every time you pick “don’t ask again”, so check it when a project behaves differently from the rest. - Committing a key that only works for users.
"defaultMode": "bypassPermissions",skipDangerousModePermissionPromptand similar keys are ignored in a repository’s.claude/settings.json, by design. - Starting in a subdirectory. Claude Code reads the project
.claude/settings.jsonfrom the directory you launched it in. Start inapp/and the file at the repository root isn’t the project file for that session. - Expecting it in the cloud. Cloud sessions on claude.ai don’t read your user or local settings, or a managed file on your laptop. Only the committed project file and server-managed settings reach them.
Hooks without hand-merging JSON
The duplicate "hooks" key is exactly the mistake people make when they paste setup snippets into a file that already has hooks. Agent Pets sets its own up for you: npx getagentpets init adds the hooks next to any you already have. Then:
- Each Claude Code, Codex, OpenCode and omp session becomes a pet that walks along the bottom of every Chrome page. When one needs permission, its pet bounces; click it and answer Allow, Always or Deny.
- A capsule over each pet says Thinking, Your Turn or Done, and you can read the latest answer and send the next message from any tab.
- In another app, a desktop notification names the pet that needs you, with Allow and Deny on it.
It runs entirely on your computer, and the terminal prompt keeps working as usual.
Get Agent Pets — was $25, now $6Get Agent Pets — $25
Questions
Where is the Claude Code settings.json file?
Your personal file is ~/.claude/settings.json, which is %USERPROFILE%\.claude\settings.json on Windows. Each project can also have .claude/settings.json, shared through git, and .claude/settings.local.json, which is only yours. Installing Claude Code doesn’t create any of them; create the file if it isn’t there.
Which Claude Code settings file takes precedence?
Managed settings win, then --settings on the command line, then .claude/settings.local.json, then .claude/settings.json, then ~/.claude/settings.json. Lists such as permissions.allow are combined across files instead of replaced.
Can I put MCP servers in settings.json?
No. Claude Code ignores an mcpServers key in settings.json without an error. Put shared servers in .mcp.json at the repository root, or run claude mcp add, which stores personal servers in ~/.claude.json.
Do I need to restart Claude Code after editing settings.json?
Usually not. Claude Code watches its settings files and applies most changes, including permissions and hooks, to the running session. A few keys, such as model and effortLevel, are read only at startup; use /model or /effort to change those mid-session.
What is the difference between ~/.claude/settings.json and ~/.claude.json?
~/.claude/settings.json holds your settings: permissions, hooks, env, model and so on. ~/.claude.json is app state that Claude Code writes itself: your account, personal MCP servers, per-project trust and a few /config toggles. Permissions or hooks placed in ~/.claude.json are ignored.
Sources: Claude Code’s documentation on settings files and precedence, the settings reference, managed settings, debugging your configuration, CLAUDE.md, MCP, permissions and environment variables; the settings JSON schema; claude --help and claude doctor on Claude Code 2.1.287.