Claude Code reads settings from three JSON files at different scopes. This reference covers every field, the merge order, and copy-paste configs for common setups.
TL;DR
Three files, one merge chain. ~/.claude/settings.json (global) is your baseline. .claude/settings.json (project) configures team-shared settings. .claude/settings.local.json (local) holds your personal overrides. Values merge with local taking priority.
File Locations
Settings file paths
# Global settings (applies to all projects)
~/.claude/settings.json
# Project settings (shared with team, commit to repo)
<project-root>/.claude/settings.json
# Local settings (personal overrides, add to .gitignore)
<project-root>/.claude/settings.local.jsonClaude Code reads all three files on startup and merges them. If a field exists in multiple files, the most specific one wins: local overrides project, project overrides global.
On Windows, the global path is %USERPROFILE%\.claude\settings.json. On macOS and Linux, it's ~/.claude/settings.json.
Merge Order
Settings merge with a last-writer-wins strategy at the field level. Arrays are replaced, not appended. Objects are deep-merged.
Merge example
// ~/.claude/settings.json (global)
{
"model": "claude-opus-4-6",
"allowedTools": ["Read", "Write", "Bash(git *)"],
"theme": "dark"
}
// .claude/settings.json (project)
{
"allowedTools": ["Read", "Write", "Bash(git *)", "Bash(npm test)"],
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
}
}
}
// .claude/settings.local.json (local)
{
"model": "claude-sonnet-4-6"
}
// Effective merged result:
{
"model": "claude-sonnet-4-6", // local wins over global
"allowedTools": ["Read", "Write", "Bash(git *)", "Bash(npm test)"], // project replaces global
"theme": "dark", // inherited from global
"mcpServers": { ... } // inherited from project
}Arrays Replace, Not Merge
If both global and project settings define allowedTools, the project array completely replaces the global one. It does not append. Make sure project-level arrays include everything you need.
Permissions Config
The allowedTools array controls which tools Claude can use without asking for permission. Each entry is a tool name, optionally with a glob pattern for arguments.
Permissions examples
{
// Allow all git commands, npm test, and file operations
"allowedTools": [
"Read",
"Write",
"Edit",
"Bash(git *)",
"Bash(npm test)",
"Bash(npm run lint)",
"Bash(npx tsc --noEmit)"
]
}
// More restrictive: only allow reads and specific commands
{
"allowedTools": [
"Read",
"Glob",
"Grep",
"Bash(git status)",
"Bash(git diff)"
]
}The glob pattern after Bash() uses standard glob matching. Bash(git *) matches any command starting with git. Bash(npm run *) matches any npm script. Commands not in the list require manual approval.
For a deeper look at the permission system, including --dangerously-skip-permissions and its use cases, see the Claude Code permissions guide.
Model Selection
Claude Code defaults to the latest Opus model. You can override it at any settings level or via environment variables.
Model configuration
// Use Sonnet for faster, cheaper responses
{
"model": "claude-sonnet-4-6"
}
// Use a specific model version
{
"model": "claude-opus-4-6"
}
// Point to a different API provider (e.g., Morph)
{
"apiBaseUrl": "https://api.morphllm.com",
"model": "claude-sonnet-4-6"
}Environment variable priority: CLAUDE_MODEL or ANTHROPIC_MODEL override settings.json. This is useful in CI where you want Sonnet for cost but Opus locally for quality.
For a comparison of available models, see the Claude Code models guide.
MCP Server Config
MCP (Model Context Protocol) servers extend Claude Code with external tools. Configure them in settings.json to auto-start when Claude launches.
MCP server configuration
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/docs"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "ghp_..."
}
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "postgresql://user:pass@localhost:5432/mydb"
}
}
}
}Each server gets a command (the binary to run), args (command-line arguments), and optional env (environment variables passed only to that server). Servers start automatically when Claude Code launches and stop when it exits.
For a curated list of MCP servers, see best MCP servers for Claude Code.
Environment Variables
Settings.json can set environment variables that Claude Code passes to all tool executions:
Environment variable configuration
{
"env": {
"NODE_ENV": "development",
"DATABASE_URL": "postgresql://localhost:5432/myapp",
"MORPH_API_KEY": "sk-morph-..."
}
}These variables are available in all Bash tool calls Claude makes. They merge with your shell environment, with settings.json values taking precedence over inherited variables.
Sensitive Values
Put API keys and secrets in settings.local.json (not committed) or use environment variables from your shell. Never commit secrets in settings.json.
Full Schema Reference
| Field | Type | Default | Description |
|---|---|---|---|
model | string | claude-opus-4-6 | Model ID for the main conversation |
smallModel | string | claude-haiku-4-5 | Model for background tasks (summarization, classification) |
allowedTools | string[] | [] | Tools that skip permission prompts |
mcpServers | object | {} | MCP server definitions |
env | object | {} | Environment variables for tool execution |
apiBaseUrl | string | https://api.anthropic.com | API endpoint (change for proxies like Morph) |
hooks | object | {} | Shell commands that run on events (pre-commit, post-tool) |
theme | string | system | Terminal theme: "dark", "light", or "system" |
Common Configurations
Team settings (.claude/settings.json, committed)
{
"allowedTools": [
"Read", "Write", "Edit", "Glob", "Grep",
"Bash(git *)",
"Bash(npm test)",
"Bash(npm run lint)",
"Bash(npx tsc --noEmit)"
],
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"command": "npx prettier --write $CLAUDE_FILE_PATH"
}
]
}
}Local overrides (.claude/settings.local.json, gitignored)
{
"model": "claude-sonnet-4-6",
"apiBaseUrl": "https://api.morphllm.com",
"env": {
"ANTHROPIC_API_KEY": "sk-morph-..."
},
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "ghp_..."
}
}
}
}CI settings (restrictive)
{
"model": "claude-sonnet-4-6",
"allowedTools": [
"Read", "Glob", "Grep",
"Bash(git diff)", "Bash(git log)",
"Bash(npm test)", "Bash(npm run lint)"
]
}FAQ
Can I use YAML instead of JSON?
No. Claude Code only reads JSON settings files. If you prefer YAML for readability, you can maintain a YAML source and generate JSON from it as a build step, but Claude only reads .json.
How do I reset settings to defaults?
Delete the settings file and restart Claude Code. It will regenerate defaults. Or, selectively remove fields from your JSON to fall back to the next level in the merge chain.
Can team members have different models?
Yes. Set the team model in .claude/settings.json (committed) and let individuals override it in .claude/settings.local.json (gitignored). The local file takes priority.
Route Claude Code Through Morph
Set apiBaseUrl to Morph in your settings.json. Get 50% faster file edits with the fast apply model and lower token costs. One config change.