Chapter 23 | settings.json: Comprehensive Overview

7 MIN READ | UPDATED: 2026-05-15

Chapter 23: settings.json Overview

Learning Objectives

Understand the priority and purpose of the four types of settings files, and know where to place settings for teams, individuals, and experiments.

Four Types of Settings

flowchart TB
    Final["Final Effective Settings"] --> Override["Override from High to Low"]
    Override --> CMD["1. Command-line Flag
(Highest Priority)"] Override --> Local["2. .claude/settings.local.json
(Project Local, gitignore)"] Override --> Project["3. .claude/settings.json
(Project Shared, in git)"] Override --> User["4. ~/.claude/settings.json
(User-level)"] Override --> Default["5. Claude Code Default
(Lowest)"] style Local fill:#fff9c4 style Project fill:#c8e6c9

→ Higher priority overrides lower priority. In case of conflict, local wins.

Role of Each File

File Who Writes/Reads Example Content
~/.claude/settings.json You (configure once, effective everywhere) Default model, theme, global hooks
<project>/.claude/settings.json Team Shared (committed to git) Project-level permissions, shared hooks, agent defaults
<project>/.claude/settings.local.json Personal within Project (not committed to git) Personal credentials, local paths, experimental settings
Command-line flag Temporary (one-time) claude --model haiku for a quick task

gitignore Strategy

.claude/
├── agents/              ← in git (team shared agents)
├── commands/            ← in git
├── hooks/               ← in git
├── settings.json        ← in git
├── settings.local.json  ← .gitignore (personalization)
├── telegram-notify.json ← .gitignore (credentials)
└── .notify-sent         ← .gitignore (runtime state)

Our project's .claude/.gitignore:

.notify-sent
telegram-notify.json
settings.local.json

Quick Reference for Common Fields

{
  "model": "claude-opus-4-7",
  
  "permissions": {
    "defaultMode": "bypassPermissions",
    "allow": ["Bash(npm:*)"],
    "deny": ["Bash(sudo:*)"]
  },
  
  "hooks": {
    "PreToolUse": [...],
    "Stop": [...]
  },
  
  "env": {
    "PYTHONPATH": "src/"
  },
  
  "includeCoAuthoredBy": false
}
Field Purpose
model Default model (used by main Claude)
permissions Detailed in Chapter 24
hooks Detailed in Ch 25/26
env Environment variables injected into all Bash subprocesses
includeCoAuthoredBy Whether to add Co-Authored-By: Claude to commits

Personal vs. Team Examples

// ~/.claude/settings.json (Your personal preferences, cross-project)
{
  "model": "claude-opus-4-7",
  "includeCoAuthoredBy": false
}
// <project>/.claude/settings.json (Team shared)
{
  "permissions": {
    "defaultMode": "bypassPermissions",
    "deny": ["Bash(sudo:*)", ...]
  },
  "hooks": { ... }
}
// <project>/.claude/settings.local.json (Your personal settings for this project)
{
  "env": {
    "TELEGRAM_BOT_TOKEN": "xxx",
    "TELEGRAM_CHAT_ID": "yyy"
  }
}

Verifying Settings Take Effect

After starting Claude Code, run:

/help        view active settings
/permissions view parsed permission rules

Or:

# See which settings files are loaded
ls -la ~/.claude/settings.json
ls -la <project>/.claude/settings.json
ls -la <project>/.claude/settings.local.json

Anti-patterns

❌ Writing credentials into project shared settings.json (will be pushed to GitHub)
❌ Putting team consensus into settings.local (others won't see it)
❌ Setting overly strict deny rules at the user level (affects all projects)
❌ Incorrect JSON (missing commas, single quotes) (settings silently fail to apply)

What You Can Do Now

  • Place each setting in the correct location
  • Use .gitignore to prevent credentials from being exposed
  • Verify that settings have taken effect

The next chapter will formally discuss the permissions field—the security guardrail for multi-agent systems.