settings.json — the most underused file in Claude Code
Most users never open ~/.claude/settings.json. It's the difference between "I use Claude Code" and "Claude Code works the way I work."
File locations
Claude Code reads settings from three places, in order of precedence (last wins):
~/.claude/settings.json— global defaults<project>/.claude/settings.json— project-shared (committed)<project>/.claude/settings.local.json— project-local (gitignored, your personal overrides)
Every key worth knowing
{
"model": "claude-sonnet-4-6",
"permissions": {
"allow": [
"Bash(git status)",
"Bash(git diff:*)",
"Bash(npm run test:*)",
"Read",
"Grep"
],
"deny": [
"Bash(rm -rf:*)",
"Bash(sudo:*)"
]
},
"env": {
"EDITOR": "code --wait"
},
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "~/projects"]
}
},
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [{ "type": "command", "command": "prettier --write \$CLAUDE_FILE_PATH" }]
}
]
},
"outputStyle": "default",
"statusLine": {
"type": "command",
"command": "echo \"\$CLAUDE_MODEL | \$(git branch --show-current 2>/dev/null)\""
},
"forceLoginMethod": "claudeai"
}
What each key does
model— your default model (Opus 4.7 / Sonnet 4.6 / Haiku 4.5).permissions.allow— Bash patterns auto-approved without prompting.permissions.deny— patterns that are always blocked, even if asked.env— environment variables Claude inherits when running tools.mcpServers— MCP servers loaded automatically (full chapter 4 coverage).hooks— shell commands triggered by tool events (chapter 4).outputStyle— how Claude formats its responses. "default" / "concise" / "explanatory".statusLine.command— shell command whose output is shown in the status line.forceLoginMethod— pin auth to "claudeai" subscription or "anthropic" API key.
Project vs user settings
Anything project-shared (CLAUDE.md, allowed Bash patterns, MCP servers your team uses) belongs in <project>/.claude/settings.json and is committed.
Anything personal (your editor, your hooks, your OPenAI API key in env) belongs in <project>/.claude/settings.local.json and is gitignored.
Try it
Create a ~/.claude/settings.json with the example above (adjusting paths). Then in your current project, add a .claude/settings.json with at least one project-specific allow rule. Notice how the prompts dry up.
Course download
The "Resources" section of this lesson has a battle-tested starter settings.json you can drop in and customize.