Claude Code Settings
Table of Contents
1. Introduction
Claude Code uses a hierarchical settings system with multiple configuration files. Settings are merged with the following precedence (highest to lowest):
- Enterprise managed policies
- Command-line arguments
- Local project settings (
.claude/settings.local.json) - Shared project settings (
.claude/settings.json) - User settings (
~/.claude/settings.json)
This means local settings override shared project settings, which override user settings.
1.1. Settings Philosophy
- Project settings: Version-controlled, shared with team
- Local settings: Git-ignored, personal overrides
- User settings: Personal defaults for all projects
1.2. Common Use Cases
- Restrict dangerous tools (project settings)
- Set project-specific environment variables (project settings)
- Configure personal notification hooks (local settings)
- Set default model preference (local/user settings)
2. Project Settings (Shared)
These settings are version-controlled and shared with the team. Configure project-wide policies, permissions, and environment variables here.
2.1. Core Configuration
{
"permissions": {
"allow": [
"WebSearch",
"Bash(mkdir:*)",
"Bash(mv:*)",
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git push:*)"
],
"deny": []
},
"env": {
"PROJECT_ROOT": "/Users/kyeongsoo/Projects/mandoo180.github.io"
},
"enableAllProjectMcpServers": true,
"enabledMcpjsonServers": [
"emacs",
"filesystem"
]
}
2.2. Permissions Explained
2.2.1. Allow List
The allow list explicitly permits specific tools or tool patterns:
WebSearch- Allow web searches for up-to-date informationBash(mkdir:*)- Safe directory creationBash(mv:*)- File moving operationsBash(git add:*)- Staging changesBash(git commit:*)- Creating commitsBash(git push:*)- Pushing to remote
Pattern matching: Use * as wildcard. Bash(git:*) would match all git commands.
2.2.2. Deny List
The deny list blocks specific operations. Empty by default, but you might add:
"deny": [ "Bash(rm -rf:*)", "Bash(dd:*)", "Bash(mkfs:*)" ]
This prevents destructive operations that could cause data loss.
2.2.3. Tool Names
Common tools you can allow/deny:
Read- Reading filesWrite- Writing filesEdit- Editing filesBash(command:*)- Bash commands (use wildcards)WebSearch- Web searchingWebFetch- Fetching URLsGlob- File pattern matchingGrep- Content searching
2.3. Environment Variables
Set project-specific environment variables available to all Claude Code sessions:
"env": {
"PROJECT_ROOT": "/path/to/project",
"NODE_ENV": "development",
"PYTHONPATH": "./src:./lib",
"CUSTOM_VAR": "value"
}
Use cases:
- Project root path for scripts
- Environment type (dev/staging/prod)
- Custom paths (Python, Node modules)
- Feature flags
2.4. MCP Server Configuration
2.4.1. Enable All Project Servers
"enableAllProjectMcpServers": true
When true, all servers defined in .mcp.json are automatically enabled.
2.4.2. Selective Server Enablement
"enableAllProjectMcpServers": false, "enabledMcpjsonServers": [ "emacs", "filesystem" ]
Explicitly list which MCP servers to enable from .mcp.json.
3. Local Settings (Personal)
These settings are git-ignored and personal to each developer. Use for preferences, experimental features, and local tools.
3.1. Example Configuration
{
"model": "sonnet",
"alwaysThinkingEnabled": false
}
3.2. Common Local Settings
3.2.1. Model Selection
{
"model": "sonnet" // or "opus", "haiku"
}
Override the default model for this project.
3.2.2. Thinking Mode
{
"alwaysThinkingEnabled": false
}
Control whether Claude shows internal reasoning by default.
3.2.3. Notification Hooks
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "terminal-notifier -title 'Claude Code' -message 'Awaiting input'"
}
]
}
]
}
}
Run system notifications when Claude needs input (macOS example).
4. Advanced Configuration
4.1. Hooks System
Hooks execute commands before/after tool usage, enabling powerful workflow automation.
4.1.1. Hook Structure
{
"hooks": {
"ToolName": [
{
"matcher": "pattern",
"hooks": [
{
"type": "command",
"position": "before", // or "after"
"command": "command to run",
"blocking": true
}
]
}
]
}
}
4.1.2. Example: Git Status Before Commit
{
"hooks": {
"Bash": [
{
"matcher": "git commit",
"hooks": [
{
"type": "command",
"position": "before",
"command": "git status",
"blocking": true
}
]
}
]
}
}
Shows git status before any commit command.
4.1.3. Example: Notification on Completion
{
"hooks": {
"Bash": [
{
"matcher": "npm test",
"hooks": [
{
"type": "command",
"position": "after",
"command": "terminal-notifier -title 'Tests' -message 'Test run complete'"
}
]
}
]
}
}
Desktop notification when tests finish.
4.1.4. Hook Parameters
matcher- Pattern to match (empty string matches all)type- Currently only"command"is supportedposition-"before"or"after"tool executioncommand- Shell command to executeblocking- Iftrue, wait for command to complete
4.2. Sandbox Settings
Control sandboxing behavior for added security.
{
"sandbox": {
"enabled": true,
"allowedPaths": [
"/Users/kyeongsoo/Projects"
]
}
}
Warning: Modifying sandbox settings can affect security. Only change if you understand the implications.
4.3. Custom Tool Permissions
Fine-grained control over tool behavior.
{
"permissions": {
"allow": [
"Read",
"Write(/path/to/allowed/*)",
"Bash(ls:*)",
"Bash(grep:*)"
],
"deny": [
"Write(/etc/*)",
"Bash(sudo:*)"
]
}
}
Use path patterns for Write and command patterns for Bash.
5. Settings Hierarchy Example
Understanding how settings merge:
5.1. User Settings (~/.claude/settings.json)
{
"model": "sonnet",
"alwaysThinkingEnabled": false,
"permissions": {
"allow": ["Read", "Write"]
}
}
5.2. Project Settings (.claude/settings.json)
{
"permissions": {
"allow": ["Read", "Write", "Bash(git:*)"]
},
"env": {
"PROJECT_ROOT": "/path/to/project"
}
}
5.3. Local Settings (.claude/settings.local.json)
{
"model": "opus",
"hooks": {
"Notification": [...]
}
}
5.4. Effective Settings
After merging (local > project > user):
{
"model": "opus", // from local (overrides user)
"alwaysThinkingEnabled": false, // from user
"permissions": {
"allow": ["Read", "Write", "Bash(git:*)"] // from project
},
"env": {
"PROJECT_ROOT": "/path/to/project" // from project
},
"hooks": {
"Notification": [...] // from local
}
}
6. Best Practices
6.1. Do's
- Version control
.claude/settings.jsonfor team consistency - Use local settings for personal preferences
- Document why specific tools are allowed/denied
- Test hooks before committing them to project settings
- Use environment variables for project-specific paths
6.2. Don'ts
- Don't commit
.claude/settings.local.json(it's personal) - Don't hardcode absolute paths in project settings when possible
- Don't allow overly broad permissions (
Bash(*:*)is dangerous) - Don't store secrets or API keys in settings (use environment variables)
- Don't override security policies without understanding implications
6.3. Security Considerations
- Principle of least privilege: Only allow tools that are needed
- Deny dangerous operations:
rm -rf,dd,mkfs,sudo - Restrict filesystem access: Use path patterns in
Writepermissions - Review hooks carefully: Hooks execute arbitrary commands
- Version control project settings: Team reviews for security
7. Troubleshooting
7.1. Settings Not Taking Effect
- Restart Claude Code after changing settings
- Check JSON syntax with
jq . .claude/settings.json - Verify file is in correct location
- Check settings precedence (local > project > user)
7.2. Permission Denied Errors
- Check
permissions.allowincludes required tool - Verify no
denyrule is blocking it - Check pattern matching (
*wildcard usage) - Try more specific pattern if broad pattern doesn't work
7.3. Hooks Not Running
- Verify JSON syntax is correct
- Check
matcherpattern matches the tool usage - Test command manually in terminal first
- Check Claude Code logs for error messages
- Ensure
blockingis set if you need sequential execution
8. Related Configuration
- Slash Commands - Custom commands can reference environment variables
- Agent Skills - Skills respect permission settings
- MCP Servers - Enable/disable via settings