.claude Configuration Layers
Global, project, and local — who owns each layer, and what belongs where
🎯 The three layers
Claude Code reads configuration from three locations, merged together, from broadest to most specific:
| Layer | Location | Committed to git? | Owner | Purpose |
|---|---|---|---|---|
| Global | ~/.claude/ | No (lives on your machine) | You, personally | Defaults that apply to every project you work on |
| Project | <repo>/.claude/ | Yes | The team | Shared conventions, rules, skills, and permissions for this repo |
| Local | <repo>/.claude/settings.local.json | No (gitignored) | You, personally | Your personal overrides for this specific repo |
💡 Rule of thumb
If it should be the same for every engineer on the team working in this repo → project. If it's about your personal machine or personal preference across all repos → global. If it's a personal exception just for this repo (e.g. you've pre-approved a command your teammates haven't) → local.
🌐 Global layer: ~/.claude/
~/.claude/
├── CLAUDE.md # personal defaults loaded in every project
├── settings.json # global permissions, hooks, environment variables
└── skills/ # personal skills, available in every projectUse this for things that are about you, not about any one repo: your preferred commit message style, personal shortcuts, credentials-adjacent MCP servers you use everywhere (see MCP), or skills like "how I like PR descriptions written."
📁 Project layer: .claude/ (committed to git)
This is the layer a whole engineering team shares. It has two distinct mechanisms that are easy to confuse:
rules/ — auto-loaded by file path
Each file in .claude/rules/ declares which file paths it applies to via frontmatter. When Claude Code touches a matching file, the rule loads automatically — no trigger phrase needed.
.claude/rules/
├── controller.md # paths: ["**/controller/*.java"]
├── service.md # paths: ["**/service/**/*.java"]
├── mapper.md # paths: ["**/mapper/*.java"]
└── entity.md # paths: ["**/entity/*.java"]---
paths:
- "**/controller/*.java"
---
# Controller Conventions
## Class template
```java
@RestController
@RequiredArgsConstructor
@RequestMapping("/example")
public class ExampleController {
private final ExampleService exampleService;
}
```
## Must follow
- Constructor injection only, `@Autowired` is banned
- All responses wrapped in `R<T>`
- Controllers must not contain business logic — delegate to the service layer💡 Rules are for layer-specific patterns
Rules shine in layered architectures (controller/service/mapper/entity, or components/hooks/api in a frontend) where each layer has a distinct, mechanical convention. The path match means the right convention loads automatically without the AI (or you) having to figure out which one applies.
skills/ — loaded on demand by task match
Unlike rules, skills aren't tied to a file path — they're tied to what the task is about, matched against the skill's description. See Claude Skills for the full breakdown.
.claude/skills/
├── coding-standards/SKILL.md # triggers when writing/reviewing code generally
├── unit-testing/SKILL.md # triggers when writing tests
├── security-standards/SKILL.md # triggers on auth, input validation, secrets
└── database/SKILL.md # triggers on schema/migration/query worksettings.json — shared permissions and hooks
{
"permissions": {
"allow": [
"Bash(mvn test:*)",
"Bash(git status)",
"Bash(git diff:*)"
]
}
}Commit team-wide safe defaults here: commands everyone should be able to run without a prompt (test runners, read-only git commands, linting).
🔒 Local layer: settings.local.json (gitignored)
Personal, per-repo overrides — never committed. Typical contents: extra permissions you've pre-approved for yourself, personal MCP server credentials, or a slightly different allow-list than the team default.
{
"permissions": {
"allow": [
"WebFetch(domain:github.com)",
"Bash(gh api:*)",
"Read(//Users/you/.claude/plugins/cache/**)"
]
}
}⚠️ Never commit settings.local.json
It's meant to be personal and machine-specific — make sure .claude/settings.local.json is in .gitignore. If it's accidentally committed, permissions tuned for one engineer's workflow (or, worse, local paths/credentials) leak into the shared project config.
🧩 Putting it together: how a request resolves
When you ask Claude Code to "add validation to the controller," here's what loads, in order:
- Global
~/.claude/CLAUDE.md— your personal defaults (always loaded) - Project
AGENTS.md/CLAUDE.md— this repo's architecture and stack (always loaded, see AGENTS.md) - Project
.claude/rules/controller.md— auto-loads because you're editing a file undercontroller/ - Project
.claude/skills/dto-validation/SKILL.md— loads because "validation" matches its description - Merged permissions from project
settings.json+ your personalsettings.local.json
🎉 Result
Every layer contributes exactly what it's responsible for: your personal preferences from global, shared architecture and conventions from project, and your individual permission tweaks from local — without any single file becoming an unmanageable dumping ground.