Introduction

Welcome back to Customizing Claude Code for Your Projects! In the first two units, we established how to guide Claude's behavior through project instructions (CLAUDE.md) and how to control which files it sees (.claudeignore). Now, in this third unit, we'll explore a more granular level of customization: settings files.

While CLAUDE.md defines what to do and .claudeignore defines what to see, settings files control how Claude operates, from which model it uses to how it handles permissions. We'll learn to configure behavior at multiple levels, creating both team-wide standards and personal preferences that shape every interaction with Claude.

Configuration as Control

Before diving into specific files, let's understand why settings files matter. Every time Claude starts, it makes decisions: which model to use (Sonnet, Haiku, or Opus), how to handle permissions (ask every time, auto-approve certain tools, or plan without executing), and what operations to allow or deny. Without configuration, these decisions follow default behavior, which might not match our workflow.

Settings files give us declarative control over these choices. Instead of manually switching models or repeatedly approving the same permissions, we define preferences once and Claude respects them automatically. More importantly, settings exist at different levels: some apply globally across all projects, others define team standards for a specific repository, and still others represent personal preferences that override everything else. This layered approach lets us balance consistency with flexibility.

The Three Configuration Layers

Claude recognizes three distinct levels of configuration, each stored in a different location. The user level lives in ~/.claude/settings.json and defines your personal defaults across all projects. When you prefer Sonnet as your general-purpose model or always want to review bash commands, those preferences belong here.

The project level lives in .claude/settings.json within the project directory. This file typically gets committed to version control, establishing shared standards for everyone working on the codebase. If a data analysis project should default to Haiku for cost efficiency or block access to sensitive files, those rules belong in project settings.

The local level lives in .claude/settings.local.json, also in the project directory but typically excluded from version control (like .env files). This is where you override project settings with personal preferences. Perhaps your team uses normal permission mode, but you prefer plan mode for careful review. Local settings let you customize without affecting others.

Viewing Current Configuration

Let's start by examining the user-level settings. We simply ask Claude to show us what's currently configured:

This output reveals our baseline configuration. The file contains JSON that defines permission settings within a permissions block, with "defaultMode": "default" meaning Claude will ask before using most tools rather than auto-approving or planning only.

These settings apply everywhere unless overridden by project or local configuration. Notice how Claude uses the Read tool to access the file and reports both the number of lines and the actual content. If we had a model preference configured here, it would appear in this file as well, but by default the model selection isn't specified in user settings.

Configuring Project Defaults

Now, let's say we're working on a data analysis project where we want different behavior. We'll configure project-specific settings:

Claude creates .claude/settings.json in the project directory with several important configurations. The "model": "haiku" setting specifies Haiku as the preferred model for this project, choosing the faster and more cost-effective option for routine analysis tasks.

The "permissions" block contains the permission-related settings. Within it, "defaultMode": "default" ensures Claude will request approval before executing operations, maintaining safety controls. The "deny" array contains patterns that block access to sensitive files:

  • "Read(./.env)" prevents reading the environment file in the project root.
  • "Read(./.env.*)" blocks variants like or .
Adding Personal Overrides

Project settings work well for shared standards, but what if we personally want different permission handling? Local settings let us customize without affecting the team:

Claude creates .claude/settings.local.json with a minimal override. This file specifies "defaultMode": "plan" within the permissions block, which changes permission handling to Plan Mode (where Claude outlines actions without executing them). The file doesn't repeat model or deny patterns because it only contains overrides; everything else inherits from the project and user levels.

This local file should be added to .gitignore so your personal preferences don't get committed to the repository or affect other developers. Each team member can maintain their own local overrides while the shared project settings remain consistent.

Verifying Active Configuration

After setting up multiple configuration layers, we should verify what's actually in effect. The /status command provides this information:

The output shows our effective configuration with clear information. Setting sources: User settings, Shared project settings indicates that both user-level defaults and project settings are active. The model shown reflects the current session's model; project model preferences will apply when starting new sessions.

This transparency helps us understand which settings are active. If we see unexpected behavior, /status quickly reveals our current configuration and which settings files are being applied.

Understanding Settings Precedence

The precedence system follows a logical hierarchy: higher layers override lower ones. At the foundation sits ~/.claude/settings.json, which provides your baseline defaults. Next comes .claude/settings.json in the project directory, which overrides user settings with project-specific rules. Finally, .claude/settings.local.json takes highest priority, allowing personal customization without affecting the team.

Beyond these file-based layers, two additional mechanisms exist. Command-line flags (like claude --model opus) override everything for that specific session. Managed configurations (set by organizations through Claude Teams or Enterprise) can enforce certain settings that individual files cannot override.

This means a complete precedence chain looks like: managed settings > CLI flags > local settings > project settings > user settings. In practice, most customization happens in the middle three layers, letting you balance personal preference, project standards, and organizational requirements.

Allow and Deny Lists

Within the permissions block, two arrays give you fine-grained control over what Claude can do: allow and deny. These lists use patterns to match specific operations.

The deny array blocks operations regardless of the default mode. Even with permissive permissions, denied operations are blocked:

The allow array explicitly permits operations without prompting, useful when defaultMode is restrictive:

Patterns use glob-style matching. The tool name comes first (Read, Write, Bash, Edit), followed by the pattern in parentheses. Read(*.py) matches any Python file, while Bash(pytest*) matches bash commands starting with pytest.

When operations match both lists, deny wins. The interaction with :

Common Configuration Patterns

Let's examine practical settings templates for different workflows. For a production-critical project, we might use restrictive settings:

This configuration uses Sonnet for reliability, requires explicit approval for most actions, and blocks dangerous commands like rm or sudo, as well as edits to environment files and production configurations.

For rapid prototyping, we might prefer efficiency:

Here we use Haiku for speed, enable auto-approval mode for edits, and explicitly allow reading files, writing Python code, and running python or pytest commands without interruption.

For learning and exploration, a cautious approach works best:

This simple configuration keeps Claude in plan mode, where it explains what it would do without executing anything. This gives us time to review and learn from its reasoning before allowing actions.

Managing Settings Over Time

Settings aren't static; they evolve as projects mature and requirements change. When starting a new feature branch, consider whether the work needs different model selection or permission handling. If you're refactoring critical authentication code, temporarily adding stricter permissions to your local settings provides extra safety.

As projects grow, periodically review .claude/settings.json to ensure the configuration still matches the team's workflow. If you find yourself repeatedly approving the same operations, add them to the allow list within the permissions block in project settings. Conversely, if certain tools are never needed, add them to the deny list to prevent accidental use.

Remember that settings complement other customization mechanisms. Use CLAUDE.md for what to build, .claudeignore for what to see, and settings files for how to operate. Together, these tools create a comprehensive environment tailored to your project's needs.

Conclusion and Next Steps

We've explored how settings files provide fine-grained control over Claude's behavior across multiple configuration layers. User settings establish personal defaults, project settings define team standards, and local overrides let you customize without affecting others. The precedence system ensures the right configuration applies at the right time, while the permissions block with its defaultMode, allow, and deny settings shapes how Claude interacts with your codebase.

Combined with the project instructions and context management we learned earlier, settings files complete your toolkit for customizing Claude to match any workflow. Whether you're building a production system, prototyping rapidly, or learning a new technology, the right configuration makes Claude a more effective partner. Now it's time to put these concepts into practice and discover how configuration transforms your development experience!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal