You’re staring at your settings.json. It’s got three levels of configuration—user, project, enterprise—and you’re wondering which one controls what, and more importantly, where you should put your MCP server config versus your environment variables.
Here’s the thing: Claude Code’s settings hierarchy isn’t just about organization. It’s about control, flexibility, and knowing exactly where a setting lives when you need to debug it at 2 AM. Get this right, and your entire development environment becomes predictable and maintainable. Get it wrong, and you’ll spend hours chasing configuration issues that would’ve taken minutes to solve.
Let’s dig in.
Why Settings Matter: The Foundation of Control
Before we dive into the hierarchy, let’s establish why you should care about settings at all. Settings are how you control every aspect of Claude Code’s behavior without writing code or repeating instructions. They’re the difference between Claude Code conforming to your needs and you conforming to Claude Code.
Consider two scenarios. In the first, you manually specify your LLM model, MCP servers, timeouts, and autonomous mode settings every time you start a session. You do this five times a day across three projects. That’s hundreds of decisions repeated manually. In the second scenario, settings encode all these decisions once. Claude Code reads the settings and starts with everything configured. Same system, vastly different experience.
Settings are also how organizations scale. When you’re a solo developer, you know your preferences. When you’re on a team of 20, you need standards. When you’re managing 200 developers across multiple teams, you need governance. Settings enable all three: personal defaults, team standards, and organizational policy.
The Settings Hierarchy: Who Wins?
Think of Claude Code’s settings hierarchy like CSS cascading, except it actually makes sense and has clear, predictable behavior.
The order of precedence:
- User Settings (~/.claude/settings.json) – Your personal baseline
- Project Settings (project-root/.claude/settings.json) – Overrides user for this repo
- Enterprise Settings (enterprise-wide config) – Organization-level standards
- Environment Variables – Override everything at runtime
When Claude Code starts, it merges these in order. Later layers win. An environment variable ANTHROPIC_API_KEY=sk-xxx will override whatever you set in your settings.json files.
This matters because you might have a user-wide setting that works for 90% of your projects, but one specific project needs a different configuration. Rather than maintaining multiple copies or remembering to change things manually, Claude Code’s hierarchy handles it automatically. You define your baseline once, then override selectively where needed.
Understanding the Merge Process
Here’s what actually happens under the hood: Claude Code loads settings in this exact order, and for each layer, it performs a deep merge with previous layers. This means scalar values (strings, numbers, booleans) replace the previous value, while objects and arrays extend or override based on configuration.
For example, if your user settings define 5 MCP servers and your project settings define 3 different servers, you don’t lose the 5 from user settings—you get all 8 (assuming no naming conflicts). But if a project server has the same name as a user server, the project version wins. This prevents the common problem where settings become “all or nothing”—you can truly layer configurations at different levels without losing work at other levels. It’s a sophisticated system designed for real-world complexity.
The merge algorithm uses path-based matching for objects. So if you have user-level timeouts and project-level timeout overrides, they merge intelligently. You might have timeout: { modelCall: 120000, toolExecution: 30000 } at user level, and project level only overrides modelCall: 60000. You end up with both modelCall and toolExecution at project level, with the modelCall value from the project overriding the user default.
User-Level Settings: Your Personal Baseline
This lives at ~/.claude/settings.json. It’s your personal configuration across all Claude Code projects.
What goes here? Your preferred LLM model, default provider (Anthropic, Bedrock, etc.), global MCP servers you use everywhere, API keys and credentials (more on that in a moment), IDE integrations, default behavior for interactive vs autonomous mode, and global tool preferences and timeouts.
Here’s a typical user-level settings.json:
{
"model": "claude-3-5-sonnet-20241022",
"provider": "anthropic",
"apiKey": "${ANTHROPIC_API_KEY}",
"mcpServers": {
"filesystem": {
"command": "node",
"args": ["~/claude/mcp/server-fs/index.js"],
"env": {
"MCP_PORT": "3001"
}
},
"github": {
"command": "node",
"args": ["~/claude/mcp/server-github/index.js"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
},
"autonomousMode": false,
"defaultInteraction": "interactive",
"maxTokensPerRequest": 8000,
"timeout": {
"modelCall": 120000,
"toolExecution": 30000,
"mcpServer": 15000
}
}
Notice the ${ANTHROPIC_API_KEY} syntax? That’s Claude Code’s variable substitution. It looks for that environment variable at startup and replaces it. Keep your actual secrets out of committed settings files.
Why Variable Substitution Matters
The ${VAR_NAME} syntax is crucial because it keeps your settings file safe to commit to Git without exposing secrets. When Claude Code starts, it reads settings.json, and for any value matching ${NAME}, it looks for an environment variable and substitutes the value. If the environment variable doesn’t exist, it throws an error (fail-safe).
This means you can version-control your settings structure without versioning your secrets. Your teammates can clone the repo, set their own environment variables, and everything works. No risk of accidentally committing API keys. The fail-safe behavior is important—if a required environment variable is missing, Claude Code won’t run with stale or wrong credentials. It’ll tell you what’s missing.
User Settings: Authentication Best Practices
Never put literal API keys in ~/.claude/settings.json. Use environment variables instead:
# Set in your shell profile (~/.bashrc, ~/.zshrc, etc.)
export ANTHROPIC_API_KEY="sk-ant-..."
export GITHUB_TOKEN="ghp_..."
export SLACK_BOT_TOKEN="xoxb-..."
Then reference them in settings:
{
"apiKey": "${ANTHROPIC_API_KEY}",
"mcpServers": {
"github": {
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
This layering means your settings.json is safe to share (you might need to show it to a colleague for debugging), but your actual secrets live only in environment variables, which never get committed or shared.
Project-Level Settings: Repository-Specific Overrides
This is .claude/settings.json in your project root. It overrides user settings for this specific project.
What goes here? Project-specific LLM model (maybe you need Opus for this one), project-only MCP servers, tool and command configurations specific to this repo, build/compile settings, testing configuration, project-specific timeouts and resource limits, and local development overrides.
Here’s an example for a data science project that needs different settings than your usual software engineering work:
{
"model": "claude-3-opus-20250219",
"provider": "anthropic",
"maxTokensPerRequest": 20000,
"tools": {
"jupyter": {
"enabled": true,
"kernel": "python3"
},
"python": {
"version": "3.11",
"venv": ".venv"
}
},
"mcpServers": {
"python-repl": {
"command": "python",
"args": ["-m", "mcp_server_python"],
"env": {
"PYTHONPATH": "./src:./notebooks"
}
},
"pandas-tools": {
"command": "node",
"args": ["./tools/pandas-mcp.js"],
"env": {
"DATA_PATH": "./data"
}
}
},
"autonomousMode": true,
"timeout": {
"modelCall": 300000,
"toolExecution": 60000
}
}
The key difference: this project uses Opus instead of Sonnet, enables Jupyter, sets autonomousMode: true because your data science work is more self-contained, and increases timeouts because data processing is slower. Notice you’re not redefining the filesystem or github servers—those come from user settings and are preserved automatically. This is the power of deep merging: you customize only what’s different for this project.
Project-Specific MCP Servers
You often want tools that only work in specific projects. Project-level MCP servers are perfect for this:
{
"mcpServers": {
"local-api": {
"command": "node",
"args": ["./dev-tools/api-mcp-server.js"],
"env": {
"API_PORT": "8888",
"API_LOG_LEVEL": "debug"
}
},
"database-query": {
"command": "python",
"args": ["-m", "mcp_db_query"],
"env": {
"DATABASE_URL": "postgresql://localhost/myproject_dev",
"QUERY_TIMEOUT": "30"
}
}
}
}
These servers are only available when you’re in this project directory. When you switch to another project, they’re not loaded. This keeps tool availability clean—each project only loads the tools it actually needs.
Enterprise-Level Settings: Organization Standards
For teams using Claude Code at scale, enterprise settings enforce standards across all projects. This typically lives in a centralized location your DevOps/platform team manages. It can be a Git repository your team clones, a centralized config server, environment variables set by your CI/CD pipeline, or a configuration management system (Consul, etcd, etc.).
What goes here? Approved LLM models (enforce cost controls), centralized MCP server registry, security policies (audit logging, data handling), compliance requirements, shared tool configurations, default provider (Bedrock vs Anthropic), data residency requirements, and logging and monitoring endpoints.
Here’s what an enterprise settings file might look like:
{
"enterprise": {
"name": "Acme Corp",
"approvedModels": [
"claude-3-opus-20250219",
"claude-3-5-sonnet-20241022",
"claude-3-haiku-20250307"
],
"provider": "bedrock",
"region": "us-east-1",
"auditLogging": {
"enabled": true,
"destination": "s3://acme-audit-logs/claude-code/",
"logLevel": "detailed",
"retentionDays": 90
},
"mcpServers": {
"compliance-checker": {
"command": "/usr/local/bin/compliance-mcp",
"args": ["--enterprise-mode"],
"env": {
"AUDIT_ENDPOINT": "https://audit.internal.acme.com"
}
},
"github-enterprise": {
"command": "node",
"args": ["/opt/mcp/github-enterprise/index.js"],
"env": {
"GITHUB_ENTERPRISE_TOKEN": "${GH_ENTERPRISE_TOKEN}",
"GITHUB_ENTERPRISE_URL": "https://github.internal.acme.com"
}
}
},
"dataPolicies": {
"piiScan": true,
"dataResidency": "US",
"allowedCloudProviders": ["aws", "azure"],
"encryptionRequired": true
},
"costControl": {
"monthlyBudgetUsd": 5000,
"maxTokensPerCall": 50000,
"rateLimitPerMinute": 100
}
}
}
Enterprise settings give your organization control without requiring every developer to understand compliance requirements. They know it’s handled. A developer might use Sonnet locally, but their company’s enterprise settings lock them to Opus when it’s deployed. They don’t need to understand why—they just follow the structure.
Configuring MCP Servers: The Detailed Breakdown
MCP (Model Context Protocol) servers are how Claude Code extends its capabilities. They run as separate processes and communicate with Claude Code via stdio. Each MCP server config needs a command (the executable to run), args (command-line arguments), env (environment variables for that server), timeout (how long to wait before giving up, optional), restartPolicy (auto-restart behavior, optional), and healthCheck (periodic verification that server is alive, optional).
Here’s a detailed example with multiple servers:
{
"mcpServers": {
"filesystem": {
"command": "node",
"args": [
"/opt/mcp-servers/filesystem/index.js",
"--allowed-dirs=/home/user/projects,/tmp/work"
],
"env": {
"LOG_LEVEL": "info"
},
"timeout": 30000,
"healthCheck": {
"enabled": true,
"intervalMs": 60000
}
},
"database": {
"command": "python",
"args": [
"-m",
"mcp_server_postgresql",
"--host=localhost",
"--port=5432"
],
"env": {
"DATABASE_URL": "${DATABASE_URL}",
"DB_PASSWORD": "${DB_PASSWORD}"
},
"restartPolicy": "always",
"maxRestarts": 3,
"restartDelayMs": 5000
},
"slack": {
"command": "npx",
"args": ["@mcpservers/slack"],
"env": {
"SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}",
"SLACK_SIGNING_SECRET": "${SLACK_SIGNING_SECRET}"
},
"timeout": 15000
},
"custom-tool": {
"command": "/opt/bin/my-custom-mcp",
"args": ["--config=/etc/mcp/custom.conf"],
"env": {
"DEBUG": "true"
},
"restartPolicy": "on-failure"
}
}
}
When Claude Code starts, it spawns each configured MCP server as a separate process, establishes communication, and then has access to all their tools. Each server is isolated—if one crashes, the others keep running.
MCP Server Lifecycle
Claude Code manages the lifecycle of MCP servers: at startup, it spawns each server; if configured, it periodically verifies servers are responsive through health checks; based on restartPolicy, it either restarts or disables the server on failure; when Claude Code exits, it gracefully shuts down all servers.
The restartPolicy can be never (don’t restart on failure), always (always restart on failure), or on-failure (restart only on non-zero exit codes). This matters because some servers need to stay up (database connections) while others are less critical. A filesystem server crashing might be recoverable. A database server crashing should trigger a restart loop until it comes back up.
Environment Variables: Runtime Override Masters
Some settings are meant to be environment variables. Don’t commit ANTHROPIC_API_KEY to Git. Use env vars instead.
Key environment variables Claude Code respects:
# Provider selection
CLAUDE_CODE_USE_BEDROCK=false
CLAUDE_CODE_USE_ANTHROPIC=true
# Authentication
ANTHROPIC_API_KEY=sk-ant-...
BEDROCK_REGION=us-east-1
AWS_PROFILE=default
# Model selection (overrides settings.json)
CLAUDE_CODE_MODEL=claude-3-opus-20250219
# MCP server configuration
MCP_SERVERS_PATH=/opt/mcp-servers
MCP_TIMEOUT=30000
# Logging and debugging
CLAUDE_CODE_LOG_LEVEL=debug
CLAUDE_CODE_LOG_FILE=/var/log/claude-code.log
# Autonomous vs interactive
CLAUDE_CODE_AUTONOMOUS_MODE=false
# API endpoints (for self-hosted setups)
ANTHROPIC_API_BASE=https://api.anthropic.com
BEDROCK_ENDPOINT=https://bedrock-runtime.us-east-1.amazonaws.com
# GitHub integration
GITHUB_TOKEN=ghp_...
GITHUB_ENTERPRISE_TOKEN=ghe_...
# Other integrations
SLACK_BOT_TOKEN=xoxb-...
DATABASE_URL=postgresql://user:pass@host/db
# Performance tuning
CLAUDE_CODE_MAX_TOKENS=20000
CLAUDE_CODE_TIMEOUT=120000
You can mix and match. Use env vars for secrets, settings.json for configuration that doesn’t change per environment. This separation keeps your files clean and your secrets safe.
Here’s how you’d use environment variables in your shell:
export ANTHROPIC_API_KEY="sk-ant-xxx"
export CLAUDE_CODE_MODEL="claude-3-opus-20250219"
export CLAUDE_CODE_LOG_LEVEL="debug"
claude-code --init # Starts with these env vars
Environment Variable Precedence Rules
Environment variables always win, but there’s a specific order:
- Environment variables override settings.json values
- Command-line arguments override environment variables (most specific)
- If an env var is set but the settings file has a different value, the env var wins
This means if you do:
export CLAUDE_CODE_MODEL=claude-3-opus-20250219
claude-code --model claude-3-5-sonnet-20241022
The command-line flag wins because it’s the most specific. This lets you override even environment variables when you need surgical control over a single execution.
Model Selection and Provider Configuration
You need to tell Claude Code which LLM to use and where to get it.
Setting the model:
{
"model": "claude-3-opus-20250219",
"provider": "anthropic"
}
Or using a different provider (AWS Bedrock):
{
"model": "anthropic.claude-3-opus-20250219-v1:0",
"provider": "bedrock",
"bedrock": {
"region": "us-east-1",
"profile": "default"
}
}
Or self-hosted:
{
"model": "claude-3-opus-20250219",
"provider": "custom",
"apiBase": "https://your-anthropic-proxy.internal/api",
"apiKey": "${CUSTOM_API_KEY}"
}
The model names differ by provider. Anthropic API uses claude-3-opus-20250219, claude-3-5-sonnet-20241022, claude-3-haiku-20250307. AWS Bedrock uses anthropic.claude-3-opus-20250219-v1:0, anthropic.claude-3-5-sonnet@20241022-v2:0, etc. Custom endpoints can use whatever they expect.
Provider-Specific Configurations
Each provider has different configuration needs. Bedrock requires region and IAM profile. Anthropic requires API key and base URL. Custom providers require endpoint and authentication details.
Autonomous vs Interactive Mode
This controls how Claude Code behaves when you’re not watching.
Interactive mode (default):
{
"autonomousMode": false,
"defaultInteraction": "interactive",
"pausePoints": [
"before-destructive-action",
"before-external-api-call",
"before-file-modification"
]
}
Claude Code stops and asks you before taking risky actions. Perfect for learning, debugging, or when you want full control.
Autonomous mode with selective approval:
{
"autonomousMode": true,
"autoApprovalThreshold": "low-risk",
"autoApprovalRules": {
"fileRead": true,
"fileWrite": false,
"externalApi": false,
"systemCommand": false
}
}
Claude Code auto-approves only safe actions (reading files) but still asks for confirmation on writes, API calls, or system commands.
Full autonomous mode (use carefully):
{
"autonomousMode": true,
"autoApprovalThreshold": "all",
"auditLogging": {
"enabled": true,
"destination": "/var/log/claude-code/actions.log"
}
}
Everything gets auto-approved. Make sure you have audit logging enabled so you can see what happened.
Decision Matrix: Which Settings Level?
Here’s how to decide where each setting belongs:
| Setting | User | Project | Enterprise | Env Var |
|---|---|---|---|---|
| API Key | ✗ | ✗ | ✗ | ✓ |
| Model Choice | ✓ | ✓ | ✓ | ✓ |
| MCP Servers (global) | ✓ | ✗ | ✗ | ✗ |
| MCP Servers (project-specific) | ✗ | ✓ | ✗ | ✗ |
| MCP Servers (enterprise) | ✗ | ✗ | ✓ | ✗ |
| Provider (Anthropic vs Bedrock) | ✓ | ✓ | ✓ | ✓ |
| Max Tokens | ✓ | ✓ | ✗ | ✗ |
| Autonomous Mode | ✓ | ✓ | ✓ | ✓ |
| Audit Logging | ✗ | ✗ | ✓ | ✗ |
| IDE Integration | ✓ | ✗ | ✗ | ✗ |
| Tool Timeouts | ✓ | ✓ | ✗ | ✗ |
| Data Policies | ✗ | ✗ | ✓ | ✗ |
| Debug Logging | ✓ | ✓ | ✗ | ✓ |
| Cost Limits | ✗ | ✗ | ✓ | ✗ |
The rule: Secrets go in env vars, personal preferences go in user settings, project-specific config goes in project settings, and org policies go in enterprise settings. This isn’t arbitrary; it emerges from where each type of configuration needs to be managed and who should control it.
Merging and Precedence: How It All Works
When Claude Code starts, here’s the exact merge order:
- Load enterprise defaults (if configured)
- Load user settings from
~/.claude/settings.json - Load project settings from
.claude/settings.json - Apply environment variables (these override everything)
- Apply command-line flags (these override everything)
For arrays and objects, the merge is deep. If user settings define mcpServers.filesystem and project settings define mcpServers.database, you get both.
Here’s a concrete example:
User settings:
{
"model": "claude-3-5-sonnet-20241022",
"mcpServers": {
"filesystem": { "command": "node", "args": ["fs-server.js"] }
}
}
Project settings:
{
"model": "claude-3-opus-20250219",
"mcpServers": {
"database": { "command": "python", "args": ["-m", "db_server"] }
}
}
Environment:
CLAUDE_CODE_MODEL=claude-3-5-sonnet-20241022 # Overrides both
Final merged result:
{
"model": "claude-3-5-sonnet-20241022",
"mcpServers": {
"filesystem": { "command": "node", "args": ["fs-server.js"] },
"database": { "command": "python", "args": ["-m", "db_server"] }
}
}
Notice: The env var’s model wins, and you get both MCP servers because they’re deep-merged. This is the power of the system—you don’t lose anything unless you explicitly override it.
Debugging Settings Issues
When things aren’t working as expected:
- Check what settings are actually loaded:
bash
claude-code --show-config
This prints the merged, final configuration (minus secrets).
- Check which environment variables are active:
bash
env | grep CLAUDE_CODE
env | grep ANTHROPIC
- Validate your settings.json syntax:
bash
python -m json.tool ~/.claude/settings.json
- Enable debug logging:
bash
export CLAUDE_CODE_LOG_LEVEL=debug
claude-code [your-command]
-
Check precedence conflicts: If an env var is set, it wins. If you set
ANTHROPIC_API_KEYbut your settings.json saysprovider: bedrock, the env var is ignored. -
Trace the merge process:
bash
claude-code --debug-settings
Shows exactly which files were loaded and in what order.
Common Settings Pitfalls: Learning From Mistakes
Teams repeatedly make the same settings mistakes. Understanding these patterns helps you avoid them.
Pitfall 1: Credentials in Settings – Someone puts an API key directly in settings.json and commits it to git. Now it’s in version control forever. Even if you delete the file, it’s in the history. This is a security disaster. Always use environment variables for secrets.
Pitfall 2: Over-Specifying at User Level – You set everything in ~/.claude/settings.json. Then you switch projects and realize the settings don’t fit. You manually edit the file for each project. You become frustrated with Claude Code. The real issue: you over-specified at the wrong level. User settings should be defaults, not absolutes.
Pitfall 3: Conflicting MCP Servers – Project A configures filesystem server on port 3000. Project B configures filesystem server on port 3000. When you work on both, they conflict. Port 3000 is in use. Services fail silently. Hours of debugging later, you discover the port conflict. Solution: use per-project ports or dynamic port allocation.
Pitfall 4: Forgetting to Document Settings – You add a new setting that does something non-obvious. You don’t document it. Your team doesn’t understand what it does. They ignore it. Six months later, when you ask “why isn’t anyone using this setting?” the answer is “we didn’t know what it did.” Documentation isn’t optional for team settings.
Pitfall 5: Not Versioning Settings Changes – You update your settings schema. Old projects still expect the old format. They break. No record of what changed or why. Solution: version your settings files. Document migrations.
Production Debugging: When Settings Go Wrong
Sometimes settings don’t work as expected. Here’s how to debug systematically.
The setting seems to be ignored: Run claude-code --show-config to see the actual merged configuration. Is your setting there? If not, it’s being overridden. Check environment variables and command-line flags.
Changes don’t take effect: Did you reload? Some settings require restarting Claude Code. Some require restarting the MCP server. Some require both.
Different behavior in different contexts: The same code behaves differently in projects A and B. Check project-level settings. One project might override a user-level setting.
Performance issues: MCP servers are slow. One of your configured servers might be the bottleneck. Use the performance settings to set stricter timeouts. If a server takes more than X seconds, disable it and investigate offline.
Advanced Settings Patterns and Team Governance
Configuration governance matters more than people realize. The most sophisticated teams treat their settings like code—they go through review, testing, and have clear ownership. Someone owns the enterprise settings and reviews changes. Someone owns the project baseline template. This prevents configuration drift and ensures consistency.
When your team scales, you’ll want versioning on your settings taxonomy. Maybe Version 1 of your configuration was simple. Version 2 added enterprise controls. Version 3 added security policies. Document this evolution so when you onboard new team members, they understand the historical context.
The key principle is intentionality. Every setting exists for a reason. When you’re configuring Claude Code for your team, ask yourself: Why this setting? Why this value? What’s the business case? When new team members ask “why did we set this to 150000 tokens instead of 200000?” you should have an answer. That answer might be “we measured token usage and found 150000 was sufficient for 95% of our use cases while keeping costs reasonable” or “we have weak internet connections in some of our offices, so we reduced context window to keep responses fast.” Those answers create alignment.
Settings become part of your team’s decision-making legacy. A setting changed six months ago for a good reason. That reason might become relevant again in different context. By documenting the history of your settings, you preserve organizational learning.
Pattern: Settings as Infrastructure
The teams getting the most value from Claude Code treat settings configuration as first-class infrastructure. They maintain settings repositories with version control, change logs, and peer review processes. When someone wants to add a new MCP server to enterprise settings, they submit a PR. The PR goes through review to ensure the server doesn’t conflict with existing tools and doesn’t violate security policies. Once approved, it’s merged and becomes immediately available to all developers.
This might sound heavy, but it prevents two categories of problems: configuration conflicts (where two teams add incompatible servers) and security violations (where someone accidentally adds a tool that exfiltrates sensitive data). For organizations running Claude Code at serious scale, this governance becomes critical.
Pattern: Configuration Validation and Linting
You can automate validation of your settings files using JSON schema. Define what valid settings look like, then validate against it:
# Validate project settings against schema
ajv validate -s settings.schema.json -d .claude/settings.json
This catches typos and invalid configurations before they cause problems. A developer might mistype “mopdel” instead of “model” in their project settings. Rather than having this silently fail or use a default, validation catches it immediately.
Pattern: Settings Documentation as Code
The best teams generate documentation directly from their settings schemas. If your enterprise settings schema defines the approved models, that documentation updates automatically. You’re never in a situation where the documentation says “use Opus” but the code only allows Sonnet. They’re synchronized.
Pattern: Configuration Migration Strategies
As your organization evolves, settings schemas change. Maybe you’re adding a new authentication method, or deprecating an old MCP server. You need migration strategies to move existing settings forward without breaking anyone’s setup.
Define migration rules: “if a project has the old ‘apiV1’ server configured, replace it with the new ‘apiV2’ server.” Run these migrations automatically when developers update Claude Code, with clear logging about what changed.
Team Settings Management: Making it Scalable
As your team grows, ad-hoc settings management becomes unscalable. You need processes.
The Settings Registry: Maintain a list of all settings, what they mean, who owns them, and what changed recently. This can be a simple YAML file or a spreadsheet. When someone wants to add a new setting, they add it to the registry. This creates visibility and prevents duplication.
The Settings Review Process: Changes to enterprise or shared project settings go through review. Is this setting necessary? Does it conflict with existing settings? Will it affect performance? A quick review catches problems before they affect everyone.
The Settings Testing: Before deploying new settings to the whole team, test them with a subset. Does the filesystem server work with these timeouts? Do performance limits cause legitimate work to be blocked? Small-scale testing prevents large-scale problems.
The Settings Monitoring: Track which settings are actually used. Which MCP servers do developers enable? Which timeouts are hit frequently? This data guides optimization. If a timeout is hit 10x per day, it’s too strict.
The Settings Documentation: For organizational settings, documentation is critical. “We limit tokens per call to 50,000 because it prevents runaway costs while supporting normal work. If you hit this limit, request an exception and let’s discuss the use case.”
Transition: Settings as Configuration-as-Code
The frontier of what leading organizations do is treating settings as code in the fullest sense. Settings live in a Git repository. Changes go through CI/CD. There’s a test suite that validates settings. Rollbacks are tracked. This is sophisticated but powerful for large organizations.
When settings are configuration-as-code, they’re versionable, reviewable, and auditable. “We changed the token limit on March 15th for the following reason…” is traceable. Teams can track when and why their configuration changed.
Real-World Scenarios: Settings in Action
Let’s ground this in practical examples where settings hierarchies solve real problems.
Scenario 1: The Distributed Team
Your team spans three time zones. During the day in one location, it’s night in another. You want to maintain consistent code quality standards globally, but response times vary dramatically by location. Solution: Set maxContextTokens at the enterprise level to ensure consistent processing, but set requestTimeout at the user level, allowing developers in slow-network regions to increase timeouts without affecting the enterprise baseline.
Scenario 2: The Legacy Monorepo
You have a monolithic codebase that’s been in maintenance mode for years. You want to introduce strict AI-assisted code review for new features in the modern section, but you’re not touching the legacy code. Solution: Use user-level settings with reviewStrictness: "balanced" for your baseline, then create .vscode/settings.json in the legacy directory with reviewStrictness: "lenient" (since touching that code is risky). In the new feature directory, use reviewStrictness: "strict" to enforce high standards where it matters.
Scenario 3: The Enterprise Transition
Your company is migrating from self-hosted Claude to Bedrock. You can’t flip the switch all at once—different teams migrate on different schedules. Solution: Use environment variables for the provider selection. Teams can set CLAUDE_CODE_USE_BEDROCK=true when they’re ready to migrate, while others keep using the Anthropic API. The same settings files work for both providers because the provider is set via environment variable, not baked into configuration.
Scenario 4: The Compliance Lockdown
Your organization suddenly needs to enforce that all requests go through an internal gateway for audit purposes. You can’t modify every developer’s machine. Solution: Update enterprise settings to specify a custom apiBase pointing to your gateway. All developers automatically use the gateway on their next Claude Code startup, without any local changes needed. Compliance is enforced at the enterprise level, not through manual coordination.
Transitioning Between Environments
Settings become particularly powerful when you need to work in multiple environments—local development, CI/CD, staging, production. Each environment might need different configurations.
Local Development: You want lenient settings, fast feedback, and the ability to experiment. autonomousMode: false, reviewStrictness: "balanced", larger context windows.
CI/CD Pipeline: You want strict, consistent standards with audit trails. autonomousMode: true with restricted auto-approval rules, strict review strictness, detailed logging.
Team Collaboration: You want shared standards but per-developer customization. Enterprise settings define the baseline, project settings enforce team standards, user settings allow personalization.
The hierarchy supports all of these because you’re not forced to choose one configuration for all contexts. You layer configurations appropriately for each context.
Summary
Claude Code’s settings hierarchy gives you flexibility without chaos. Use user settings for your personal baseline, project settings for repo-specific overrides, enterprise settings for organizational policy, and environment variables for secrets and runtime tweaks.
Remember:
- Secrets → Env vars (never commit literal credentials)
- Personal preferences → User settings (your baseline across all projects)
- Project-specific config → Project settings (what differs per repository)
- Org policy → Enterprise settings (what the organization mandates)
- Deep merging means you get everything unless explicitly overridden (you don’t lose settings unless you actively replace them)
- Settings document decisions (every setting should have a reason that future you can understand)
Master these three levels and you’ll spend less time debugging and more time building. The system becomes transparent—you always know where a setting lives and why it has the value it does. Your team can collaborate on shared configurations without exposing individual secrets. Your organization can enforce standards without micromanaging developers.
That’s the power of a well-designed configuration hierarchy. Get it right, and your entire development workflow becomes more predictable, more secure, and more maintainable.
-iNet