Settings & Permission Management
Configuring settings.json, allowed tools, and MCP servers.
Learning Objectives
- Configure settings.json and settings.local.json
- Manage tool permissions and trust levels
- Add MCP servers to Claude Code
Settings & Permission Management
Claude Code's behavior is configured through a layered settings system that controls everything from tool permissions to MCP server connections. The settings.jsonfile is the central configuration mechanism, and understanding its structure and precedence rules is essential for the CCA-F exam.
Settings.json Overview
Claude Code uses JSON configuration files at multiple levels to control permissions, behavior, and integrations. Like CLAUDE.md, settings follow a hierarchy:
Settings File Locations
- User settings:
~/.claude/settings.json— personal settings that apply to all projects. - Project settings:
.claude/settings.json— project-specific settings committed to version control. - Local project settings:
.claude/settings.local.json— personal overrides for a specific project (not committed to version control).
# Settings file hierarchy (least to most specific):
~/.claude/settings.json # User (all projects)
.claude/settings.json # Project (shared via git)
.claude/settings.local.json # Local project (personal, gitignored)settings.json in the project is committed and shared;settings.local.json is personal and gitignored. User-level settings apply globally. More specific settings override less specific ones.Tool Permission Configuration
The most important section of settings.json is tool permissions. This controls which tools Claude Code can use without asking for approval:
{
"permissions": {
"allow": [
"Edit",
"Write",
"Bash(npm test)",
"Bash(npm run build)",
"Bash(npm run lint)",
"Bash(npx tsc --noEmit)",
"Bash(git status)",
"Bash(git diff)",
"Bash(git log)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force)",
"Bash(npm publish)"
]
}
}Permission Patterns
Permissions support several matching patterns:
- Tool name only:
"Edit"— allows all uses of the Edit tool. - Tool with argument:
"Bash(npm test)"— allows only this specific bash command. - Tool with prefix match:
"Bash(npm run *)"— allows any npm run command. - MCP tool:
"mcp__servername__toolname"— allows a specific MCP tool.
{
"permissions": {
"allow": [
"Edit",
"Write",
"Bash(npm *)",
"Bash(npx *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git add *)",
"Bash(git commit *)",
"mcp__postgres__query"
],
"deny": [
"Bash(git push *)",
"Bash(rm -rf *)",
"Bash(curl *)",
"mcp__postgres__drop_table"
]
}
}deny list takes precedence overallow. If a tool matches both an allow rule and a deny rule, it is denied. This is a critical security principle tested on the exam.Permission Precedence
When evaluating whether a tool call is permitted, Claude Code checks in this order:
- Check the deny list — if the tool matches any deny rule, it is blocked.
- Check the allow list — if the tool matches an allow rule, it is permitted.
- If no rule matches, prompt the user for approval.
The deny-first evaluation means you can use a broad allow pattern and then carve out specific exceptions:
{
"permissions": {
"allow": [
"Bash(git *)"
],
"deny": [
"Bash(git push --force *)",
"Bash(git reset --hard *)",
"Bash(git clean *)"
]
}
}MCP Server Configuration
MCP (Model Context Protocol) servers extend Claude Code's capabilities by connecting it to external tools and services. MCP servers are configured in settings.json:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "postgresql://localhost:5432/mydb"
}
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
},
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/path/to/allowed/directory"
]
}
}
}MCP Server Configuration Fields
- command: The executable to run (e.g.,
npx,node,python). - args: Arguments passed to the command. For npx-based servers, this typically includes
-y(auto-confirm) and the package name. - env: Environment variables passed to the MCP server process. Supports variable expansion with
${VAR_NAME}syntax to reference environment variables from your shell.
mcp__servername__toolname format in permission rules.Environment Variable Handling
For security, sensitive values like API keys and tokens should not be hardcoded in settings.json. Instead, use environment variable references:
{
"mcpServers": {
"slack": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-slack"],
"env": {
"SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}",
"SLACK_TEAM_ID": "${SLACK_TEAM_ID}"
}
}
}
}The ${VAR_NAME} syntax reads the value from your shell environment at runtime. This means the actual token is never stored in the settings file and never committed to version control.
Project Settings for Teams
A well-configured project settings file establishes shared permissions and tool access for the entire team:
// .claude/settings.json (committed to git)
{
"permissions": {
"allow": [
"Edit",
"Write",
"Bash(npm test *)",
"Bash(npm run *)",
"Bash(npx tsc *)",
"Bash(npx prisma *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git add *)",
"Bash(git commit *)"
],
"deny": [
"Bash(git push --force *)",
"Bash(rm -rf *)",
"Bash(npm publish *)",
"Bash(npx prisma migrate reset *)"
]
},
"mcpServers": {
"project-db": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "${DATABASE_URL}"
}
}
}
}// .claude/settings.local.json (personal, gitignored)
{
"permissions": {
"allow": [
"Bash(git push *)"
]
},
"mcpServers": {
"my-notes": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/notes"]
}
}
}Hooks Configuration
Claude Code supports hooks — custom scripts that run before or after specific tool invocations. Hooks are configured in settings.json and provide a way to enforce policies or trigger side effects:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo "Running bash command validation""
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $CLAUDE_FILE_PATH"
}
]
}
],
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "terminal-notifier -message "$CLAUDE_NOTIFICATION""
}
]
}
]
}
}Hook Types
- PreToolUse: Runs before a tool is executed. Can be used for validation or logging. If the hook exits with a non-zero status, the tool call is blocked.
- PostToolUse: Runs after a tool completes. Useful for formatting, logging, or triggering follow-up actions.
- Notification: Runs when Claude Code emits a notification (e.g., when waiting for user input).
Complete Settings Reference
Here is a comprehensive settings.json showing all major configuration sections:
{
"permissions": {
"allow": [],
"deny": []
},
"mcpServers": {},
"hooks": {
"PreToolUse": [],
"PostToolUse": [],
"Notification": []
}
}Exam-Relevant Concepts Summary
- Three settings levels: user, project (committed), local project (gitignored).
- Permission rules: deny takes precedence over allow; unmatched tools prompt the user.
- Bash permissions support pattern matching:
"Bash(npm *)". - MCP tools use
mcp__servername__toolnameformat in permission rules. - Environment variables use
${VAR_NAME}syntax for secure secret handling. - Hooks: PreToolUse (can block), PostToolUse (post-processing), Notification.
- Project settings.json is committed to git; settings.local.json is not.