Claude Code settings.json Reference

Complete reference for Claude Code's settings.json configuration file: all keys, values, and examples for permissions, hooks, MCP servers, model selection, and more.

💥 50p impulse-buy: Power Prompts PDF (first 10 buyers) 30 battle-tested Claude Code prompts · 8-page PDF · paste into CLAUDE.md and never re-type a prompt again · 50p impulse-buy, no commitment

Claude Code's behavior is controlled by settings.json files at the project and global level. This is the complete key reference with examples.

File locations

# Project-level (checked into git — shared with team):
.claude/settings.json

# User-level (not in git — personal preferences):
~/.claude/settings.json

# Resolution: project overrides global for the same key.
# Both files are merged — non-overlapping keys from global still apply.

Annotated full example

{
  // ── Model & session defaults ──────────────────────────────────────────────
  "model": "claude-sonnet-4-6",          // default model for interactive sessions
  "theme": "dark",                       // "dark" | "light" | "auto"
  "verbose": false,                      // show full tool input/output in UI
  "preferredNotifChannel": "terminal",   // notification channel

  // ── Permissions ──────────────────────────────────────────────────────────
  "permissions": {
    "allow": [
      // Read-only tools — always safe to allow:
      "Read",
      "Grep",
      "Glob",
      // Git read operations:
      "Bash(git status)",
      "Bash(git diff*)",
      "Bash(git log*)",
      "Bash(git show*)",
      "Bash(git branch*)",
      // Test runners (read-heavy, write test output only):
      "Bash(pytest *)",
      "Bash(npm test)",
      "Bash(npm run test*)",
      "Bash(go test *)",
      // File editing (project root only):
      "Edit",
      "Write"
    ],
    "deny": [
      // Destructive operations — always require explicit approval:
      "Bash(rm -rf*)",
      "Bash(git push*)",         // no auto-push
      "Bash(git reset --hard*)", // no hard resets without review
      "Bash(curl*)",             // no outbound HTTP without review
      "Bash(wget*)"
    ]
  },

  // ── Hooks ─────────────────────────────────────────────────────────────────
  "hooks": {
    "PostToolUse": [
      {
        // Auto-format Python files after Claude edits them:
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "if echo "$CLAUDE_TOOL_INPUT_FILE_PATH" | grep -q '\.py$'; then ruff format "$CLAUDE_TOOL_INPUT_FILE_PATH" 2>/dev/null; fi"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        // Block edits to migration files:
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "if echo "$CLAUDE_TOOL_INPUT_FILE_PATH" | grep -q 'alembic/versions/\|migrations/'; then echo 'BLOCKED: never edit migration files manually' >&2; exit 2; fi"
          }
        ]
      }
    ]
  },

  // ── MCP servers ──────────────────────────────────────────────────────────
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..."
      }
    }
  }
}

Permissions key reference

# Tool specifier formats:
"Read"                  # bare tool name — allow all uses
"Bash(git *)"           # Bash with glob prefix — matches "git status", "git log", etc.
"Edit(src/**)"          # Edit limited to src/ path prefix
"Write(tests/**)"       # Write limited to tests/ directory

# Deny takes precedence over allow.
# If a command matches both, it is denied and the user is prompted.

# Special values:
"*"                     # allow ALL tools (equivalent to --dangerouslySkipPermissions)

Hook event types

{
  "hooks": {
    "PreToolUse": [...],   // before tool executes; exit 2 to block
    "PostToolUse": [...],  // after tool completes; informational only
    "Stop": [...],         // when Claude Code session ends
    "Notification": [...]  // when Claude sends a notification
  }
}

// Hook entry format:
{
  "matcher": "Edit",  // tool name to match ("*" for all tools)
  "hooks": [
    {
      "type": "command",
      "command": "your-shell-command-here"
    }
  ]
}

Model values (2026)

{
  // Best quality (complex reasoning, long context):
  "model": "claude-opus-4-7",

  // Best price/quality balance (recommended for most tasks):
  "model": "claude-sonnet-4-6",

  // Fastest/cheapest (quick tasks, high volume):
  "model": "claude-haiku-4-5-20251001"
}

Validate and debug

# Check for config errors:
claude --doctor

# Validate JSON syntax:
python3 -m json.tool .claude/settings.json

# View effective settings (merged global + project):
cat ~/.claude/settings.json
cat .claude/settings.json
# (Claude merges these; project values win on conflict)

For a complete guide to hooks with examples, see Claude Code hooks tutorial. For MCP server configuration, see Claude Code MCP setup guide. For permissions and allowedTools patterns, see Claude Code permissions guide.

Frequently asked questions

Where is Claude Code's settings.json?
Project settings: .claude/settings.json relative to your project root. Global settings: ~/.claude/settings.json. Project settings override global for the same keys. Both files use the same JSON schema.
What can I configure in Claude Code's settings.json?
Permissions (which tools are allowed without prompting), hooks (shell commands that run before/after tool calls), MCP servers, default model, theme, API key, and advanced options like verbose logging.
How do I set the default model in Claude Code settings?
Add model: 'claude-sonnet-4-6' to ~/.claude/settings.json. You can override per-session with the --model flag. Available values: claude-sonnet-4-6, claude-opus-4-7, claude-haiku-4-5-20251001.
Should I commit .claude/settings.json to git?
Yes, for project-level permissions and hooks that should apply to all teammates. Exclude from git any settings.json that contains tokens, API keys, or personal preferences. Use ~/.claude/settings.json for personal settings.
How do I validate my settings.json?
Run claude --doctor to check for configuration errors. For JSON syntax validation, use: python3 -m json.tool .claude/settings.json. Claude Code also shows a warning on startup if settings.json has a parse error.

Free tools

Cost Calculator → API Cookbook → Diff Summarizer → Skills Browser →

More examples

Claude API Python QuickstartClaude API Node.js / TypeScript QuickstartClaude API Streaming in PythonClaude API Streaming in Node.js / TypeScriptClaude API Tool Use in PythonClaude API Tool Use in Node.js / TypeScript