File hierarchy
~/.claude/settings.json (global, all projects) ↓ overridden by.claude/settings.json (project, shared with team) ↓ overridden by.claude/settings.local.json (local machine, gitignore)settings.local.json always takes precedence. It is the ideal place for personal overrides without creating Git conflicts.
Complete structure
{ "model": "claude-sonnet-4-5", "permissions": { "allow": ["Bash(git *)", "Bash(pnpm *)", "Read"], "deny": ["Bash(rm -rf *)", "Write(file_path:*.env*)"], "ask": ["Bash(npm publish)"] }, "env": { "NODE_ENV": "development", "LOG_LEVEL": "debug" }, "hooks": { "PostToolUse": [{ "matcher": "Edit|Write", "hooks": [{ "type": "command", "command": ".claude/hooks/format.sh" }] }] }}Available keys
| Key | Role |
|---|---|
model | Default model |
permissions.allow | Auto-approved tools |
permissions.deny | Blocked tools |
permissions.ask | Tools requiring confirmation |
env | Injected environment variables |
hooks | Scripts triggered on events |
spinnerVerbs | Words in the loading spinner |
spinnerTipsOverride | Tips displayed during processing |
enableAllProjectMcpServers | Enables all project MCP servers |
Spinner customization
{ "spinnerVerbs": { "mode": "replace", "verbs": ["Caffeinating…", "Thinking…", "Optimizing…"] }, "spinnerTipsOverride": { "tips": ["/compact when context is full"], "excludeDefault": true }}mode: "add" extends the default list rather than replacing it. These keys have no functional impact, only cosmetic.
What should stay in .gitignore
.claude/settings.local.json # Local machine overrides.claude/CLAUDE.md # Personal instructions.env.local # SecretsFiles to commit (settings.json, agents/, commands/, hooks/, rules/) represent the shared team configuration. Never include API keys or tokens in these files.
Enter your email to read the full card and get the complete PDF bundle.
All content is free and open-source. We just ask for your email.