Master the settings hierarchy, model selection, effort levels, and CLI flags
Claude Code has a layered settings system that lets you configure everything from models to permissions. In this lesson, you'll learn how settings cascade, which models to choose, and how to fine-tune Claude's behavior.
Settings cascade from broad to specific. More specific settings override broader ones:
┌─────────────────────────┐ ← Highest priority
│ Managed Settings │ (org-wide, IT-deployed)
├─────────────────────────┤
│ CLI Arguments │ (--model, --allowedTools, etc.)
├─────────────────────────┤
│ Local Project Settings │ (.claude/settings.local.json)
├─────────────────────────┤
│ Shared Project Settings│ (.claude/settings.json)
├─────────────────────────┤
│ User Settings │ (~/.claude/settings.json)
└─────────────────────────┘ ← Lowest priority
| Scope | Path | Shared? |
|---|---|---|
| Managed | /Library/Application Support/ClaudeCode/managed-settings.json (macOS) | Org-wide |
Full access
Unlock all 14 lessons, templates, and resources for Claude Code Mastery. Free.
| User | ~/.claude/settings.json | Personal, all projects |
| Project (shared) | .claude/settings.json | Team via git |
| Project (local) | .claude/settings.local.json | Personal, this project |
Pro Tip: Put team conventions in
.claude/settings.json(committed to git) and personal preferences in.claude/settings.local.json(gitignored).
Q: If you set model: opus in your user settings and model: sonnet in your project's shared settings, which model will Claude use?
Sonnet. Project settings override user settings. The hierarchy is: Managed > CLI > Local > Shared Project > User. Since shared project settings are more specific than user settings, sonnet wins.
{
"model": "opus"
}
| Alias | Model | Best For |
|---|---|---|
default | Depends on account (usually Opus 4.6) | General use |
sonnet | Latest Sonnet (4.5) | Daily coding tasks |
opus | Latest Opus (4.6) | Complex reasoning |
haiku | Haiku | Simple/fast tasks |
sonnet[1m] | Sonnet with 1M token context | Long sessions |
opusplan | Opus for planning, Sonnet for execution | Hybrid workflow |
Switch mid-session:
/model opus
Set via CLI:
claude --model opus
Set via environment:
export ANTHROPIC_MODEL=opus
Controls how deeply Claude reasons before responding:
{
"effortLevel": "high"
}
| Level | Behavior | Cost |
|---|---|---|
low | Fast, minimal reasoning | Cheapest |
medium | Balanced | Medium |
high | Deep reasoning (default) | Highest |
Gotcha: Effort level only applies to Opus 4.6's adaptive reasoning. Adjust in
/modelusing left/right arrow keys.
Fill in the blanks:
___ANTHROPIC_____/___opusplanANTHROPIC_MODEL/model{
"permissions": {
"defaultMode": "default"
}
}
| Mode | Behavior | Use Case |
|---|---|---|
default | Prompts for each tool use | Normal development |
acceptEdits | Auto-accepts file edits | Fast iteration |
plan | Read-only analysis mode | Code review |
delegate | Coordination-only | Agent team leads |
dontAsk | Auto-denies unless pre-approved | Restricted environments |
bypassPermissions | Skips all prompts ⚠️ | Sandboxed/CI environments |
Fine-grained control over what Claude can do:
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git commit *)",
"Read"
],
"deny": [
"Bash(git push *)",
"Bash(rm *)",
"Edit(.env)"
]
}
}
| Pattern | Matches |
|---|---|
Bash | All bash commands |
Bash(npm run build) | Exact command |
Bash(npm run *) | Commands starting with npm run |
Edit(/src/**/*.ts) | Editing TypeScript files in src/ |
WebFetch(domain:example.com) | Fetching from example.com |
mcp__puppeteer__* | All tools from puppeteer MCP server |
Important: Rules evaluate in order: deny → ask → allow. Deny always wins.
Q: You have allow: ["Bash(git *)"] and deny: ["Bash(git push *)"] in your settings. What happens when Claude tries to run git push origin main?
The command is denied. Deny rules always take precedence over allow rules, regardless of order. The evaluation chain is: deny → ask → allow.
| Variable | Purpose |
|---|---|
ANTHROPIC_API_KEY | API key for authentication |
ANTHROPIC_MODEL | Default model |
CLAUDE_CODE_EFFORT_LEVEL | Effort level (low/medium/high) |
MAX_THINKING_TOKENS | Limit thinking budget (0 = disable) |
| Variable | Overrides |
|---|---|
ANTHROPIC_DEFAULT_OPUS_MODEL | What opus alias resolves to |
ANTHROPIC_DEFAULT_SONNET_MODEL | What sonnet alias resolves to |
CLAUDE_CODE_SUBAGENT_MODEL | Model for subagents |
| Variable | Effect |
|---|---|
DISABLE_PROMPT_CACHING | Disable for all models |
DISABLE_PROMPT_CACHING_OPUS | Disable for Opus only |
{
"env": {
"CLAUDE_CODE_EFFORT_LEVEL": "medium",
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
}
}
Extended thinking lets Claude reason through complex problems before responding. It's enabled by default.
| Method | How |
|---|---|
| Toggle in session | Option+T (Mac) / Alt+T |
| Global default | /config → toggle thinking |
| Environment variable | MAX_THINKING_TOKENS=10000 |
Press Ctrl+O to toggle verbose mode and see Claude's thinking as gray italic text.
Gotcha: With Opus 4.6, thinking uses adaptive reasoning — the model dynamically allocates thinking tokens based on your effort level.
MAX_THINKING_TOKENSis ignored on Opus 4.6 (except when set to 0 to disable entirely).
Q: How do you disable extended thinking entirely on Opus 4.6?
Set MAX_THINKING_TOKENS=0. This is the only value that works on Opus 4.6, since it uses adaptive reasoning and ignores other values. You can also toggle it with Option+T / Alt+T mid-session.
By default, Claude has access to the directory where it was launched. Extend this:
# At startup
claude --add-dir ../shared-lib --add-dir ../common
# During session
/add-dir ../other-project
{
"additionalDirectories": ["../shared-lib"]
}
| Flag | Description |
|---|---|
--model <alias> | Set model for session |
--print, -p | Non-interactive (headless) mode |
--continue, -c | Continue most recent conversation |
--resume, -r | Resume specific session |
--permission-mode <mode> | Start in a specific permission mode |
--allowedTools <tools> | Auto-approve specific tools |
--add-dir <path> | Add working directories |
--system-prompt <text> | Replace entire system prompt |
--append-system-prompt <text> | Add to system prompt |
--max-turns <n> | Limit agentic turns (headless) |
--max-budget-usd <n> | Spending limit (headless) |
--output-format <fmt> | Output format (text/json/stream-json) |
--json-schema <schema> | Structured JSON output |
--dangerously-skip-permissions | Skips all prompts ⚠️ |
Fill in the blanks:
.claude/settings.___--max-___-usdCLAUDE_CODE____LEVEL.claude/settings.local.json--max-budget-usdCLAUDE_CODE_EFFORT_LEVEL~/.claude/settings.json (create it if it doesn't exist){
"model": "sonnet"
}
/status to verify the model/model opus to switch mid-session/cost to compare token usage between modelsReflection: Did you notice a difference in response quality or speed between models?
Scenario: Your team wants everyone to use Sonnet by default and block rm -rf commands, but you personally prefer Opus for complex architecture work.
How would you set this up?
Team settings (.claude/settings.json, committed to git):
{
"model": "sonnet",
"permissions": {
"deny": ["Bash(rm -rf *)"]
}
}
Your personal override (.claude/settings.local.json, gitignored):
{
"model": "opus"
}
Local settings override shared project settings, so you'll get Opus while the team defaults to Sonnet. The deny rule applies to everyone (including you) since deny rules cascade.
| Concept | One-Liner |
|---|---|
| Hierarchy | Managed > CLI > Local > Shared Project > User |
| Settings files | ~/.claude/settings.json (user), .claude/settings.json (project) |
| Model aliases | opus, sonnet, haiku, opusplan, sonnet[1m] |
| Effort levels | low / medium / high — controls Opus 4.6 reasoning depth |
| Permission rules | deny > ask > allow, first match wins |
| Thinking toggle | Option+T / Alt+T mid-session |
| Working dirs | --add-dir or additionalDirectories in settings |
Next up: Memory & CLAUDE.md System → — Learn how to give Claude persistent instructions and let it build its own memory.