Settings & Configuration
settings.json is the control panel for Claude Code — choose the model, restrict tools, inject environment variables, and fine-tune permissions without editing flags on every run.
Why bother with settings?
Out of the box, Claude Code makes sensible choices — but your project may need something different. Maybe you want Claude to always use a specific model for cost reasons, prevent it from ever touching production credentials, or auto-inject environment variables from a shared CI profile. That's what settings.json is for.
| Setting area | What you control |
|---|---|
| Model | Pin claude-opus-4, haiku-3-5, or any available model |
| Permissions | Allow, deny, or prompt for each tool category |
| Env vars | Inject variables that Claude sees on every run |
| Proxy | Route traffic through a corporate HTTP proxy |
Configuration scopes
Settings are read from four places. Higher entries in the table override lower ones — so a local setting beats a project setting, which beats a user setting.
| Scope | File | Committed? | Who uses it |
|---|---|---|---|
| Managed | Injected by your platform / MDM | N/A | Enterprise admins only |
| Local | .claude/settings.local.json | No — gitignored | Your private overrides |
| Project | .claude/settings.json | Yes — shared with team | Team-wide rules |
| User | ~/.claude/settings.json | No | Personal preferences |
Anatomy of settings.json
Below is an example for an inventory REST API project using Node.js. It fixes the model, restricts shell commands, and injects two env vars that Claude will see in every session.
{
"model": "claude-opus-4-5",
"permissions": {
"allow": [
"Read(*)",
"Write(src/**)",
"Bash(npm run *)",
"Bash(git status)",
"Bash(git diff)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(curl *)",
"Write(.env*)"
]
},
"env": {
"NODE_ENV": "development",
"API_VERSION": "v2"
}
}| Key | Purpose |
|---|---|
| model | Which Claude model to use in this project |
| permissions.allow | Tools Claude can use without asking |
| permissions.deny | Tools that are always blocked |
| env | Key-value pairs injected into every session |
Model selection
The model key accepts any Anthropic model identifier. Set it at the user level to apply globally, or at the project level to pin a specific model for that repository.
// ~/.claude/settings.json (user-level — your global default)
{
"model": "claude-haiku-3-5" // faster + cheaper for exploratory work
}
// .claude/settings.json (project-level — overrides global default)
{
"model": "claude-opus-4-5" // highest quality for the production API
}/model — it respects the settings value as the default but lets you override temporarily.Permission rules
Each rule is a string with a tool name plus an optional glob pattern in parentheses. Rules live under three lists:
| List | Behaviour |
|---|---|
| allow | Proceed without asking |
| deny | Always block, no override |
| ask | Pause and confirm each time |
{
"permissions": {
"allow": [
"Read(*)", // read any file
"Write(src/**)", // write only inside src/
"Bash(npm run *)", // any npm script
"Bash(git *)" // any git command
],
"deny": [
"Bash(rm -rf *)", // never delete recursively
"Write(.env*)" // never touch env files
],
"ask": [
"Write(package.json)" // pause before editing deps
]
}
}deny rules take precedence over allow rules. If a command matches both, it is blocked.Environment variables
Any key-value pair under env is visible to Claude in the shell environment during your session. Use this for non-secret configuration that should be consistent across the team.
{
"env": {
"NODE_ENV": "development",
"API_BASE_URL": "http://localhost:3001",
"LOG_LEVEL": "debug"
}
}settings.json is committed to git. Use settings.local.json (gitignored) for secrets, or rely on your OS keychain.Network proxy
If your organization routes outbound traffic through an HTTP proxy, tell Claude Code the port number. All requests to the Anthropic API will be sent via the proxy.
// ~/.claude/settings.json (user-level — applies everywhere)
{
"network": {
"httpProxyPort": 8080
}
}localhost. Pair this with a local proxy tool such as Squid or Charles if you need full traffic inspection.Worked example: project + local settings together
The classic pattern is to commit a shared settings.json for the team and keep a private settings.local.json for your own overrides. Here's how a developer named Priya would set it up on her laptop:
{
"model": "claude-opus-4-5",
"permissions": {
"allow": [
"Read(*)",
"Write(src/**)",
"Bash(npm run *)",
"Bash(git *)"
],
"deny": [
"Write(.env*)",
"Bash(rm -rf *)"
]
},
"env": {
"NODE_ENV": "development"
}
}{
"model": "claude-haiku-3-5",
"env": {
"PRIYA_LAPTOP": "true",
"LOG_LEVEL": "verbose"
},
"network": {
"httpProxyPort": 3128
}
}What happens: Priya's local override swaps the model to haiku (cheaper for quick experiments) and adds her personal proxy. The team-wide permission rules and NODE_ENV still apply from settings.json because the local file only overrides the keys it defines.
Verifying your configuration
Two slash commands let you inspect the merged configuration at any time.
| Command | What it does |
|---|---|
| /config | Opens an interactive menu for viewing and editing settings.json entries live. |
| /status | Shows the active model, current API key status, active permissions, and project context. |
Key settings reference
| Key | Type | Example | What it controls |
|---|---|---|---|
| model | string | "claude-opus-4-5" | Which model to use |
| permissions.allow | string[] | ["Read(*)", "Bash(git *)"] | Tools allowed silently |
| permissions.deny | string[] | ["Bash(rm -rf *)"] | Tools always blocked |
| permissions.ask | string[] | ["Write(package.json)"] | Tools that need confirmation |
| env | object | {"NODE_ENV": "dev"} | Shell env vars injected per session |
| network.httpProxyPort | number | 8080 | Port for outbound HTTP proxy |
| includeCoAuthoredBy | boolean | false | Suppress Co-Authored-By git footer |
| hooks | object | {"PostToolUse": [...]} | Lifecycle event handlers |
Before you continue
settings.jsoncontrols model, permissions, env vars, proxy, and hooks.- Precedence: Managed → Local → Project → User — higher scopes win.
- Commit shared project settings; keep secrets in
settings.local.json. - Use
/configand/statusto inspect the merged configuration. - Next lesson: Permission Modes — controlling what Claude Code can read, write, and execute.
What's Next
Configuration is dialled in. Next: Permission Modes — controlling exactly what Claude Code is allowed to read, write, and execute.