Claude Code · Lesson 19
Settings & Configuration
settings.json is the control panel for Claude Code — choose the model, restrict tools, inject environment variables, and fine-tune permissions without ever editing a flag again.
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.
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 original 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.
// .claude/settings.json (committed — shared with your team)
{
"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"
}
}modelWhich Claude model to use in this project
permissions.allowTools Claude can use without asking
permissions.denyTools that are always blocked
envKey-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:
{
"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
}
}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.
/configOpens an interactive menu for viewing and editing settings.json entries live.
/statusShows 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 |
Setup Checklist
What's Next
Configuration is dialled in. Next: Permission Modes — controlling exactly what Claude Code is allowed to read, write, and execute.