Skip to main content

What Are Settings?

Claude Code’s settings system controls:
  • Permissions (allow/ask/deny rules for tools)
  • Hooks (lifecycle event handlers)
  • MCP servers (external integrations)
  • Models (default model selection)
  • Display (status line, spinner, output style)
  • Sandbox (bash command isolation)
  • Environment variables (via env key)
Settings are configured in settings.json files with a hierarchical override system.

Why Settings Matter

Settings enable:
  • Team collaboration: Share project settings via git
  • Personal customization: Override team settings locally
  • Security: Control tool access with granular permissions
  • Automation: Configure hooks for notifications and validation
  • Consistency: Standardize model, permissions, and behavior across projects

Settings Hierarchy

Claude Code uses a 5-level user-writable override chain:
1

Command line arguments (highest)

Scope: Single sessionExample:
claude --model opus --agent my-agent
2

Project local settings

Location: .claude/settings.local.jsonScope: Project-specific personal overridesVersion control: Git-ignored
{
  "disableAllHooks": true,
  "model": "haiku"
}
3

Project settings

Location: .claude/settings.jsonScope: Team-shared project settingsVersion control: Committed to git
{
  "permissions": {
    "allow": ["Edit(*)", "Write(*)"]
  },
  "enableAllProjectMcpServers": true
}
4

User local settings

Location: ~/.claude/settings.local.jsonScope: Personal overrides for all projects
{
  "model": "sonnet"
}
5

User settings (lowest)

Location: ~/.claude/settings.jsonScope: Global personal defaults
{
  "language": "english",
  "cleanupPeriodDays": 30
}
Policy layer (enforced, cannot be overridden):
  • Location: managed-settings.json (organization-controlled)
  • Purpose: Security policies, compliance requirements
  • Precedence: Highest — overrides all user settings
Permission precedence: deny rules always win, regardless of lower-priority allow rules.

Core Settings

General Configuration

model
string
default:"default"
Default model for sessions.Accepted values: sonnet, opus, haiku, default, or full model IDs
{"model": "opus"}
agent
string
Default agent for the main conversation. Value is the agent name from .claude/agents/.
{"agent": "code-reviewer"}
language
string
default:"english"
Claude’s preferred response language.
{"language": "japanese"}
cleanupPeriodDays
number
default:"30"
Sessions inactive longer than this are deleted at startup.
{"cleanupPeriodDays": 60}
autoUpdatesChannel
string
default:"latest"
Release channel: "stable" or "latest".
{"autoUpdatesChannel": "stable"}
plansDirectory
string
default:".claude/plans/"
Directory where /plan outputs are stored.
{"plansDirectory": "./my-plans"}

Permissions

Control what tools Claude can use:
{
  "permissions": {
    "allow": [
      "Edit(*)",
      "Write(*)",
      "Bash(npm run *)",
      "Bash(git *)",
      "WebFetch(domain:*)",
      "mcp__*"
    ],
    "ask": [
      "Bash(rm *)",
      "Bash(git push *)"
    ],
    "deny": [
      "Read(.env)",
      "Read(./secrets/**)"
    ],
    "additionalDirectories": ["../shared-libs/"],
    "defaultMode": "acceptEdits"
  }
}
Permission modes:
  • default — Standard permission checking
  • acceptEdits — Auto-accept file edits
  • askEdits — Ask before every operation
  • viewOnly — Read-only mode
  • bypassPermissions — Skip all checks (dangerous)
  • plan — Read-only exploration
Tool syntax:
ToolSyntaxExample
BashBash(pattern)Bash(npm run *), Bash(* install)
ReadRead(path)Read(.env), Read(./secrets/**)
EditEdit(path)Edit(src/**), Edit(*.ts)
WriteWrite(path)Write(*.md)
WebFetchWebFetch(domain:pattern)WebFetch(domain:example.com)
TaskTask(agent)Task(Explore), Task(my-agent)
MCPmcp__server__toolmcp__memory__*
Bash wildcards can appear at any position: Bash(* install), Bash(npm *), Bash(git * main)

Hooks

Execute scripts at lifecycle events:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ${CLAUDE_PROJECT_DIR}/.claude/hooks/validate.py",
            "timeout": 5000,
            "async": true
          }
        ]
      }
    ],
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Session started!'",
            "timeout": 1000,
            "once": true
          }
        ]
      }
    ]
  },
  "disableAllHooks": false
}
18 hook events: PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, UserPromptSubmit, Notification, Stop, SubagentStart, SubagentStop, PreCompact, SessionStart, SessionEnd, Setup, TeammateIdle, TaskCompleted, ConfigChange, WorktreeCreate, WorktreeRemove

Hooks Concept

Complete guide to hooks with examples

MCP Servers

{
  "enableAllProjectMcpServers": true,
  "enabledMcpjsonServers": ["memory", "github"],
  "disabledMcpjsonServers": ["experimental-server"]
}
  • enableAllProjectMcpServers: Auto-approve all .mcp.json servers
  • enabledMcpjsonServers: Allowlist specific servers
  • disabledMcpjsonServers: Blocklist specific servers

MCP Servers Concept

Learn about MCP server configuration and best servers to use

Display & UX

{
  "statusLine": {
    "type": "command",
    "command": "git branch --show-current",
    "padding": 0
  },
  "outputStyle": "Explanatory",
  "spinnerTipsEnabled": true,
  "spinnerVerbs": {
    "mode": "replace",
    "verbs": ["Cooking", "Brewing", "Crafting"]
  },
  "spinnerTipsOverride": {
    "tips": ["Use /compact at ~50%", "Start with plan mode"],
    "excludeDefault": true
  },
  "showTurnDuration": false,
  "respectGitignore": true
}
Status line: Custom status bar showing context usage, model, cost, session info Output styles: default, Explanatory (verbose), Concise

Sandbox

Bash command isolation:
{
  "sandbox": {
    "enabled": true,
    "autoAllowBashIfSandboxed": true,
    "excludedCommands": ["git", "docker", "gh"],
    "allowUnsandboxedCommands": false,
    "network": {
      "allowUnixSockets": ["/var/run/docker.sock"],
      "allowLocalBinding": true,
      "allowedDomains": ["api.example.com"],
      "deniedDomains": ["malicious.com"]
    }
  }
}

Attribution

Customize git commit and PR attribution:
{
  "attribution": {
    "commit": "Co-Authored-By: Claude <[email protected]>",
    "pr": "Generated with Claude Code"
  }
}
Set to "" to hide attribution.

Environment Variables

Set via env key to avoid wrapper scripts:
{
  "env": {
    "ANTHROPIC_API_KEY": "...",
    "NODE_ENV": "development",
    "CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "50",
    "MCP_TIMEOUT": "10000"
  }
}
Common variables:
  • CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: Auto-compact threshold (1-100, default ~95)
  • CLAUDE_CODE_ENABLE_TELEMETRY: Enable/disable telemetry
  • MCP_TIMEOUT: MCP startup timeout (ms)
  • BASH_MAX_TIMEOUT_MS: Bash command timeout

Real Example from Repository

From .claude/settings.json:
{
  "permissions": {
    "allow": [
      "Edit(*)",
      "Write(*)",
      "Bash",
      "WebFetch(domain:*)",
      "mcp__*"
    ],
    "ask": [
      "Bash(rm *)",
      "Bash(git *)",
      "Bash(npm *)"
    ]
  },
  "spinnerVerbs": {
    "mode": "replace",
    "verbs": [
      "Admiring Shayan's code",
      "Learning from Shayan",
      "Studying Shayan's patterns"
    ]
  },
  "plansDirectory": "./reports",
  "outputStyle": "Explanatory",
  "statusLine": {
    "type": "command",
    "command": "echo 'shayan's best practice status line'",
    "padding": 0
  },
  "attribution": {
    "commit": "Co-Authored-By: Claude <[email protected]>",
    "pr": "Generated with [Claude Code](https://claude.ai/code)"
  },
  "respectGitignore": true,
  "enableAllProjectMcpServers": true,
  "disableAllHooks": false,
  "hooks": {
    "PreToolUse": [/* ... */],
    "PostToolUse": [/* ... */],
    "Stop": [/* ... */]
  }
}

Best Practices

Never commit personal preferences to .claude/settings.json:
// .claude/settings.local.json (git-ignored)
{
  "disableAllHooks": true,
  "model": "haiku"
}
Don’t use "allow": ["Bash"] — be specific:
"allow": [
  "Bash(npm run *)",
  "Bash(git status)",
  "Bash(git diff *)"
]
Prevent accidental leaks:
"deny": [
  "Read(.env)",
  "Read(.env.*)",
  "Read(./secrets/**)",
  "Read(**/credentials.json)"
]
Speed up testing:
{"disableAllHooks": true}
Never commit API keys:
// .claude/settings.local.json
{
  "env": {
    "GITHUB_TOKEN": "ghp_...",
    "ANTHROPIC_API_KEY": "sk-..."
  }
}

Configuration Commands

claude
/config
Opens interactive settings UI with search functionality.

Complete Example

{
  "model": "sonnet",
  "language": "english",
  "cleanupPeriodDays": 30,
  "plansDirectory": "./plans",
  
  "permissions": {
    "allow": [
      "Edit(*)",
      "Write(*)",
      "Bash(npm run *)",
      "Bash(git *)",
      "mcp__*"
    ],
    "deny": [
      "Read(.env)",
      "Read(./secrets/**)"
    ]
  },
  
  "enableAllProjectMcpServers": true,
  
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Tool starting'",
            "timeout": 5000
          }
        ]
      }
    ]
  },
  
  "sandbox": {
    "enabled": true,
    "excludedCommands": ["git", "docker"]
  },
  
  "statusLine": {
    "type": "command",
    "command": "git branch --show-current"
  },
  
  "spinnerTipsEnabled": true,
  "showTurnDuration": false,
  
  "env": {
    "NODE_ENV": "development"
  }
}

Hooks

Configure lifecycle event handlers

MCP Servers

Enable external integrations

Settings Best Practice

Complete settings reference with all 38 settings

Global vs Project Settings

Which features are global-only vs dual-scope

Further Reading

Build docs developers (and LLMs) love